I have a use case where I'm trying to infer if a specific user has admin access to a resource. I'm using GraphDB.
My ontology contains Users, Roles, Permissions and Resources. A User can have N roles. Each Role has different Permissions, one of which is the administration permissions. And each Role applies to a specific Resource.
So what I'm trying to infer is a direct relation indicating that a user has admin access to the resource. I'm trying to make PropertyChains and rolification fit for my use case, but I don't quite make it work. I'm not sure if that's even the right path.
I draft this piece of the ontology here:
@prefix : <https://stackoverflow.com/myQuestion#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
<https://stackoverflow.com/myQuestion>
a owl:Ontology .
:hasRole a owl:ObjectProperty ;
rdfs:domain :User ;
rdfs:range :Role .
:roleHasPermission a owl:ObjectProperty ;
rdfs:domain :Role ;
rdfs:range :Permission ;
:appliesToResource a owl:ObjectProperty ;
rdfs:domain :Role ;
rdfs:range :Resource .
:userHasAdminPermission a owl:ObjectProperty ;
rdfs:domain :User ;
rdfs:range :Resource .
:User a owl:Class .
:Role a owl:Class .
:Permission a owl:Class .
:Resource a owl:Class .
:AdminPermission a :Permission .
:OtherPermission a :Permission .
It is possible to achieve that using owl:propertyChainAxiom
but it will require an introduction of unique "node spcific loops" in the data related to the specic resource (:AdminPermission
) and using that in the target chain.
The tricky part is the generation of such "loops". One way of doing that can be achieved using a combination of an inverse property and an interplay with two restrictions of owl:hasValue
kind so to derive these around the specific target node.
Let's introduce a class :AdminRole
as a place holder of these:
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
:roleHasAdminPermission owl:inverseOf :adminPermissionAppliesToRole .
:AdminRole rdfs:subClassOf :Role;
owl:equivalentClass [
a owl:Restriction ;
owl:onProperty :roleHasPermission;
owl:hasValue :AdminPermission
];
owl:equivalentClass [
a owl:Restriction ;
owl:onProperty :roleHasAdminPermission;
owl:hasValue :AdminPermission
] .
:userHasAdminPermission owl:propertyChainAxiom
(:hasRole :roleHasPermission :adminPermissionAppliesToRole :appliesToResource) .
Whenever a node is related with :roleHasPermission
to :AdminPermission
it became member of :AdminRole
and respectively, each member of :AdminRole
must be related with :roleHasAdminPermission
to :AdminPermission
Next, introduce :adminPermissionAppliesToRole
as an inverse of :roleHasAdminPermission
thus creating the loop we are after.
What is left is to define the owl:propertyChainAxiom
through that loop to derive the :userHasAdminPermission
between the User and the Resource.
A check with some sample data (using owl2-rl inference):
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
insert data {
:Administrator a :Role ;
:roleHasPermission :AdminPermission .
:Administrator :appliesToResource :Archive .
:Clerk a :Role ;
:roleHasPermission :OtherPermission .
:Clerk :appliesToResource :SomethingOther .
:Ron a :User;
:hasRole :Administrator .
:Jane a :User;
:hasRole :Clerk .
}
and a sample query to check:
describe :Ron
will show :
:Ron :userHasAdminPermission :Archive
HTH