npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

tyranid-gracl

v0.5.19

Published

tyranid.js plugin for gracl

Downloads

277

Readme

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.

Links

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