feat: Admin roles (wip)
parent
52dd4b4f55
commit
74498e6d1c
|
@ -16,8 +16,8 @@
|
||||||
"test:unit": "jest --verbose"
|
"test:unit": "jest --verbose"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"redux-thunk": "^2.3.0",
|
"react-diff-viewer": "^3.1.1",
|
||||||
"react-diff-viewer": "^3.1.1"
|
"redux-thunk": "^2.3.0"
|
||||||
},
|
},
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Boaz Poolman",
|
"name": "Boaz Poolman",
|
||||||
|
@ -39,6 +39,7 @@
|
||||||
"strapi-server.js"
|
"strapi-server.js"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@strapi/admin": "^4.0.0-beta.2",
|
||||||
"@strapi/helper-plugin": "4.0.0-beta.2",
|
"@strapi/helper-plugin": "4.0.0-beta.2",
|
||||||
"@strapi/icons": "^0.0.1-alpha.42",
|
"@strapi/icons": "^0.0.1-alpha.42",
|
||||||
"@strapi/parts": "^0.0.1-alpha.42",
|
"@strapi/parts": "^0.0.1-alpha.42",
|
||||||
|
|
|
@ -2,12 +2,13 @@
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
default: {
|
default: {
|
||||||
destination: "extensions/config-sync/files/",
|
destination: "src/extensions/config-sync/files/",
|
||||||
minify: false,
|
minify: false,
|
||||||
importOnBootstrap: false,
|
importOnBootstrap: false,
|
||||||
include: [
|
include: [
|
||||||
"core-store",
|
"core-store",
|
||||||
"role-permissions",
|
"user-role",
|
||||||
|
"admin-role",
|
||||||
"i18n-locale",
|
"i18n-locale",
|
||||||
],
|
],
|
||||||
exclude: [
|
exclude: [
|
||||||
|
|
|
@ -94,8 +94,8 @@ module.exports = () => ({
|
||||||
const fileConfigs = {};
|
const fileConfigs = {};
|
||||||
|
|
||||||
await Promise.all(configFiles.map(async (file) => {
|
await Promise.all(configFiles.map(async (file) => {
|
||||||
const type = file.split('.')[0].replace('##', '::'); // Grab the first part of the filename.
|
const type = file.split('.')[0]; // Grab the first part of the filename.
|
||||||
const name = file.split(/\.(.+)/)[1].split('.').slice(0, -1).join('.').replace('##', '::'); // Grab the rest of the filename minus the file extension.
|
const name = file.split(/\.(.+)/)[1].split('.').slice(0, -1).join('.'); // Grab the rest of the filename minus the file extension.
|
||||||
|
|
||||||
if (
|
if (
|
||||||
configType && configType !== type
|
configType && configType !== type
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
const { logMessage } = require('../utils');
|
const { logMessage, sanitizeConfig } = require('../utils');
|
||||||
const difference = require('../utils/getObjectDiff');
|
const difference = require('../utils/getObjectDiff');
|
||||||
|
|
||||||
const ConfigType = class ConfigType {
|
const ConfigType = class ConfigType {
|
||||||
constructor(queryString, configPrefix, uid, fieldsToStringify) {
|
constructor(queryString, configPrefix, uid, jsonFields) {
|
||||||
if (!queryString) {
|
if (!queryString) {
|
||||||
strapi.log.error(logMessage('Query string is missing for ConfigType'));
|
strapi.log.error(logMessage('Query string is missing for ConfigType'));
|
||||||
}
|
}
|
||||||
this.queryString = queryString;
|
this.queryString = queryString;
|
||||||
this.configPrefix = configPrefix;
|
this.configPrefix = configPrefix;
|
||||||
this.uid = uid;
|
this.uid = uid;
|
||||||
this.fieldsToStringify = fieldsToStringify || [];
|
this.jsonFields = jsonFields || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,7 +48,7 @@ const ConfigType = class ConfigType {
|
||||||
) {
|
) {
|
||||||
await strapi.plugin('config-sync').service('main').deleteConfigFile(configName);
|
await strapi.plugin('config-sync').service('main').deleteConfigFile(configName);
|
||||||
} else {
|
} else {
|
||||||
await strapi.plugin('config-sync').service('main').writeConfigFile(this.configPrefix, currentConfig[this.uid].replace('::', '##'), currentConfig);
|
await strapi.plugin('config-sync').service('main').writeConfigFile(this.configPrefix, currentConfig[this.uid], currentConfig);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ const ConfigType = class ConfigType {
|
||||||
const queryAPI = strapi.query(this.queryString);
|
const queryAPI = strapi.query(this.queryString);
|
||||||
|
|
||||||
const configExists = await queryAPI
|
const configExists = await queryAPI
|
||||||
.findOne({ [this.uid]: configName });
|
.findOne({ where: { [this.uid]: configName } });
|
||||||
|
|
||||||
if (configExists && configContent === null) {
|
if (configExists && configContent === null) {
|
||||||
await queryAPI.delete({ where: { [this.uid]: configName } });
|
await queryAPI.delete({ where: { [this.uid]: configName } });
|
||||||
|
@ -78,11 +78,11 @@ const ConfigType = class ConfigType {
|
||||||
|
|
||||||
if (!configExists) {
|
if (!configExists) {
|
||||||
const query = { ...configContent };
|
const query = { ...configContent };
|
||||||
this.fieldsToStringify.map((field) => query[field] = JSON.stringify(configContent[field]));
|
this.jsonFields.map((field) => query[field] = JSON.stringify(configContent[field]));
|
||||||
await queryAPI.create(query);
|
await queryAPI.create({ data: query });
|
||||||
} else {
|
} else {
|
||||||
const query = { ...configContent };
|
const query = { ...configContent };
|
||||||
this.fieldsToStringify.map((field) => query[field] = JSON.stringify(configContent[field]));
|
this.jsonFields.map((field) => query[field] = JSON.stringify(configContent[field]));
|
||||||
await queryAPI.update({ where: { [this.uid]: configName }, data: { ...query } });
|
await queryAPI.update({ where: { [this.uid]: configName }, data: { ...query } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,11 +101,10 @@ const ConfigType = class ConfigType {
|
||||||
const shouldExclude = strapi.config.get('plugin.config-sync.exclude').includes(`${this.configPrefix}.${config[this.uid]}`);
|
const shouldExclude = strapi.config.get('plugin.config-sync.exclude').includes(`${this.configPrefix}.${config[this.uid]}`);
|
||||||
if (shouldExclude) return;
|
if (shouldExclude) return;
|
||||||
|
|
||||||
// Do not export the _id field, as it is immutable
|
config = sanitizeConfig(config);
|
||||||
delete config._id;
|
|
||||||
|
|
||||||
const formattedObject = { ...config };
|
const formattedObject = { ...config };
|
||||||
this.fieldsToStringify.map((field) => formattedObject[field] = JSON.parse(config[field]));
|
this.jsonFields.map((field) => formattedObject[field] = JSON.parse(config[field]));
|
||||||
|
|
||||||
configs[`${this.configPrefix}.${config[this.uid]}`] = formattedObject;
|
configs[`${this.configPrefix}.${config[this.uid]}`] = formattedObject;
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
const { assignPermissions } = require('@strapi/admin/server/services/role');
|
||||||
|
|
||||||
|
const { sanitizeConfig } = require('../utils');
|
||||||
|
const ConfigType = require("../services/type");
|
||||||
|
|
||||||
|
const AdminRolePermissionsConfigType = class AdminRolePermissionsConfigType extends ConfigType {
|
||||||
|
/**
|
||||||
|
* Import a single role-permissions config file into the db.
|
||||||
|
*
|
||||||
|
* @param {string} configName - The name of the config file.
|
||||||
|
* @param {string} configContent - The JSON content of the config file.
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
importSingle = async (configName, configContent) => {
|
||||||
|
// Check if the config should be excluded.
|
||||||
|
const shouldExclude = strapi.config.get('plugin.config-sync.exclude').includes(`${this.configPrefix}.${configName}`);
|
||||||
|
if (shouldExclude) return;
|
||||||
|
|
||||||
|
const queryAPI = strapi.query(this.queryString);
|
||||||
|
|
||||||
|
const existingConfig = await queryAPI
|
||||||
|
.findOne({ where: { [this.uid]: configName } });
|
||||||
|
|
||||||
|
if (existingConfig && configContent === null) {
|
||||||
|
await queryAPI.delete({ where: { [this.uid]: configName } });
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!existingConfig) {
|
||||||
|
const { permissions } = configContent;
|
||||||
|
delete configContent.permissions;
|
||||||
|
const query = { ...configContent };
|
||||||
|
this.jsonFields.map((field) => query[field] = JSON.stringify(configContent[field]));
|
||||||
|
const newConfig = await queryAPI.create({ data: query });
|
||||||
|
await assignPermissions(newConfig.id, permissions);
|
||||||
|
} else {
|
||||||
|
await assignPermissions(existingConfig.id, configContent.permissions);
|
||||||
|
delete configContent.permissions;
|
||||||
|
const query = { ...configContent };
|
||||||
|
this.jsonFields.map((field) => query[field] = JSON.stringify(configContent[field]));
|
||||||
|
await queryAPI.update({ where: { [this.uid]: configName }, data: query });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all role-permissions config from the db.
|
||||||
|
*
|
||||||
|
* @returns {object} Object with key value pairs of configs.
|
||||||
|
*/
|
||||||
|
getAllFromDatabase = async () => {
|
||||||
|
const AllConfig = await strapi.query(this.queryString).findMany({ limit: 0 });
|
||||||
|
const configs = {};
|
||||||
|
|
||||||
|
await Promise.all(Object.values(AllConfig).map(async (config) => {
|
||||||
|
// Check if the config should be excluded.
|
||||||
|
const shouldExclude = strapi.config.get('plugin.config-sync.exclude').includes(`${this.configPrefix}.${config[this.uid]}`);
|
||||||
|
if (shouldExclude) return;
|
||||||
|
|
||||||
|
config = sanitizeConfig(config);
|
||||||
|
|
||||||
|
const existingPermissions = await strapi.admin.services.permission.findMany({
|
||||||
|
where: { role: { code: config.code } },
|
||||||
|
});
|
||||||
|
|
||||||
|
existingPermissions.map((permission) => sanitizeConfig(permission));
|
||||||
|
|
||||||
|
const formattedObject = { ...config, permissions: existingPermissions };
|
||||||
|
this.jsonFields.map((field) => formattedObject[field] = JSON.parse(config[field]));
|
||||||
|
|
||||||
|
configs[`${this.configPrefix}.${config[this.uid]}`] = formattedObject;
|
||||||
|
}));
|
||||||
|
|
||||||
|
return configs;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = AdminRolePermissionsConfigType;
|
|
@ -1,10 +1,12 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const ConfigType = require("../services/type");
|
const ConfigType = require("../services/type");
|
||||||
const RolePermissionsConfigType = require("./role-permissions");
|
const UserRoleConfigType = require("./user-role");
|
||||||
|
const AdminRoleConfigType = require("./admin-role");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
'i18n-locale': new ConfigType('plugin::i18n.locale', 'i18n-locale', 'code'),
|
'i18n-locale': new ConfigType('plugin::i18n.locale', 'i18n-locale', 'code'),
|
||||||
'core-store': new ConfigType('strapi::core-store', 'core-store', 'key', ['value']),
|
'core-store': new ConfigType('strapi::core-store', 'core-store', 'key', ['value']),
|
||||||
'role-permissions': new RolePermissionsConfigType('plugin::users-permissions.role', 'role-permissions', 'type'),
|
'user-role': new UserRoleConfigType('plugin::users-permissions.role', 'user-role', 'type'),
|
||||||
|
'admin-role': new AdminRoleConfigType('admin::role', 'admin-role', 'code'),
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
const { sanitizeConfig } = require('../utils');
|
||||||
const ConfigType = require("../services/type");
|
const ConfigType = require("../services/type");
|
||||||
|
|
||||||
const RolePermissionsConfigType = class RolePermissionsConfigType extends ConfigType {
|
const UserRolePermissionsConfigType = class UserRolePermissionsConfigType extends ConfigType {
|
||||||
/**
|
/**
|
||||||
* Import a single role-permissions config file into the db.
|
* Import a single role-permissions config file into the db.
|
||||||
*
|
*
|
||||||
|
@ -10,7 +11,7 @@ const RolePermissionsConfigType = class RolePermissionsConfigType extends Config
|
||||||
*/
|
*/
|
||||||
importSingle = async (configName, configContent) => {
|
importSingle = async (configName, configContent) => {
|
||||||
// Check if the config should be excluded.
|
// Check if the config should be excluded.
|
||||||
const shouldExclude = strapi.plugins['config-sync'].config.exclude.includes(`${this.configPrefix}.${configName}`);
|
const shouldExclude = strapi.config.get('plugin.config-sync.exclude').includes(`${this.configPrefix}.${configName}`);
|
||||||
if (shouldExclude) return;
|
if (shouldExclude) return;
|
||||||
|
|
||||||
const roleService = strapi.plugin('users-permissions').service('role');
|
const roleService = strapi.plugin('users-permissions').service('role');
|
||||||
|
@ -63,8 +64,7 @@ const RolePermissionsConfigType = class RolePermissionsConfigType extends Config
|
||||||
const shouldExclude = strapi.config.get('plugin.config-sync.exclude').includes(`${this.configPrefix}.${config.type}`);
|
const shouldExclude = strapi.config.get('plugin.config-sync.exclude').includes(`${this.configPrefix}.${config.type}`);
|
||||||
if (shouldExclude) return;
|
if (shouldExclude) return;
|
||||||
|
|
||||||
// Do not export the _id field, as it is immutable
|
config = sanitizeConfig(config);
|
||||||
delete config._id;
|
|
||||||
|
|
||||||
configs[`${this.configPrefix}.${config.type}`] = config;
|
configs[`${this.configPrefix}.${config.type}`] = config;
|
||||||
});
|
});
|
||||||
|
@ -73,4 +73,4 @@ const RolePermissionsConfigType = class RolePermissionsConfigType extends Config
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = RolePermissionsConfigType;
|
module.exports = UserRolePermissionsConfigType;
|
|
@ -10,8 +10,18 @@ const getService = (name) => {
|
||||||
|
|
||||||
const logMessage = (msg = '') => `[strapi-plugin-config-sync]: ${msg}`;
|
const logMessage = (msg = '') => `[strapi-plugin-config-sync]: ${msg}`;
|
||||||
|
|
||||||
|
const sanitizeConfig = (config) => {
|
||||||
|
delete config._id;
|
||||||
|
delete config.id;
|
||||||
|
delete config.updatedAt;
|
||||||
|
delete config.createdAt;
|
||||||
|
|
||||||
|
return config;
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getService,
|
getService,
|
||||||
getCoreStore,
|
getCoreStore,
|
||||||
logMessage,
|
logMessage,
|
||||||
|
sanitizeConfig,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue