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

fragments-user

v1.0.0-alpha.13

Published

have a token-auth protected API running within minutes with fragments

Downloads

2

Readme

fragments-user

the documentation in this readme is work in progress and currently unfinished !

fragment-user is currently in alpha state and subject to breaking changes without notice.

ALPHA NPM Package Build Status codecov.io Dependencies Downloads per Month

have a token-auth protected API running within minutes with fragments

fragments is an up and coming Node.js library that structures web applications with (request time) dependency injection.

fragments-user is a collection of factories for fragments that provide small to large building blocks for the rapid and fun development of maintainable, testable and elegant postgres-backed rest APIs with token-based-auth (JWT) and rights management. it comes preloaded with authentication and user management API endpoints.

fragments-user also serves as an example-application for fragments.
the tests for that example-application serve as additional integration tests for fragments.

install

npm install fragments-user

in your fragments app file make sure you are using fragments-postgres and fragments-user:

#!/usr/bin/env node

var hinoki = require('hinoki');
var fragments = require('fragments');
var fragmentsPostgres = require('fragments-postgres');
var app = hinoki.source(__dirname + '/src/factories');

var source = hinoki.source([
  app,
  fragmentsPostgres,
  fragments.source,
  fragments.umgebung,
]);

source = hinoki.decorateSourceToAlsoLookupWithPrefix(source, 'fragments_');

module.exports = fragments(source);

if (require.main === module) {
  module.exports.runCommand();
}

configuration environment variables

make sure that the following environment variables are set to your own values:

export PORT=8080
export BASE_URL="http://localhost:$PORT"

export MIGRATION_PATH="migrations"

export POSTGRES_DATABASE='my_database'
export DATABASE_URL="postgres://localhost:5432/$POSTGRES_DATABASE"
export POSTGRES_POOL_SIZE=40

export JWT_ENCRYPTION_PASSWORD='replace this with your super secret jwt encryption password'
export JWT_SIGNING_SECRET='replace this with your super secret jwt signing secret'

commands

call ./app to see a list of all available commands.

fragments-user itself adds the following commands:

rights {user-id} - list the rights of user with `user-id`
rights:delete {user-id} {right} - revoke `right` from user with `id`
rights:insert {user-id} {right} - grant `right` to user with `id`
users [optional-user-id] - show all users or just the user with `optional-user-id` (if given)
users:delete {user-id} - delete user with `user-id`
users:insert {name} {email} {password} - insert user
fake:users {count} - insert `count` fake users

add migrations/20150327204310-users.sql to the migrations folder of your app.

reset your database if necessary:

./app pg:drop-create

migrate:

./app pg:migrate

insert a user:

./app users:insert casca [email protected] opensesame

confirm that the user is inserted by listing all users:

./app users

start the server:

./app serve

you can find the server callback/middleware in src/factories/server.coffee. it only contains a user API. if you need more than that - and you probably do - just copy the server factory over to your application and extend it.

customization

fragments-user provides sensible defaults. customizing them is dead-simple.

you can overwrite every part which vastly changes the behaviour

user API documentation

the http command used in the following is https://github.com/jkbrzt/httpie

the code and test for each API action are linked. refer to them for additional documentation (especially for edge cases). use the code as inspiration to build your own API actions. most actions are only a few lines of code.

signup ! (tests)

signup

http POST localhost:8080/api/signup username=casca [email protected] password=opensesame

if you don't want users to be able to sign up just omit apiSignupPost from your middleware.

login ! (tests)

login to get an access token in the response:

http POST localhost:8080/api/login username=casca password=opensesame

if you don't want the API to be at /api just add the factory urlApi in your own app which overwrites urlApi in src/factories/url.coffee. overwrite other fragments as needed.

get current user (tests)

see the user that is logged in with a specific token:

http GET localhost:8080/api/me 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

(don’t forget to replace the token with the one you got in the response to the login request)

you should get a forbidden response as the user doesn't have the right to access the cockpit yet.

let’s give user the right to access cockpit:

./app rights:insert 1 canAccessCockpit

(don’t forget to replace the id with the one you got in the response to the user insert)

see the user logged in with a specific token:

http GET localhost:8080/api/me 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

you should now get the user record in the response.

update current user ! (tests)

http PATCH localhost:8080/api/me name=griffith 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

filter all users (tests)

to read all users the logged in user needs the right canReadUsers.
let's grant that right:

./app rights:insert 1 canReadUsers

insert some fake users so we have some records to filter:

./app fake:users 100

all users:

http GET localhost:8080/api/users 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

with limit and offset:

http GET 'localhost:8080/api/users?limit=5&offset=20' 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

ordered by username:

http GET 'localhost:8080/api/users?order=name&asc=true' 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

where email:

http GET 'localhost:8080/api/users?where[email][email protected]' 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

where email contains:

http GET 'localhost:8080/api/users?where[email][contains]=yahoo' 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

where email ends:

http GET 'localhost:8080/api/users?where[email][ends]=gmail.com' 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

where name:

http GET 'localhost:8080/api/users?where[name]=Rashawn.Haag' 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

where name contains:

http GET 'localhost:8080/api/users?where[name][contains]=nn' 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

where name begins:

http GET 'localhost:8080/api/users?where[name][begins]=an' 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

id below:

http GET 'localhost:8080/api/users?where[id][lt]=10' 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

id between 10 and 20 (inclusive):

http GET 'localhost:8080/api/users?where[id][gte]=10&where[id][lte]=20' 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

created today:

http GET 'localhost:8080/api/users?where[created_at]=today' 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

... you get the idea. if something feels like it should work but doesn't: file an issue !

create user ! (tests)

to create users the logged in user needs the right canCreateUsers.
let's grant that right:

./app rights:insert 1 canCreateUsers

now let's create a user:

http POST 'localhost:8080/api/users name=ubik [email protected] password=opensesame rights='' 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

get user where id (tests)

http GET 'localhost:8080/api/users/55' 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

update user ! (tests)

to update users the logged in user needs the right canUpdateUsers.
let's grant that right:

./app rights:insert 1 canUpdateUsers

now let's update a user:

http PATCH 'localhost:8080/api/users/1 name=ubik [email protected] password=opensesame rights='' 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

delete user ! (tests)

to delete users the logged in user needs the right canDeleteUsers.
let's grant that right:

./app rights:insert 1 canDeleteUsers

now let's delete a user:

http DELETE 'localhost:8080/api/users/3 'Authorization:Bearer eyJhbGciOiJIUzI1NiJ9.ZTdiMjJhZDk4OWY4Y2M5ZGQ1ZjcxM2Q3MDIxZjc2NTk.Tl-xvkKK9YP9Oz9o-BvuN2R3qi8VGwFpRzSh5cik-78'

access control

just overwrite them

some properties of the currently implemented rights management.

a user can't update his own rights. it's not even allowed.

a user with the right to create users can potentially create a user that has more rights.

a user with the right to updates users can change his and other users rights.

the rights canCreateUsers and canUpdateUsers can be escalated into all rights. they are to be considered superuser rights.

license: MIT