• Stars
    star
    173
  • Rank 220,124 (Top 5 %)
  • Language
    JavaScript
  • Created over 6 years ago
  • Updated almost 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Opinionated user management service for AdonisJs

Opinionated user management service for AdonisJs

Make sure @adonisjs/framework version is >= 5.0.6

AdonisJs is all about removing redundant code from your code base. This add-on tries to do the same.

What is Persona?

Persona is a simple, functional service to let you create, verify and update user profiles.

Persona is not for everyone; if your login system is too complex and relies on many factors, Persona is not for you. However, persona works great for most use cases.

What does it do?

  1. Helps you register new users.
  2. Generates email verification tokens.
  3. Validates credentials on login.
  4. On email change, sets the user account to a pending state and re-generates the email verification token.
  5. Allows changing passwords.
  6. Allows recovering forgotten passwords.

What does it NOT do?

  1. Does not generate any routes, controllers or views for you.
  2. Does not send emails. However, it emits events that you can use to send emails.
  3. Does not create sessions or generate JWT tokens.

Setup

Run the following command to grab the add-on from npm:

adonis install @adonisjs/persona

# for yarn
adonis install @adonisjs/persona --yarn

Follow up by registering the provider inside the providers array:

const providers = [
  '@adonisjs/persona/providers/PersonaProvider'
]

You may then access it as follows:

const Persona = use('Persona')

Config

The config file is saved as config/persona.js.

Key Value Description
uids ['email'] An array of database columns that will be used as uids. If your system allows username and emails both, then simply add them to this array.
email email The field to be used as email. Every time a user changes the value of this field, their account will be set to the pending state.
password password The field to be used as password.
model App/Models/User The user model to be used.
newAccountState pending The default account state for new users.
verifiedAccountState active The account state for users after verifying their email address.
dateFormat YYYY-MM-DD HH:mm:ss Your database date format, required for determining if the token has been expired or not.
validationMessages function A function that returns an object of messages to be used for validation. The syntax is the same as Validator custom messages.

Constraints

There are some intentional constraints in place.

  1. Only works with Lucid models.

  2. The App/Models/User must have a relationship setup with App/Models/Token and vice-versa.

    class User extends Model {
      tokens () {
        return this.hasMany('App/Models/Token')
      }
    }
    
    class Token extends Model {
      user () {
        return this.belongsTo('App/Models/User')
      }
    }
  3. User table must have a string column called account_status.

API

Let's go through the API of persona.

register(payload, [callback])

The optional callback is invoked with the original payload just before the user is saved to the database. You can use it if you need to attach any other properties to the payload.

The register method takes the user input data and performs the following actions on it.

  1. Validates that all uids are unique.
  2. Checks that email is unique and is a valid email address.
  3. Makes sure the password is confirmed.
  4. Creates a new user account with the account_status = pending.
  5. Generates and saves an email verification token inside the tokens table.
  6. Emits a user::created event. You can listen for this event to send an email to the user.

Make sure to use querystring module to encode the token when sending via Email.

const Persona = use('Persona')

async register ({ request, auth, response }) {
  const payload = request.only(['email', 'password', 'password_confirmation'])

  const user = await Persona.register(payload)

  // optional
  await auth.login(user)
  response.redirect('/dashboard')
}

verify(payload, [callback])

The optional callback is invoked with the user instance just before the password verification. You can use it to check for userRole or any other property you want.

Verifies the user credentials. The value of uid will be checked against all the uids.

async login ({ request, auth, response }) {
  const payload = request.only(['uid', 'password'])
  const user = await Persona.verify(payload)

  await auth.login(user)
  response.redirect('/dashboard')
}

verifyEmail(token)

Verifies the user's email using the token. Ideally that should be after someone clicks a URL from their email address.

  1. Removes the token from the tokens table.
  2. Set user account_status = active.
async verifyEmail ({ params, session, response }) {
  const user = await Persona.verifyEmail(params.token)

  session.flash({ message: 'Email verified' })
  response.redirect('back')
}

updateProfile(user, payload)

Updates the user columns inside the database. However, if the email is changed, it performs the following steps:

Please note that this method will throw an exception if the user is trying to change the password.

  1. Sets the user's account_status = pending.
  2. Generates an email verification token.
  3. Fires the email::changed event.
