Skip to content

Instantly share code, notes, and snippets.

@radekg
Last active September 3, 2022 18:45
Show Gist options
  • Save radekg/192ed65e53299bce74f59cfdbabf94ac to your computer and use it in GitHub Desktop.
Save radekg/192ed65e53299bce74f59cfdbabf94ac to your computer and use it in GitHub Desktop.
Blog: Zanzibar-style ACLs in Prolog
directory(
dirname('data'),
objectid('851a7566-b83d-4993-bd04-9b8244091d45'),
parent(objectid())).
directory(
dirname('documents'),
objectid('b94c1f40-818b-47be-882b-ce1a8fbee254'),
parent(
objectid('851a7566-b83d-4993-bd04-9b8244091d45'))).
directory(
dirname('pdfs'),
objectid('7f916bd9-f324-40f2-97d3-95e7cc7d722e'),
parent(
objectid('b94c1f40-818b-47be-882b-ce1a8fbee254'))).
document(
filename('a-data-item.png'),
objectid('9c57448c-e901-4fd3-a47e-b6ecf0470c5f'),
parent(
objectid('851a7566-b83d-4993-bd04-9b8244091d45'))).
document(
filename('a-document.md'),
objectid('f666cc22-1e92-457b-b7ee-0f6b48825185'),
parent(
objectid('b94c1f40-818b-47be-882b-ce1a8fbee254'))).
document(
filename('a-file.pdf'),
objectid('bee100a0-30b1-4184-94aa-3d408b75e938'),
parent(
objectid('7f916bd9-f324-40f2-97d3-95e7cc7d722e'))).
document(
filename('another.pdf'),
objectid('ecf47371-fd08-44f1-9c06-7c970d948ae8'),
parent(
objectid('7f916bd9-f324-40f2-97d3-95e7cc7d722e'))).
% Permissions for the data directory.
permissions(
objectid('851a7566-b83d-4993-bd04-9b8244091d45'),
[owners, [berta], editors, [charlie]]).
% Permissions for the pdfs directory.
permissions(
objectid('7f916bd9-f324-40f2-97d3-95e7cc7d722e'),
[viewers, [alan]]).
% Direct permissions for the PDF file.
permissions(
objectid('bee100a0-30b1-4184-94aa-3d408b75e938'),
[viewers, [jake]]).
append([], Out, Out).
append([X|T], Y, [X|Out]) :-
append(T, Y, Out).
in_list(X, [X|_]).
in_list(X, [_|Ys]) :- in_list(X, Ys).
find_kv(K, [K, [VK|Vs]|_], [VK|Vs]).
find_kv(K, [_, _|Rest], Out) :- find_kv(K, Rest, Out).
find_kv(_, [_|_], []).
find_kv(_, [], []).
object_permissions(Id, [ RoleH | RoleTail ], Out) :-
permissions(objectid(Id), Permissions),
find_kv(RoleH, Permissions, RolePermissions),
object_permissions(Id, RoleTail, Ys),
append(RolePermissions, Ys, Out).
object_permissions(_, _, []).
optional_object_permissions(ObjectId, Roles, Permissions) :-
object_permissions(ObjectId, Roles, Permissions).
optional_object_permissions(_, _, []).
inherits(objectid(), _, _) :- false.
inherits(objectid(ObjectId), Roles, User) :-
optional_object_permissions(ObjectId, Roles, Permissions),
in_list(User, Permissions).
inherits(objectid(ObjectId), Roles, User) :-
directory(_, objectid(ObjectId), parent(objectid(ParentObjectId))),
inherits(objectid(ParentObjectId), Roles, User).
% Owner query API:
is_doc_owner(objectid(X), User) :-
object_permissions(X, [owners], Permitted),
in_list(User, Permitted).
is_doc_owner(objectid(X), User) :-
document(_, objectid(X), parent(ParentId)),
inherits(ParentId, [owners], User).
% Editor query API:
is_doc_editor(objectid(X), User) :-
object_permissions(X, [editors, owners], Permitted),
in_list(User, Permitted).
is_doc_editor(objectid(X), User) :-
document(_, objectid(X), parent(ParentId)),
inherits(ParentId, [editors, owners], User).
% Viewer query API:
is_doc_viewer(objectid(X), User) :-
object_permissions(X, [viewers, editors, owners], Permitted),
in_list(User, Permitted).
is_doc_viewer(objectid(X), User) :-
document(_, objectid(X), parent(ParentId)),
inherits(ParentId, [viewers, editors, owners], User).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment