• Stars
    star
    172
  • Rank 213,462 (Top 5 %)
  • Language
    JavaScript
  • Created about 6 years ago
  • Updated over 3 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
15,023
star
2

lucid

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

adonis-app

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

ace

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

legacy-docs

πŸ“„ The official documentation of AdonisJs
186
star
6

auth

Official Authentication package for AdonisJS
TypeScript
179
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
161
star
9

ally

AdonisJS Social Authentication Provider
TypeScript
147
star
10

adonis-cli

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

adonis-api-app

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

validator

Schema based validator for AdonisJS
TypeScript
112
star
13

fold

IoC container with all required goodies to write flexible node applications
TypeScript
111
star
14

lucid-slugify

Generate unique slugs using your Lucid models
TypeScript
97
star
15

mail

AdonisJS Email Provider
TypeScript
94
star
16

http-server

AdonisJS HTTP Server along with its Router
TypeScript
93
star
17

repl

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

v5-docs

πŸ“š Source code and documentation for the official docs website.
TypeScript
87
star
19

adonis-rally

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

attachment-lite

Turn any field on your Lucid models to an attachment data type
TypeScript
71
star
21

adonis-websocket

Official websocket provider for AdonisJs
JavaScript
61
star
22

redis

Package for working with Redis in AdonisJS
TypeScript
59
star
23

vow

Test Runner For AdonisJs
JavaScript
55
star
24

adonis-websocket-client

Websocket client for AdonisJs framework.
JavaScript
51
star
25

rfcs

πŸ’¬ Sharing big changes with community to add them to the AdonisJs eco-system
51
star
26

discussion

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

drive

Filesystem provider built on top of node-flydrive
TypeScript
49
star
28

bouncer

Authorization Package for AdonisJS
TypeScript
47
star
29

shield

A middleware for AdonisJS to keep web applications secure from common web attacks
TypeScript
46
star
30

i18n

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

adonis-websocket-protocol

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

vite

⚑Vite plugin for AdonisJS
TypeScript
35
star
33

application

AdonisJS application class to read app related data
TypeScript
34
star
34

route-model-binding

Add route model binding to your AdonisJS applications
TypeScript
33
star
35

adonis-documentation

The documentation website source code hosted on http://adonisjs.com
CSS
32
star
36

session

Package for dealing with HTTP sessions in AdonisJS apps
TypeScript
32
star
37

bodyparser

BodyParser Middleware For AdonisJS
TypeScript
31
star
38

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
31
star
39

sink

Development Toolbox for AdonisJS providers
TypeScript
30
star
40

limiter

The official rate limiter package for AdonisJS
TypeScript
30
star
41

require-ts

In memory typescript compiler with disk caching
TypeScript
28
star
42

env

Framework agnostic environment variables parser and validator
TypeScript
27
star
43

transmit

A Server-Sent-Event module for AdonisJS
TypeScript
27
star
44

adonis-slim-app

AdonisJS 4 - Smallest possible application for Adonisjs
JavaScript
27
star
45

mrm-preset

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

adonis-http-logger

AdonisJs logger to log http requests
JavaScript
22
star
47

view

Template Engine For AdonisJS
TypeScript
20
star
48

logger

AdonisJS Logger built on top of pino
TypeScript
19
star
49

adonis-commands

Set of core commands for adonis framework
JavaScript
19
star
50

drive-s3

S3 driver for AdonisJS drive
TypeScript
19
star
51

encryption

Data encryption service for AdonisJS
TypeScript
18
star
52

events

Event emitter with asynchronous events.
TypeScript
18
star
53

adonis-ignitor

Library that gives fire to start AdonisJs application
JavaScript
18
star
54

hash

Multi driver hashing module following PHC string format
TypeScript
16
star
55

errors

Information about exceptions thrown by AdonisJs
15
star
56

create-adonisjs

Scaffolding tool to create AdonisJS 6 projects
TypeScript
15
star
57

ioc-transformer

Typescript transformer to transform import statements to IoC container use calls
TypeScript
13
star
58

adonis-addon

This repo contains a small boilerplate to create addons/providers for AdonisJs
13
star
59

pkg-starter-kit

AdonisJS starter kit to create a new package
TypeScript
13
star
60

profiler

Profile to time function calls with context in AdonisJS
TypeScript
12
star
61

vow-browser

Browser client for the adonis vow
JavaScript
12
star
62

web-starter-kit

Starter kit for creating traditional server rendered applications using AdonisJS
TypeScript
11
star
63

config

Config management provider used by AdonisJS framework
TypeScript
11
star
64

v6-docs

Documentation website for AdonisJS v6
TypeScript
11
star
65

adonis-middleware

List of official middleware for adonis framework
JavaScript
10
star
66

adonis-websocket-packet

Library to create and validate AdonisJs websocket packets
JavaScript
10
star
67

adonis-generic-exceptions

A module with all generic exceptions other modules can use
TypeScript
10
star
68

adonis-cors

Cors middleware for Adonisjs
JavaScript
9
star
69

static

Static files server middleware for AdonisJS
TypeScript
8
star
70

transmit-client

A client for the native Server-Sent-Event module of AdonisJS
TypeScript
8
star
71

v5_to_v6_upgrade_guide

Migration Guide to AdonisJS v6
TypeScript
8
star
72

adonis-manager

Base manager class others parts can use to expose driver based API
TypeScript
7
star
73

slim-starter-kit

Smallest possible AdonisJS application with just the framework core and the Japa test runner
TypeScript
7
star
74

drive-gcs

Google cloud storage driver for AdonisJS drive
TypeScript
6
star
75

adonis-loggly

Loggly transporter for AdonisJs Logger
JavaScript
6
star
76

cors

CORS middleware implementation
TypeScript
6
star
77

presets

A collection of presets to configure AdonisJS packages
TypeScript
6
star
78

adonisjs.com

Source code for the AdonisJS website
TypeScript
6
star
79

adonis-middleware-base

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

adonis-msgpack-encoder

Msgpack encoder to Adonis Websocket server
JavaScript
4
star
81

upgrade-kit

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

adonis-binding-resolver

Adonis binding resolver to resolve custom bindings in adonis apps - Check Readme
JavaScript
3
star
83

lucid.adonisjs.com

Documentation for Lucid
TypeScript
3
star
84

api-starter-kit

Starter kit for creating JSON API server using AdonisJS
TypeScript
3
star
85

.github

2
star
86

encore

Webpack Encore integration package for AdonisJS
TypeScript
2
star
87

tooling-config

Eslint, prettier, and typescript configurations for AdonisJS projects
TypeScript
2
star