async update ({ request, auth }) {
  const payload = request.only(['firstname', 'email'])
  const user = auth.user
  await Persona.updateProfile(user, payload)
}

updatePassword(user, payload)

Updates the user's password by performing the following steps:

Make sure to have the beforeSave hook in place for hashing the password. Otherwise the password will be saved as a plain string.

  1. Ensures old_password matches the user's password.
  2. Makes sure the new password is confirmed.
  3. Updates the user password.
  4. Fires the password::changed event. You can listen for this event to send an email about the password change.
async updatePassword ({ request, auth }) {
  const payload = request.only(['old_password', 'password', 'password_confirmation'])
  const user = auth.user
  await Persona.updatePassword(user, payload)
}

forgotPassword(uid)

Takes a forgot password request from the user by passing their uid. Uid will be matched against all the uids inside the config file.

  1. Finds a user with the matching uid.
  2. Generates a password change token.
  3. Emits the forgot::password event. You can listen for this event to send an email with the token to reset the password.
async forgotPassword ({ request }) {
  await Persona.forgotPassword(request.input('uid'))
}

updatePasswordByToken(token, payload)

Updates the user password using a token. This method performs the following checks:

  1. Makes sure the token is valid and not expired.
  2. Ensures the password is confirmed.
  3. Updates the user's password.
async updatePasswordByToken ({ request, params }) {
  const token = params.token
  const payload = request.only(['password', 'password_confirmation'])

  const user = await Persona.updatePasswordByToken(token, payload)
}

Custom messages

You can define a function inside the config/persona.js file, which returns an object of messages to be used as validation messages. The syntax is the same as Validator custom messages.

{
  validationMessages (action) => {
    return {
      'email.required': 'Email is required',
      'password.mis_match': 'Invalid password'
    }
  }
}

The validationMessages method gets an action parameter. You can use it to customize the messages for different actions. Following is the list of actions.

  1. register
  2. login
  3. emailUpdate
  4. passwordUpdate

Events emitted

Below is the list of events emitted at different occasions.

Event Payload Description
user::created { user, token } Emitted when a new user is created
email::changed { user, oldEmail, token } Emitted when a user changes their email address
password::changed { user } Emitted when a user changes their password by providing the old password
forgot::password { user, token } Emitted when a user asks for a token to change their password
password::recovered { user } Emitted when a user's password is changed using the token

Exceptions raised

The entire API is driven by exceptions, which means you will hardly have to write if/else statements.

This is great, since Adonis allows managing responses by catching exceptions globally.

ValidationException

Raised when validation fails. If you are already handling Validator exceptions, you won't have to do anything special.

InvalidTokenException

Raised when a supplied token, to verify an email or reset password with, is invalid.

Custom rules

At times, you may want to have custom set of rules when registering or login new users. You can override following methods for same.

The code can be added inside the hooks file or even in the registeration controller.

registerationRules

Persona.registerationRules = function () {
  return {
    email: 'required|email|unique:users,email',
    password: 'required|confirmed'
  }
}

updateEmailRules

Persona.updateEmailRules = function (userId) {
  return {
    email: `required|email|unique:users,email,id,${userId}`
  }
}

updatePasswordRules

Persona.updatePasswordRules = function (enforceOldPassword = true) {
  if (!enforceOldPassword) {
    return {
      password: 'required|confirmed'
    }
  }

  return {
    old_password: 'required',
    password: 'required|confirmed'
  }
}

loginRules

Persona.loginRules = function () {
  return {
    uid: 'required',
    password: 'required'
  }
}

More Repositories

1

core

AdonisJS is a TypeScript-first web framework for building web apps and API servers. It comes with support for testing, modern tooling, an ecosystem of official packages, and more.
TypeScript
16,897
star
2

lucid

AdonisJS SQL ORM. Supports PostgreSQL, MySQL, MSSQL, Redshift, SQLite and many more
TypeScript
1,074
star
3

adonis-app

Application structure for new adonis app, think of it as scaffolding a new project
JavaScript
371
star
4

ace

Node.js framework for creating command line applications
TypeScript
365
star
5

auth

Official Authentication package for AdonisJS
TypeScript
195
star
6

legacy-docs

