Files
directus/api/src/middleware/authenticate.ts
Rijk van Zanten b7d87e581a System permissions for app access (#4004)
* Pass relations through schema, instead of individual reads

* Fetch field transforms upfront

* Fix length check

* List if user has app access or not in accountability

* Load permissions up front, merge app access minimal permissions

* Show app access required permissions in permissions overview

* Show system minimal permissions in permissions detail

* Fix app access check in authenticate for jwt use

* Fix minimal permissions for presets

* Remove /permissions/me in favor of root use w/ permissions

* Fix logical nested OR in an AND

* Use root permissions endpoint with filter instead of /me

* Allow filter query on /permissions

* Add system minimal app access permissions into result of /permissions

* Remove stray console log

* Remove stray console.dir

* Set current role as role for minimal permissions

* Fix no-permissions state for user detail

* Add filter items function that allows altering existing result set
2021-02-11 12:50:56 -05:00

87 lines
2.6 KiB
TypeScript

import { RequestHandler } from 'express';
import jwt, { TokenExpiredError, JsonWebTokenError } from 'jsonwebtoken';
import isJWT from '../utils/is-jwt';
import database from '../database';
import asyncHandler from '../utils/async-handler';
import { InvalidCredentialsException } from '../exceptions';
import env from '../env';
/**
* Verify the passed JWT and assign the user ID and role to `req`
*/
const authenticate: RequestHandler = asyncHandler(async (req, res, next) => {
req.accountability = {
user: null,
role: null,
admin: false,
app: false,
ip: req.ip.startsWith('::ffff:') ? req.ip.substring(7) : req.ip,
userAgent: req.get('user-agent'),
};
if (!req.token) return next();
if (isJWT(req.token)) {
let payload: { id: string };
try {
payload = jwt.verify(req.token, env.SECRET as string) as { id: string };
} catch (err) {
if (err instanceof TokenExpiredError) {
throw new InvalidCredentialsException('Token expired.');
} else if (err instanceof JsonWebTokenError) {
throw new InvalidCredentialsException('Token invalid.');
} else {
throw err;
}
}
const user = await database
.select('role', 'directus_roles.admin_access', 'directus_roles.app_access')
.from('directus_users')
.leftJoin('directus_roles', 'directus_users.role', 'directus_roles.id')
.where({
'directus_users.id': payload.id,
status: 'active',
})
.first();
if (!user) {
throw new InvalidCredentialsException();
}
req.accountability.user = payload.id;
req.accountability.role = user.role;
req.accountability.admin = user.admin_access === true || user.admin_access == 1;
req.accountability.app = user.app_access === true || user.app_access == 1;
} else {
// Try finding the user with the provided token
const user = await database
.select('directus_users.id', 'directus_users.role', 'directus_roles.admin_access', 'directus_roles.app_access')
.from('directus_users')
.leftJoin('directus_roles', 'directus_users.role', 'directus_roles.id')
.where({
'directus_users.token': req.token,
status: 'active',
})
.first();
if (!user) {
throw new InvalidCredentialsException();
}
req.accountability.user = user.id;
req.accountability.role = user.role;
req.accountability.admin = user.admin_access === true || user.admin_access == 1;
req.accountability.app = user.app_access === true || user.app_access == 1;
}
if (req.accountability?.user) {
await database('directus_users').update({ last_access: new Date() }).where({ id: req.accountability.user });
}
return next();
});
export default authenticate;