UNPKG

sails-hook-blacksails

Version:
446 lines (416 loc) 12.5 kB
/** @module ConfigHelper * version: 20180301 * lastUpdater: Kent */ import _ from 'lodash'; import fs from 'fs'; // import appRootPath from 'app-root-path'; const appRootPath = sails.config.blacksails.sailsRoot; const configProdPath = 'config/env/production'; const configDevPath = 'config/env/development'; const configTestPath = 'config/env/test'; const configLocalPath = 'config/local'; const configLocalDefaultPath = 'config/local.default.js'; const currentConfigPath = 'config/local.current.js'; module.exports = { getAuthConfig() { return sails.config.authorization; }, getProjectConfig(projectName) { try { const config = sails.config.project; if (projectName) { return config[projectName]; } return config; } catch (e) { throw e; } }, isDropMode() { return (sails.config.models.migrate === 'drop'); }, isSafeMode() { return (sails.config.models.migrate === 'safe'); }, isInitTestData() { return (sails.config.models.initTestData == true); }, isProduction() { return (sails.config.environment === 'production'); }, isDevelopment() { return (sails.config.environment === undefined) || (typeof sails.config.environment === 'undefined') || (sails.config.environment === 'development'); }, isTesting() { return (sails.config.environment === 'test'); }, getBaseUrl() { return sails.config.appUrl; }, getDefualtVuePath() { return '../../../../sails-hook-admin/views/admin/default/vue.ejs'; }, getDefaultLayoutPath() { return '../../sails-hook-admin/views/admin/default'; }, async update(formatConfig) { try { for (let data of formatConfig) { data = { ...data, key: data.key || '', }; const modelConfig = await Config.findOne({ where: { name: data.name, key: data.key, }, }); if (modelConfig) { modelConfig.value = data.value; modelConfig.type = data.type; if (data.desc) { modelConfig.description = data.desc; } await modelConfig.save(); } else { await Config.create(data); } } return true; } catch (e) { throw e; } }, async sync(extraConfig) { sails.log.info('Syncing model config & local config'); try { // sails.log.debug('!!! appRootPath=>', appRootPath) if (extraConfig) { const formatExtraConfig = ConfigHelper.jsonTOPath(JSON.parse(JSON.stringify(extraConfig))); await this.update(formatExtraConfig); } const localConfig = require(`${appRootPath}/${configLocalPath}`); const { project } = sails.config; const dbConfig = await ConfigHelper.getModelJSONConfig(); let envConfig = {}; if (ConfigHelper.isProduction()) { envConfig = require(`${appRootPath}/${configProdPath}`); } else if (ConfigHelper.isDevelopment()) { envConfig = require(`${appRootPath}/${configDevPath}`); } else { delete localConfig.port; delete localConfig.appUrl; delete localConfig.environment; envConfig = require(`${appRootPath}/${configTestPath}`); } const allConfig = _.merge( {}, // 最後載入環境 config,確保以 env config 為主 { project }, envConfig, localConfig, dbConfig, ); delete allConfig.passport; delete allConfig.bootstrapTimeout; const pureJSONConfig = JSON.parse(JSON.stringify(allConfig)); await this.update(ConfigHelper.jsonTOPath(pureJSONConfig)); return await ConfigHelper.load(); } catch (e) { throw e; } }, load: async () => { sails.log.info('Updating sails configs'); try { const modelConfig = await ConfigHelper.getModelJSONConfig(); sails.config = _.merge( {}, sails.config, modelConfig, ); // sails.emit('hook:admin-config:reloaded'); // 把 config 寫入到 local.current.js const data = `module.exports = ${JSON.stringify({ aws: sails.config.aws, ...modelConfig, }, null, 2)};`; await fs.writeFileSync(`${appRootPath}/${currentConfigPath}`, data, 'utf8'); return sails.config; } catch (e) { throw e; } }, init: () => { }, jsonTOPath: (data) => { // sails.log.debug(data); try { let result = []; for (const key of Object.keys(data)) { if (_.isArray(data[key])) { result.push({ name: key, value: JSON.stringify(data[key]), type: 'array', }); } else if (_.isObject(data[key])) { let formatObject = ConfigHelper.getPath(data[key], '', []); formatObject = formatObject.map(e => ({ name: key, ...e, })); result = result.concat(formatObject); } else { const item = { name: key, value: data[key], type: 'text', }; if (!Number.isNaN(parseInt(data[key], 10))) { item.type = 'number'; } if (!_.isEmpty(data[key]) && (data[key] == true || data[key] == false)) { item.type = 'boolean'; } result.push(item); } } return result; } catch (e) { throw e; } }, pathTOJSON: (data) => { try { const result = {}; data.forEach((info) => { let { name } = info; // if (name.startsWith('project-')) { // // eslint-disable-next-line no-param-reassign // info.key = `${name}.${info.key}`; // name = 'project'; // } result[name] = result[name] || {}; if (info.key) { const pathArray = info.key.split('.'); if (pathArray.length > 0) { const value = info.type === 'array' ? JSON.parse(info.value) : info.value; result[name] = ConfigHelper.arrayTOObject(result[name], pathArray, value); } else { let { value } = info; if (info.type === 'boolean') { value = !!info.value; } else if (info.type === 'number') { value = parseInt(info.value, 10); } result[name] = value; } } else { let { value } = info; if (info.type === 'boolean') { value = !!info.value; } else if (info.type === 'number') { value = parseInt(info.value, 10); } result[name] = value; } }); // sails.log.info(result); return result; } catch (e) { throw e; } }, getPath: (curData, path, result, allData, nowPointer) => { const data = curData; try { if (_.isEmpty(data)) { // 判斷該物件內是否還有其他的物件 for (const item in allData) { if (!_.isEmpty(allData[item]) && _.isObject(allData[item])) { ConfigHelper.getPath(allData[item], item, result, allData, item); break; } } return result; } for (const key of Object.keys(data)) { if (_.isArray(data[key])) { const value = data[key]; result.push({ key: `${path}${path ? '.' : ''}${key}`, value: JSON.stringify(value), type: 'array', }); delete data[key]; return ConfigHelper.getPath(data, path, result, allData, nowPointer); } if (_.isObject(data[key])) { return ConfigHelper.getPath(data[key], `${path}${path ? '.' : ''}${key}`, result, data, key); } const item = { key: `${path}${path ? '.' : ''}${key}`, value: data[key], type: 'text', }; if (!Number.isNaN(parseInt(data[key], 10))) { item.type = 'number'; } if (!_.isEmpty(data[key]) && (data[key] == true || data[key] == false)) { item.type = 'boolean'; } result.push(item); delete data[key]; return ConfigHelper.getPath(data, path, result, allData, nowPointer); } } catch (e) { throw e; } }, arrayTOObject: (obj, keys, value) => { try { const lastKey = keys.pop(); const lastObj = keys.reduce((obj, key) => obj[key] = obj[key] || {}, obj); lastObj[lastKey] = value; return obj; } catch (e) { throw e; } }, getModelJSONConfig: async () => { try { let modelConfig = await Config.findAll(); modelConfig = modelConfig.map(data => data.toJSON()); modelConfig = ConfigHelper.pathTOJSON(modelConfig); return modelConfig; } catch (e) { throw e; } }, getApiKey(key) { try { const apiKeyObject = sails.config['api-key']; if (apiKeyObject) { const targetKey = _.get(apiKeyObject, key); sails.log(`[!] Get API KEY '${key}', value: '${targetKey}'.`); return targetKey || null; } return null; } catch (e) { sails.log.error(e); throw e; } }, async insertMenuItem(itemArray) { // sails.log.debug('Inserting new menuItems...'); try { if (!this.isDevelopment()) { return false; } const defaultRole = await Role.findOne({ where: { authority: 'admin' }, }); /* eslint no-await-in-loop: 0 */ for (const item of itemArray) { if (!item.title) { sails.log.warn(`Missing Menuitem Title founded. menu href '${item.title}' has no title('${item.title}').`); } let ParentMenuItemId = item.ParentMenuItemId; if (item.parentKey) { const parentItem = await MenuItem.findOne({ where: { key: item.parentKey, }, }); if (parentItem) ParentMenuItemId = parentItem.id; } const menuItem = await MenuItem.create({ icon: item.icon, iconType: item.iconType, model: item.model, href: item.href, title: item.title, key: item.key || null, order: item.order || 100, isActive: true, ParentMenuItemId, }); if (typeof item.role === 'string' && item.role !== 'admin') { sails.log.info(`Menuitem's extra authority founded. menu '${item.title}' needs role '${item.role}'.`); const targetRole = await Role.findOne({ where: { authority: item.role }, }); if (!targetRole) { throw Error(`Can not find target authority '${item.role}'.`); } await RoleMenuItem.create({ name: 'READ_WRITE', RoleId: targetRole.id, MenuItemId: menuItem.id, }); } else if (_.isArray(item.roles)) { sails.log.info('Menuitem\'s extra authority authority ARRAY founded.'); for (const role of item.roles) { sails.log.info(`menu '${item.title}' needs role '${role}'.`); const targetRole = await Role.findOne({ where: { authority: role }, }); if (!targetRole) { throw Error(`Can not find target authority '${role}'.`); } await RoleMenuItem.create({ name: 'READ_WRITE', RoleId: targetRole.id, MenuItemId: menuItem.id, }); } } else { await RoleMenuItem.create({ name: 'READ_WRITE', RoleId: defaultRole.id, MenuItemId: menuItem.id, }); } } return true; } catch (e) { sails.log.error(e); throw e; } }, // support TEXT only async updateByKey(key, value) { let keyPath = key.split('.'); const dbName = keyPath[0]; keyPath = keyPath.splice(1); const dbKey = keyPath.join('.'); const configEntry = await Config.findOne({ where: { name: dbName, key: dbKey, }, }); sails.log(key, dbName, dbKey); sails.log(configEntry); if (configEntry == null) { await Config.create({ name: dbName, key: dbKey, value, type: 'text', }); } else { configEntry.value = value; configEntry.save(); } await ConfigHelper.sync(); await ConfigHelper.load(); }, };