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

feathers-attribute-permissions

v0.3.2

Published

A versioning service for feathers.js

Downloads

14

Readme

Feathers Attribute Permissions

ALPHA VERSION DOCUMENTATION

If you're reading this, feathers-attribute-permissions is in alpha, and not all of the functionality is fully described or finalized.


Why?

  • You're using feathers.js serverside, and you'd like use attribute based permissions for user interaction.
  • You're a strong, wise person with a bright future.

Quick Example

The following assumes you're familiar with feathers.js workflow. If you've never heard of feathers.js before, it's great. Learn it: feathers.js

Install

npm install feathers-attribute-permissions

Create an app with authentication and a user service


import feathers from 'feathers'
import rest from 'feathers-rest'
import hooks from 'feathers-hooks'
import auth from 'feathers-authentication'
import local from 'feathers-authentication-local'
import jwt from 'feathers-authentication-jwt'
import memory from 'feathers-memory'
import errorHandler from 'feathers-errors/handler'

import parser from 'body-parser'

const server = feathers()
  .configure(rest())
  .configure(hooks())

  .use(parser.json())
  .use(parser.urlencoded({ extended: true }))

  .configure(auth({ secret: 'man-in-the-machine' }))
  .configure(local())
  .configure(jwt())

  .use('/users', memory())
  .user('/articles', memory())

  .use(errorHandler())

//Auth hooks
const jwtLocalAuth = auth.hooks.authentication(['local', 'jwt'])
const jwtAuth = auth.hooks.authentication('jwt')

server.service('authentication').hooks({
  before: {
    create: [ jwtLocalAuth ],
    remove: [ jwtAuth ]
  }
})

//start that server up
server.listen(3000)

Set up the user service with authentication and permissions


import Permissions from 'feathers-attribute-permissions'

//very basic permissions creation. If permissions gets a
//string, it will create a series of attributes service
//methods. In this case:
//users-view
//users-create
//users-edit
//users-remove
const userPermissions = new Permissions('users')

//user hooks
const hashPass = local.hooks.hashPassword({
    passwordField: 'password'
  })

const users = server.service('users')
users.hooks({

  before: {
    find: jwtAuth,
    get:  jwtAuth,
    //the check permissions hook is attached to the permissions
    //object and it should be placed after authentication
    //on before 'create','patch','update' or 'remove' hooks
    create: [ jwtAuth, hashPass, userPermissions.check ],
    patch:  [ jwtAuth, hashPass, userPermissions.check ],
    update: [ jwtAuth, hashPass, userPermissions.check ],
    remove: [ jwtAuth, hashPass, userPermissions.check ]
  },

  after: {
    //the filter permissions hook is also attached to the
    //permissions object and it should be placed on
    //after 'find' or 'get' hooks
    get:  [ userPermissions.filter ]
    find: [ userPermissions.filter ]
  }

})

Set up permissions for the articles service


const articlePermissions = new Permissions({
  view:   'articles-view',
  edit:   'articles-manage'
  create: 'articles-manage',
  remove: 'articles-manage'
})

const articles = server.service('articles')

articles.hooks({

  //you can also set up the check hook as an 'all' hook,
  //and it will be ignored during 'find' and 'get'
  before: {
    all: [ jwtAuth, articlePermissions.check ]
  }

  //likewise with the filter hook. It will be ignored during
  //'update', 'patch', 'create' and 'remove'
  after: {
    all:  articlePermissions.filter
  }

})

Set up a client


import feathers from 'feathers/lib/client'
import rest from 'feathers-rest/client'
import hooks from 'feathers-hooks'
import auth from 'feathers-authentication/client'

import storage from 'localstorage-memory'
//or just window.localStorage, if you're testing in the browser

import fetch from 'fetch-isomorphic'
//or just window.fetch if you're testing in the browser

const client = feathers()
  .configure(rest('http://localHost:3000').fetch(fetch))
  .configure(hooks())
  .configure(auth({ storage }))

Create a couple of users on the server


//Set up a user that has the maximum permissions
const userService = server.service('users')

userService.create({
  email: '[email protected]',
  password: 'admin',

  //users need to have a permissions object on them. Each field should
  //be a permissions flag set to true.

  //undefined flags, or flags set to a falsy value will result in
  //permissions being denied
  permissions: {
    'users-create': true,
    'users-edit': true,
    'users-view': true,
    'users-remove': true,
    'articles-manage': true,
    'articles-view': true
  }
})

userService.create({

  email: '[email protected]',
  password: 'joe-user',

  permissions: {
    'users-view': false,
    'articles-view': true
  }

})

Test it Out on the Client


async function test() {

  await client.authenticate({ strategy: 'local', email: '[email protected]', password: 'joe-user'})

  const users = await client.service('users').find({})

  console.log(users) // users will be [], because joe doesn't have permissions to see them

  try {
    const me = await client.service('users').get(1)
  } catch (err) {
    //Poor joe can't even get himself!
    console.log(err.message) // You do not have Permission to view document with id 0
  }

  try {
    await.service('articles').create({
      body: 'I am mad that I don\'t have permissions to do anything!'
    })
  } catch (err) {
    console.log(err.message) //You do not have Permission to create articles.
  }

}

test()

Configuration

todo: Detail Permission configuration here

String or [String] configuration

Object configuration

Function configuration


Overrides on Documents

todo: Detail how permission objects on non-user documents can override user permissions


Options

todo: describe userEntityField, userIdField, permissionsField, originalField


Utility Methods and Hooks

todo: talk about the various packaged utility methods and hooks that come bundled to help with more complex permissions