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

@cloudflare/authr

v3.0.0

Published

a flexible, expressive, language-agnostic access-control framework.

Downloads

4,155

Readme

authr

an incredibly granular and expressive permissions framework.

getting started

to get started, install the package!

npm install --save @cloudflare/authr

setting up objects for authr

even though we use typescript for the js implementation, we must be able to bridge with js, and we still need guarantees that the objects that authr deals with have methods that were purposed for it, we need a JS interface. but since javascript doesn't have such a thing, we can use symbols.

symbols have a lot of uses, but for authr's purposes, it guarantees that a certain object has explicitly implemented certain functionality specifically for authr; kind of like an interface! these symbols are made available for use by the package as exported constants.

note: a lot of important details about the philosophy and inner-workings of this library are glossed over. if you have not read the main README yet, it is highly recommended that you do so: cloudflare/authr/README.md

GET_RULES

in order to establish an subject (also called "actor") in this system, this constant MUST be the key in an object that is assigned to a callable function. when the function is called, it must return an array of Rules.

the typescript interface definition is this:

interface ISubject {
    [GET_RULES](): Rule[];
}

to implement in js, it would probably end up looking like this:

import { GET_RULES, Rule } from '@cloudflare/authr';

var user = {
    [GET_RULES]: () => ([
        Rule.allow({
            rsrc_type: 'zone',
            rsrc_match: [['@id', '=', '123']],
            action: ['delete', 'pause']
        }),
        Rule.deny({
            rsrc_type: 'private_key',
            rsrc_match: [],
            action: '*'
        })
    ])
};

once you have this, you have just setup a subject in the authr framework! subjects are entities in a system that are capable of taking actions against specific resources.

for resources, there are two symbols to implement on your object to make it a recognizable resource.

GET_RESOURCE_TYPE

this constant MUST be the key in an object that is assigned to a callable function that returns a string that identifies the resource type. like so:

import { GET_RESOURCE_TYPE } from '@cloudflare/authr';

var resource = {
    [GET_RESOURCE_TYPE]: () => 'zone'
};

pretty simple function, right? resources in the permission framework are entities that are capable of being acted upon, like a zone (a cloudflare object), or even a user.

GET_RESOURCE_ATTRIBUTE

this constant MUST be the key in an object that is assigned to a callable function. when the function is called, it will be given one string parameter that designates the key of the attribute being looked for. like so:

import {
    GET_RESOURCE_TYPE,
    GET_RESOURCE_ATTRIBUTE
} from '@cloudflare/authr';

var resource = {
    [GET_RESOURCE_TYPE]: () => 'zone',
    [GET_RESOURCE_ATTRIBUTE]: k => {
        var attr = {
            'id': 123,
            'type': 'full'
        };
        return attr[k] || null;
    }
};

when using these two constants in an object, you have just setup a resource in the authr framework!

but wait! symbols are new as hell and can't be used in old browsers!

mm. true. but there are some decent shims that can achieve the same things. not ideal, but, it gets the job done.

api

when you have all the objects in place and ready with their constants, you can finally start checking access-control. in this framework, there is only one way to do that: can.

can([subject], [action], [resource]): boolean

this is the core functionality of authr, the ultimate question: "can this subject perform this action on this resource?"

to get the answer to that question, we must pass all three parameters into this function

  • subject ISubject - the subject (actor) attempting the action
  • action string - the action being attempted
  • resource IResource - the resource that will be affected by the change

returns true if they are allowed, and false if they are not.

example

import {
    can
    GET_RULES,
    GET_RESOURCE_TYPE,
    GET_RESOURCE_ATTRIBUTE,
    Rule
} from '@cloudflare/authr';

var admin = {
    [GET_RULES]: () => ([
        Rule.allow({
            rsrc_type: 'zone',
            rsrc_match: [['@status', '=', 'V']],
            action: '*'
        })
    ])
};

var user = {
    [GET_RULES]: () => ([
        Rule.allow({
            rsrc_type: 'zone',
            rsrc_match: [['@id', '=', '123']],
            action: ['init', 'delete']
        })
    ])
};

var zones = {
    '123': {
        [GET_RESOURCE_TYPE]: () => 'zone',
        [GET_RESOURCE_ATTRIBUTE]: k => {
            var attr = {
                'id': 123,
                'status': 'V'
            };
            return attr[k] || null;
        }
    },
    '567': {
        [GET_RESOURCE_TYPE]: () => 'zone',
        [GET_RESOURCE_ATTRIBUTE]: k => {
            var attr = {
                'id': 567,
                'status': 'V'
            };
            return attr[k] || null;
        }
    }
};

console.log(can(admin, 'delete', zones['123'])); // => true
console.log(can(user, 'delete', zones['567'])); // => false
console.log(can(admin, 'do_admin_things', zones['123'])); // true