I’m working on a Prolog program that will model Google Zanzibar style rewrite rules. The program I have looks like the following:
:- dynamic(config/4).
:- dynamic(tuple/6).
:- assertz(config("document", "editor")).
:- assertz(config("group", "member")).
:- assertz(tuple("document", "1", "editor", "user", "jon")).
:- assertz(tuple("document", "1", "editor", userset("group", "eng", "member"))).
:- assertz(tuple("group", "eng", "member", "user", "andres")).
checkWR(ObjectType, ObjectId, Relation, UserObjectType, UserObjectId) :-
tuple(ObjectType, ObjectId, Relation, UserObjectType, UserObjectId),
tuple(ObjectType, ObjectId, Relation, userset(UsersetObjectType, UsersetObjectId, UsersetRelation)),
check(UsersetObjectType, UsersetObjectId, UsersetRelation, UserObjectType, UserObjectId).
check(ObjectType, ObjectId, Relation, UserObjectType, UserObjectId) :-
config(ObjectType, Relation),
checkWR(ObjectType, ObjectId, Relation, UserObjectType, UserObjectId), !.
The behavior I’d like to see is the following:
?- check("document", "1", "editor", "user", "jon").
true
?- check("document", "1", "editor", "user", "andres").
true
?- check("document", "editor", userset("group", "eng", "member")).
true
The idea is that direct relationships such as document:1#editor@user:jon
or relationships through indirect relationships such as document:1#editor@group:eng#member
and group:eng#member@user:andres
should lead to a path.
The problem I’m having is expressing the effective union in checkWR
. What I really want is the outcome or union of either
tuple(ObjectType, ObjectId, Relation, UserObjectType, UserObjectId),
or
tuple(ObjectType, ObjectId, Relation, userset(UsersetObjectType, UsersetObjectId, UsersetRelation)),
check(UsersetObjectType, UsersetObjectId, UsersetRelation, UserObjectType, UserObjectId).
If a direct fact/relationship exists or if a userset relationship exists and the check
of that is solvable, then checkWR
should yield a solution.
Can someone help me express this? I tried with a union rule composing these two with the HEAD and TAIL, but that didn’t work for me.