mirror of
https://github.com/strapi/strapi.git
synced 2025-08-06 15:53:11 +00:00

* Add a domain layer for the permission, rework the engine handling of the permissions Signed-off-by: Convly <jean-sebastien.herbaux@epitech.eu> * Add permissions-fields-to-properties migration for the admin Signed-off-by: Convly <jean-sebastien.herbaux@epitech.eu> * Removes useless console.log Signed-off-by: Convly <jean-sebastien.herbaux@epitech.eu> * Remove debug logLevel from provider-login.test.e2e.js Signed-off-by: Convly <jean-sebastien.herbaux@epitech.eu> * Adds the new layout for the GET permissions, allow to subscribe to actionRegistered events, adds i18n handlers Signed-off-by: Convly <jean-sebastien.herbaux@epitech.eu> * Fix typo Signed-off-by: Convly <jean-sebastien.herbaux@epitech.eu> * Update permissions validators Signed-off-by: Convly <jean-sebastien.herbaux@epitech.eu> * Update unit tests Signed-off-by: Convly <jean-sebastien.herbaux@epitech.eu> * Update integrations test + fix some validation issues Signed-off-by: Convly <jean-sebastien.herbaux@epitech.eu> * Change plugins & settings section format for the permissions layout * only return locales property to localized subjects for the permission's layout * Do not send the locales property to the permission's layout when there is no locales created * Add the 'locales' property to publish & delete routes * Fix unwanted mutation of the sections builder states on multiple builds * Fix units tests with (new engine) * Fix admin-role e2e test - Add locales property to the update payload * fix e2e testsé * Update e2e snapshots * Fix unit test for i18n bootstrap * Add mocks for i18n/bootstrap test * Fix has-locale condition & updatePermission validator * Avoid mutation in migration, always authorize super admin for has-locales condition * Rework rbac domain objects, add a hook module and a provider factory * Remove old providers * Update the admin services & tests for the new rbac domain & providers * Fix tests, bootstrap functions & services following rbac domain rework * Update migration runner * PR comments Signed-off-by: Convly <jean-sebastien.herbaux@epitech.eu> * Remove useless console.log * Fix sanitizeCondition bug * Section builder rework * Add test for the section-builder section & add jsdoc for the permission domain * pr comments (without the migrations) * fix fields-to-properties migration * Add jsdoc for the sections-builder * Moves createBoundAbstractDomain from permission domain to the engine service * Remove debug logLevel for admin role test (e2e) * Fix core-store * Fix hooks & move business logic from i18n bootstrap to dedicated services * add route get-non-localized-fields * use write and read permission * refacto * add input validator * add route doc * handle ST Co-authored-by: Pierre Noël <petersg83@gmail.com> Co-authored-by: Alexandre BODIN <alexandrebodin@users.noreply.github.com>
215 lines
6.2 KiB
JavaScript
215 lines
6.2 KiB
JavaScript
'use strict';
|
|
|
|
const { yup } = require('strapi-utils');
|
|
const _ = require('lodash');
|
|
const { isEmpty, has, isNil, isArray } = require('lodash/fp');
|
|
const { getService } = require('../utils');
|
|
const actionDomain = require('../domain/action');
|
|
const {
|
|
checkFieldsAreCorrectlyNested,
|
|
checkFieldsDontHaveDuplicates,
|
|
} = require('./common-functions');
|
|
|
|
const getActionFromProvider = actionId => {
|
|
return getService('permission').actionProvider.get(actionId);
|
|
};
|
|
|
|
const email = yup
|
|
.string()
|
|
.email()
|
|
.lowercase();
|
|
|
|
const firstname = yup.string().min(1);
|
|
|
|
const lastname = yup.string().min(1);
|
|
|
|
const username = yup.string().min(1);
|
|
|
|
const password = yup
|
|
.string()
|
|
.min(8)
|
|
.matches(/[a-z]/, '${path} must contain at least one lowercase character')
|
|
.matches(/[A-Z]/, '${path} must contain at least one uppercase character')
|
|
.matches(/\d/, '${path} must contain at least one number');
|
|
|
|
const roles = yup.array(yup.strapiID()).min(1);
|
|
|
|
const isAPluginName = yup
|
|
.string()
|
|
.test('is-a-plugin-name', 'is not a plugin name', function(value) {
|
|
return [undefined, 'admin', ...Object.keys(strapi.plugins)].includes(value)
|
|
? true
|
|
: this.createError({ path: this.path, message: `${this.path} is not an existing plugin` });
|
|
});
|
|
|
|
const arrayOfConditionNames = yup
|
|
.array()
|
|
.of(yup.string())
|
|
.test('is-an-array-of-conditions', 'is not a plugin name', function(value) {
|
|
const ids = strapi.admin.services.permission.conditionProvider.keys();
|
|
return _.isUndefined(value) || _.difference(value, ids).length === 0
|
|
? true
|
|
: this.createError({ path: this.path, message: `contains conditions that don't exist` });
|
|
});
|
|
|
|
const permissionsAreEquals = (a, b) =>
|
|
a.action === b.action && (a.subject === b.subject || (_.isNil(a.subject) && _.isNil(b.subject)));
|
|
|
|
const checkNoDuplicatedPermissions = permissions =>
|
|
!Array.isArray(permissions) ||
|
|
permissions.every((permA, i) =>
|
|
permissions.slice(i + 1).every(permB => !permissionsAreEquals(permA, permB))
|
|
);
|
|
|
|
const checkNilFields = action =>
|
|
function(fields) {
|
|
// If the parent has no action field, then we ignore this test
|
|
if (isNil(action)) {
|
|
return true;
|
|
}
|
|
|
|
return actionDomain.appliesToProperty('fields', action) || isNil(fields);
|
|
};
|
|
|
|
const fieldsPropertyValidation = action =>
|
|
yup
|
|
.array()
|
|
.of(yup.string())
|
|
.nullable()
|
|
.test(
|
|
'field-nested',
|
|
'Fields format are incorrect (bad nesting).',
|
|
checkFieldsAreCorrectlyNested
|
|
)
|
|
.test(
|
|
'field-nested',
|
|
'Fields format are incorrect (duplicates).',
|
|
checkFieldsDontHaveDuplicates
|
|
)
|
|
.test(
|
|
'fields-restriction',
|
|
'The permission at ${path} must have fields set to null or undefined',
|
|
checkNilFields(action)
|
|
);
|
|
|
|
const updatePermissions = yup
|
|
.object()
|
|
.shape({
|
|
permissions: yup
|
|
.array()
|
|
.requiredAllowEmpty()
|
|
.of(
|
|
yup
|
|
.object()
|
|
.shape({
|
|
action: yup
|
|
.string()
|
|
.required()
|
|
.test('action-validity', 'action is not an existing permission action', function(
|
|
actionId
|
|
) {
|
|
// If the action field is Nil, ignore the test and let the required check handle the error
|
|
if (isNil(actionId)) {
|
|
return true;
|
|
}
|
|
|
|
return !!getActionFromProvider(actionId);
|
|
}),
|
|
subject: yup
|
|
.string()
|
|
.nullable()
|
|
.test('subject-validity', 'Invalid subject submitted', function(subject) {
|
|
const action = getActionFromProvider(this.options.parent.action);
|
|
|
|
if (!action) {
|
|
return true;
|
|
}
|
|
|
|
if (isNil(action.subjects)) {
|
|
return isNil(subject);
|
|
}
|
|
|
|
if (isArray(action.subjects)) {
|
|
return action.subjects.includes(subject);
|
|
}
|
|
|
|
return false;
|
|
}),
|
|
properties: yup
|
|
.object()
|
|
.test('properties-structure', 'Invalid property set at ${path}', function(
|
|
properties
|
|
) {
|
|
const action = getActionFromProvider(this.options.parent.action);
|
|
const hasNoProperties = isEmpty(properties) || isNil(properties);
|
|
|
|
if (!has('options.applyToProperties', action)) {
|
|
return hasNoProperties;
|
|
}
|
|
|
|
if (hasNoProperties) {
|
|
return true;
|
|
}
|
|
|
|
const { applyToProperties } = action.options;
|
|
|
|
if (!isArray(applyToProperties)) {
|
|
return false;
|
|
}
|
|
|
|
return Object.keys(properties).every(property =>
|
|
applyToProperties.includes(property)
|
|
);
|
|
})
|
|
.test('fields-property', 'Invalid fields property at ${path}', async function(
|
|
properties = {}
|
|
) {
|
|
const action = getActionFromProvider(this.options.parent.action);
|
|
|
|
if (!action || !properties) {
|
|
return true;
|
|
}
|
|
|
|
if (!actionDomain.appliesToProperty('fields', action)) {
|
|
return true;
|
|
}
|
|
|
|
try {
|
|
await fieldsPropertyValidation(action).validate(properties.fields, {
|
|
strict: true,
|
|
abortEarly: false,
|
|
});
|
|
return true;
|
|
} catch (e) {
|
|
// Propagate fieldsPropertyValidation error with updated path
|
|
throw this.createError({
|
|
message: e.message,
|
|
path: `${this.path}.fields`,
|
|
});
|
|
}
|
|
}),
|
|
conditions: yup.array().of(yup.string()),
|
|
})
|
|
.noUnknown()
|
|
)
|
|
.test(
|
|
'duplicated-permissions',
|
|
'Some permissions are duplicated (same action and subject)',
|
|
checkNoDuplicatedPermissions
|
|
),
|
|
})
|
|
.required()
|
|
.noUnknown();
|
|
|
|
module.exports = {
|
|
email,
|
|
firstname,
|
|
lastname,
|
|
username,
|
|
password,
|
|
roles,
|
|
isAPluginName,
|
|
arrayOfConditionNames,
|
|
updatePermissions,
|
|
};
|