From 9aef2ca3250f31fde5e5710c56c221bfaf9b9dca Mon Sep 17 00:00:00 2001 From: Jim Laurie Date: Thu, 1 Feb 2018 16:50:05 +0100 Subject: [PATCH 01/20] Database config getter and setter Add in strapi.config get and set functions await strapi.config.set("key name", "data", "environment", "core/api/plugin", "api-name/plugin-name") await strapi.config.get("key name", "environment", "core/api/plugin", "api-name/plugin-name") --- packages/strapi/lib/Strapi.js | 5 ++- packages/strapi/lib/core/configs.js | 67 +++++++++++++++++++++++++++++ packages/strapi/lib/core/index.js | 4 +- 3 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 packages/strapi/lib/core/configs.js diff --git a/packages/strapi/lib/Strapi.js b/packages/strapi/lib/Strapi.js index 40ebc268f0..e4e66b29f1 100755 --- a/packages/strapi/lib/Strapi.js +++ b/packages/strapi/lib/Strapi.js @@ -8,7 +8,7 @@ const path = require('path'); const cluster = require('cluster'); const { includes, get, assign, forEach } = require('lodash'); const { logger, models } = require('strapi-utils'); -const { nestedConfigurations, appConfigurations, apis, middlewares, hooks, plugins, admin } = require('./core'); +const { nestedConfigurations, appConfigurations, apis, middlewares, hooks, plugins, admin, configs } = require('./core'); const initializeMiddlewares = require('./middlewares'); const initializeHooks = require('./hooks'); const { EventEmitter } = require('events'); @@ -179,6 +179,9 @@ class Strapi extends EventEmitter { // Populate AST with configurations. await appConfigurations.call(this); + // Init core database configs manager + await configs.call(this); + // Initialize hooks and middlewares. await Promise.all([ initializeMiddlewares.call(this), diff --git a/packages/strapi/lib/core/configs.js b/packages/strapi/lib/core/configs.js new file mode 100644 index 0000000000..7469861c13 --- /dev/null +++ b/packages/strapi/lib/core/configs.js @@ -0,0 +1,67 @@ +'use strict'; + +module.exports = function() { + return new Promise((resolve, reject) => { + this.models['strapi-configs'] = { + connection: 'default', + info: { + name: 'strapi-configs', + description: '' + }, + attributes: { + key: { + type: 'string' + }, + value: { + type: 'string' + }, + type: { + type: 'string' + }, + environment: { + type: 'string' + } + }, + globalId: 'StrapiConfigs', + collectionName: 'strapi-configs' + }; + + this.config.get = async (key, environment = strapi.config.environment, type = 'core', name = '') => { + const prefix = `${type}${name ? `_${name}` : ''}`; + + const data = await strapi.models['strapi-configs'].findOne({ + key: `${prefix}_${key}`, + environment + }); + + if (!data) { + return null; + } + + if (data.type === 'object' || data.type === 'array' || data.type === 'boolean') { + try { + return JSON.parse(data.value); + } catch (err) { + return new Date(data.value); + } + } else if (data.type === 'number') { + return parseFloat(data.value); + } else { + return null; + } + }; + + this.config.set = async (key, value, environment = strapi.config.environment, type, name) => { + const prefix = `${type}${name ? `_${name}` : ''}`; + + await strapi.models['strapi-configs'].create({ + key: `${prefix}_${key}`, + value: JSON.stringify(value) || value.toString(), + environment, + type: (typeof value).toString() + }); + }; + + resolve(); + }); +}; diff --git a/packages/strapi/lib/core/index.js b/packages/strapi/lib/core/index.js index 11d2a90f73..8a0114e0db 100755 --- a/packages/strapi/lib/core/index.js +++ b/packages/strapi/lib/core/index.js @@ -6,6 +6,7 @@ const middlewares = require('./middlewares'); const hooks = require('./hooks'); const plugins = require('./plugins'); const admin = require('./admin'); +const configs = require('./configs'); module.exports = { nestedConfigurations: nested, @@ -14,5 +15,6 @@ module.exports = { middlewares, hooks, plugins, - admin + admin, + configs }; From 29af75cc51ee4d13c4f8dbbb06440bacab7dc5a5 Mon Sep 17 00:00:00 2001 From: Jim Laurie Date: Thu, 1 Feb 2018 18:12:38 +0100 Subject: [PATCH 02/20] Use database config for users-permissions plugin Delete advanced, grant and email json files Update setter to update data --- .../.gitignore | 3 - .../config/advanced.json | 6 - .../config/functions/bootstrap.js | 154 ++++++++---------- .../controllers/Auth.js | 15 +- .../controllers/User.js | 6 +- .../controllers/UsersPermissions.js | 31 +--- .../services/Providers.js | 18 +- packages/strapi/lib/core/configs.js | 24 ++- 8 files changed, 114 insertions(+), 143 deletions(-) delete mode 100644 packages/strapi-plugin-users-permissions/config/advanced.json diff --git a/packages/strapi-plugin-users-permissions/.gitignore b/packages/strapi-plugin-users-permissions/.gitignore index c2e4863da9..34a1b10972 100755 --- a/packages/strapi-plugin-users-permissions/.gitignore +++ b/packages/strapi-plugin-users-permissions/.gitignore @@ -3,10 +3,7 @@ coverage build node_modules jwt.json -grant.json actions.json -email.json -advanced.json # Cruft .DS_Store diff --git a/packages/strapi-plugin-users-permissions/config/advanced.json b/packages/strapi-plugin-users-permissions/config/advanced.json deleted file mode 100644 index 0979d94ffe..0000000000 --- a/packages/strapi-plugin-users-permissions/config/advanced.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "advanced": { - "unique_email": true, - "allow_register": true - } -} \ No newline at end of file diff --git a/packages/strapi-plugin-users-permissions/config/functions/bootstrap.js b/packages/strapi-plugin-users-permissions/config/functions/bootstrap.js index cb5ac73abb..5936471700 100644 --- a/packages/strapi-plugin-users-permissions/config/functions/bootstrap.js +++ b/packages/strapi-plugin-users-permissions/config/functions/bootstrap.js @@ -13,7 +13,7 @@ const _ = require('lodash'); const fs = require('fs'); const uuid = require('uuid/v4'); -module.exports = cb => { +module.exports = async cb => { if (!_.get(strapi.plugins['users-permissions'], 'config.jwtSecret')) { try { const jwtSecret = uuid(); @@ -28,108 +28,84 @@ module.exports = cb => { } } - if (!_.get(strapi.plugins['users-permissions'], 'config.grant')) { - try { - const grant = { - email: { - enabled: true, - icon: 'envelope' - }, - facebook: { - enabled: false, - icon: 'facebook-official', - key: '', - secret: '', - callback: '/auth/facebook/callback', - scope: ['email'] - }, - google: { - enabled: false, - icon: 'google', - key: '', - secret: '', - callback: '/auth/google/callback', - scope: ['email'] - }, - github: { - enabled: false, - icon: 'github', - key: '', - secret: '', - redirect_uri: '/auth/github/callback', - scope: [ - 'user', - 'user:email' - ] - }, - twitter: { - enabled: false, - icon: 'twitter', - key: '', - secret: '', - callback: '/auth/twitter/callback' - } - }; + if (!await strapi.config.get('grant', strapi.config.environment, 'plugin', 'users-permissions')) { + const grant = { + email: { + enabled: true, + icon: 'envelope' + }, + facebook: { + enabled: false, + icon: 'facebook-official', + key: '', + secret: '', + callback: '/auth/facebook/callback', + scope: ['email'] + }, + google: { + enabled: false, + icon: 'google', + key: '', + secret: '', + callback: '/auth/google/callback', + scope: ['email'] + }, + github: { + enabled: false, + icon: 'github', + key: '', + secret: '', + redirect_uri: '/auth/github/callback', + scope: [ + 'user', + 'user:email' + ] + }, + twitter: { + enabled: false, + icon: 'twitter', + key: '', + secret: '', + callback: '/auth/twitter/callback' + } + }; - fs.writeFileSync(path.join(strapi.config.appPath, 'plugins', 'users-permissions', 'config', 'grant.json'), JSON.stringify({ - grant - }, null, 2), 'utf8'); - - _.set(strapi.plugins['users-permissions'], 'config.grant', grant); - } catch(err) { - strapi.log.error(err); - } + await strapi.config.set('grant', grant, strapi.config.environment, 'plugin', 'users-permissions'); } - if (!_.get(strapi.plugins['users-permissions'], 'config.email')) { - try { - const email = { - 'reset_password': { - display: 'Email.template.reset_password', - icon: 'refresh', - options: { - from: { - name: 'Administration Panel', - email: 'no-reply@strapi.io' - }, - response_email: '', - object: '­Reset password 🔑 ', - message: `

We heard that you lost your password. Sorry about that!

+ if (!await strapi.config.get('email', strapi.config.environment, 'plugin', 'users-permissions')) { + const email = { + 'reset_password': { + display: 'Email.template.reset_password', + icon: 'refresh', + options: { + from: { + name: 'Administration Panel', + email: 'no-reply@strapi.io' + }, + response_email: '', + object: '­Reset password 🔑 ', + message: `

We heard that you lost your password. Sorry about that!

But don’t worry! You can use the following link to reset your password:

<%= URL %>?code=<%= TOKEN %>

Thanks.

` - } } - }; + } + }; - fs.writeFileSync(path.join(strapi.config.appPath, 'plugins', 'users-permissions', 'config', 'email.json'), JSON.stringify({ - email - }, null, 2), 'utf8'); - - _.set(strapi.plugins['users-permissions'], 'config.email', email); - } catch(err) { - strapi.log.error(err); - } + await strapi.config.set('email', email, strapi.config.environment, 'plugin', 'users-permissions'); } - if (!_.get(strapi.plugins['users-permissions'], 'config.advanced')) { - try { - const advanced = { - unique_email: true, - allow_register: true - }; + if (!await strapi.config.get('advanced', strapi.config.environment, 'plugin', 'users-permissions')) { + const advanced = { + unique_email: true, + allow_register: true + }; - fs.writeFileSync(path.join(strapi.config.appPath, 'plugins', 'users-permissions', 'config', 'advanced.json'), JSON.stringify({ - advanced - }, null, 2), 'utf8'); - - _.set(strapi.plugins['users-permissions'], 'config.advanced', advanced); - } catch(err) { - strapi.log.error(err); - } + await strapi.config.set('advanced', advanced, strapi.config.environment, 'plugin', 'users-permissions'); } strapi.plugins['users-permissions'].services.userspermissions.syncSchema(() => { diff --git a/packages/strapi-plugin-users-permissions/controllers/Auth.js b/packages/strapi-plugin-users-permissions/controllers/Auth.js index 243ff2fa6a..4f797ef436 100644 --- a/packages/strapi-plugin-users-permissions/controllers/Auth.js +++ b/packages/strapi-plugin-users-permissions/controllers/Auth.js @@ -17,7 +17,7 @@ module.exports = { const params = ctx.request.body; if (provider === 'local') { - if (!_.get(strapi.plugins['users-permissions'].config.grant['email'], 'enabled') && !ctx.request.admin) { + if (!_.get(await strapi.config.get('grant', strapi.config.environment, 'plugin', 'users-permissions'), 'email.enabled') && !ctx.request.admin) { return ctx.badRequest(null, 'This provider is disabled.'); } @@ -70,7 +70,7 @@ module.exports = { }); } } else { - if (!_.get(strapi.plugins['users-permissions'].config.grant[provider], 'enabled')) { + if (!_.get(await strapi.config.get('grant', strapi.config.environment, 'plugin', 'users-permissions'), [provider, 'enabled'])) { return ctx.badRequest(null, 'This provider is disabled.'); } @@ -123,7 +123,9 @@ module.exports = { }, connect: async (ctx, next) => { - _.defaultsDeep(strapi.plugins['users-permissions'].config.grant, { + const grantConfig = await strapi.config.get('grant', strapi.config.environment, 'plugin', 'users-permissions'); + + _.defaultsDeep(grantConfig, { server: { protocol: 'http', host: `${strapi.config.currentEnvironment.server.host}:${strapi.config.currentEnvironment.server.port}` @@ -131,13 +133,13 @@ module.exports = { }); const provider = ctx.request.url.split('/')[2]; - const config = strapi.plugins['users-permissions'].config.grant[provider]; + const config = grantConfig[provider]; if (!_.get(config, 'enabled')) { return ctx.badRequest(null, 'This provider is disabled.'); } - const grant = new Grant(strapi.plugins['users-permissions'].config.grant); + const grant = new Grant(grantConfig); return strapi.koaMiddlewares.compose(grant.middleware)(ctx, next); }, @@ -192,7 +194,8 @@ module.exports = { }, register: async (ctx) => { - if (!strapi.plugins['users-permissions'].config.advanced.allow_register) { + console.log(await strapi.config.get('advanced', strapi.config.environment, 'plugin', 'users-permissions')); + if (!(await strapi.config.get('advanced', strapi.config.environment, 'plugin', 'users-permissions')).allow_register) { return ctx.badRequest(null, ctx.request.admin ? [{ messages: [{ id: 'Auth.advanced.allow_register' }] }] : 'Register action is currently disabled.'); } diff --git a/packages/strapi-plugin-users-permissions/controllers/User.js b/packages/strapi-plugin-users-permissions/controllers/User.js index afd61eb3db..b55271bfd8 100644 --- a/packages/strapi-plugin-users-permissions/controllers/User.js +++ b/packages/strapi-plugin-users-permissions/controllers/User.js @@ -70,7 +70,7 @@ module.exports = { */ create: async (ctx) => { - if (strapi.plugins['users-permissions'].config.advanced.unique_email && ctx.request.body.email) { + if ((await strapi.config.get('advanced', strapi.config.environment, 'plugin', 'users-permissions')).unique_email && ctx.request.body.email) { const user = await strapi.query('user', 'users-permissions').findOne({ email: ctx.request.body.email }); if (user) { @@ -96,7 +96,7 @@ module.exports = { update: async (ctx, next) => { try { - if (strapi.plugins['users-permissions'].config.advanced.unique_email && ctx.request.body.email) { + if ((await strapi.config.get('advanced', strapi.config.environment, 'plugin', 'users-permissions')).unique_email && ctx.request.body.email) { const user = await strapi.query('user', 'users-permissions').findOne({ email: ctx.request.body.email }); if (user) { @@ -114,7 +114,7 @@ module.exports = { delete ctx.request.body.role; } - if (ctx.request.body.email && strapi.plugins['users-permissions'].config.advanced.unique_email) { + if (ctx.request.body.email && (await strapi.config.get('advanced', strapi.config.environment, 'plugin', 'users-permissions')).unique_email) { const user = await strapi.query('user', 'users-permissions').findOne({ email: ctx.request.body.email }); diff --git a/packages/strapi-plugin-users-permissions/controllers/UsersPermissions.js b/packages/strapi-plugin-users-permissions/controllers/UsersPermissions.js index 05162eb303..a1998565cd 100644 --- a/packages/strapi-plugin-users-permissions/controllers/UsersPermissions.js +++ b/packages/strapi-plugin-users-permissions/controllers/UsersPermissions.js @@ -171,7 +171,7 @@ module.exports = { }, getEmailTemplate: async (ctx) => { - ctx.send(strapi.plugins['users-permissions'].config.email); + ctx.send(await strapi.config.get('email', strapi.config.environment, 'plugin', 'users-permissions')); }, updateEmailTemplate: async (ctx) => { @@ -179,19 +179,13 @@ module.exports = { return ctx.badRequest(null, [{ messages: [{ id: 'Cannot be empty' }] }]); } - strapi.reload.isWatching = false; - - fs.writeFileSync(path.join(strapi.config.appPath, 'plugins', 'users-permissions', 'config', 'email.json'), JSON.stringify({ - email: ctx.request.body - }, null, 2), 'utf8'); + await strapi.config.set('email', ctx.request.body, strapi.config.environment, 'plugin', 'users-permissions') ctx.send({ ok: true }); - - strapi.reload(); }, getAdvancedSettings: async (ctx) => { - ctx.send(strapi.plugins['users-permissions'].config.advanced); + ctx.send(await strapi.config.get('advanced', strapi.config.environment, 'plugin', 'users-permissions')); }, updateAdvancedSettings: async (ctx) => { @@ -199,19 +193,13 @@ module.exports = { return ctx.badRequest(null, [{ messages: [{ id: 'Cannot be empty' }] }]); } - strapi.reload.isWatching = false; - - fs.writeFileSync(path.join(strapi.config.appPath, 'plugins', 'users-permissions', 'config', 'advanced.json'), JSON.stringify({ - advanced: ctx.request.body - }, null, 2), 'utf8'); + await strapi.config.set('advanced', ctx.request.body, strapi.config.environment, 'plugin', 'users-permissions'); ctx.send({ ok: true }); - - strapi.reload(); }, getProviders: async (ctx) => { - ctx.send(strapi.plugins['users-permissions'].config.grant); + ctx.send(await strapi.config.get('grant', strapi.config.environment, 'plugin', 'users-permissions')); }, updateProviders: async (ctx) => { @@ -219,15 +207,8 @@ module.exports = { return ctx.badRequest(null, [{ messages: [{ id: 'Cannot be empty' }] }]); } - strapi.reload.isWatching = false; - - fs.writeFileSync(path.join(strapi.config.appPath, 'plugins', 'users-permissions', 'config', 'grant.json'), JSON.stringify({ - grant: ctx.request.body - }, null, 2), 'utf8'); - + await strapi.config.set('grant', ctx.request.body, strapi.config.environment, 'plugin', 'users-permissions'); ctx.send({ ok: true }); - - strapi.reload(); } }; diff --git a/packages/strapi-plugin-users-permissions/services/Providers.js b/packages/strapi-plugin-users-permissions/services/Providers.js index 9aaaef16cd..9025b07d4d 100644 --- a/packages/strapi-plugin-users-permissions/services/Providers.js +++ b/packages/strapi-plugin-users-permissions/services/Providers.js @@ -49,7 +49,9 @@ exports.connect = (provider, query) => { email: profile.email }); - if (_.isEmpty(_.find(users, {provider})) && !strapi.plugins['users-permissions'].config.advanced.allow_register) { + const advanced = await strapi.config.get('advanced', strapi.config.environment, 'plugin', 'users-permissions'); + + if (_.isEmpty(_.find(users, {provider})) && !advanced.allow_register) { return resolve([null, [{ messages: [{ id: 'Auth.advanced.allow_register' }] }], 'Register action is actualy not available.']); } @@ -57,7 +59,7 @@ exports.connect = (provider, query) => { return resolve([user, null]); } - if (!_.isEmpty(_.find(users, user => user.provider !== provider)) && strapi.plugins['users-permissions'].config.advanced.unique_email) { + if (!_.isEmpty(_.find(users, user => user.provider !== provider)) && advanced.unique_email) { return resolve([null, [{ messages: [{ id: 'Auth.form.error.email.taken' }] }], 'Email is already taken.']); } @@ -87,9 +89,11 @@ exports.connect = (provider, query) => { * @param {Function} callback */ -const getProfile = (provider, query, callback) => { +const getProfile = async (provider, query, callback) => { const access_token = query.access_token || query.code || query.oauth_token; + const grant = await strapi.config.get('grant', strapi.config.environment, 'plugin', 'users-permissions'); + switch (provider) { case 'facebook': const facebook = new Purest({ @@ -136,8 +140,8 @@ const getProfile = (provider, query, callback) => { request.post({ url: 'https://github.com/login/oauth/access_token', form: { - client_id: strapi.plugins['users-permissions'].config.grant.github.key, - client_secret: strapi.plugins['users-permissions'].config.grant.github.secret, + client_id: grant.github.key, + client_secret: grant.github.secret, code: access_token } }, (err, res, body) => { @@ -156,8 +160,8 @@ const getProfile = (provider, query, callback) => { case 'twitter': const twitter = new Purest({ provider: 'twitter', - key: strapi.plugins['users-permissions'].config.grant.twitter.key, - secret: strapi.plugins['users-permissions'].config.grant.twitter.secret + key: grant.twitter.key, + secret: grant.twitter.secret }); twitter.query().get('account/verify_credentials').auth(access_token, query.access_secret).qs({screen_name: query['raw[screen_name]'], include_email: 'true'}).request((err, res, body) => { diff --git a/packages/strapi/lib/core/configs.js b/packages/strapi/lib/core/configs.js index 7469861c13..11c1bbf3f0 100644 --- a/packages/strapi/lib/core/configs.js +++ b/packages/strapi/lib/core/configs.js @@ -54,12 +54,28 @@ module.exports = function() { this.config.set = async (key, value, environment = strapi.config.environment, type, name) => { const prefix = `${type}${name ? `_${name}` : ''}`; - await strapi.models['strapi-configs'].create({ + const data = await strapi.models['strapi-configs'].findOne({ key: `${prefix}_${key}`, - value: JSON.stringify(value) || value.toString(), - environment, - type: (typeof value).toString() + environment }); + + if (data) { + await strapi.models['strapi-configs'].update({ _id: data._id }, { + key: `${prefix}_${key}`, + value: JSON.stringify(value) || value.toString(), + environment, + type: (typeof value).toString() + }, { + strict: false + }); + } else { + await strapi.models['strapi-configs'].create({ + key: `${prefix}_${key}`, + value: JSON.stringify(value) || value.toString(), + environment, + type: (typeof value).toString() + }); + } }; resolve(); From 0e739d8e32f8c8ddbd28f03b21d49ad3501620bb Mon Sep 17 00:00:00 2001 From: Jim Laurie Date: Fri, 2 Feb 2018 14:50:10 +0100 Subject: [PATCH 03/20] Hide config model in content type builder and content manager --- .../controllers/ContentManager.js | 5 ++++- .../services/ContentTypeBuilder.js | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/strapi-plugin-content-manager/controllers/ContentManager.js b/packages/strapi-plugin-content-manager/controllers/ContentManager.js index df8dbbcb87..e67c54ef80 100755 --- a/packages/strapi-plugin-content-manager/controllers/ContentManager.js +++ b/packages/strapi-plugin-content-manager/controllers/ContentManager.js @@ -22,8 +22,11 @@ module.exports = { 'associations' ]); + const models = _.mapValues(strapi.models, pickData); + delete models['strapi-configs']; + ctx.body = { - models: _.mapValues(strapi.models, pickData), + models, plugins: Object.keys(strapi.plugins).reduce((acc, current) => { acc[current] = { models: _.mapValues(strapi.plugins[current].models, pickData) diff --git a/packages/strapi-plugin-content-type-builder/services/ContentTypeBuilder.js b/packages/strapi-plugin-content-type-builder/services/ContentTypeBuilder.js index a6b3bd4a21..60fc4dc6c2 100755 --- a/packages/strapi-plugin-content-type-builder/services/ContentTypeBuilder.js +++ b/packages/strapi-plugin-content-type-builder/services/ContentTypeBuilder.js @@ -10,6 +10,10 @@ module.exports = { const models = []; _.forEach(strapi.models, (model, name) => { + if (name === 'strapi-configs') { + return true; + } + models.push({ icon: 'fa-cube', name: _.get(model, 'info.name', 'model.name.missing'), From 0c2b54532e52d4be30cde86330f96e873df84079 Mon Sep 17 00:00:00 2001 From: Jim Laurie Date: Fri, 2 Feb 2018 18:08:49 +0100 Subject: [PATCH 04/20] Disable health route hit on config update --- .../admin/src/containers/HomePage/saga.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/saga.js b/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/saga.js index 4c6fa10703..487165bfb8 100755 --- a/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/saga.js +++ b/packages/strapi-plugin-users-permissions/admin/src/containers/HomePage/saga.js @@ -70,7 +70,7 @@ export function* submitData(action) { const body = yield select(makeSelectModifiedData()); const opts = { method: 'PUT', body }; - yield call(request, `/users-permissions/${action.endPoint}`, opts, true); + yield call(request, `/users-permissions/${action.endPoint}`, opts); yield put(submitSucceeded()); } catch(error) { strapi.notification.error('notification.error'); From 38df372696a6ad51ddb432e7009a5f68ca0661bf Mon Sep 17 00:00:00 2001 From: Jim Laurie Date: Mon, 5 Feb 2018 14:16:32 +0100 Subject: [PATCH 05/20] Set application name and description in database Settings manager can now get/update database configs --- .../files/config/application.json | 2 - .../config/functions/bootstrap.js | 22 ++++ .../controllers/SettingsManager.js | 6 +- .../services/SettingsManager.js | 106 +++++++++++------- 4 files changed, 89 insertions(+), 47 deletions(-) create mode 100644 packages/strapi-plugin-settings-manager/config/functions/bootstrap.js diff --git a/packages/strapi-generate-new/files/config/application.json b/packages/strapi-generate-new/files/config/application.json index 9e79e661fd..53d41b8817 100755 --- a/packages/strapi-generate-new/files/config/application.json +++ b/packages/strapi-generate-new/files/config/application.json @@ -1,6 +1,4 @@ { - "name": "Default Application", - "description": "This API is going to be awesome!", "favicon": { "path": "favicon.ico", "maxAge": 86400000 diff --git a/packages/strapi-plugin-settings-manager/config/functions/bootstrap.js b/packages/strapi-plugin-settings-manager/config/functions/bootstrap.js new file mode 100644 index 0000000000..397fc87ccc --- /dev/null +++ b/packages/strapi-plugin-settings-manager/config/functions/bootstrap.js @@ -0,0 +1,22 @@ +'use strict'; + +/** + * An asynchronous bootstrap function that runs before + * your application gets started. + * + * This gives you an opportunity to set up your data model, + * run jobs, or perform some special logic. + */ + +module.exports = async cb => { + if (!await strapi.config.get('application', '', 'core')) { + const application = { + name: 'Default Application', + description: 'This API is going to be awesome!' + }; + + await strapi.config.set('application', application, '', 'core'); + } + + cb(); +}; diff --git a/packages/strapi-plugin-settings-manager/controllers/SettingsManager.js b/packages/strapi-plugin-settings-manager/controllers/SettingsManager.js index 9858541946..0ce5cb12ad 100755 --- a/packages/strapi-plugin-settings-manager/controllers/SettingsManager.js +++ b/packages/strapi-plugin-settings-manager/controllers/SettingsManager.js @@ -59,7 +59,7 @@ module.exports = { if (env && _.isEmpty(_.find(Service.getEnvironments(), { name: env }))) return ctx.badRequest(null, [{ messages: [{ id: 'request.error.environment.unknown' }] }]); - _.has(Service, slug) ? ctx.send(Service[slug](env)) : ctx.badRequest(null, [{ messages: [{ id: 'request.error.config' }] }]); + _.has(Service, slug) ? ctx.send(await Service[slug](env)) : ctx.badRequest(null, [{ messages: [{ id: 'request.error.config' }] }]); }, update: async ctx => { @@ -71,7 +71,7 @@ module.exports = { let model; if (_.has(Service, slug)) { - model = Service[slug](env); + model = await Service[slug](env); } else { return ctx.badRequest(null, [{ messages: [{ id: 'request.error.config' }] }]); } @@ -87,7 +87,7 @@ module.exports = { strapi.reload.isWatching = false; - const updateErrors = Service.updateSettings(params, items, env); + const updateErrors = await Service.updateSettings(params, items, env); !_.isEmpty(updateErrors) ? ctx.badRequest(null, Service.formatErrors(updateErrors)) : ctx.send({ ok: true }); diff --git a/packages/strapi-plugin-settings-manager/services/SettingsManager.js b/packages/strapi-plugin-settings-manager/services/SettingsManager.js index 2ed5451d7c..0c3ef8b993 100755 --- a/packages/strapi-plugin-settings-manager/services/SettingsManager.js +++ b/packages/strapi-plugin-settings-manager/services/SettingsManager.js @@ -56,47 +56,53 @@ module.exports = { ] }, - application: () => ({ - name: 'form.application.name', - description: 'form.application.description', - sections: [ - { - name: '', - items: [ - { - name: 'form.application.item.name', - target: 'application.name', - type: 'string', - value: _.get(strapi.config, 'name', null), - validations : { - maxLength: 255, - required: true + application: async () => { + const application = await strapi.config.get('application', '', 'core') + + return { + name: 'form.application.name', + description: 'form.application.description', + sections: [ + { + name: '', + items: [ + { + name: 'form.application.item.name', + target: 'application.name', + source: 'db', + type: 'string', + value: _.get(application, 'name', null), + validations : { + maxLength: 255, + required: true + } + }, + { + name: 'form.application.item.description', + target: 'application.description', + source: 'db', + type: 'string', + value: _.get(application, 'description', null), + validations : { + maxLength: 255, + required: true + } + }, + { + name: 'form.application.item.version', + target: 'package.version', + type: 'string', + value: _.get(strapi.config, 'info.version', null), + validations : { + regex: '^(\\d+\\.)?(\\d+\\.)?(\\*|\\d+)$', + required: true + } } - }, - { - name: 'form.application.item.description', - target: 'application.description', - type: 'string', - value: _.get(strapi.config, 'description', null), - validations : { - maxLength: 255, - required: true - } - }, - { - name: 'form.application.item.version', - target: 'package.version', - type: 'string', - value: _.get(strapi.config, 'info.version', null), - validations : { - regex: '^(\\d+\\.)?(\\d+\\.)?(\\*|\\d+)$', - required: true - } - } - ] - } - ] - }), + ] + } + ] + } + }, request: env => ({ name: 'form.request.name', @@ -806,15 +812,31 @@ module.exports = { return [params, errors]; }, - updateSettings: (params, items, env = '') => { + updateSettings: async (params, items, env = '') => { const appPath = strapi.config.appPath; const errors = []; - _.forEach(items, ({ target }) => { + async function asyncForEach(array, callback) { + for (let index = 0; index < array.length; index++) { + await callback(array[index], index, array); + } + } + + await asyncForEach(items, async ({ target, source }) => { if (_.has(params, target)) { let input = _.get(params, target, null); const [file, ...objPath] = target.split('.'); + if (source === 'db') { + const data = await strapi.config.get(file, env, 'core'); + + _.set(data, objPath, input); + + await strapi.config.set(file, data, env, 'core'); + + return; + } + if (target === 'language.defaultLocale') input = _.lowerCase(input).replace(/ /g, '_'); const filePath = (file === 'package') ? path.join(appPath, 'package.json') : path.join(appPath, 'config', `${env ? `environments/${env}` : ''}`, `${_.replace(file, '.', '/')}.json`); From 30118187345da946d4cd1285ea53c8e102075338 Mon Sep 17 00:00:00 2001 From: Jim Laurie Date: Mon, 5 Feb 2018 16:25:50 +0100 Subject: [PATCH 06/20] Handle database configs for bookshelf Create request to get/create/update configs Display logs to create configs table --- packages/strapi/lib/Strapi.js | 5 +- packages/strapi/lib/core/configs.js | 192 +++++++++++++++++----------- 2 files changed, 123 insertions(+), 74 deletions(-) diff --git a/packages/strapi/lib/Strapi.js b/packages/strapi/lib/Strapi.js index e4e66b29f1..d15b79063f 100755 --- a/packages/strapi/lib/Strapi.js +++ b/packages/strapi/lib/Strapi.js @@ -180,7 +180,7 @@ class Strapi extends EventEmitter { await appConfigurations.call(this); // Init core database configs manager - await configs.call(this); + await configs.pre.call(this); // Initialize hooks and middlewares. await Promise.all([ @@ -188,6 +188,9 @@ class Strapi extends EventEmitter { initializeHooks.call(this) ]); + // Set configs post middleware and hooks init. + await configs.post.call(this); + // Harmonize plugins configuration. await plugins.call(this); } diff --git a/packages/strapi/lib/core/configs.js b/packages/strapi/lib/core/configs.js index 11c1bbf3f0..28a713e28c 100644 --- a/packages/strapi/lib/core/configs.js +++ b/packages/strapi/lib/core/configs.js @@ -1,83 +1,129 @@ 'use strict'; -module.exports = function() { - return new Promise((resolve, reject) => { - this.models['strapi-configs'] = { - connection: 'default', - info: { - name: 'strapi-configs', - description: '' - }, - attributes: { - key: { - type: 'string' +module.exports = { + pre: function () { + return new Promise((resolve, reject) => { + this.models['strapi-configs'] = { + connection: 'default', + info: { + name: 'strapi-configs', + description: '' }, - value: { - type: 'string' + attributes: { + key: { + type: 'string' + }, + value: { + type: 'string' + }, + type: { + type: 'string' + }, + environment: { + type: 'string' + } }, - type: { - type: 'string' - }, - environment: { - type: 'string' - } - }, - globalId: 'StrapiConfigs', - collectionName: 'strapi-configs' - }; + globalId: 'StrapiConfigs', + collectionName: 'strapi-configs' + }; - this.config.get = async (key, environment = strapi.config.environment, type = 'core', name = '') => { - const prefix = `${type}${name ? `_${name}` : ''}`; + this.config.get = async (key, environment = strapi.config.environment, type = 'core', name = '') => { + const prefix = `${type}${name ? `_${name}` : ''}`; - const data = await strapi.models['strapi-configs'].findOne({ - key: `${prefix}_${key}`, - environment - }); + const findAction = strapi.models['strapi-configs'].orm === 'mongoose' ? 'findOne' : 'forge'; - if (!data) { - return null; - } - - if (data.type === 'object' || data.type === 'array' || data.type === 'boolean') { - try { - return JSON.parse(data.value); - } catch (err) { - return new Date(data.value); - } - } else if (data.type === 'number') { - return parseFloat(data.value); - } else { - return null; - } - }; - - this.config.set = async (key, value, environment = strapi.config.environment, type, name) => { - const prefix = `${type}${name ? `_${name}` : ''}`; - - const data = await strapi.models['strapi-configs'].findOne({ - key: `${prefix}_${key}`, - environment - }); - - if (data) { - await strapi.models['strapi-configs'].update({ _id: data._id }, { + const where = { key: `${prefix}_${key}`, - value: JSON.stringify(value) || value.toString(), - environment, - type: (typeof value).toString() - }, { - strict: false - }); - } else { - await strapi.models['strapi-configs'].create({ - key: `${prefix}_${key}`, - value: JSON.stringify(value) || value.toString(), - environment, - type: (typeof value).toString() - }); - } - }; + environment + }; - resolve(); - }); + let data = strapi.models['strapi-configs'].orm === 'mongoose' + ? await strapi.models['strapi-configs'].findOne(where) + : await strapi.models['strapi-configs'].forge(where).fetch().then(configs => configs.toJSON()); + + if (!data) { + return null; + } + + if (data.type === 'object' || data.type === 'array' || data.type === 'boolean') { + try { + return JSON.parse(data.value); + } catch (err) { + return new Date(data.value); + } + } else if (data.type === 'number') { + return parseFloat(data.value); + } else { + return null; + } + }; + + this.config.set = async (key, value, environment = strapi.config.environment, type, name) => { + const prefix = `${type}${name ? `_${name}` : ''}`; + + const where = { + key: `${prefix}_${key}`, + environment + }; + + let data = strapi.models['strapi-configs'].orm === 'mongoose' + ? await strapi.models['strapi-configs'].findOne(where) + : await strapi.models['strapi-configs'].forge(where).fetch().then(configs => configs.toJSON()); + + if (data) { + data = Object.assign(data, { + value: JSON.stringify(value) || value.toString(), + type: (typeof value).toString() + }); + + strapi.models['strapi-configs'].orm === 'mongoose' + ? await strapi.models['strapi-configs'].update({ _id: data._id }, data, { strict: false }) + : await strapi.models['strapi-configs'].forge({ id: data.id }).save(data, { patch: true }); + } else { + data = Object.assign(where, { + value: JSON.stringify(value) || value.toString(), + type: (typeof value).toString() + }); + + strapi.models['strapi-configs'].orm === 'mongoose' + ? await strapi.models['strapi-configs'].create(data) + : await strapi.models['strapi-configs'].forge().save(data); + } + }; + + resolve(); + }); + }, + post: function () { + return new Promise(async (resolve, reject) => { + const Model = this.models['strapi-configs']; + + if (Model.orm !== 'bookshelf') { + return resolve(); + } + + const hasTable = await this.connections[Model.connection].schema.hasTable(Model.tableName || Model.collectionName); + + if (!hasTable) { + const quote = Model.client === 'pg' ? '"' : '`'; + + console.log(` +⚠️ TABLE \`strapi-configs\` DOESN'T EXIST + +CREATE TABLE ${quote}${Model.tableName || Model.collectionName}${quote} ( + id ${Model.client === 'pg' ? 'SERIAL' : 'INT AUTO_INCREMENT'} NOT NULL PRIMARY KEY, + key text, + value text, + environment text, + type text +); + `); + + // Stop the server. + return this.stop(); + } + + resolve(); + }); + } }; From f5031d01554455a803c0f12a85e95bdb814bb22b Mon Sep 17 00:00:00 2001 From: Jim Laurie Date: Tue, 6 Feb 2018 11:42:16 +0100 Subject: [PATCH 07/20] Rename table as core_store --- packages/strapi/lib/Strapi.js | 10 +++--- packages/strapi/lib/core/index.js | 4 +-- .../strapi/lib/core/{configs.js => store.js} | 36 +++++++++---------- 3 files changed, 25 insertions(+), 25 deletions(-) rename packages/strapi/lib/core/{configs.js => store.js} (67%) diff --git a/packages/strapi/lib/Strapi.js b/packages/strapi/lib/Strapi.js index d15b79063f..92ad30412d 100755 --- a/packages/strapi/lib/Strapi.js +++ b/packages/strapi/lib/Strapi.js @@ -8,7 +8,7 @@ const path = require('path'); const cluster = require('cluster'); const { includes, get, assign, forEach } = require('lodash'); const { logger, models } = require('strapi-utils'); -const { nestedConfigurations, appConfigurations, apis, middlewares, hooks, plugins, admin, configs } = require('./core'); +const { nestedConfigurations, appConfigurations, apis, middlewares, hooks, plugins, admin, store } = require('./core'); const initializeMiddlewares = require('./middlewares'); const initializeHooks = require('./hooks'); const { EventEmitter } = require('events'); @@ -179,8 +179,8 @@ class Strapi extends EventEmitter { // Populate AST with configurations. await appConfigurations.call(this); - // Init core database configs manager - await configs.pre.call(this); + // Init core store manager + await store.pre.call(this); // Initialize hooks and middlewares. await Promise.all([ @@ -188,8 +188,8 @@ class Strapi extends EventEmitter { initializeHooks.call(this) ]); - // Set configs post middleware and hooks init. - await configs.post.call(this); + // Core store post middleware and hooks init validation. + await store.post.call(this); // Harmonize plugins configuration. await plugins.call(this); diff --git a/packages/strapi/lib/core/index.js b/packages/strapi/lib/core/index.js index 8a0114e0db..a3b0970e94 100755 --- a/packages/strapi/lib/core/index.js +++ b/packages/strapi/lib/core/index.js @@ -6,7 +6,7 @@ const middlewares = require('./middlewares'); const hooks = require('./hooks'); const plugins = require('./plugins'); const admin = require('./admin'); -const configs = require('./configs'); +const store = require('./store'); module.exports = { nestedConfigurations: nested, @@ -16,5 +16,5 @@ module.exports = { hooks, plugins, admin, - configs + store }; diff --git a/packages/strapi/lib/core/configs.js b/packages/strapi/lib/core/store.js similarity index 67% rename from packages/strapi/lib/core/configs.js rename to packages/strapi/lib/core/store.js index 28a713e28c..c0d2f8660d 100644 --- a/packages/strapi/lib/core/configs.js +++ b/packages/strapi/lib/core/store.js @@ -3,10 +3,10 @@ module.exports = { pre: function () { return new Promise((resolve, reject) => { - this.models['strapi-configs'] = { + this.models['core_store'] = { connection: 'default', info: { - name: 'strapi-configs', + name: 'core_store', description: '' }, attributes: { @@ -24,22 +24,22 @@ module.exports = { } }, globalId: 'StrapiConfigs', - collectionName: 'strapi-configs' + collectionName: 'core_store' }; this.config.get = async (key, environment = strapi.config.environment, type = 'core', name = '') => { const prefix = `${type}${name ? `_${name}` : ''}`; - const findAction = strapi.models['strapi-configs'].orm === 'mongoose' ? 'findOne' : 'forge'; + const findAction = strapi.models['core_store'].orm === 'mongoose' ? 'findOne' : 'forge'; const where = { key: `${prefix}_${key}`, environment }; - let data = strapi.models['strapi-configs'].orm === 'mongoose' - ? await strapi.models['strapi-configs'].findOne(where) - : await strapi.models['strapi-configs'].forge(where).fetch().then(configs => configs.toJSON()); + let data = strapi.models['core_store'].orm === 'mongoose' + ? await strapi.models['core_store'].findOne(where) + : await strapi.models['core_store'].forge(where).fetch().then(configs => configs.toJSON()); if (!data) { return null; @@ -66,9 +66,9 @@ module.exports = { environment }; - let data = strapi.models['strapi-configs'].orm === 'mongoose' - ? await strapi.models['strapi-configs'].findOne(where) - : await strapi.models['strapi-configs'].forge(where).fetch().then(configs => configs.toJSON()); + let data = strapi.models['core_store'].orm === 'mongoose' + ? await strapi.models['core_store'].findOne(where) + : await strapi.models['core_store'].forge(where).fetch().then(configs => configs.toJSON()); if (data) { data = Object.assign(data, { @@ -76,18 +76,18 @@ module.exports = { type: (typeof value).toString() }); - strapi.models['strapi-configs'].orm === 'mongoose' - ? await strapi.models['strapi-configs'].update({ _id: data._id }, data, { strict: false }) - : await strapi.models['strapi-configs'].forge({ id: data.id }).save(data, { patch: true }); + strapi.models['core_store'].orm === 'mongoose' + ? await strapi.models['core_store'].update({ _id: data._id }, data, { strict: false }) + : await strapi.models['core_store'].forge({ id: data.id }).save(data, { patch: true }); } else { data = Object.assign(where, { value: JSON.stringify(value) || value.toString(), type: (typeof value).toString() }); - strapi.models['strapi-configs'].orm === 'mongoose' - ? await strapi.models['strapi-configs'].create(data) - : await strapi.models['strapi-configs'].forge().save(data); + strapi.models['core_store'].orm === 'mongoose' + ? await strapi.models['core_store'].create(data) + : await strapi.models['core_store'].forge().save(data); } }; @@ -96,7 +96,7 @@ module.exports = { }, post: function () { return new Promise(async (resolve, reject) => { - const Model = this.models['strapi-configs']; + const Model = this.models['core_store']; if (Model.orm !== 'bookshelf') { return resolve(); @@ -108,7 +108,7 @@ module.exports = { const quote = Model.client === 'pg' ? '"' : '`'; console.log(` -⚠️ TABLE \`strapi-configs\` DOESN'T EXIST +⚠️ TABLE \`core_store\` DOESN'T EXIST CREATE TABLE ${quote}${Model.tableName || Model.collectionName}${quote} ( id ${Model.client === 'pg' ? 'SERIAL' : 'INT AUTO_INCREMENT'} NOT NULL PRIMARY KEY, From 244b2809198566a2235255741729a0463bacc5b9 Mon Sep 17 00:00:00 2001 From: Jim Laurie Date: Tue, 6 Feb 2018 13:10:43 +0100 Subject: [PATCH 08/20] New format store constructor strapi.store(source).get(params) strapi.store(source).set({params, value}) Co-authored-by: Aurelsicoko --- .../config/functions/bootstrap.js | 11 +- .../services/SettingsManager.js | 16 ++- .../config/functions/bootstrap.js | 24 ++-- .../controllers/Auth.js | 22 +++- .../controllers/User.js | 16 ++- .../controllers/UsersPermissions.js | 36 +++++- .../services/Providers.js | 12 +- packages/strapi/lib/core/store.js | 112 +++++++++++------- 8 files changed, 175 insertions(+), 74 deletions(-) diff --git a/packages/strapi-plugin-settings-manager/config/functions/bootstrap.js b/packages/strapi-plugin-settings-manager/config/functions/bootstrap.js index 397fc87ccc..2d69808ae7 100644 --- a/packages/strapi-plugin-settings-manager/config/functions/bootstrap.js +++ b/packages/strapi-plugin-settings-manager/config/functions/bootstrap.js @@ -9,13 +9,18 @@ */ module.exports = async cb => { - if (!await strapi.config.get('application', '', 'core')) { - const application = { + const pluginStore = strapi.store({ + environment: '', + type: 'core' + }); + + if (!await pluginStore.get({key: 'application'})) { + const value = { name: 'Default Application', description: 'This API is going to be awesome!' }; - await strapi.config.set('application', application, '', 'core'); + await pluginStore.set({key: 'application', value}); } cb(); diff --git a/packages/strapi-plugin-settings-manager/services/SettingsManager.js b/packages/strapi-plugin-settings-manager/services/SettingsManager.js index 0c3ef8b993..4d067eff5d 100755 --- a/packages/strapi-plugin-settings-manager/services/SettingsManager.js +++ b/packages/strapi-plugin-settings-manager/services/SettingsManager.js @@ -57,7 +57,11 @@ module.exports = { }, application: async () => { - const application = await strapi.config.get('application', '', 'core') + const application = await strapi.store({ + environment: '', + type: 'core', + key: 'application' + }).get(); return { name: 'form.application.name', @@ -828,11 +832,17 @@ module.exports = { const [file, ...objPath] = target.split('.'); if (source === 'db') { - const data = await strapi.config.get(file, env, 'core'); + const store = strapi.store({ + environment: env, + type: 'core', + key: file + }); + + const data = await store.get(); _.set(data, objPath, input); - await strapi.config.set(file, data, env, 'core'); + await store.set({value: data}); return; } diff --git a/packages/strapi-plugin-users-permissions/config/functions/bootstrap.js b/packages/strapi-plugin-users-permissions/config/functions/bootstrap.js index 5936471700..b1ad737fe9 100644 --- a/packages/strapi-plugin-users-permissions/config/functions/bootstrap.js +++ b/packages/strapi-plugin-users-permissions/config/functions/bootstrap.js @@ -28,8 +28,14 @@ module.exports = async cb => { } } - if (!await strapi.config.get('grant', strapi.config.environment, 'plugin', 'users-permissions')) { - const grant = { + const pluginStore = strapi.store({ + environment: strapi.config.environment, + type: 'plugin', + name: 'users-permissions' + }); + + if (!await pluginStore.get({key: 'grant'})) { + const value = { email: { enabled: true, icon: 'envelope' @@ -70,11 +76,11 @@ module.exports = async cb => { } }; - await strapi.config.set('grant', grant, strapi.config.environment, 'plugin', 'users-permissions'); + await pluginStore.set({key: 'grant', value}); } - if (!await strapi.config.get('email', strapi.config.environment, 'plugin', 'users-permissions')) { - const email = { + if (!await pluginStore.get({key: 'email'})) { + const value = { 'reset_password': { display: 'Email.template.reset_password', icon: 'refresh', @@ -96,16 +102,16 @@ module.exports = async cb => { } }; - await strapi.config.set('email', email, strapi.config.environment, 'plugin', 'users-permissions'); + await pluginStore.set({key: 'email', value}); } - if (!await strapi.config.get('advanced', strapi.config.environment, 'plugin', 'users-permissions')) { - const advanced = { + if (!await pluginStore.get({key: 'advanced'})) { + const value = { unique_email: true, allow_register: true }; - await strapi.config.set('advanced', advanced, strapi.config.environment, 'plugin', 'users-permissions'); + await pluginStore.set({key: 'advanced', value}); } strapi.plugins['users-permissions'].services.userspermissions.syncSchema(() => { diff --git a/packages/strapi-plugin-users-permissions/controllers/Auth.js b/packages/strapi-plugin-users-permissions/controllers/Auth.js index 4f797ef436..a8e825e0dd 100644 --- a/packages/strapi-plugin-users-permissions/controllers/Auth.js +++ b/packages/strapi-plugin-users-permissions/controllers/Auth.js @@ -16,8 +16,13 @@ module.exports = { const provider = ctx.params.provider || 'local'; const params = ctx.request.body; + const store = await strapi.store({ + type: 'plugin', + name: 'users-permissions' + }); + if (provider === 'local') { - if (!_.get(await strapi.config.get('grant', strapi.config.environment, 'plugin', 'users-permissions'), 'email.enabled') && !ctx.request.admin) { + if (!_.get(await store.get({key: 'grant'}), 'email.enabled') && !ctx.request.admin) { return ctx.badRequest(null, 'This provider is disabled.'); } @@ -70,7 +75,7 @@ module.exports = { }); } } else { - if (!_.get(await strapi.config.get('grant', strapi.config.environment, 'plugin', 'users-permissions'), [provider, 'enabled'])) { + if (!_.get(await store.get({key: 'grant'}), [provider, 'enabled'])) { return ctx.badRequest(null, 'This provider is disabled.'); } @@ -123,7 +128,11 @@ module.exports = { }, connect: async (ctx, next) => { - const grantConfig = await strapi.config.get('grant', strapi.config.environment, 'plugin', 'users-permissions'); + const grantConfig = await strapi.store({ + type: 'plugin', + name: 'users-permissions', + key: 'grant' + }).get(); _.defaultsDeep(grantConfig, { server: { @@ -194,8 +203,11 @@ module.exports = { }, register: async (ctx) => { - console.log(await strapi.config.get('advanced', strapi.config.environment, 'plugin', 'users-permissions')); - if (!(await strapi.config.get('advanced', strapi.config.environment, 'plugin', 'users-permissions')).allow_register) { + if (!(await strapi.store({ + type: 'plugin', + name: 'users-permissions', + key: 'advanced' + }).get()).allow_register) { return ctx.badRequest(null, ctx.request.admin ? [{ messages: [{ id: 'Auth.advanced.allow_register' }] }] : 'Register action is currently disabled.'); } diff --git a/packages/strapi-plugin-users-permissions/controllers/User.js b/packages/strapi-plugin-users-permissions/controllers/User.js index b55271bfd8..5aae928f95 100644 --- a/packages/strapi-plugin-users-permissions/controllers/User.js +++ b/packages/strapi-plugin-users-permissions/controllers/User.js @@ -70,7 +70,11 @@ module.exports = { */ create: async (ctx) => { - if ((await strapi.config.get('advanced', strapi.config.environment, 'plugin', 'users-permissions')).unique_email && ctx.request.body.email) { + if ((await strapi.store({ + type: 'plugin', + name: 'users-permissions', + key: 'advanced' + }).get()).unique_email && ctx.request.body.email) { const user = await strapi.query('user', 'users-permissions').findOne({ email: ctx.request.body.email }); if (user) { @@ -96,7 +100,13 @@ module.exports = { update: async (ctx, next) => { try { - if ((await strapi.config.get('advanced', strapi.config.environment, 'plugin', 'users-permissions')).unique_email && ctx.request.body.email) { + const advancedConfigs = await strapi.store({ + type: 'plugin', + name: 'users-permissions', + key: 'advanced' + }).get(); + + if (advancedConfigs.unique_email && ctx.request.body.email) { const user = await strapi.query('user', 'users-permissions').findOne({ email: ctx.request.body.email }); if (user) { @@ -114,7 +124,7 @@ module.exports = { delete ctx.request.body.role; } - if (ctx.request.body.email && (await strapi.config.get('advanced', strapi.config.environment, 'plugin', 'users-permissions')).unique_email) { + if (ctx.request.body.email && advancedConfigs.unique_email) { const user = await strapi.query('user', 'users-permissions').findOne({ email: ctx.request.body.email }); diff --git a/packages/strapi-plugin-users-permissions/controllers/UsersPermissions.js b/packages/strapi-plugin-users-permissions/controllers/UsersPermissions.js index a1998565cd..eebac57775 100644 --- a/packages/strapi-plugin-users-permissions/controllers/UsersPermissions.js +++ b/packages/strapi-plugin-users-permissions/controllers/UsersPermissions.js @@ -171,7 +171,11 @@ module.exports = { }, getEmailTemplate: async (ctx) => { - ctx.send(await strapi.config.get('email', strapi.config.environment, 'plugin', 'users-permissions')); + ctx.send(await strapi.store({ + type: 'plugin', + name: 'users-permissions', + key: 'email' + }).get()); }, updateEmailTemplate: async (ctx) => { @@ -179,13 +183,21 @@ module.exports = { return ctx.badRequest(null, [{ messages: [{ id: 'Cannot be empty' }] }]); } - await strapi.config.set('email', ctx.request.body, strapi.config.environment, 'plugin', 'users-permissions') + await strapi.store({ + type: 'plugin', + name: 'users-permissions', + key: 'email' + }).set({value: ctx.request.body}) ctx.send({ ok: true }); }, getAdvancedSettings: async (ctx) => { - ctx.send(await strapi.config.get('advanced', strapi.config.environment, 'plugin', 'users-permissions')); + ctx.send(await strapi.store({ + type: 'plugin', + name: 'users-permissions', + key: 'advanced' + }).get()); }, updateAdvancedSettings: async (ctx) => { @@ -193,13 +205,21 @@ module.exports = { return ctx.badRequest(null, [{ messages: [{ id: 'Cannot be empty' }] }]); } - await strapi.config.set('advanced', ctx.request.body, strapi.config.environment, 'plugin', 'users-permissions'); + await strapi.store({ + type: 'plugin', + name: 'users-permissions', + key: 'advanced' + }).set({value: ctx.request.body}) ctx.send({ ok: true }); }, getProviders: async (ctx) => { - ctx.send(await strapi.config.get('grant', strapi.config.environment, 'plugin', 'users-permissions')); + ctx.send(await strapi.store({ + type: 'plugin', + name: 'users-permissions', + key: 'grant' + }).get()); }, updateProviders: async (ctx) => { @@ -207,7 +227,11 @@ module.exports = { return ctx.badRequest(null, [{ messages: [{ id: 'Cannot be empty' }] }]); } - await strapi.config.set('grant', ctx.request.body, strapi.config.environment, 'plugin', 'users-permissions'); + await strapi.store({ + type: 'plugin', + name: 'users-permissions', + key: 'grant' + }).set({value: ctx.request.body}) ctx.send({ ok: true }); } diff --git a/packages/strapi-plugin-users-permissions/services/Providers.js b/packages/strapi-plugin-users-permissions/services/Providers.js index 9025b07d4d..9a3fdb7414 100644 --- a/packages/strapi-plugin-users-permissions/services/Providers.js +++ b/packages/strapi-plugin-users-permissions/services/Providers.js @@ -49,7 +49,11 @@ exports.connect = (provider, query) => { email: profile.email }); - const advanced = await strapi.config.get('advanced', strapi.config.environment, 'plugin', 'users-permissions'); + const advanced = await strapi.store({ + type: 'plugin', + name: 'users-permissions', + key: 'advanced' + }).get(); if (_.isEmpty(_.find(users, {provider})) && !advanced.allow_register) { return resolve([null, [{ messages: [{ id: 'Auth.advanced.allow_register' }] }], 'Register action is actualy not available.']); @@ -92,7 +96,11 @@ exports.connect = (provider, query) => { const getProfile = async (provider, query, callback) => { const access_token = query.access_token || query.code || query.oauth_token; - const grant = await strapi.config.get('grant', strapi.config.environment, 'plugin', 'users-permissions'); + const grant = await strapi.store({ + type: 'plugin', + name: 'users-permissions', + key: 'grant' + }).get(); switch (provider) { case 'facebook': diff --git a/packages/strapi/lib/core/store.js b/packages/strapi/lib/core/store.js index c0d2f8660d..a4d0b1f4e9 100644 --- a/packages/strapi/lib/core/store.js +++ b/packages/strapi/lib/core/store.js @@ -27,69 +27,95 @@ module.exports = { collectionName: 'core_store' }; - this.config.get = async (key, environment = strapi.config.environment, type = 'core', name = '') => { - const prefix = `${type}${name ? `_${name}` : ''}`; + this.store = (source = {}) => { + const get = async (params = {}) => { + const configs = Object.assign(source, params); - const findAction = strapi.models['core_store'].orm === 'mongoose' ? 'findOne' : 'forge'; + const { + key, + environment = strapi.config.environment, + type = 'core', + name = '' + } = configs; - const where = { - key: `${prefix}_${key}`, - environment - }; + const prefix = `${type}${name ? `_${name}` : ''}`; - let data = strapi.models['core_store'].orm === 'mongoose' + const findAction = strapi.models['core_store'].orm === 'mongoose' ? 'findOne' : 'forge'; + + const where = { + key: `${prefix}_${key}`, + environment + }; + + let data = strapi.models['core_store'].orm === 'mongoose' ? await strapi.models['core_store'].findOne(where) : await strapi.models['core_store'].forge(where).fetch().then(configs => configs.toJSON()); - if (!data) { - return null; - } - - if (data.type === 'object' || data.type === 'array' || data.type === 'boolean') { - try { - return JSON.parse(data.value); - } catch (err) { - return new Date(data.value); + if (!data) { + return null; } - } else if (data.type === 'number') { - return parseFloat(data.value); - } else { - return null; - } - }; - this.config.set = async (key, value, environment = strapi.config.environment, type, name) => { - const prefix = `${type}${name ? `_${name}` : ''}`; - - const where = { - key: `${prefix}_${key}`, - environment + if (data.type === 'object' || data.type === 'array' || data.type === 'boolean') { + try { + return JSON.parse(data.value); + } catch (err) { + return new Date(data.value); + } + } else if (data.type === 'number') { + return parseFloat(data.value); + } else { + return null; + } }; - let data = strapi.models['core_store'].orm === 'mongoose' + const set = async (params = {}) => { + const configs = Object.assign(source, params); + + const { + key, + value, + environment = strapi.config.environment, + type, + name + } = configs; + + const prefix = `${type}${name ? `_${name}` : ''}`; + + const where = { + key: `${prefix}_${key}`, + environment + }; + + let data = strapi.models['core_store'].orm === 'mongoose' ? await strapi.models['core_store'].findOne(where) : await strapi.models['core_store'].forge(where).fetch().then(configs => configs.toJSON()); - if (data) { - data = Object.assign(data, { - value: JSON.stringify(value) || value.toString(), - type: (typeof value).toString() - }); + if (data) { + data = Object.assign(data, { + value: JSON.stringify(value) || value.toString(), + type: (typeof value).toString() + }); - strapi.models['core_store'].orm === 'mongoose' + strapi.models['core_store'].orm === 'mongoose' ? await strapi.models['core_store'].update({ _id: data._id }, data, { strict: false }) : await strapi.models['core_store'].forge({ id: data.id }).save(data, { patch: true }); - } else { - data = Object.assign(where, { - value: JSON.stringify(value) || value.toString(), - type: (typeof value).toString() - }); + } else { + data = Object.assign(where, { + value: JSON.stringify(value) || value.toString(), + type: (typeof value).toString() + }); - strapi.models['core_store'].orm === 'mongoose' + strapi.models['core_store'].orm === 'mongoose' ? await strapi.models['core_store'].create(data) : await strapi.models['core_store'].forge().save(data); + } + }; + + return { + get, + set } - }; + } resolve(); }); From b784c32be1cfcc013c8d632fb62e3384e2822242 Mon Sep 17 00:00:00 2001 From: Jim Laurie Date: Tue, 6 Feb 2018 15:08:25 +0100 Subject: [PATCH 09/20] Add tag column --- .../controllers/ContentManager.js | 2 +- .../services/ContentTypeBuilder.js | 2 +- packages/strapi/lib/core/store.js | 23 ++++++++++++++----- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/packages/strapi-plugin-content-manager/controllers/ContentManager.js b/packages/strapi-plugin-content-manager/controllers/ContentManager.js index e67c54ef80..a90e275b33 100755 --- a/packages/strapi-plugin-content-manager/controllers/ContentManager.js +++ b/packages/strapi-plugin-content-manager/controllers/ContentManager.js @@ -23,7 +23,7 @@ module.exports = { ]); const models = _.mapValues(strapi.models, pickData); - delete models['strapi-configs']; + delete models['core_store']; ctx.body = { models, diff --git a/packages/strapi-plugin-content-type-builder/services/ContentTypeBuilder.js b/packages/strapi-plugin-content-type-builder/services/ContentTypeBuilder.js index 60fc4dc6c2..0a3223f5ec 100755 --- a/packages/strapi-plugin-content-type-builder/services/ContentTypeBuilder.js +++ b/packages/strapi-plugin-content-type-builder/services/ContentTypeBuilder.js @@ -10,7 +10,7 @@ module.exports = { const models = []; _.forEach(strapi.models, (model, name) => { - if (name === 'strapi-configs') { + if (name === 'core_store') { return true; } diff --git a/packages/strapi/lib/core/store.js b/packages/strapi/lib/core/store.js index a4d0b1f4e9..63c6b91f75 100644 --- a/packages/strapi/lib/core/store.js +++ b/packages/strapi/lib/core/store.js @@ -21,6 +21,9 @@ module.exports = { }, environment: { type: 'string' + }, + tag: { + type: 'string' } }, globalId: 'StrapiConfigs', @@ -35,7 +38,8 @@ module.exports = { key, environment = strapi.config.environment, type = 'core', - name = '' + name = '', + tag = '' } = configs; const prefix = `${type}${name ? `_${name}` : ''}`; @@ -44,7 +48,8 @@ module.exports = { const where = { key: `${prefix}_${key}`, - environment + environment, + tag }; let data = strapi.models['core_store'].orm === 'mongoose' @@ -76,14 +81,16 @@ module.exports = { value, environment = strapi.config.environment, type, - name + name, + tag = '' } = configs; const prefix = `${type}${name ? `_${name}` : ''}`; const where = { key: `${prefix}_${key}`, - environment + environment, + tag }; let data = strapi.models['core_store'].orm === 'mongoose' @@ -102,7 +109,8 @@ module.exports = { } else { data = Object.assign(where, { value: JSON.stringify(value) || value.toString(), - type: (typeof value).toString() + type: (typeof value).toString(), + tag }); strapi.models['core_store'].orm === 'mongoose' @@ -141,8 +149,11 @@ CREATE TABLE ${quote}${Model.tableName || Model.collectionName}${quote} ( key text, value text, environment text, - type text + type text, + flag text ); + +ALTER TABLE ${quote}${Model.tableName || Model.collectionName}${quote} ADD COLUMN ${quote}parent${quote} integer, ADD FOREIGN KEY (${quote}parent${quote}) REFERENCES ${quote}${Model.tableName || Model.collectionName}${quote}(${quote}id${quote}); `); // Stop the server. From ae6d88bca4826e2848b7702224f01c13b34ea7a8 Mon Sep 17 00:00:00 2001 From: Pierre Burgy Date: Mon, 12 Feb 2018 11:39:31 +0100 Subject: [PATCH 10/20] Add Heroku deploy button in README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 25f2ce20f3..60a1d9c1cb 100755 --- a/README.md +++ b/README.md @@ -15,6 +15,9 @@ Dependency Status + + Deploy +


From 7ef60701fe2c73a567951b03f55d8ab411c6d6f1 Mon Sep 17 00:00:00 2001 From: Pierre Burgy Date: Mon, 12 Feb 2018 11:43:55 +0100 Subject: [PATCH 11/20] Change version in README.md documentation --- docs/3.x.x/en/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/3.x.x/en/README.md b/docs/3.x.x/en/README.md index dab7d7d2ed..6e0d68fc17 100644 --- a/docs/3.x.x/en/README.md +++ b/docs/3.x.x/en/README.md @@ -12,10 +12,10 @@ The most advanced open-source Content Management Framework to build powerful API {% endcenter %} -## v3@alpha.8 is available! +## v3@alpha.9 is available! We've been working on a major update for Strapi during the past months, rewriting the core framework and the dashboard. -This documentation is only related to Strapi v3@alpha.8 ([v1 documentation is still available](http://strapi.io/documentation/1.x.x)). +This documentation is only related to Strapi v3@alpha.9 ([v1 documentation is still available](http://strapi.io/documentation/1.x.x)). **[Get Started](getting-started/installation.md)**
Learn how to install Strapi and start developing your API. From 859a96df3a29e4f931219219575248187451f02c Mon Sep 17 00:00:00 2001 From: Pierre Burgy Date: Mon, 12 Feb 2018 11:48:29 +0100 Subject: [PATCH 12/20] Add Heroku deploy button in documentation README.md --- docs/3.x.x/en/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/3.x.x/en/README.md b/docs/3.x.x/en/README.md index 6e0d68fc17..e666fd751f 100644 --- a/docs/3.x.x/en/README.md +++ b/docs/3.x.x/en/README.md @@ -9,6 +9,9 @@ The most advanced open-source Content Management Framework to build powerful API [![npm downloads](https://img.shields.io/npm/dm/strapi.svg)](https://www.npmjs.org/package/strapi) [![Build status](https://travis-ci.org/strapi/strapi.svg?branch=master)](https://travis-ci.org/strapi/strapi) [![Slack status](http://strapi-slack.herokuapp.com/badge.svg)](http://slack.strapi.io) + + Deploy + {% endcenter %} From 54e0dd1d84045b579d3a9f02981131e722204a0d Mon Sep 17 00:00:00 2001 From: Pierre Burgy Date: Mon, 12 Feb 2018 12:07:36 +0100 Subject: [PATCH 13/20] Add tutorials in doc --- docs/3.x.x/en/SUMMARY.md | 2 +- docs/3.x.x/en/tutorials/README.md | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 docs/3.x.x/en/tutorials/README.md diff --git a/docs/3.x.x/en/SUMMARY.md b/docs/3.x.x/en/SUMMARY.md index e3b077afaa..2f9ca65070 100644 --- a/docs/3.x.x/en/SUMMARY.md +++ b/docs/3.x.x/en/SUMMARY.md @@ -49,7 +49,7 @@ * [Table of contents](api-reference/reference.md) ### Tutorials -* Coming soon +* [Table of contents](tutorials/README.md) ### Migration * [Migrating from v1 to v3](migration/migration-guide.md) diff --git a/docs/3.x.x/en/tutorials/README.md b/docs/3.x.x/en/tutorials/README.md new file mode 100644 index 0000000000..7040501137 --- /dev/null +++ b/docs/3.x.x/en/tutorials/README.md @@ -0,0 +1,13 @@ +## Tutorials + +After having realized the [Getting Started guide](https://strapi.io/getting-started), it is time to go further with Strapi. Official and community tutorials are here to help you: + +### Development + + - [Building a static blog using Gatsby and Strapi (official)](https://hackernoon.com/building-a-static-blog-using-gatsby-and-strapi-8b5acfc82ad8) + +### Deployment + +- [Using mLab with Strapi (official)](https://medium.com/@strapi/using-mlab-with-strapi-e3f968a9c530) +- [How to deploy a Strapi API on Ubuntu 16.04 (official)](https://medium.com/@strapi/how-to-deploy-a-strapi-api-on-ubuntu-16-04-17f8fbbf5c5b) +- [Deploying a Strapi API on Heroku (official)](https://medium.com/@strapi/deploying-a-strapi-api-on-heroku-9c8b7809675c) From 7607d20310d0239dfc1e8c319ccb2f05daa52168 Mon Sep 17 00:00:00 2001 From: Jim Laurie Date: Mon, 12 Feb 2018 14:10:20 +0100 Subject: [PATCH 14/20] Fix PR feedback --- packages/strapi/lib/core/store.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/strapi/lib/core/store.js b/packages/strapi/lib/core/store.js index 63c6b91f75..2f03b0a392 100644 --- a/packages/strapi/lib/core/store.js +++ b/packages/strapi/lib/core/store.js @@ -32,7 +32,7 @@ module.exports = { this.store = (source = {}) => { const get = async (params = {}) => { - const configs = Object.assign(source, params); + Object.assign(source, params); const { key, @@ -40,7 +40,7 @@ module.exports = { type = 'core', name = '', tag = '' - } = configs; + } = source; const prefix = `${type}${name ? `_${name}` : ''}`; @@ -52,9 +52,9 @@ module.exports = { tag }; - let data = strapi.models['core_store'].orm === 'mongoose' + const data = strapi.models['core_store'].orm === 'mongoose' ? await strapi.models['core_store'].findOne(where) - : await strapi.models['core_store'].forge(where).fetch().then(configs => configs.toJSON()); + : await strapi.models['core_store'].forge(where).fetch().then(config => configs.toJSON()); if (!data) { return null; @@ -74,7 +74,7 @@ module.exports = { }; const set = async (params = {}) => { - const configs = Object.assign(source, params); + Object.assign(source, params); const { key, @@ -83,7 +83,7 @@ module.exports = { type, name, tag = '' - } = configs; + } = source; const prefix = `${type}${name ? `_${name}` : ''}`; @@ -95,10 +95,10 @@ module.exports = { let data = strapi.models['core_store'].orm === 'mongoose' ? await strapi.models['core_store'].findOne(where) - : await strapi.models['core_store'].forge(where).fetch().then(configs => configs.toJSON()); + : await strapi.models['core_store'].forge(where).fetch().then(config => config.toJSON()); if (data) { - data = Object.assign(data, { + Object.assign(data, { value: JSON.stringify(value) || value.toString(), type: (typeof value).toString() }); @@ -107,15 +107,15 @@ module.exports = { ? await strapi.models['core_store'].update({ _id: data._id }, data, { strict: false }) : await strapi.models['core_store'].forge({ id: data.id }).save(data, { patch: true }); } else { - data = Object.assign(where, { + Object.assign(where, { value: JSON.stringify(value) || value.toString(), type: (typeof value).toString(), tag }); strapi.models['core_store'].orm === 'mongoose' - ? await strapi.models['core_store'].create(data) - : await strapi.models['core_store'].forge().save(data); + ? await strapi.models['core_store'].create(where) + : await strapi.models['core_store'].forge().save(where); } }; From d5470f0d07db0483ade3ae1365d9904b027f3dbd Mon Sep 17 00:00:00 2001 From: Pierre Burgy Date: Mon, 12 Feb 2018 14:35:53 +0100 Subject: [PATCH 15/20] Move Heroku button in README.md --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 60a1d9c1cb..9f0ba11c89 100755 --- a/README.md +++ b/README.md @@ -15,9 +15,6 @@ Dependency Status - - Deploy -


@@ -31,6 +28,10 @@ We've been working on a major update to Strapi for several months now, rewriting the core framework and the administration panel. Performances has been increased, Developer eXperience has been improved and a brand new plugins ecosystem has been introduced. **Both versions are available, we still recommend you to use v1 for production usage.**. + + Deploy + + #### Alpha The alpha has support for the latest version of Node.js (v8) and npm (v5). From f155736012bcb2560692682d1b248d457d0d1ee8 Mon Sep 17 00:00:00 2001 From: Jim Laurie Date: Mon, 12 Feb 2018 14:38:54 +0100 Subject: [PATCH 16/20] Fix mask for admin routes --- packages/strapi/lib/middlewares/mask/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/strapi/lib/middlewares/mask/index.js b/packages/strapi/lib/middlewares/mask/index.js index 8f960f6d69..5bf2e918e2 100644 --- a/packages/strapi/lib/middlewares/mask/index.js +++ b/packages/strapi/lib/middlewares/mask/index.js @@ -70,7 +70,7 @@ module.exports = strapi => { }; // Only pick successful JSON requests. - if ([200, 201, 202].includes(ctx.status) && ctx.type === 'application/json') { + if ([200, 201, 202].includes(ctx.status) && ctx.type === 'application/json' && !ctx.request.admin) { ctx.body = mask(ctx.body); } }); From b74dd97beccfbb7102776a717e0f7a20623ecffd Mon Sep 17 00:00:00 2001 From: Jim Laurie Date: Mon, 12 Feb 2018 15:16:23 +0100 Subject: [PATCH 17/20] Fix get null config bookshelf --- packages/strapi/lib/core/store.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/strapi/lib/core/store.js b/packages/strapi/lib/core/store.js index 2f03b0a392..5051cdac63 100644 --- a/packages/strapi/lib/core/store.js +++ b/packages/strapi/lib/core/store.js @@ -54,7 +54,11 @@ module.exports = { const data = strapi.models['core_store'].orm === 'mongoose' ? await strapi.models['core_store'].findOne(where) - : await strapi.models['core_store'].forge(where).fetch().then(config => configs.toJSON()); + : await strapi.models['core_store'].forge(where).fetch().then(config => { + if (config) { + return config.toJSON(); + } + }); if (!data) { return null; @@ -95,7 +99,11 @@ module.exports = { let data = strapi.models['core_store'].orm === 'mongoose' ? await strapi.models['core_store'].findOne(where) - : await strapi.models['core_store'].forge(where).fetch().then(config => config.toJSON()); + : await strapi.models['core_store'].forge(where).fetch().then(config => { + if (config) { + return config.toJSON(); + } + }); if (data) { Object.assign(data, { @@ -150,7 +158,7 @@ CREATE TABLE ${quote}${Model.tableName || Model.collectionName}${quote} ( value text, environment text, type text, - flag text + tag text ); ALTER TABLE ${quote}${Model.tableName || Model.collectionName}${quote} ADD COLUMN ${quote}parent${quote} integer, ADD FOREIGN KEY (${quote}parent${quote}) REFERENCES ${quote}${Model.tableName || Model.collectionName}${quote}(${quote}id${quote}); From 1a7e3b70f6ddaf9f65ad27aedc343e68672d6581 Mon Sep 17 00:00:00 2001 From: Jim Laurie Date: Mon, 12 Feb 2018 17:43:16 +0100 Subject: [PATCH 18/20] Add store data documentation --- .../3.x.x/en/configurations/configurations.md | 80 +++++++++++++++---- 1 file changed, 66 insertions(+), 14 deletions(-) diff --git a/docs/3.x.x/en/configurations/configurations.md b/docs/3.x.x/en/configurations/configurations.md index cadad1a605..053017c511 100644 --- a/docs/3.x.x/en/configurations/configurations.md +++ b/docs/3.x.x/en/configurations/configurations.md @@ -9,8 +9,6 @@ Contains the main configurations relative to your project. **Path —** `./config/application.json`. ```json { - "name": "Default Application", - "description": "This API is going to be awesome!", "favicon": { "path": "favicon.ico", "maxAge": 86400000 @@ -22,8 +20,6 @@ Contains the main configurations relative to your project. } ``` - - `name` (string): Application's name. - - `description` (string): Application's description. - `favicon` - `path` (string): Path to the favicon file. Default value: `favicon.ico`. - `maxAge` (integer): Cache-control max-age directive in ms. Default value: `86400000`. @@ -351,20 +347,76 @@ The syntax is inspired by the [template literals ES2015 specifications](https:// In any JSON configurations files in your project, you can inject dynamic values like this: -**Path —** `./config/application.json`. +**Path —** `./config/environments/production/database.json`. ```json { - "name": "${process.env.APP_NAME}", - "description": "${process.env.APP_DESCRIPTION}", - "favicon": { - "path": "favicon.ico", - "maxAge": 86400000 - }, - "public": { - "path": "./public", - "maxAge": 60000 + "defaultConnection": "default", + "connections": { + "default": { + "connector": "strapi-mongoose", + "settings": { + "client": "mongo", + "uri": "${process.env.DATABASE_URI || ''}", + "host": "${process.env.DATABASE_HOST || '127.0.0.1'}", + "port": "${process.env.DATABASE_PORT || 27017}", + "database": "${process.env.DATABASE_NAME || 'production'}", + "username": "${process.env.DATABASE_USERNAME || ''}", + "password": "${process.env.DATABASE_PASSWORD || ''}" + }, + "options": {} + } } } ``` > Note: You can't execute functions inside the curly braces. Only strings are allowed. + +*** + +## Database configuration + +Configuration files are not multi server friendly. So we create a data store for config you will want to update in production. + +#### Usage + +## Get settings: + +- `environment` (string): Sets the environment you want to store the data in. By default it's current environment (can be an empty string if your config is environment agnostic). +- `type` (string): Sets if your config is for an `api`, `plugin` or `core`. By default it's `core`. +- `name` (string): You have to set the plugin or api name if `type` is `api` or `plugin`. +- `key` (string, required): The name of the key you want to store. + +``` +// strapi.store(object).get(object); + +// create reusable plugin store variable +const pluginStore = strapi.store({ + environment: strapi.config.environment, + type: 'plugin', + name: 'users-permissions' +}); + +await pluginStore.get({key: 'grant'}); +``` + +## Set settings: + + - `value` (any, required): The value you want to store. + + ``` + // strapi.store(object).set(object); + + // create reusable plugin store variable + const pluginStore = strapi.store({ + environment: strapi.config.environment, + type: 'plugin', + name: 'users-permissions' + }); + + await pluginStore.set({ + key: 'grant', + value: { + ... + } +}); + ``` From 9f6a57245b7ddf2d6ff4456adbedff2291bd52c0 Mon Sep 17 00:00:00 2001 From: Luca Perret Date: Mon, 12 Feb 2018 19:08:37 +0100 Subject: [PATCH 19/20] allowing docker volume on node_modules --- packages/strapi-generate-new/lib/before.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/strapi-generate-new/lib/before.js b/packages/strapi-generate-new/lib/before.js index e6069c5e2c..d839d89857 100755 --- a/packages/strapi-generate-new/lib/before.js +++ b/packages/strapi-generate-new/lib/before.js @@ -45,7 +45,7 @@ module.exports = (scope, cb) => { // Ensure we aren't going to inadvertently delete any files. try { const files = fs.readdirSync(scope.rootPath); - if (files.length) { + if (files.length > 1) { return logger.error('`$ strapi new` can only be called in an empty directory.'); } } catch (err) { From 3eb09a54d5e844eae58a5996a37a8f93a093c1ad Mon Sep 17 00:00:00 2001 From: Luca Perret Date: Mon, 12 Feb 2018 19:14:36 +0100 Subject: [PATCH 20/20] use tmp path for temporal connectivity check --- packages/strapi-bookshelf/lib/utils/connectivity.js | 4 ++-- packages/strapi-generate-new/lib/before.js | 9 +++++---- packages/strapi-mongoose/lib/utils/connectivity.js | 4 ++-- packages/strapi-redis/lib/utils/connectivity.js | 4 ++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/strapi-bookshelf/lib/utils/connectivity.js b/packages/strapi-bookshelf/lib/utils/connectivity.js index 70be3ef3b5..92f2b098dc 100644 --- a/packages/strapi-bookshelf/lib/utils/connectivity.js +++ b/packages/strapi-bookshelf/lib/utils/connectivity.js @@ -8,7 +8,7 @@ const path = require('path'); const logger = require('strapi-utils').logger; module.exports = (scope, success, error) => { - const knex = require(path.resolve(`${scope.rootPath}/node_modules/knex`))({ + const knex = require(path.resolve(`${scope.tmpPath}/node_modules/knex`))({ client: scope.client.module, connection: Object.assign({}, scope.database.settings, { user: scope.database.settings.username @@ -18,7 +18,7 @@ module.exports = (scope, success, error) => { knex.raw('select 1+1 as result').then(() => { logger.info('The app has been connected to the database successfully'); knex.destroy(); - execSync(`rm -r ${scope.rootPath}`); + execSync(`rm -r ${scope.tmpPath}`); logger.info('Copying the dashboard...'); diff --git a/packages/strapi-generate-new/lib/before.js b/packages/strapi-generate-new/lib/before.js index d839d89857..66362bc33d 100755 --- a/packages/strapi-generate-new/lib/before.js +++ b/packages/strapi-generate-new/lib/before.js @@ -41,6 +41,7 @@ module.exports = (scope, cb) => { // Make changes to the rootPath where the Strapi project will be created. scope.rootPath = path.resolve(process.cwd(), scope.name || ''); + scope.tmpPath = path.resolve(process.cwd(), 'tmp'); // Ensure we aren't going to inadvertently delete any files. try { @@ -212,14 +213,14 @@ module.exports = (scope, cb) => { }); }), new Promise(resolve => { - let cmd = `npm install --prefix "${scope.rootPath}" ${scope.client.connector}@alpha`; + let cmd = `npm install --prefix "${scope.tmpPath}" ${scope.client.connector}@alpha`; if (scope.client.module) { cmd += ` ${scope.client.module}`; } exec(cmd, () => { if (scope.client.module) { - const lock = require(path.join(`${scope.rootPath}`,`/node_modules/`,`${scope.client.module}/package.json`)); + const lock = require(path.join(`${scope.tmpPath}`,`/node_modules/`,`${scope.client.module}/package.json`)); scope.client.version = lock.version; } @@ -231,9 +232,9 @@ module.exports = (scope, cb) => { Promise.all(asyncFn) .then(() => { try { - require(path.join(`${scope.rootPath}`,`/node_modules/`,`${scope.client.connector}/lib/utils/connectivity.js`))(scope, cb.success, connectionValidation); + require(path.join(`${scope.tmpPath}`,`/node_modules/`,`${scope.client.connector}/lib/utils/connectivity.js`))(scope, cb.success, connectionValidation); } catch(err) { - shell.rm('-r', scope.rootPath); + shell.rm('-r', scope.tmpPath); logger.info('Copying the dashboard...'); cb.success(); } diff --git a/packages/strapi-mongoose/lib/utils/connectivity.js b/packages/strapi-mongoose/lib/utils/connectivity.js index 650e422c3b..efbf699c9b 100644 --- a/packages/strapi-mongoose/lib/utils/connectivity.js +++ b/packages/strapi-mongoose/lib/utils/connectivity.js @@ -8,7 +8,7 @@ const path = require('path'); const logger = require('strapi-utils').logger; module.exports = (scope, success, error) => { - const Mongoose = require(path.resolve(`${scope.rootPath}/node_modules/mongoose`)); + const Mongoose = require(path.resolve(`${scope.tmpPath}/node_modules/mongoose`)); const { username, password } = scope.database.settings const connectOptions = {} @@ -28,7 +28,7 @@ module.exports = (scope, success, error) => { Mongoose.connection.close(); - execSync(`rm -r ${scope.rootPath}`); + execSync(`rm -r ${scope.tmpPath}`); logger.info('Copying the dashboard...'); diff --git a/packages/strapi-redis/lib/utils/connectivity.js b/packages/strapi-redis/lib/utils/connectivity.js index 9cc49c898d..8480390dd3 100644 --- a/packages/strapi-redis/lib/utils/connectivity.js +++ b/packages/strapi-redis/lib/utils/connectivity.js @@ -8,7 +8,7 @@ const path = require('path'); const logger = require('strapi-utils').logger; module.exports = (scope, success, error) => { - const Redis = require(`${scope.rootPath}/node_modules/ioredis`); + const Redis = require(`${scope.tmpPath}/node_modules/ioredis`); const redis = new Redis({ port: scope.database.settings.port, host: scope.database.settings.host, @@ -26,7 +26,7 @@ module.exports = (scope, success, error) => { logger.info('The app has been connected to the database successfully!'); - execSync(`rm -r ${scope.rootPath}`); + execSync(`rm -r ${scope.tmpPath}`); logger.info('Copying the dashboard...');