@strapi/strapi 4.0.0-next.6 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/README.md +12 -12
  2. package/bin/strapi.js +41 -60
  3. package/lib/Strapi.js +234 -114
  4. package/lib/commands/build.js +16 -6
  5. package/lib/commands/console.js +1 -1
  6. package/lib/commands/content-types/list.js +22 -0
  7. package/lib/commands/develop.js +17 -18
  8. package/lib/commands/generate-template.js +4 -5
  9. package/lib/commands/hooks/list.js +22 -0
  10. package/lib/commands/middlewares/list.js +22 -0
  11. package/lib/commands/new.js +3 -1
  12. package/lib/commands/policies/list.js +22 -0
  13. package/lib/commands/routes/list.js +28 -0
  14. package/lib/commands/services/list.js +22 -0
  15. package/lib/commands/watchAdmin.js +18 -8
  16. package/lib/container.js +6 -6
  17. package/lib/core/app-configuration/config-loader.js +1 -37
  18. package/lib/core/app-configuration/index.js +6 -46
  19. package/lib/core/app-configuration/load-config-file.js +43 -0
  20. package/lib/core/bootstrap.js +5 -117
  21. package/lib/core/domain/component/index.js +24 -0
  22. package/lib/core/domain/component/validator.js +29 -0
  23. package/lib/core/domain/content-type/index.js +140 -0
  24. package/lib/core/domain/content-type/validator.js +64 -0
  25. package/lib/core/domain/module/index.js +108 -0
  26. package/lib/core/domain/module/validation.js +33 -0
  27. package/lib/core/loaders/admin.js +16 -0
  28. package/lib/core/loaders/apis.js +159 -0
  29. package/lib/core/{load-components.js → loaders/components.js} +5 -7
  30. package/lib/core/loaders/index.js +11 -0
  31. package/lib/core/loaders/middlewares.js +36 -0
  32. package/lib/core/loaders/plugins/get-enabled-plugins.js +116 -0
  33. package/lib/core/loaders/plugins/index.js +123 -0
  34. package/lib/core/loaders/policies.js +28 -0
  35. package/lib/core/loaders/src-index.js +39 -0
  36. package/lib/core/registries/apis.js +29 -0
  37. package/lib/core/{app-configuration/config-provider.js → registries/config.js} +4 -11
  38. package/lib/core/registries/content-types.js +97 -0
  39. package/lib/core/registries/controllers.d.ts +7 -0
  40. package/lib/core/registries/controllers.js +114 -0
  41. package/lib/core/registries/hooks.d.ts +20 -0
  42. package/lib/core/registries/hooks.js +87 -0
  43. package/lib/core/registries/middlewares.d.ts +5 -0
  44. package/lib/core/registries/middlewares.js +89 -0
  45. package/lib/core/registries/modules.js +44 -0
  46. package/lib/core/registries/plugins.js +28 -0
  47. package/lib/core/registries/policies.d.ts +9 -0
  48. package/lib/core/registries/policies.js +89 -0
  49. package/lib/core/registries/services.d.ts +7 -0
  50. package/lib/core/registries/services.js +114 -0
  51. package/lib/core/utils.js +35 -0
  52. package/lib/core-api/controller/collection-type.js +45 -26
  53. package/lib/core-api/controller/index.d.ts +25 -0
  54. package/lib/core-api/controller/index.js +33 -11
  55. package/lib/core-api/controller/single-type.js +29 -15
  56. package/lib/core-api/controller/transform.js +62 -6
  57. package/lib/core-api/routes/index.js +71 -0
  58. package/lib/core-api/service/collection-type.js +43 -21
  59. package/lib/core-api/service/index.d.ts +21 -0
  60. package/lib/core-api/service/index.js +8 -67
  61. package/lib/core-api/service/pagination.js +130 -0
  62. package/lib/core-api/service/single-type.js +17 -19
  63. package/lib/factories.d.ts +48 -0
  64. package/lib/factories.js +84 -0
  65. package/lib/index.d.ts +10 -31
  66. package/lib/index.js +5 -1
  67. package/lib/middlewares/body.js +33 -0
  68. package/lib/middlewares/compression.js +8 -0
  69. package/lib/middlewares/cors.js +58 -0
  70. package/lib/middlewares/errors.js +40 -0
  71. package/lib/middlewares/favicon.js +19 -0
  72. package/lib/middlewares/index.d.ts +5 -0
  73. package/lib/middlewares/index.js +30 -117
  74. package/lib/middlewares/ip.js +8 -0
  75. package/lib/middlewares/logger.js +27 -0
  76. package/lib/middlewares/powered-by.js +20 -0
  77. package/lib/middlewares/public/index.js +98 -73
  78. package/lib/middlewares/query.js +46 -0
  79. package/lib/middlewares/response-time.js +15 -0
  80. package/lib/middlewares/responses.js +19 -0
  81. package/lib/middlewares/security.js +51 -0
  82. package/lib/middlewares/session/index.js +6 -6
  83. package/lib/migrations/draft-publish.js +57 -0
  84. package/lib/services/auth/index.js +87 -0
  85. package/lib/services/core-store.js +64 -51
  86. package/lib/services/cron.js +54 -0
  87. package/lib/services/entity-service/attributes/index.js +31 -0
  88. package/lib/services/entity-service/attributes/transforms.js +20 -0
  89. package/lib/services/entity-service/components.js +39 -15
  90. package/lib/services/entity-service/index.d.ts +91 -0
  91. package/lib/services/entity-service/index.js +120 -59
  92. package/lib/services/entity-service/params.js +52 -94
  93. package/lib/services/entity-validator/index.js +76 -43
  94. package/lib/services/entity-validator/validators.js +129 -43
  95. package/lib/services/errors.js +77 -0
  96. package/lib/{core → services}/fs.js +10 -2
  97. package/lib/services/metrics/index.js +41 -38
  98. package/lib/services/metrics/sender.js +2 -2
  99. package/lib/services/server/admin-api.js +14 -0
  100. package/lib/services/server/api.js +36 -0
  101. package/lib/services/server/compose-endpoint.js +141 -0
  102. package/lib/services/server/content-api.js +16 -0
  103. package/lib/{server.js → services/server/http-server.js} +0 -0
  104. package/lib/services/server/index.js +127 -0
  105. package/lib/services/server/koa.js +64 -0
  106. package/lib/services/server/middleware.js +122 -0
  107. package/lib/services/server/policy.js +32 -0
  108. package/lib/services/server/register-middlewares.js +110 -0
  109. package/lib/services/server/register-routes.js +106 -0
  110. package/lib/services/server/routing.js +120 -0
  111. package/lib/services/utils/upload-files.js +1 -1
  112. package/lib/services/webhook-runner.js +1 -1
  113. package/lib/utils/ee.js +3 -3
  114. package/lib/utils/get-dirs.js +17 -0
  115. package/lib/utils/index.js +2 -0
  116. package/lib/utils/is-initialized.js +1 -1
  117. package/lib/utils/run-checks.js +0 -15
  118. package/lib/utils/signals.js +24 -0
  119. package/lib/utils/startup-logger.js +2 -2
  120. package/lib/utils/update-notifier/index.js +3 -2
  121. package/package.json +93 -96
  122. package/lib/commands/generate.js +0 -76
  123. package/lib/core/index.js +0 -17
  124. package/lib/core/load-apis.js +0 -20
  125. package/lib/core/load-extensions.js +0 -71
  126. package/lib/core/load-functions.js +0 -21
  127. package/lib/core/load-middlewares.js +0 -130
  128. package/lib/core/load-modules.js +0 -55
  129. package/lib/core/load-plugins.js +0 -68
  130. package/lib/core/load-policies.js +0 -36
  131. package/lib/core/walk.js +0 -27
  132. package/lib/core-api/index.js +0 -39
  133. package/lib/load/check-reserved-filename.js +0 -10
  134. package/lib/load/load-config-files.js +0 -22
  135. package/lib/load/require-file-parse.js +0 -15
  136. package/lib/middlewares/boom/defaults.json +0 -5
  137. package/lib/middlewares/boom/index.js +0 -147
  138. package/lib/middlewares/cors/index.js +0 -66
  139. package/lib/middlewares/cron/defaults.json +0 -5
  140. package/lib/middlewares/cron/index.js +0 -43
  141. package/lib/middlewares/favicon/defaults.json +0 -7
  142. package/lib/middlewares/favicon/index.js +0 -32
  143. package/lib/middlewares/gzip/defaults.json +0 -6
  144. package/lib/middlewares/gzip/index.js +0 -19
  145. package/lib/middlewares/helmet/defaults.json +0 -18
  146. package/lib/middlewares/helmet/index.js +0 -9
  147. package/lib/middlewares/ip/defaults.json +0 -7
  148. package/lib/middlewares/ip/index.js +0 -25
  149. package/lib/middlewares/language/defaults.json +0 -9
  150. package/lib/middlewares/language/index.js +0 -40
  151. package/lib/middlewares/logger/defaults.json +0 -5
  152. package/lib/middlewares/logger/index.js +0 -37
  153. package/lib/middlewares/parser/defaults.json +0 -11
  154. package/lib/middlewares/parser/index.js +0 -71
  155. package/lib/middlewares/poweredBy/defaults.json +0 -5
  156. package/lib/middlewares/poweredBy/index.js +0 -16
  157. package/lib/middlewares/public/defaults.json +0 -8
  158. package/lib/middlewares/responseTime/defaults.json +0 -5
  159. package/lib/middlewares/responseTime/index.js +0 -25
  160. package/lib/middlewares/responses/defaults.json +0 -5
  161. package/lib/middlewares/responses/index.js +0 -18
  162. package/lib/middlewares/router/defaults.json +0 -7
  163. package/lib/middlewares/router/index.js +0 -64
  164. package/lib/middlewares/router/utils/composeEndpoint.js +0 -25
  165. package/lib/middlewares/router/utils/routerChecker.js +0 -92
  166. package/lib/utils/get-prefixed-dependencies.js +0 -7
