move most of the code to strapi/ee

This commit is contained in:
Ben Irvin 2023-05-22 15:53:03 +02:00
parent 894a2766bf
commit 8b10c20465
4 changed files with 41 additions and 29 deletions

View File

@ -5,14 +5,25 @@ const { features } = require('@strapi/strapi/lib/utils/ee');
const createLocalStrategy = require('../../../server/services/passport/local-strategy'); const createLocalStrategy = require('../../../server/services/passport/local-strategy');
const sso = require('./passport/sso'); const sso = require('./passport/sso');
const { isSsoLocked } = require('../utils/sso-lock');
const localStrategyMiddleware = async ([error, user, message], done) => {
if (await isSsoLocked(user)) {
return done(error, null, {
message: 'Login not allowed, please contact your administrator',
});
}
return done(error, user, message);
};
const getPassportStrategies = () => { const getPassportStrategies = () => {
const localStrategy = createLocalStrategy(strapi);
if (!features.isEnabled('sso')) { if (!features.isEnabled('sso')) {
return [localStrategy]; return [createLocalStrategy(strapi)];
} }
const localStrategy = createLocalStrategy(strapi, localStrategyMiddleware);
if (!strapi.isLoaded) { if (!strapi.isLoaded) {
sso.syncProviderRegistryWithConfig(); sso.syncProviderRegistryWithConfig();
} }

View File

@ -1,36 +1,41 @@
'use strict'; 'use strict';
const { features } = require('@strapi/strapi/ee');
const { isEmpty } = require('lodash/fp');
const isSsoLocked = async (user) => { const isSsoLocked = async (user) => {
if (!strapi.EE || !user) { if (!features.isEnabled('sso') || !user) {
// TODO: we should be calling strapi.features.isEnabled("sso") but that's EE code. Should we load it dynamically when EE is enabled? Or add EE code to override this strategy? // TODO: we should be calling strapi.features.isEnabled("sso") but that's EE code. Should we load it dynamically when EE is enabled? Or add EE code to override this strategy?
return false; return false;
} }
// TODO: if user object has roles === undefined, we need to query for it. [] should be fine, it means we got the roles object but they don't have any // check if any roles are locked
const adminStore = await strapi.store({ type: 'core', name: 'admin' }); const adminStore = await strapi.store({ type: 'core', name: 'admin' });
const { providers } = await adminStore.get({ key: 'auth' }); const { providers } = await adminStore.get({ key: 'auth' });
const lockedRoles = providers.authenticationDisabled || []; const lockedRoles = providers.authenticationDisabled || [];
if (isEmpty(lockedRoles)) {
return false;
}
// Ensure we have user.roles and get them if we don't have them
let roles = user.roles;
if (!user.roles) {
const u = await strapi.query('admin::user').findOne({
where: { id: user.id },
populate: ['roles'],
});
roles = u.roles;
}
// Check for roles that have blocked // Check for roles that have blocked
const isLocked = lockedRoles.some((lockedId) => const isLocked = lockedRoles.some((lockedId) =>
// lockedRoles will be a string to avoid issues with frontend and bigints // lockedRoles will be a string to avoid issues with frontend and bigints
user.roles?.some((role) => lockedId === role.id.toString()) roles?.some((role) => lockedId === role.id.toString())
); );
return isLocked; return isLocked;
}; };
const userPopulateForSso = () => {
if (!strapi.EE) {
// TODO: we should be calling strapi.features.isEnabled("sso") but that's EE code. Should we load it dynamically when EE is enabled? Or add EE code to override this strategy?
return undefined;
}
return ['roles'];
};
module.exports = { module.exports = {
isSsoLocked, isSsoLocked,
userPopulateForSso,
}; };

View File

@ -5,7 +5,7 @@ const _ = require('lodash');
const { getAbsoluteAdminUrl } = require('@strapi/utils'); const { getAbsoluteAdminUrl } = require('@strapi/utils');
const { ApplicationError } = require('@strapi/utils').errors; const { ApplicationError } = require('@strapi/utils').errors;
const { getService } = require('../utils'); const { getService } = require('../utils');
const { isSsoLocked, userPopulateForSso } = require('./passport/utils/sso-lock'); const { isSsoLocked } = require('../../ee/server/utils/sso-lock');
/** /**
* hashes a password * hashes a password
@ -31,7 +31,6 @@ const validatePassword = (password, hash) => bcrypt.compare(password, hash);
const checkCredentials = async ({ email, password }) => { const checkCredentials = async ({ email, password }) => {
const user = await strapi.query('admin::user').findOne({ const user = await strapi.query('admin::user').findOne({
where: { email }, where: { email },
populate: userPopulateForSso(),
}); });
if (!user || !user.password) { if (!user || !user.password) {
@ -59,11 +58,10 @@ const checkCredentials = async ({ email, password }) => {
* @param {string} param.email user email for which to reset the password * @param {string} param.email user email for which to reset the password
*/ */
const forgotPassword = async ({ email } = {}) => { const forgotPassword = async ({ email } = {}) => {
const user = await strapi const user = await strapi.query('admin::user').findOne({ where: { email, isActive: true } });
.query('admin::user')
.findOne({ where: { email, isActive: true }, populate: userPopulateForSso() });
if (!user || (await isSsoLocked(user))) { if (!user || (await isSsoLocked(user))) {
// TODO: this needs to be removed and overidden in /ee/
return; return;
} }
@ -104,9 +102,10 @@ const forgotPassword = async ({ email } = {}) => {
const resetPassword = async ({ resetPasswordToken, password } = {}) => { const resetPassword = async ({ resetPasswordToken, password } = {}) => {
const matchingUser = await strapi const matchingUser = await strapi
.query('admin::user') .query('admin::user')
.findOne({ where: { resetPasswordToken, isActive: true }, populate: userPopulateForSso() }); .findOne({ where: { resetPasswordToken, isActive: true } });
if (!matchingUser || isSsoLocked(matchingUser)) { if (!matchingUser || isSsoLocked(matchingUser)) {
// TODO: this needs to be removed and overidden in /ee/
throw new ApplicationError(); throw new ApplicationError();
} }

View File

@ -2,9 +2,8 @@
const { toLower } = require('lodash/fp'); const { toLower } = require('lodash/fp');
const { Strategy: LocalStrategy } = require('passport-local'); const { Strategy: LocalStrategy } = require('passport-local');
const { isSsoLocked } = require('./utils/sso-lock');
const createLocalStrategy = (strapi) => { const createLocalStrategy = (strapi, middleware) => {
return new LocalStrategy( return new LocalStrategy(
{ {
usernameField: 'email', usernameField: 'email',
@ -18,10 +17,8 @@ const createLocalStrategy = (strapi) => {
password, password,
}) })
.then(async ([error, user, message]) => { .then(async ([error, user, message]) => {
if (await isSsoLocked(user)) { if (middleware) {
return done(error, null, { return middleware([error, user, message], done);
message: 'Login not allowed, please contact your administrator',
});
} }
return done(error, user, message); return done(error, user, message);