Add import/export services for roles, permissions & webhooks.
parent
c85fa56223
commit
4f0cce1b54
|
@ -2,5 +2,10 @@
|
|||
"destination": "extensions/config-sync/files/",
|
||||
"minify": false,
|
||||
"importOnBootstrap": false,
|
||||
"include": [
|
||||
"core-store",
|
||||
"role-permissions",
|
||||
"webhooks"
|
||||
],
|
||||
"exclude": []
|
||||
}
|
||||
|
|
|
@ -12,14 +12,10 @@ const fs = require('fs');
|
|||
* See more details here: https://strapi.io/documentation/v3.x/concepts/configurations.html#bootstrap
|
||||
*/
|
||||
|
||||
module.exports = () => {
|
||||
module.exports = async () => {
|
||||
if (strapi.plugins['config-sync'].config.importOnBootstrap) {
|
||||
if (fs.existsSync(strapi.plugins['config-sync'].config.destination)) {
|
||||
const configFiles = fs.readdirSync(strapi.plugins['config-sync'].config.destination);
|
||||
|
||||
configFiles.map((file) => {
|
||||
strapi.plugins['config-sync'].services.config.importFromFile(file.slice(0, -5));
|
||||
});
|
||||
await strapi.plugins['config-sync'].services.main.importAllConfig();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{
|
||||
"method": "GET",
|
||||
"path": "/export",
|
||||
"handler": "config.export",
|
||||
"handler": "config.exportAll",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
|||
{
|
||||
"method": "GET",
|
||||
"path": "/import",
|
||||
"handler": "config.import",
|
||||
"handler": "config.importAll",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
|
|
|
@ -13,13 +13,8 @@ module.exports = {
|
|||
* @param {object} ctx - Request context object.
|
||||
* @returns {void}
|
||||
*/
|
||||
export: async (ctx) => {
|
||||
const coreStoreAPI = strapi.query('core_store');
|
||||
const coreStore = await coreStoreAPI.find({ _limit: -1 });
|
||||
|
||||
Object.values(coreStore).map(async ({ key, value }) => {
|
||||
await strapi.plugins['config-sync'].services.config.writeConfigFile(key, value);
|
||||
});
|
||||
exportAll: async (ctx) => {
|
||||
await strapi.plugins['config-sync'].services.main.exportAllConfig();
|
||||
|
||||
ctx.send({
|
||||
message: `Config was successfully exported to ${strapi.plugins['config-sync'].config.destination}.`
|
||||
|
@ -32,7 +27,7 @@ module.exports = {
|
|||
* @param {object} ctx - Request context object.
|
||||
* @returns {void}
|
||||
*/
|
||||
import: async (ctx) => {
|
||||
importAll: async (ctx) => {
|
||||
// Check for existance of the config file destination dir.
|
||||
if (!fs.existsSync(strapi.plugins['config-sync'].config.destination)) {
|
||||
ctx.send({
|
||||
|
@ -42,11 +37,7 @@ module.exports = {
|
|||
return;
|
||||
}
|
||||
|
||||
const configFiles = fs.readdirSync(strapi.plugins['config-sync'].config.destination);
|
||||
|
||||
configFiles.map((file) => {
|
||||
strapi.plugins['config-sync'].services.config.importFromFile(file.slice(0, -5));
|
||||
});
|
||||
await strapi.plugins['config-sync'].services.main.importAllConfig();
|
||||
|
||||
ctx.send({
|
||||
message: 'Config was successfully imported.'
|
||||
|
@ -75,7 +66,7 @@ module.exports = {
|
|||
const getConfigs = async () => {
|
||||
return Promise.all(configFiles.map(async (file) => {
|
||||
const formattedConfigName = file.slice(0, -5); // remove the .json extension.
|
||||
const fileContents = await strapi.plugins['config-sync'].services.config.readConfigFile(formattedConfigName);
|
||||
const fileContents = await strapi.plugins['config-sync'].services.main.readConfigFile(formattedConfigName);
|
||||
formattedConfigs[formattedConfigName] = fileContents;
|
||||
}));
|
||||
};
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const util = require('util');
|
||||
|
||||
/**
|
||||
* Main services for config import/export.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Write a single config file.
|
||||
*
|
||||
* @param {string} configName - The name of the config file.
|
||||
* @param {string} fileContents - The JSON content of the config file.
|
||||
* @returns {void}
|
||||
*/
|
||||
writeConfigFile: async (configName, fileContents) => {
|
||||
// Check if the config should be excluded.
|
||||
const shouldExclude = strapi.plugins['config-sync'].config.exclude.includes(configName);
|
||||
if (shouldExclude) return;
|
||||
|
||||
// Check if the JSON content should be minified.
|
||||
const json =
|
||||
!strapi.plugins['config-sync'].config.minify ?
|
||||
JSON.stringify(JSON.parse(fileContents), null, 2)
|
||||
: fileContents;
|
||||
|
||||
if (!fs.existsSync(strapi.plugins['config-sync'].config.destination)) {
|
||||
fs.mkdirSync(strapi.plugins['config-sync'].config.destination, { recursive: true });
|
||||
}
|
||||
|
||||
const writeFile = util.promisify(fs.writeFile);
|
||||
await writeFile(`${strapi.plugins['config-sync'].config.destination}${configName}.json`, json);
|
||||
},
|
||||
|
||||
/**
|
||||
* Read from a config file.
|
||||
*
|
||||
* @param {string} configName - The name of the config file.
|
||||
* @returns {object} The JSON content of the config file.
|
||||
*/
|
||||
readConfigFile: async (configName) => {
|
||||
const readFile = util.promisify(fs.readFile);
|
||||
return await readFile(`${strapi.plugins['config-sync'].config.destination}${configName}.json`)
|
||||
.then((data) => {
|
||||
return JSON.parse(data);
|
||||
})
|
||||
.catch(() => {
|
||||
return null;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Import a config file into the db.
|
||||
*
|
||||
* @param {string} configName - The name of the config file.
|
||||
* @returns {void}
|
||||
*/
|
||||
importFromFile: async (configName) => {
|
||||
// Check if the config should be excluded.
|
||||
const shouldExclude = strapi.plugins['config-sync'].config.exclude.includes(configName);
|
||||
if (shouldExclude) return;
|
||||
|
||||
const coreStoreAPI = strapi.query('core_store');
|
||||
const fileContents = await strapi.plugins['config-sync'].services.config.readConfigFile(configName);
|
||||
|
||||
const configExists = await strapi
|
||||
.query('core_store')
|
||||
.findOne({ key: configName });
|
||||
|
||||
if (!configExists) {
|
||||
await coreStoreAPI.create({ key: configName, value: fileContents });
|
||||
} else {
|
||||
await coreStoreAPI.update({ key: configName }, { value: fileContents });
|
||||
}
|
||||
}
|
||||
};
|
|
@ -0,0 +1,65 @@
|
|||
'use strict';
|
||||
|
||||
const coreStoreQueryString = 'core_store';
|
||||
const configPrefix = 'core-store'; // Should be the same as the filename.
|
||||
|
||||
/**
|
||||
* Import/Export for core-store configs.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Export all core-store config to files.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
exportAll: async () => {
|
||||
const coreStore = await strapi.query(coreStoreQueryString).find({ _limit: -1 });
|
||||
|
||||
await Promise.all(Object.values(coreStore).map(async ({ id, ...config }) => {
|
||||
config.value = JSON.parse(config.value);
|
||||
await strapi.plugins['config-sync'].services.main.writeConfigFile(configPrefix, config.key, config);
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* Import a single core-store 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) => {
|
||||
const { value, ...fileContent } = configContent;
|
||||
const coreStoreAPI = strapi.query(coreStoreQueryString);
|
||||
|
||||
const configExists = await coreStoreAPI
|
||||
.findOne({ key: configName, environment: fileContent.environment });
|
||||
|
||||
if (!configExists) {
|
||||
await coreStoreAPI.create({ value: JSON.stringify(value), ...fileContent });
|
||||
} else {
|
||||
await coreStoreAPI.update({ key: configName }, { value: JSON.stringify(value), ...fileContent });
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Import all core-store config files into the db.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
importAll: async () => {
|
||||
// The main.importAllConfig service will loop the core-store.importSingle service.
|
||||
await strapi.plugins['config-sync'].services.main.importAllConfig(configPrefix);
|
||||
},
|
||||
|
||||
/**
|
||||
* Export a single core-store config to a file.
|
||||
*
|
||||
* @param {string} configName - The name of the config file.
|
||||
* @returns {void}
|
||||
*/
|
||||
exportSingle: async (configName) => {
|
||||
// @TODO: write export for a single core-store config.
|
||||
},
|
||||
};
|
|
@ -0,0 +1,126 @@
|
|||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const util = require('util');
|
||||
|
||||
/**
|
||||
* Main services for config import/export.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Write a single config file.
|
||||
*
|
||||
* @param {string} configType - The type of the config.
|
||||
* @param {string} configName - The name of the config file.
|
||||
* @param {string} fileContents - The JSON content of the config file.
|
||||
* @returns {void}
|
||||
*/
|
||||
writeConfigFile: async (configType, configName, fileContents) => {
|
||||
// Check if the config should be excluded.
|
||||
const shouldExclude = strapi.plugins['config-sync'].config.exclude.includes(`${configType}.${configName}`);
|
||||
if (shouldExclude) return;
|
||||
|
||||
// Check if the JSON content should be minified.
|
||||
const json =
|
||||
!strapi.plugins['config-sync'].config.minify ?
|
||||
JSON.stringify(fileContents, null, 2)
|
||||
: JSON.stringify(fileContents);
|
||||
|
||||
if (!fs.existsSync(strapi.plugins['config-sync'].config.destination)) {
|
||||
fs.mkdirSync(strapi.plugins['config-sync'].config.destination, { recursive: true });
|
||||
}
|
||||
|
||||
const writeFile = util.promisify(fs.writeFile);
|
||||
await writeFile(`${strapi.plugins['config-sync'].config.destination}${configType}.${configName}.json`, json)
|
||||
.then(() => {
|
||||
// @TODO:
|
||||
// Add logging for successfull config export.
|
||||
})
|
||||
.catch(() => {
|
||||
// @TODO:
|
||||
// Add logging for failed config export.
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Read from a config file.
|
||||
*
|
||||
* @param {string} configType - The type of config.
|
||||
* @param {string} configName - The name of the config file.
|
||||
* @returns {object} The JSON content of the config file.
|
||||
*/
|
||||
readConfigFile: async (configType, configName) => {
|
||||
const readFile = util.promisify(fs.readFile);
|
||||
return await readFile(`${strapi.plugins['config-sync'].config.destination}${configType}.${configName}.json`)
|
||||
.then((data) => {
|
||||
return JSON.parse(data);
|
||||
})
|
||||
.catch(() => {
|
||||
return null;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Import all config files into the db.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
importAllConfig: async (configType = null) => {
|
||||
const configFiles = fs.readdirSync(strapi.plugins['config-sync'].config.destination);
|
||||
|
||||
configFiles.map((file) => {
|
||||
const type = file.split('.')[0]; // Grab the first part of the filename.
|
||||
const name = file.split(/\.(.+)/)[1].split('.').slice(0, -1).join('.'); // Grab the rest of the filename minus the file extension.
|
||||
|
||||
if (configType && configType !== type) {
|
||||
return;
|
||||
}
|
||||
|
||||
strapi.plugins['config-sync'].services.main.importSingleConfig(type, name);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Export all config files.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
exportAllConfig: async (configType = null) => {
|
||||
await Promise.all(strapi.plugins['config-sync'].config.include.map(async (type) => {
|
||||
if (configType && configType !== type) {
|
||||
return;
|
||||
}
|
||||
|
||||
await strapi.plugins['config-sync'].services[type].exportAll();
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* Import a single config file into the db.
|
||||
*
|
||||
* @param {string} configType - The type of config.
|
||||
* @param {string} configName - The name of the config file.
|
||||
* @returns {void}
|
||||
*/
|
||||
importSingleConfig: async (configType, configName) => {
|
||||
// Check if the config should be excluded.
|
||||
const shouldExclude = strapi.plugins['config-sync'].config.exclude.includes(`${configType}.${configName}`);
|
||||
if (shouldExclude) return;
|
||||
|
||||
const fileContents = await strapi.plugins['config-sync'].services.main.readConfigFile(configType, configName);
|
||||
|
||||
await strapi.plugins['config-sync'].services[configType].importSingle(configName, fileContents);
|
||||
},
|
||||
|
||||
/**
|
||||
* Export a single config file.
|
||||
*
|
||||
* @param {string} configType - The type of config.
|
||||
* @param {string} configName - The name of the config file.
|
||||
* @returns {void}
|
||||
*/
|
||||
exportSingleConfig: async (configType, configName) => {
|
||||
|
||||
},
|
||||
};
|
|
@ -0,0 +1,85 @@
|
|||
'use strict';
|
||||
|
||||
const { sanitizeEntity } = require('strapi-utils');
|
||||
|
||||
const configPrefix = 'role-permissions'; // Should be the same as the filename.
|
||||
|
||||
/**
|
||||
* Import/Export for role-permissions configs.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Export all role-permissions config to files.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
exportAll: async () => {
|
||||
const service =
|
||||
strapi.plugins['users-permissions'].services.userspermissions;
|
||||
|
||||
const [roles, plugins] = await Promise.all([
|
||||
service.getRoles(),
|
||||
service.getPlugins(),
|
||||
]);
|
||||
|
||||
const rolesWithPermissions = await Promise.all(
|
||||
roles.map(async role => service.getRole(role.id, plugins))
|
||||
);
|
||||
|
||||
const sanitizedRolesArray = rolesWithPermissions.map(role =>
|
||||
sanitizeEntity(role, {
|
||||
model: strapi.plugins['users-permissions'].models.role,
|
||||
})
|
||||
);
|
||||
|
||||
await Promise.all(sanitizedRolesArray.map(async (config) => {
|
||||
await strapi.plugins['config-sync'].services.main.writeConfigFile(configPrefix, config.type, config);
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* 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) => {
|
||||
const service =
|
||||
strapi.plugins['users-permissions'].services.userspermissions;
|
||||
|
||||
const role = await strapi
|
||||
.query('role', 'users-permissions')
|
||||
.findOne({ type: configName });
|
||||
|
||||
const users = role ? role.users : [];
|
||||
configContent.users = users;
|
||||
|
||||
if (!role) {
|
||||
await service.createRole(configContent);
|
||||
} else {
|
||||
await service.updateRole(role.id, configContent);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Import all role-permissions config files into the db.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
importAll: async () => {
|
||||
// The main.importAllConfig service will loop the role-permissions.importSingle service.
|
||||
await strapi.plugins['config-sync'].services.main.importAllConfig(configPrefix);
|
||||
},
|
||||
|
||||
/**
|
||||
* Export a single role-permissions config to a file.
|
||||
*
|
||||
* @param {string} configName - The name of the config file.
|
||||
* @returns {void}
|
||||
*/
|
||||
exportSingle: async (configName) => {
|
||||
// @TODO: write export for a single role-permissions config.
|
||||
},
|
||||
};
|
|
@ -0,0 +1,62 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* Import/Export for webhook configs.
|
||||
*/
|
||||
|
||||
const webhookQueryString = 'strapi_webhooks';
|
||||
const configPrefix = 'webhooks'; // Should be the same as the filename.
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Export all webhooks to config files.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
exportAll: async () => {
|
||||
const webhooks = await strapi.query(webhookQueryString).find({ _limit: -1 });
|
||||
|
||||
await Promise.all(Object.values(webhooks).map(async (config) => {
|
||||
await strapi.plugins['config-sync'].services.main.writeConfigFile(configPrefix, config.id, config);
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* Import a single webhook 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) => {
|
||||
const webhookAPI = strapi.query(webhookQueryString);
|
||||
|
||||
const configExists = await webhookAPI.findOne({ id: configName });
|
||||
|
||||
if (!configExists) {
|
||||
await webhookAPI.create(configContent);
|
||||
} else {
|
||||
await webhookAPI.update({ id: configName }, configContent);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Import all webhook config files into the db.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
importAll: async () => {
|
||||
// The main.importAllConfig service will loop the webhooks.importSingle service.
|
||||
await strapi.plugins['config-sync'].services.main.importAllConfig(configPrefix);
|
||||
},
|
||||
|
||||
/**
|
||||
* Export a single webhook into a config file.
|
||||
*
|
||||
* @param {string} configName - The name of the config file.
|
||||
* @returns {void}
|
||||
*/
|
||||
exportSingle: async (configName) => {
|
||||
// @TODO: write export for a single webhook config.
|
||||
},
|
||||
};
|
Loading…
Reference in New Issue