@@ -1,98 +1,123 @@
1
1
  'use strict';
2
2
 
3
- /**
4
- * Module dependencies
5
- */
6
-
7
- // Node.js core.
8
3
  const fs = require('fs');
9
4
  const path = require('path');
10
5
  const stream = require('stream');
11
6
  const _ = require('lodash');
7
+ const { defaultsDeep } = require('lodash/fp');
12
8
  const koaStatic = require('koa-static');
13
9
  const utils = require('../../utils');
14
10
  const serveStatic = require('./serve-static');
15
11
 
12
+ const defaults = {
13
+ maxAge: 60000,
14
+ defaultIndex: true,
15
+ };
16
+
16
17
  /**
17
- * Public assets hook
18
+ * @type {import('../').MiddlewareFactory}
18
19
  */
20
+ module.exports = (config, { strapi }) => {
21
+ const { defaultIndex, maxAge } = defaultsDeep(defaults, config);
19
22
 
20
- module.exports = strapi => {
21
- return {
22
- /**
23
- * Initialize the hook
24
- */
25
-
26
- async initialize() {
27
- const { defaultIndex, maxAge, path: publicPath } = strapi.config.middleware.settings.public;
28
- const staticDir = path.resolve(strapi.dir, publicPath || strapi.config.paths.static);
23
+ if (defaultIndex === true) {
24
+ const index = fs.readFileSync(path.join(__dirname, 'index.html'), 'utf8');
29
25
 
30
- if (defaultIndex === true) {
31
- const index = fs.readFileSync(path.join(__dirname, 'index.html'), 'utf8');
26
+ const serveIndexPage = async (ctx, next) => {
27
+ // defer rendering of strapi index page
28
+ await next();
32
29
 
33
- const serveIndexPage = async (ctx, next) => {
34
- // defer rendering of strapi index page
35
- await next();
36
- if (ctx.body != null || ctx.status !== 404) return;
30
+ if (ctx.body != null || ctx.status !== 404) return;
37
31
 
38
- ctx.url = 'index.html';
39
- const isInitialized = await utils.isInitialized(strapi);
40
- const data = {
41
- serverTime: new Date().toUTCString(),
42
- isInitialized,
43
- ..._.pick(strapi, [
44
- 'config.info.version',
45
- 'config.info.name',
46
- 'config.admin.url',
47
- 'config.server.url',
48
- 'config.environment',
49
- 'config.serveAdminPanel',
50
- ]),
51
- };
52
- const content = _.template(index)(data);
53
- const body = stream.Readable({
54
- read() {
55
- this.push(Buffer.from(content));
56
- this.push(null);
57
- },
58
- });
59
- // Serve static.
60
- ctx.type = 'html';
61
- ctx.body = body;
62
- };
63
-
64
- strapi.router.get('/', serveIndexPage);
65
- strapi.router.get('/index.html', serveIndexPage);
66
- strapi.router.get(
67
- '/assets/images/(.*)',
68
- serveStatic(path.resolve(__dirname, 'assets/images'), { maxage: maxAge, defer: true })
69
- );
70
- }
32
+ ctx.url = 'index.html';
33
+ const isInitialized = await utils.isInitialized(strapi);
34
+ const data = {
35
+ serverTime: new Date().toUTCString(),
36
+ isInitialized,
37
+ ..._.pick(strapi, [
38
+ 'config.info.version',
39
+ 'config.info.name',
40
+ 'config.admin.url',
41
+ 'config.server.url',
42
+ 'config.environment',
43
+ 'config.serveAdminPanel',
44
+ ]),
45
+ };
46
+ const content = _.template(index)(data);
47
+ const body = stream.Readable({
48
+ read() {
49
+ this.push(Buffer.from(content));
50
+ this.push(null);
51
+ },
52
+ });
53
+ // Serve static.
54
+ ctx.type = 'html';
55
+ ctx.body = body;
56
+ };
71
57
 
72
- // serve files in public folder unless a sub router renders something else
73
- strapi.router.get(
74
- '/(.*)',
75
- koaStatic(staticDir, {
58
+ strapi.server.routes([
59
+ {
60
+ method: 'GET',
61
+ path: '/',
62
+ handler: serveIndexPage,
63
+ config: { auth: false },
64
+ },
65
+ {
66
+ method: 'GET',
67
+ path: '/index.html',
68
+ handler: serveIndexPage,
69
+ config: { auth: false },
70
+ },
71
+ {
72
+ method: 'GET',
73
+ path: '/assets/images/(.*)',
74
+ handler: serveStatic(path.resolve(__dirname, 'assets/images'), {
76
75
  maxage: maxAge,
77
76
  defer: true,
78
- })
79
- );
77
+ }),
78
+ config: { auth: false },
79
+ },
80
+ {
81
+ method: 'GET',
82
+ path: '/(.*)',
83
+ handler: koaStatic(strapi.dirs.public, {
84
+ maxage: maxAge,
85
+ defer: true,
86
+ }),
87
+ config: { auth: false },
88
+ },
89
+ ]);
90
+ }
80
91
 
81
- if (!strapi.config.serveAdminPanel) return;
92
+ if (!strapi.config.serveAdminPanel) return async (ctx, next) => next();
82
93
 
83
- const buildDir = path.resolve(strapi.dir, 'build');
84
- const serveAdmin = ctx => {
85
- ctx.type = 'html';
86
- ctx.body = fs.createReadStream(path.join(buildDir + '/index.html'));
87
- };
94
+ const buildDir = path.resolve(strapi.dirs.root, 'build');
95
+ const serveAdmin = async (ctx, next) => {
96
+ await next();
88
97
 
89
- strapi.router.get(
90
- `${strapi.config.admin.path}/*`,
91
- serveStatic(buildDir, { maxage: maxAge, defer: false, index: 'index.html' })
92
- );
98
+ if (ctx.method !== 'HEAD' && ctx.method !== 'GET') {
99
+ return;
100
+ }
93
101
 
94
- strapi.router.get(`${strapi.config.admin.path}`, serveAdmin);
95
- strapi.router.get(`${strapi.config.admin.path}/*`, serveAdmin);
96
- },
102
+ if (ctx.body != null || ctx.status !== 404) {
103
+ return;
104
+ }
105
+
106
+ ctx.type = 'html';
107
+ ctx.body = fs.createReadStream(path.join(buildDir + '/index.html'));
97
108
  };
109
+
110
+ strapi.server.routes([
111
+ {
112
+ method: 'GET',
113
+ path: `${strapi.config.admin.path}/:path*`,
114
+ handler: [
115
+ serveAdmin,
116
+ serveStatic(buildDir, { maxage: maxAge, defer: false, index: 'index.html' }),
117
+ ],
118
+ config: { auth: false },
119
+ },
120
+ ]);
121
+
122
+ return null;
98
123
  };
@@ -0,0 +1,46 @@
1
+ 'use strict';
2
+
3
+ const { defaultsDeep } = require('lodash/fp');
4
+ const qs = require('qs');
5
+
6
+ const defaults = {
7
+ strictNullHandling: true,
8
+ arrayLimit: 100,
9
+ depth: 20,
10
+ };
11
+
12
+ /**
13
+ * Body parser hook
14
+ */
15
+ const addQsParser = (app, settings) => {
16
+ Object.defineProperty(app.request, 'query', {
17
+ configurable: false,
18
+ enumerable: true,
19
+ /*
20
+ * Get parsed query-string.
21
+ */
22
+ get() {
23
+ const qstr = this.querystring;
24
+ const cache = (this._querycache = this._querycache || {});
25
+ return cache[qstr] || (cache[qstr] = qs.parse(qstr, settings));
26
+ },
27
+
28
+ /*
29
+ * Set query-string as an object.
30
+ */
31
+ set(obj) {
32
+ this.querystring = qs.stringify(obj);
33
+ },
34
+ });
35
+
36
+ return app;
37
+ };
38
+
39
+ /**
40
+ * @type {import('./').MiddlewareFactory}
41
+ */
42
+ module.exports = (config, { strapi }) => {
43
+ addQsParser(strapi.server.app, defaultsDeep(defaults, config));
44
+
45
+ return null;
46
+ };
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * @type {import('./').MiddlewareFactory}
5
+ */
6
+ module.exports = () => {
7
+ return async (ctx, next) => {
8
+ const start = Date.now();
9
+
10
+ await next();
11
+
12
+ const delta = Math.ceil(Date.now() - start);
13
+ ctx.set('X-Response-Time', delta + 'ms');
14
+ };
15
+ };
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ const { prop, isFunction } = require('lodash/fp');
4
+
5
+ /**
6
+ * @type {import('./').MiddlewareFactory}
7
+ */
8
+ module.exports = (config = {}) => {
9
+ return async (ctx, next) => {
10
+ await next();
11
+
12
+ const status = ctx.status;
13
+ const handler = prop(`handlers.${status}`, config);
14
+
15
+ if (isFunction(handler)) {
16
+ await handler(ctx);
17
+ }
18
+ };
19
+ };
@@ -0,0 +1,51 @@
1
+ 'use strict';
2
+
3
+ const { defaultsDeep, merge } = require('lodash/fp');
4
+ const helmet = require('koa-helmet');
5
+
6
+ const defaults = {
7
+ crossOriginEmbedderPolicy: false,
8
+ crossOriginOpenerPolicy: false,
9
+ crossOriginResourcePolicy: false,
10
+ originAgentCluster: false,
11
+ contentSecurityPolicy: {
12
+ useDefaults: true,
13
+ directives: {
14
+ 'connect-src': ["'self'", 'https:'],
15
+ 'img-src': ["'self'", 'data:', 'blob:'],
16
+ 'media-src': ["'self'", 'data:', 'blob:'],
17
+ upgradeInsecureRequests: null,
18
+ },
19
+ },
20
+ xssFilter: false,
21
+ hsts: {
22
+ maxAge: 31536000,
23
+ includeSubDomains: true,
24
+ },
25
+ frameguard: {
26
+ action: 'sameorigin',
27
+ },
28
+ };
29
+
30
+ /**
31
+ * @type {import('./').MiddlewareFactory}
32
+ */
33
+ module.exports = config => (ctx, next) => {
34
+ let helmetConfig = defaultsDeep(defaults, config);
35
+
36
+ if (
37
+ ctx.method === 'GET' &&
38
+ ['/graphql', '/documentation'].some(str => ctx.path.startsWith(str))
39
+ ) {
40
+ helmetConfig = merge(helmetConfig, {
41
+ contentSecurityPolicy: {
42
+ directives: {
43
+ 'script-src': ["'self'", "'unsafe-inline'", 'cdn.jsdelivr.net'],
44
+ 'img-src': ["'self'", 'data:', 'cdn.jsdelivr.net', 'strapi.io'],
45
+ },
46
+ },
47
+ });
48
+ }
49
+
50
+ return helmet(helmetConfig)(ctx, next);
51
+ };
@@ -9,7 +9,7 @@ const session = require('koa-session');
9
9
  */
10
10
  module.exports = strapi => {
11
11
  const requireStore = store => {
12
- return require(path.resolve(strapi.config.appPath, 'node_modules', 'koa-' + store));
12
+ return require(path.resolve(strapi.dirs.root, 'node_modules', 'koa-' + store));
13
13
  };
14
14
 
15
15
  const defineStore = session => {
@@ -93,7 +93,7 @@ module.exports = strapi => {
93
93
 
94
94
  return {
95
95
  initialize() {
96
- strapi.app.keys = strapi.config.get('middleware.settings.session.secretKeys');
96
+ strapi.server.app.keys = strapi.config.get('middleware.settings.session.secretKeys');
97
97
 
98
98
  if (
99
99
  _.has(strapi.config.middleware.settings.session, 'client') &&
@@ -112,8 +112,8 @@ module.exports = strapi => {
112
112
  strapi.config.middleware.settings.session
113
113
  );
114
114
 
115
- strapi.app.use(session(options, strapi.app));
116
- strapi.app.use((ctx, next) => {
115
+ strapi.server.use(session(options, strapi.server.app));
116
+ strapi.server.use((ctx, next) => {
117
117
  ctx.state = ctx.state || {};
118
118
  ctx.state.session = ctx.session || {};
119
119
 
@@ -127,8 +127,8 @@ module.exports = strapi => {
127
127
  ) {
128
128
  const options = _.assign(strapi.config.middleware.settings.session);
129
129
 
130
- strapi.app.use(session(options, strapi.app));
131
- strapi.app.use((ctx, next) => {
130
+ strapi.server.use(session(options, strapi.server.app));
131
+ strapi.server.use((ctx, next) => {
132
132
  ctx.state = ctx.state || {};
133
133
  ctx.state.session = ctx.session || {};
134
134
 
@@ -0,0 +1,57 @@
1
+ 'use strict';
2
+
3
+ const { hasDraftAndPublish } = require('@strapi/utils').contentTypes;
4
+
5
+ const enableDraftAndPublish = async ({ oldContentTypes, contentTypes }) => {
6
+ if (!oldContentTypes) {
7
+ return;
8
+ }
9
+ // run the after content types migrations
10
+
11
+ for (const uid in contentTypes) {
12
+ if (!oldContentTypes[uid]) {
13
+ continue;
14
+ }
15
+
16
+ const oldContentType = oldContentTypes[uid];
17
+ const contentType = contentTypes[uid];
18
+
19
+ // if d&p was enabled set publishedAt to eq createdAt
20
+ if (!hasDraftAndPublish(oldContentType) && hasDraftAndPublish(contentType)) {
21
+ const qb = strapi.db.queryBuilder(uid);
22
+ await qb
23
+ .update({ published_at: qb.ref('created_at') })
24
+ .where({ published_at: null })
25
+ .execute();
26
+ }
27
+ }
28
+ };
29
+
30
+ const disableDraftAndPublish = async ({ oldContentTypes, contentTypes }) => {
31
+ if (!oldContentTypes) {
32
+ return;
33
+ }
34
+
35
+ for (const uid in contentTypes) {
36
+ if (!oldContentTypes[uid]) {
37
+ continue;
38
+ }
39
+
40
+ const oldContentType = oldContentTypes[uid];
41
+ const contentType = contentTypes[uid];
42
+
43
+ // if d&p was disabled remove unpublish content before sync
44
+ if (hasDraftAndPublish(oldContentType) && !hasDraftAndPublish(contentType)) {
45
+ await strapi.db
46
+ .queryBuilder(uid)
47
+ .delete()
48
+ .where({ published_at: null })
49
+ .execute();
50
+ }
51
+ }
52
+ };
53
+
54
+ module.exports = {
55
+ enable: enableDraftAndPublish,
56
+ disable: disableDraftAndPublish,
57
+ };
@@ -0,0 +1,87 @@
1
+ 'use strict';
2
+
3
+ const { strict: assert } = require('assert');
4
+ const { has, prop } = require('lodash/fp');
5
+
6
+ const { UnauthorizedError } = require('@strapi/utils').errors;
7
+
8
+ const INVALID_STRATEGY_MSG =
9
+ 'Invalid auth strategy. Expecting an object with properties {name: string, authenticate: function, verify: function}';
10
+
11
+ const validStrategy = strategy => {
12
+ assert(has('authenticate', strategy), INVALID_STRATEGY_MSG);
13
+ assert(typeof strategy.authenticate === 'function', INVALID_STRATEGY_MSG);
14
+
15
+ if (has('verify', strategy)) {
16
+ assert(typeof strategy.verify === 'function', INVALID_STRATEGY_MSG);
17
+ }
18
+ };
19
+
20
+ const createAuthentication = () => {
21
+ const strategies = {};
22
+
23
+ return {
24
+ register(type, strategy) {
25
+ validStrategy(strategy);
26
+
27
+ if (!strategies[type]) {
28
+ strategies[type] = [];
29
+ }
30
+
31
+ strategies[type].push(strategy);
32
+
33
+ return this;
34
+ },
35
+ async authenticate(ctx, next) {
36
+ const { route } = ctx.state;
37
+
38
+ // use route strategy
39
+ const config = prop('config.auth', route);
40
+
41
+ if (config === false) {
42
+ return next();
43
+ }
44
+
45
+ const strategiesToUse = strategies[route.info.type];
46
+
47
+ for (const strategy of strategiesToUse) {
48
+ const result = await strategy.authenticate(ctx);
49
+
50
+ const { authenticated = false, error = null, credentials } = result || {};
51
+
52
+ if (error !== null) {
53
+ return ctx.unauthorized(error);
54
+ }
55
+
56
+ if (authenticated) {
57
+ ctx.state.isAuthenticated = true;
58
+ ctx.state.auth = {
59
+ strategy,
60
+ credentials,
61
+ };
62
+
63
+ return next();
64
+ }
65
+ }
66
+
67
+ return ctx.unauthorized('Missing or invalid credentials');
68
+ },
69
+ async verify(auth, config = {}) {
70
+ if (config === false) {
71
+ return;
72
+ }
73
+
74
+ if (!auth) {
75
+ throw new UnauthorizedError();
76
+ }
77
+
78
+ if (typeof auth.strategy.verify === 'function') {
79
+ return auth.strategy.verify(auth, config);
80
+ }
81
+
82
+ return;
83
+ },
84
+ };
85
+ };
86
+
87
+ module.exports = createAuthentication;
@@ -22,21 +22,37 @@ const coreStoreModel = {
22
22
  },
23
23
  };
24
24
 
25
- const createCoreStore = ({ environment: defaultEnv, db }) => {
26
- return (source = {}) => {
27
- async function get(params = {}) {
28
- const { key, environment = defaultEnv, type = 'core', name = '', tag = '' } = Object.assign(
29
- {},
30
- source,
31
- params
32
- );
25
+ const createCoreStore = ({ db }) => {
26
+ const mergeParams = (defaultParams, params) => {
27
+ return {
28
+ ...defaultParams,
29
+ ...params,
30
+ };
31
+ };
32
+
33
+ const store = function(defaultParams = {}) {
34
+ return {
35
+ get: params => store.get(mergeParams(defaultParams, params)),
36
+ set: params => store.set(mergeParams(defaultParams, params)),
37
+ delete: params => store.delete(mergeParams(defaultParams, params)),
38
+ };
39
+ };
40
+
41
+ Object.assign(store, {
42
+ /**
43
+ * Get value from the core store
44
+ * @param {Object} params
45
+ * @returns {*}
46
+ */
47
+ async get(params = {}) {
48
+ const { key, type = 'core', environment, name, tag } = params;
33
49
 
34
50
  const prefix = `${type}${name ? `_${name}` : ''}`;
35
51
 
36
52
  const where = {
37
53
  key: `${prefix}_${key}`,
38
- environment,
39
- tag,
54
+ environment: environment || null,
55
+ tag: tag || null,
40
56
  };
41
57
 
42
58
  const data = await db.query('strapi::core-store').findOne({ where });
@@ -57,73 +73,70 @@ const createCoreStore = ({ environment: defaultEnv, db }) => {
57
73
  return new Date(data.value);
58
74
  }
59
75
  } else if (data.type === 'number') {
60
- return parseFloat(data.value);
76
+ return Number(data.value);
61
77
  } else {
62
78
  return null;
63
79
  }
64
- }
80
+ },
65
81
 
66
- async function set(params = {}) {
67
- const { key, value, environment = defaultEnv, type, name, tag = '' } = Object.assign(
68
- {},
69
- source,
70
- params
71
- );
82
+ /**
83
+ * Set value in the core store
84
+ * @param {Object} params
85
+ * @returns {*}
86
+ */
87
+ async set(params = {}) {
88
+ const { key, value, type, environment, name, tag } = params;
72
89
 
73
90
  const prefix = `${type}${name ? `_${name}` : ''}`;
74
91
 
75
92
  const where = {
76
93
  key: `${prefix}_${key}`,
77
- environment,
78
- tag,
94
+ environment: environment || null,
95
+ tag: tag || null,
79
96
  };
80
97
 
81
98
  const data = await db.query('strapi::core-store').findOne({ where });
82
99
 
83
100
  if (data) {
84
- Object.assign(data, {
85
- value: JSON.stringify(value) || value.toString(),
86
- type: (typeof value).toString(),
101
+ return db.query('strapi::core-store').update({
102
+ where: { id: data.id },
103
+ data: {
104
+ value: JSON.stringify(value) || value.toString(),
105
+ type: typeof value,
106
+ },
87
107
  });
108
+ }
88
109
 
89
-
90
-
91
- await db.query('strapi::core-store').update({ where: { id: data.id }, data });
92
- } else {
93
- const data = Object.assign({}, where, {
110
+ return db.query('strapi::core-store').create({
111
+ data: {
112
+ ...where,
94
113
  value: JSON.stringify(value) || value.toString(),
95
- type: (typeof value).toString(),
96
- tag,
97
- });
98
-
99
- await db.query('strapi::core-store').create({ data });
100
- }
101
- }
114
+ type: typeof value,
115
+ },
116
+ });
117
+ },
102
118
 
103
- async function deleteFn(params = {}) {
104
- const { key, environment = defaultEnv, type, name, tag = '' } = Object.assign(
105
- {},
106
- source,
107
- params
108
- );
119
+ /**
120
+ * Deletes a value from the core store
121
+ * @param {Object} params
122
+ * @returns {*}
123
+ */
124
+ async delete(params = {}) {
125
+ const { key, environment, type, name, tag } = params;
109
126
 
110
127
  const prefix = `${type}${name ? `_${name}` : ''}`;
111
128
 
112
129
  const where = {
113
130
  key: `${prefix}_${key}`,
114
- environment,
115
- tag,
131
+ environment: environment || null,
132
+ tag: tag || null,
116
133
  };
117
134
 
118
- await db.query('strapi::core-store').delete({ where });
119
- }
135
+ return db.query('strapi::core-store').delete({ where });
136
+ },
137
+ });
120
138
 
121
- return {
122
- get,
123
- set,
124
- delete: deleteFn,
125
- };
126
- };
139
+ return store;
127
140
  };
128
141
 
129
142
  module.exports = {