📄 The official documentation of AdonisJs
187
star
7

legacy.adonisjs.com

🕸 Source Code of the old AdonisJS website
Vue
170
star
8

adonis-fullstack-app

AdonisJS 4 - The fullstack application boilerplate for AdonisJS
JavaScript
160
star
9

ally

AdonisJS Social Authentication Provider
TypeScript
159
star
10

adonis-cli

Legacy Adonis CLI module to generate new application
JavaScript
133
star
11

adonis-api-app

AdonisJS 4 - Boilerplate for API server with pre-configured JWT
JavaScript
131
star
12

fold

IoC container with all required goodies to write flexible node applications
TypeScript
123
star
13

validator

Schema based validator for AdonisJS
TypeScript
116
star
14

http-server

AdonisJS HTTP Server along with its Router
TypeScript
110
star
15

lucid-slugify

Generate unique slugs using your Lucid models
TypeScript
106
star
16

mail

AdonisJS Email Provider
TypeScript
104
star
17

repl

Framework Agnostic REPL For Node.js. Used by AdonisJS
TypeScript
92
star
18

inertia

Official Inertia.js adapter for AdonisJS
TypeScript
89
star
19

adonis-rally

Adonis rally is a forum engine written using AdonisJs.
JavaScript
88
star
20

v5-docs

📚 Source code and documentation for the official docs website.
TypeScript
88
star
21

redis

Package for working with Redis in AdonisJS
TypeScript
73
star
22

transmit

A Server-Sent-Event module for AdonisJS
TypeScript
71
star
23

attachment-lite

Turn any field on your Lucid models to an attachment data type
TypeScript
68
star
24

drive

Filesystem provider built on top of node-flydrive
TypeScript
64
star
25

adonis-websocket

Official websocket provider for AdonisJs
JavaScript
61
star
26

vow

Test Runner For AdonisJs
JavaScript
56
star
27

bouncer

Authorization Package for AdonisJS
TypeScript
54
star
28

rfcs

💬 Sharing big changes with community to add them to the AdonisJs eco-system
52
star
29

adonis-websocket-client

Websocket client for AdonisJs framework.
JavaScript
52
star
30

discussion

Discussing about new features and sharing random thoughts: ⚠️ Not every request will be accepted
51
star
31

shield

A middleware for AdonisJS to keep web applications secure from common web attacks
TypeScript
47
star
32

v6-docs

Documentation website for AdonisJS v6
Edge
46
star
33

i18n

Internationalization module for AdonisJs. Supports file and database drivers
TypeScript
43
star
34

vite

Vite plugin for AdonisJS
TypeScript
43
star
35

session

Package for dealing with HTTP sessions in AdonisJS apps
TypeScript
41
star
36

application

AdonisJS application class to read app related data
TypeScript
40
star
37

adonis-websocket-protocol

A document describing the protocol for Adonis websocket server
37
star
38

route-model-binding

Add route model binding to your AdonisJS applications
TypeScript
37
star
39

env

Framework agnostic environment variables parser and validator
TypeScript
36
star
40

pkg-starter-kit

AdonisJS starter kit to create a new package
TypeScript
36
star
41

assembler

A development toolkit used by AdonisJS to perform tasks like starting the dev server in watch mode, running tests in watch mode, and applying codemods to modify source files
TypeScript
34
star
42

adonis-documentation

The documentation website source code hosted on http://adonisjs.com
CSS
33
star
43

bodyparser

BodyParser Middleware For AdonisJS
TypeScript
32
star
44

limiter

The official rate limiter package for AdonisJS
TypeScript
32
star
45

sink

Development Toolbox for AdonisJS providers
TypeScript
31
star
46

require-ts

In memory typescript compiler with disk caching
TypeScript
29
star
47

adonis-slim-app

AdonisJS 4 - Smallest possible application for Adonisjs
JavaScript
28
star
48

mrm-preset

This repo is the preset used to AdonisJs team to manage and keep their config in sync.
JavaScript
26
star
49

logger

AdonisJS Logger built on top of pino
TypeScript
23
star
50

adonis-http-logger

AdonisJs logger to log http requests
JavaScript
23
star
51

transmit-client

A client for the native Server-Sent-Event module of AdonisJS
TypeScript
21
star
52

