2023-06-19 11:53:24 +02:00

115 lines
2.9 KiB
JavaScript

'use strict';
const { castArray, map, every, pipe } = require('lodash/fp');
const { ForbiddenError, UnauthorizedError } = require('@strapi/utils').errors;
const { getService } = require('../utils');
const getAdvancedSettings = () => {
return strapi.store({ type: 'plugin', name: 'users-permissions' }).get({ key: 'advanced' });
};
const authenticate = async (ctx) => {
try {
const token = await getService('jwt').getToken(ctx);
if (token) {
const { id } = token;
// Invalid token
if (id === undefined) {
return { authenticated: false };
}
const user = await getService('user').fetchAuthenticatedUser(id);
// No user associated to the token
if (!user) {
return { error: 'Invalid credentials' };
}
const advancedSettings = await getAdvancedSettings();
// User not confirmed
if (advancedSettings.email_confirmation && !user.confirmed) {
return { error: 'Invalid credentials' };
}
// User blocked
if (user.blocked) {
return { error: 'Invalid credentials' };
}
// Fetch user's permissions
const permissions = await Promise.resolve(user.role.id)
.then(getService('permission').findRolePermissions)
.then(map(getService('permission').toContentAPIPermission));
// Generate an ability (content API engine) based on the given permissions
const ability = await strapi.contentAPI.permissions.engine.generateAbility(permissions);
ctx.state.user = user;
return {
authenticated: true,
credentials: user,
ability,
};
}
const publicPermissions = await getService('permission')
.findPublicPermissions()
.then(map(getService('permission').toContentAPIPermission));
if (publicPermissions.length === 0) {
return { authenticated: false };
}
const ability = await strapi.contentAPI.permissions.engine.generateAbility(publicPermissions);
return {
authenticated: true,
credentials: null,
ability,
};
} catch (err) {
return { authenticated: false };
}
};
const verify = async (auth, config) => {
const { credentials: user, ability } = auth;
if (!config.scope) {
if (!user) {
// A non authenticated user cannot access routes that do not have a scope
throw new UnauthorizedError();
} else {
// An authenticated user can access non scoped routes
return;
}
}
// If no ability have been generated, then consider auth is missing
if (!ability) {
throw new UnauthorizedError();
}
const isAllowed = pipe(
// Make sure we're dealing with an array
castArray,
// Transform the scope array into an action array
every((scope) => ability.can(scope))
)(config.scope);
if (!isAllowed) {
throw new ForbiddenError();
}
};
module.exports = {
name: 'users-permissions',
authenticate,
verify,
};