feat: integrate relation syncing in default config type (permission relations)
parent
db9745ef81
commit
eff6cb50eb
|
@ -1,5 +1,7 @@
|
|||
const { logMessage, sanitizeConfig } = require('../utils');
|
||||
const { logMessage, sanitizeConfig, dynamicSort } = require('../utils');
|
||||
const difference = require('../utils/getObjectDiff');
|
||||
const arrayDifference = require('../utils/getArrayDiff');
|
||||
|
||||
|
||||
const ConfigType = class ConfigType {
|
||||
constructor(queryString, configPrefix, uid, jsonFields, relations) {
|
||||
|
@ -10,7 +12,7 @@ const ConfigType = class ConfigType {
|
|||
this.configPrefix = configPrefix;
|
||||
this.uid = uid;
|
||||
this.jsonFields = jsonFields || [];
|
||||
this.relations = relations || {};
|
||||
this.relations = relations || [];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -55,60 +57,136 @@ const ConfigType = class ConfigType {
|
|||
}
|
||||
|
||||
/**
|
||||
* Import a single core-store config file into the db.
|
||||
* 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) => {
|
||||
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 configExists = await queryAPI
|
||||
.findOne({ where: { [this.uid]: configName } });
|
||||
let existingConfig = await queryAPI
|
||||
.findOne({
|
||||
where: { [this.uid]: configName },
|
||||
populate: this.relations.map(({ relationName }) => relationName),
|
||||
});
|
||||
|
||||
if (configExists && configContent === null) {
|
||||
await queryAPI.delete({ where: { [this.uid]: configName } });
|
||||
if (existingConfig && configContent === null) {
|
||||
const entity = await queryAPI.findOne({
|
||||
where: { [this.uid]: configName },
|
||||
populate: this.relations.map(({ relationName }) => relationName),
|
||||
});
|
||||
|
||||
await Promise.all(this.relations.map(async ({ queryString, parentName }) => {
|
||||
const relations = await strapi.query(queryString).findMany({
|
||||
where: {
|
||||
[parentName]: entity.id,
|
||||
},
|
||||
});
|
||||
|
||||
await Promise.all(relations.map(async (relation) => {
|
||||
await strapi.query(queryString).delete({
|
||||
where: { id: relation.id },
|
||||
});
|
||||
}));
|
||||
}));
|
||||
|
||||
await queryAPI.delete({
|
||||
where: { id: entity.id },
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!configExists) {
|
||||
if (!existingConfig) {
|
||||
// Format JSON fields.
|
||||
const query = { ...configContent };
|
||||
this.jsonFields.map((field) => query[field] = JSON.stringify(configContent[field]));
|
||||
await queryAPI.create({ data: query });
|
||||
|
||||
// Create entity.
|
||||
this.relations.map(({ relationName }) => delete query[relationName]);
|
||||
const newEntity = await queryAPI.create({ data: query });
|
||||
|
||||
// Create relation entities.
|
||||
this.relations.map(async ({ queryString, relationName, parentName }) => {
|
||||
const relationQueryApi = strapi.query(queryString);
|
||||
|
||||
configContent[relationName].map(async (relationEntity) => {
|
||||
const relationQuery = { ...relationEntity, [parentName]: newEntity };
|
||||
await relationQueryApi.create({ data: relationQuery });
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Format JSON fields.
|
||||
configContent = sanitizeConfig(configContent);
|
||||
const query = { ...configContent };
|
||||
this.jsonFields.map((field) => query[field] = JSON.stringify(configContent[field]));
|
||||
await queryAPI.update({ where: { [this.uid]: configName }, data: { ...query } });
|
||||
|
||||
// Update entity.
|
||||
this.relations.map(({ relationName }) => delete query[relationName]);
|
||||
const entity = await queryAPI.update({ where: { [this.uid]: configName }, data: query });
|
||||
|
||||
// Delete/create relations.
|
||||
this.relations.map(async ({ queryString, relationName, parentName, relationSortField }) => {
|
||||
const relationQueryApi = strapi.query(queryString);
|
||||
existingConfig = sanitizeConfig(existingConfig, relationName, relationSortField);
|
||||
configContent = sanitizeConfig(configContent, relationName, relationSortField);
|
||||
|
||||
const configToAdd = arrayDifference(configContent[relationName], existingConfig[relationName], relationSortField);
|
||||
const configToDelete = arrayDifference(existingConfig[relationName], configContent[relationName], relationSortField);
|
||||
|
||||
configToDelete.map(async (config) => {
|
||||
await relationQueryApi.delete({
|
||||
where: {
|
||||
[relationSortField]: config[relationSortField],
|
||||
[parentName]: entity.id,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
configToAdd.map(async (config) => {
|
||||
await relationQueryApi.create({
|
||||
data: { ...config, [parentName]: entity.id },
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all core-store config from the db.
|
||||
* 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: -1 });
|
||||
const AllConfig = await strapi.query(this.queryString).findMany({ limit: 0 });
|
||||
const configs = {};
|
||||
|
||||
Object.values(AllConfig).map((config) => {
|
||||
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 formattedConfig = { ...sanitizeConfig(config) };
|
||||
await Promise.all(this.relations.map(async ({ queryString, relationName, relationSortField, parentName }) => {
|
||||
const relations = await strapi.query(queryString).findMany({
|
||||
where: { [parentName]: { [this.uid]: config[this.uid] } },
|
||||
});
|
||||
|
||||
const formattedObject = { ...config };
|
||||
this.jsonFields.map((field) => formattedObject[field] = JSON.parse(config[field]));
|
||||
relations.map((relation) => sanitizeConfig(relation));
|
||||
relations.sort(dynamicSort(relationSortField));
|
||||
formattedConfig[relationName] = relations;
|
||||
}));
|
||||
|
||||
this.jsonFields.map((field) => formattedConfig[field] = JSON.parse(config[field]));
|
||||
configs[`${this.configPrefix}.${config[this.uid]}`] = formattedConfig;
|
||||
}));
|
||||
|
||||
configs[`${this.configPrefix}.${config[this.uid]}`] = formattedObject;
|
||||
});
|
||||
|
||||
return configs;
|
||||
}
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
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 },
|
||||
populate: this.relations.map(({ relationName }) => relationName),
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!existingConfig) {
|
||||
// Format JSON fields.
|
||||
const query = { ...configContent };
|
||||
this.jsonFields.map((field) => query[field] = JSON.stringify(configContent[field]));
|
||||
|
||||
this.relations.map(({ queryString }) => {
|
||||
const queryAPI = strapi.query(queryString);
|
||||
|
||||
// Compare relations
|
||||
// Make changes to the db
|
||||
});
|
||||
|
||||
await queryAPI.create({ data: query });
|
||||
} else {
|
||||
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,14 +1,23 @@
|
|||
'use strict';
|
||||
|
||||
const ConfigType = require("../services/type");
|
||||
const UserRoleConfigType = require("./user-role");
|
||||
const AdminRoleConfigType = require("./admin-role");
|
||||
|
||||
module.exports = {
|
||||
'i18n-locale': new ConfigType('plugin::i18n.locale', 'i18n-locale', 'code'),
|
||||
'core-store': new ConfigType('strapi::core-store', 'core-store', 'key', ['value']),
|
||||
'user-role': new UserRoleConfigType('plugin::users-permissions.role', 'user-role', 'type'),
|
||||
'admin-role': new AdminRoleConfigType(
|
||||
'user-role': new ConfigType(
|
||||
'plugin::users-permissions.role',
|
||||
'user-role',
|
||||
'type',
|
||||
[],
|
||||
[{
|
||||
queryString: 'plugin::users-permissions.permission',
|
||||
relationName: 'permissions',
|
||||
parentName: 'role',
|
||||
relationSortField: 'action',
|
||||
}]
|
||||
),
|
||||
'admin-role': new ConfigType(
|
||||
'admin::role',
|
||||
'admin-role',
|
||||
'code',
|
||||
|
@ -16,6 +25,8 @@ module.exports = {
|
|||
[{
|
||||
queryString: 'admin::permission',
|
||||
relationName: 'permissions',
|
||||
parentName: 'role',
|
||||
relationSortField: 'action',
|
||||
}]
|
||||
),
|
||||
};
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
const { sanitizeConfig } = require('../utils');
|
||||
const ConfigType = require("../services/type");
|
||||
|
||||
const UserRolePermissionsConfigType = class UserRolePermissionsConfigType 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 roleService = strapi.plugin('users-permissions').service('role');
|
||||
|
||||
const role = await strapi
|
||||
.query(this.queryString)
|
||||
.findOne({ where: { type: configName } });
|
||||
|
||||
if (role && configContent === null) {
|
||||
const publicRole = await strapi.query(this.queryString).findOne({ where: { type: 'public' } });
|
||||
const publicRoleID = publicRole.id;
|
||||
|
||||
await roleService.deleteRole(role.id, publicRoleID);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const users = role ? role.users : [];
|
||||
configContent.users = users;
|
||||
|
||||
if (!role) {
|
||||
await roleService.createRole(configContent);
|
||||
} else {
|
||||
await roleService.updateRole(role.id, configContent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all role-permissions config from the db.
|
||||
*
|
||||
* @returns {object} Object with key value pairs of configs.
|
||||
*/
|
||||
getAllFromDatabase = async () => {
|
||||
const UPService = strapi.plugin('users-permissions').service('users-permissions');
|
||||
const roleService = strapi.plugin('users-permissions').service('role');
|
||||
|
||||
const [roles, plugins] = await Promise.all([
|
||||
roleService.getRoles(),
|
||||
UPService.getPlugins(),
|
||||
]);
|
||||
|
||||
const rolesWithPermissions = await Promise.all(
|
||||
roles.map(async (role) => roleService.getRole(role.id, plugins))
|
||||
);
|
||||
|
||||
const configs = {};
|
||||
|
||||
rolesWithPermissions.map(({ id, ...config }) => {
|
||||
// Check if the config should be excluded.
|
||||
const shouldExclude = strapi.config.get('plugin.config-sync.exclude').includes(`${this.configPrefix}.${config.type}`);
|
||||
if (shouldExclude) return;
|
||||
|
||||
config = sanitizeConfig(config);
|
||||
|
||||
configs[`${this.configPrefix}.${config.type}`] = config;
|
||||
});
|
||||
|
||||
return configs;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = UserRolePermissionsConfigType;
|
|
@ -0,0 +1,7 @@
|
|||
const difference = (arrayOne, arrayTwo, compareKey) => {
|
||||
return arrayOne.filter(({ [compareKey]: id1 }) => {
|
||||
return !arrayTwo.some(({ [compareKey]: id2 }) => id2 === id1);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = difference;
|
|
@ -10,12 +10,58 @@ const getService = (name) => {
|
|||
|
||||
const logMessage = (msg = '') => `[strapi-plugin-config-sync]: ${msg}`;
|
||||
|
||||
const sanitizeConfig = (config) => {
|
||||
const sortByKeys = (unordered) => {
|
||||
return Object.keys(unordered).sort().reduce((obj, key) => {
|
||||
obj[key] = unordered[key];
|
||||
return obj;
|
||||
},
|
||||
{}
|
||||
);
|
||||
};
|
||||
|
||||
const dynamicSort = (property) => {
|
||||
let sortOrder = 1;
|
||||
|
||||
if (property[0] === "-") {
|
||||
sortOrder = -1;
|
||||
property = property.substr(1);
|
||||
}
|
||||
|
||||
return (a, b) => {
|
||||
if (sortOrder === -1) {
|
||||
return b[property].localeCompare(a[property]);
|
||||
} else {
|
||||
return a[property].localeCompare(b[property]);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const sanitizeConfig = (config, relation, relationSortField) => {
|
||||
delete config._id;
|
||||
delete config.id;
|
||||
delete config.updatedAt;
|
||||
delete config.createdAt;
|
||||
|
||||
if (relation) {
|
||||
const formattedRelations = [];
|
||||
|
||||
config[relation].map((relationEntity) => {
|
||||
delete relationEntity._id;
|
||||
delete relationEntity.id;
|
||||
delete relationEntity.updatedAt;
|
||||
delete relationEntity.createdAt;
|
||||
relationEntity = sortByKeys(relationEntity);
|
||||
|
||||
formattedRelations.push(relationEntity);
|
||||
});
|
||||
|
||||
if (relationSortField) {
|
||||
formattedRelations.sort(dynamicSort(relationSortField));
|
||||
}
|
||||
|
||||
config[relation] = formattedRelations;
|
||||
}
|
||||
|
||||
return config;
|
||||
};
|
||||
|
||||
|
@ -24,4 +70,6 @@ module.exports = {
|
|||
getCoreStore,
|
||||
logMessage,
|
||||
sanitizeConfig,
|
||||
sortByKeys,
|
||||
dynamicSort,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue