mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
api: pass user object to auth hooks (#5251)
* api: pass user object to auth hooks The motivation for this is the ability to migrate from bcrypt passwords to argon2 seamlessly. Fixes #4718 Fixes #4335 * receive user from `auth.login.before` hook * pass `otp` as well on `auth.login` hooks * api: last registered hook should have priority When registering multiple hooks for a single event, the last hook should have priority on return value. * Fix linter warning Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>
This commit is contained in:
@@ -15,8 +15,8 @@ import { RouteNotFoundException } from '../exceptions';
|
||||
*/
|
||||
const notFound: RequestHandler = async (req, res, next) => {
|
||||
try {
|
||||
const ret = await emitter.emitAsync('request.not_found', req, res);
|
||||
if (ret.reduce((prev, current) => current || prev, false)) {
|
||||
const hooksResult = await emitter.emitAsync('request.not_found', req, res);
|
||||
if (hooksResult.reduce((prev, current) => current || prev, false)) {
|
||||
return next();
|
||||
}
|
||||
next(new RouteNotFoundException(req.path));
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import argon2 from 'argon2';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { Knex } from 'knex';
|
||||
import { omit } from 'lodash';
|
||||
import ms from 'ms';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { authenticator } from 'otplib';
|
||||
@@ -59,31 +58,33 @@ export class AuthenticationService {
|
||||
|
||||
const { email, password, ip, userAgent, otp } = options;
|
||||
|
||||
const hookPayload = omit(options, 'password', 'otp');
|
||||
|
||||
const user = await database
|
||||
let user = await database
|
||||
.select('id', 'password', 'role', 'tfa_secret', 'status')
|
||||
.from('directus_users')
|
||||
.whereRaw('LOWER(??) = ?', ['email', email.toLowerCase()])
|
||||
.first();
|
||||
|
||||
await emitter.emitAsync('auth.login.before', hookPayload, {
|
||||
const updatedUser = await emitter.emitAsync('auth.login.before', options, {
|
||||
event: 'auth.login.before',
|
||||
action: 'login',
|
||||
schema: this.schema,
|
||||
payload: hookPayload,
|
||||
payload: options,
|
||||
accountability: this.accountability,
|
||||
status: 'pending',
|
||||
user: user?.id,
|
||||
database: this.knex,
|
||||
});
|
||||
|
||||
if (updatedUser) {
|
||||
user = updatedUser;
|
||||
}
|
||||
|
||||
const emitStatus = (status: 'fail' | 'success') => {
|
||||
emitAsyncSafe('auth.login', hookPayload, {
|
||||
emitAsyncSafe('auth.login', options, {
|
||||
event: 'auth.login',
|
||||
action: 'login',
|
||||
schema: this.schema,
|
||||
payload: hookPayload,
|
||||
payload: options,
|
||||
accountability: this.accountability,
|
||||
status,
|
||||
user: user?.id,
|
||||
|
||||
@@ -114,8 +114,7 @@ export class ItemsService<Item extends AnyItem = AnyItem> implements AbstractSer
|
||||
// The events are fired last-to-first based on when they were created. By reversing the
|
||||
// output array of results, we ensure that the augmentations are applied in
|
||||
// "chronological" order
|
||||
const payloadAfterHooks =
|
||||
hooksResult.length > 0 ? hooksResult.reverse().reduce((val, acc) => merge(acc, val)) : payload;
|
||||
const payloadAfterHooks = hooksResult.length > 0 ? hooksResult.reduce((val, acc) => merge(acc, val)) : payload;
|
||||
|
||||
const payloadWithPresets = this.accountability
|
||||
? await authorizationService.validatePayload('create', this.collection, payloadAfterHooks)
|
||||
@@ -402,8 +401,7 @@ export class ItemsService<Item extends AnyItem = AnyItem> implements AbstractSer
|
||||
// The events are fired last-to-first based on when they were created. By reversing the
|
||||
// output array of results, we ensure that the augmentations are applied in
|
||||
// "chronological" order
|
||||
const payloadAfterHooks =
|
||||
hooksResult.length > 0 ? hooksResult.reverse().reduce((val, acc) => merge(acc, val)) : payload;
|
||||
const payloadAfterHooks = hooksResult.length > 0 ? hooksResult.reduce((val, acc) => merge(acc, val)) : payload;
|
||||
|
||||
if (this.accountability) {
|
||||
await authorizationService.checkAccess('update', this.collection, keys);
|
||||
|
||||
Reference in New Issue
Block a user