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

simple-authorization

v0.2.3

Published

Authorization through JavaScript classes with support for React

Downloads

47

Readme

Simple Authorization

Build Status Code Climate Test Coverage

Simple Authorization is a JavaScript library inspired by Pundit for performing user authorization using simple JavaScript classes. If you've used Pundit in a Ruby project, you'll be instantly familiar.

Installation

Install the package via Yarn:

yarn add simple-authorization

Configuration

Initialize Simple Authorization to configure the data made available to your policy classes, and configure the policy class to use based on the name of the model that's being authorized.

import CommentPolicy from "../policies/comment-policy";
import PostPolicy from "../policies/post-policy";
import SimpleAuthorization from "simple-authorization";

// Assign a function that will return the data you need in
// each of your policies to make authorization decisions.
SimpleAuthorization.policyData = () => {
  const currentUser = { id: 5 };
  const role = {
    createPost: true,
    editOwnPost: true,
    editOthersPost: false
  };

  return { currentUser, role };
};

// Assign a function that will return your
// policy class based on the given model name.
SimpleAuthorization.policyResolver = modelName => {
  switch (modelName) {
    case "Comment":
      return CommentPolicy;
    case "Post":
      return PostPolicy;
  }
};

Usage

Create a base policy class to assign the data passed into the constructor to make it available to each policy.

class ApplicationPolicy {
  /**
   * Initializes the policy instance with the required data.
   *
   * @param {object} policyData The data needed for all policies
   */
  constructor({ currentUser, record, role }) {
    this.currentUser = currentUser;
    this.record = record;
    this.role = role;
  }
}

Create your policy class with the methods needed to determine whether the user is permitted to perform an action.

class PostPolicy extends ApplicationPolicy {
  /**
   * Permission to create a blog post.
   *
   * @returns {boolean} Whether the user is permitted
   */
  create() {
    return this.role.createPost;
  }

  /**
   * Permission to edit a blog post. In this example, we need to
   * know if the post was created by the current user or another
   * user when checking the user's permissions.
   *
   * `this.record` is the object we're passing in when calling `policy()`.
   *
   * @returns {boolean} Whether the user is permitted
   */
  edit() {
    if (this.record.userId === this.currentUser.id) {
      return this.role.editOwnPost;
    }

    return this.role.editOthersPost;
  }
}

The policies can be used in multiple ways by using the policy() helper method. The policy class that is used is determined by the SimpleAuthorization.policyResolver function we defined in the configuration step.

import { policy } from "simple-authorization";

// This will initialize the PostPolicy class with the data passed in from
// the return value of the `SimpleAuthorization.policyData` function.
policy("Post").create();
// => true

const post = new Post({ userId: 10 });

// This will also initialize the PostPolicy class because of the post
// instance's constructor name, and it will also make the post instance
// available as `this.record` in the PostPolicy `edit` method.
policy(post).edit();
// => false

// If you don't have an instance of a class, you can still make a plain
// object available as `this.record`.
policy("Post", { userId: 5 }).edit();
// => true

React

Simple Authorization also includes an <Authorize> React component for wrapping items that should be conditionally displayed based on the user's permissions.

import { Authorize } from "simple-authorization";

export default props => {
  return (
    <div>
      <Authorize perform="create" on="Post">
        <button>New Post</button>
      </Authorize>

      <Authorize perform="edit" on={new Post({ userId: 10 })}>
        <button>Edit Post</button>
      </Authorize>

      <Authorize perform="edit" on="Post" containing={{ userId: 5 }}>
        <button>Edit Post</button>
      </Authorize>
    </div>
  );
};

Because the SimpleAuthorization.policyData function isn't aware of when the data returned changes, the <Authorize> component keeps track of each of the mounted instances so they can be forced to render when your policy data changes.

import { Authorize } from "simple-authorization";
import store from "./store"; // Redux store

let currentUserRole;
store.subscribe(() => {
  let previousUserRole = currentUserRole;
  currentUserRole = store.getState().userRole;

  if (previousUserRole !== currentUserRole) {
    Authorize.forceUpdateAll();
  }
});

If you're looking to render markup for when a user is not permitted to perform an action, simply add cannot.

import { Authorize } from "simple-authorization";

export default props => {
  return (
    <Authorize cannot perform="create" on="Post">
      <div>You are not authorized to create new posts.</div>
    </Authorize>
  );
};

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

License

This module is available as open source under the terms of the MIT License.