gracl plugin for tyranid
aThis repository contains a plugin for tyranid
that allows for graph-based acl permissions to be enforced / utilized
within tyranid simply by adding a few schema annotations.
Links
- Github Repository
- A few slides that explain the basical algorithm and motivation of this project.
Setup
Installation
npm install tyranid-gracl
Annotate your tyranid schemas
; const Organization = id: 'o00' name: 'organization' dbName: 'organizations' fields: _id: is: 'mongoid' name: is: 'string' ; const Team = id: 't00' name: 'team' dbName: 'teams' fields: _id: is: 'mongoid' name: is: 'string' // here we indicate that "organization" is both the // parent subject and parent resource in the permissions // hierarchy organizationId: link: 'organization' relate: 'ownedBy' // can be both! // now, organization is implicitly also a subject and resource graclType: 'subject' 'resource' ; const Blog = id: 'b00' name: 'blog' dbName: 'blogs' fields: _id: is: 'mongoid' name: is: 'string' organizationId: link: 'organization' relate: 'ownedBy' graclType: 'resource' ; /** * Alternatively, if there is a collection that has no collections pointing to it via an "ownedBy" relation, you can add a permissionIds field on the collection itself and specify the graclType */const UsageLog = id: 'ul0' name: 'usagelog' dbName: 'usagelogs' graclType: 'resource' fields: _id: is: 'mongoid' text: is: 'string' ;
Register the plugin
With annotated schemas, we can create and register the plugin with tyranid.
;; // import plugin class; // instantiateconst secure = ; const db = ; Tyr;
This will install the gracl plugin in tyranid and validate your permissions hierarchies as declared through the collection schema.
Using permissions
Now, we can utilize the provided tyranid Document prototype extensions to check/set permissions. Additionally, collection.find()
queries will be automatically filtered using the hierarchy.
Method usage examples:
; /** * Example express controller to set a permission */ { // assume this is a user document mixed in via middlewhere const user = requser // organizationId of org we want to give user view access to organizationId = reqqueryorganizationId; const org = await TyrbyNameorganization; const updatedOrg = await org; // set view-blog access to true for user return res;} /** * Example express controller to check a permission */ { // assume this is a user document mixed in via middlewhere const user = requser // uid of entity we want to check if <user> has view access to uid = reqqueryuid; const entity = await Tyr; const canView = await entity; return res;} /** * Example express controller using filtered queries */ { const blogs = await TyrbyNameblog; return res;} /** * Example creating a mongodb query that is restricted using permissions */ { const originalQuery = name: $in: 'myBlog' 'otherBlog' ; const secured = await TyrbyNameblog; return secured;} /** * Example express controller to delete all permissions for an entity */ { const uid = reqqueryuid; await TyrsecurepermissionsModel; return res;}
Explaining Permissions
In order to determine why or why not a subject is allowed access to a resource document,
you can utilize the doc.$explainAccess(permission, subject)
method:
/** * get metadata explaining access */; result === ; /** * use a final `true` argument to return a human readable version */; /** * reason: * The subject (u005aeb2a7199af181806f44866) is allowed access to resource (p005aeb2a7199af181806f4485c): - The subject is allowed edit-post access through permission 5aeb2a711cb4be9be52c3844. > Resource Hierarchy: b005aeb2a7199af181806f44856 -> o005aeb2a7199af181806f4484f > Subject Hierarchy: u005aeb2a7199af181806f44866 -> t005aeb2a7199af181806f44862 -> o005aeb2a7199af181806f4484f - The subject is allowed edit-post access through permission 5aeb2a711cb4be9be52c3844. > Resource Hierarchy: b005aeb2a7199af181806f44856 -> o005aeb2a7199af181806f4484f > Subject Hierarchy: u005aeb2a7199af181806f44866 -> t005aeb2a7199af181806f44863 -> o005aeb2a7199af181806f4484f * */