Socket
Socket
Sign inDemoInstall

tyranid-gracl

Package Overview
Dependencies
664
Maintainers
4
Versions
98
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    tyranid-gracl

tyranid.js plugin for gracl


Version published
Maintainers
4
Install size
4.59 MB
Created

Readme

Source

a gracl plugin for tyranid

npm version Build Status

This 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.

Setup

Installation

npm install tyranid-gracl

Annotate your tyranid schemas

import Tyr from 'tyranid';

const Organization = new Tyr.Collection({
  id: 'o00',
  name: 'organization',
  dbName: 'organizations',
  fields: {
    _id: { is: 'mongoid' },
    name: { is: 'string' },
  }
});


const Team = new Tyr.Collection({
  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' ]
    }
  }
});


export const Blog = new Tyr.Collection({
  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
 */
export const UsageLog = new Tyr.Collection({
  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 Tyr from 'tyranid';
import pmongo from 'promised-mongo';

// import plugin class
import { GraclPlugin } from 'tyranid-gracl';

// instantiate
const secure = new GraclPlugin();

const db = pmongo('mongodb://127.0.0.1:27017/tyranid_gracl_test');

Tyr.config({
  db: db,
  validate: [{ dir: root + '/test/models', fileMatch: '[a-z].js' }],
  // add to tyranid config...
  secure: secure
});

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:

import Tyr from 'tyranid';

/**
 *  Example express controller to set a permission
 */
export async function giveUserBlogViewAccessToOrg(req, res) {
  // assume this is a user document mixed in via middlewhere
  const user = req.user,
    // organizationId of org we want to give user view access to
    organizationId = req.query.organizationId;

  const org = await Tyr.byName.organization.byId(organizationId);

  const updatedOrg = await org.$allow('view-blog', user); // set view-blog access to true for user

  return res.json(updatedOrg);
}

/**
 *  Example express controller to check a permission
 */
export async function checkCanViewUid(req, res) {
  // assume this is a user document mixed in via middlewhere
  const user = req.user,
    // uid of entity we want to check if <user> has view access to
    uid = req.query.uid;

  const entity = await Tyr.byUid(uid);
  const canView = await entity.$isAllowedForThis('view', user);

  return res.json(canView);
}

/**
 *  Example express controller using filtered queries
 */
export async function findBlogs(req, res) {
  const blogs = await Tyr.byName.blog.findAll({ query: {}, auth: req.user });
  return res.json(blogs);
}

/**
 *  Example creating a mongodb query that is restricted using permissions
 */
export async function getQueryForBlogsICanEdit(req, res) {
  const originalQuery = {
    name: {
      $in: ['myBlog', 'otherBlog']
    }
  };
  const secured = await Tyr.byName.blog.secureQuery(
    originalQuery,
    'edit',
    req.user
  );
  return secured;
}

/**
 *  Example express controller to delete all permissions for an entity
 */
export async function deletePermissionsRelatingToUid(req, res) {
  const uid = req.query.uid;
  await Tyr.secure.permissionsModel.deletePermissions(await Tyr.byUid(uid));
  return res.json({ message: 'Success!' });
}

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
 */
const result = await org.$explainAccess('view-post', user);

result ===
  {
    explainations: [
      {
        type: 'ALLOW',
        resourcePath: [
          'b005aeb2a7199af181806f44856',
          'o005aeb2a7199af181806f4484f'
        ],
        subjectPath: [
          'u005aeb2a7199af181806f44866',
          't005aeb2a7199af181806f44862',
          'o005aeb2a7199af181806f4484f'
        ],
        permissionId: '5aeb2a711cb4be9be52c3844',
        permissionType: 'edit-post',
        property: 'blogId'
      },
      {
        type: 'ALLOW',
        resourcePath: [
          'b005aeb2a7199af181806f44856',
          'o005aeb2a7199af181806f4484f'
        ],
        subjectPath: [
          'u005aeb2a7199af181806f44866',
          't005aeb2a7199af181806f44863',
          'o005aeb2a7199af181806f4484f'
        ],
        permissionId: '5aeb2a711cb4be9be52c3844',
        permissionType: 'edit-post',
        property: 'blogId'
      }
    ],
    hasAccess: true,
    resourceId: 'p005aeb2a7199af181806f4485c',
    subjectId: 'u005aeb2a7199af181806f44866'
  };

/**
 * use a final `true` argument to return a human readable version
 */
const reason = await org.$explainAccess(
  'view-post',
  user,
  true /* format as string  */
);

/**
 * 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
 *
 */

Keywords

FAQs

Last updated on 26 Dec 2019

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc