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

@northscaler/acl

v1.4.1

Published

Security via access control list (ACL)

Downloads

4

Readme

@northscaler/acl

This library allows you to maintain security information in access control lists (ACLs).

There are four elements required in the determination of access:

  • principal: The actor, user or system attempting to perform some action on a securable.
  • securable: The thing being secured.
  • action: The action being performed on a securable. This library defines a minimal set of primitive actions, but you can define your own.
  • access control entry: the binding of the principal, securable and action together along with the "permitted" (or "denied") boolean, or some other strategy. Some systems call this a "permission", a "right" or a "grant" in the positive sense, and a "denial", an "antipermission", or a "negative permission" in the negative sense. We use the more general term "access control entry", often abbreviated ACE (similar to ACL), which can mean either a permission or a denial.

The primary export of this module is a class called Acl, which has interrogation methods permits & denies, as well as mutating methods like permit, unpermit, deny, undeny, or, the more general secure & unsecure methods.

NOTE: In this implementation, a single denial vetoes any number of permissions, and the absence of any permissions denies.

It supports declarative or static security algorithms (think "permitted" or "denied" as a simple boolean), as well as algorithmic or dynamic security algorithms (think "permitted if today is a weekday", "denied if the balance is greater than 10000", or similar).

TL;DR

See the tests in src/test/unit/Acl.spec.js for usage.

Simple, declarative strategy example

This is simply one of the tests.

    const acl = new Acl()                                                     // 1
    const principal = uuid()                                                  // 2
    const securable = uuid()                                                  // 3
    const action = uuid()                                                     // 4

    acl.permit({ principal, securable, action })                               // 5

    expect(acl.permits({ principals: principal, actions: action, securable })) // 6
      .to.equal(true)
    expect(acl.denies({ principals: principal, actions: action, securable }))
      .to.equal(false)

    acl.unpermit({ principal, securable, action })                             // 7

    expect(acl.permits({ principals: principal, actions: action, securable })) // 8
      .to.equal(false)
    expect(acl.denies({ principals: principal, actions: action, securable }))
      .to.equal(false)

    acl.deny({ principal, securable, action })                                // 9

    expect(acl.permits({ principals: principal, actions: action, securable })) // 10
      .to.equal(false)
    expect(acl.denies({ principals: principal, actions: action, securable }))
      .to.equal(true)

    acl.undeny({ principal, securable, action })                              // 11

    expect(acl.permits({ principals: principal, actions: action, securable })) // 12
      .to.equal(false)
    expect(acl.denies({ principals: principal, actions: action, securable }))
      .to.equal(false)
  1. Creates a new access control list.
  2. A principal. This could be either an id referring to a principal as in this example, or an actual principal object. Up to you.
  3. A securable. This could be either an id referring to a securable as in this example, or an actual securable object. Up to you.
  4. An action. This could be anything you want, from one of the primitive actions, to a method name. Again, up to you.
  5. Instructs the ACL to permit the given principal the ability to take the given action against the given securable.
  6. Interrogates the ACL to ensure that the permission took place correctly.
  7. Instructs the ACL to remove the permission that was previously given. Note that this is not an explicit denial; it is only the removal of the permission.
  8. Interrogates the ACL to ensure that the removal of the permission took place correctly.
  9. Instructs the ACL to explicitly deny from given principal the ability to take the given action against the given securable.
  10. Interrogates the ACL to ensure that the denial took place correctly.
  11. Instructs the ACL to remove the denial that was previously given.
  12. Interrogates the ACL to ensure that the undenial took place correctly.

Example with dynamic strategy

This is taken from the test 'should work with a custom strategy'. It shows that you can use arbitrarily complex logic to make access control decisions. This example uses individual person's names, but they could just as easily be role type names. The goal is to ensure that only the right principals can close securables with balances (like accounts), so the action is 'close'.

    const sally = 'sally'
    const john = 'john'
    const felix = 'felix'

    const close = 'close'

    class Strategy {                                        // 1
      constructor (hiThreshold, loThreshold) {              // 2
        this.hiThreshold = hiThreshold
        this.loThreshold = loThreshold
      }

      permits ({ principal, action, securable }) {           // 3
        switch (action) {
          case close:
            switch (principal) {
              case sally:
                return true                                 // 4
              case john:
                return securable.balance < this.hiThreshold // 5
              default:
                return securable.balance < this.loThreshold // 6
            }
        }
      }

      denies ({ principal, action, securable }) {           // 7
        switch (action) {
          case close:
            switch (principal) {
              case felix:                                   // 8
                return securable instanceof Account
              default:                                      // 9
                return false
            }
        }
      }
    }

    // see rest of test for assertions
  1. Declare a strategy class. The only requirements are that it has permits & denies methods.
  2. Create a parameterized constructor so that strategy class is more flexible.
  3. Define the permission logic. We'll assume that the only securable type being passed in is an Account.
  4. In this case, principal sally is always permitted to close any account.
  5. john can close medium-valued accounts.
  6. Everyone can close low-valued accounts.
  7. This is the other method required by an access control strategy to determine if a principal is explicitly denied from taking the given action against the given securable. Here, we're only using the principal & action to make the determination.
  8. Some time ago, we must've determined that felix is unfortunately prone to hitting "enter" before thinking things through, so we have effectively barred him from closing any accounts. Even though he's effectively permitted the ability to close a low-value account by virtue of the permits method, we're vetoing that capability here, because a single denial vetoes all permits.
  9. No one else is explicitly denied the ability to close an account.