web-starter-kit

Starter kit for creating traditional server rendered applications using AdonisJS
Edge
21
star
53

drive-s3

S3 driver for AdonisJS drive
TypeScript
21
star
54

view

Template Engine For AdonisJS
TypeScript
21
star
55

adonis-commands

Set of core commands for adonis framework
JavaScript
20
star
56

events

Event emitter with asynchronous events.
TypeScript
20
star
57

adonisjs.com

Source code for the AdonisJS website
Edge
20
star
58

adonis-ignitor

Library that gives fire to start AdonisJs application
JavaScript
19
star
59

encryption

Data encryption service for AdonisJS
TypeScript
19
star
60

create-adonisjs

Scaffolding tool to create AdonisJS 6 projects
TypeScript
18
star
61

hash

Multi driver hashing module following PHC string format
TypeScript
17
star
62

errors

Information about exceptions thrown by AdonisJs
16
star
63

inertia-starter-kit

TypeScript
16
star
64

adonis-addon

This repo contains a small boilerplate to create addons/providers for AdonisJs
14
star
65

ioc-transformer

Typescript transformer to transform import statements to IoC container use calls
TypeScript
14
star
66

profiler

Profile to time function calls with context in AdonisJS
TypeScript
13
star
67

config

Config management provider used by AdonisJS framework
TypeScript
13
star
68

vow-browser

Browser client for the adonis vow
JavaScript
13
star
69

health

Health checks module for AdonisJS - This package is bundled within the core
TypeScript
12
star
70

lock

Atomic locks ( mutex ) for AdonisJS
TypeScript
12
star
71

adonis-middleware

List of official middleware for adonis framework
JavaScript
11
star
72

adonis-websocket-packet

Library to create and validate AdonisJs websocket packets
JavaScript
11
star
73

adonis-generic-exceptions

A module with all generic exceptions other modules can use
TypeScript
11
star
74

v5_to_v6_upgrade_guide

Migration Guide to AdonisJS v6
TypeScript
11
star
75

adonis-cors

Cors middleware for Adonisjs
JavaScript
10
star
76

slim-starter-kit

Smallest possible AdonisJS application with just the framework core and the Japa test runner
TypeScript
9
star
77

api-starter-kit

Starter kit for creating JSON API server using AdonisJS
TypeScript
9
star
78

drive-gcs

Google cloud storage driver for AdonisJS drive
TypeScript
8
star
79

adonis-manager

Base manager class others parts can use to expose driver based API
TypeScript
8
star
80

adonis-loggly

Loggly transporter for AdonisJs Logger
JavaScript
7
star
81

static

Static files server middleware for AdonisJS
TypeScript
7
star
82

presets

A collection of presets to configure AdonisJS packages
TypeScript
7
star
83

lucid.adonisjs.com

Documentation for Lucid
TypeScript
7
star
84

adonis-middleware-base

Very specific code written to make middleware work with Http and Websocket server.
JavaScript
6
star
85

eslint-config

ESLint presets used by the AdonisJS core team
JavaScript
5
star
86

adonis-msgpack-encoder

Msgpack encoder to Adonis Websocket server
JavaScript
5
star
87

cors

CORS middleware implementation
TypeScript
5
star
88

upgrade-kit

CLI tool for migrating from Adonis.js 5 to Adonis.js 6
TypeScript
5
star
89

cache

Cache module for AdonisJS. Supports Redis, Memcache, File and in-memory drivers
TypeScript
4
star
90

tsconfig

Base TypeScript configuration files for AdonisJS applications and packages
4
star
91

adonis-binding-resolver

Adonis binding resolver to resolve custom bindings in adonis apps - Check Readme
JavaScript
4
star
92

encore

Webpack Encore integration package for AdonisJS
TypeScript
4
star
93

tooling-config

Eslint, prettier, and typescript configurations for AdonisJS projects
TypeScript
4
star
94

prettier-config

Prettier config preset for AdonisJS packages and applications
4
star
95

eslint-plugin-adonisjs

ESLint plugin for AdonisJS to enforce framework specific rules
TypeScript
3
star
96

.github

3
star
97

adonis-app-dev

Development repository for adonis application. This repo contains all the integration tests for the final application
JavaScript
1
star