@strapi/strapi 4.0.0-next.9 → 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 (140) hide show
  1. package/README.md +12 -12
  2. package/bin/strapi.js +32 -5
  3. package/lib/Strapi.js +140 -72
  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 +14 -15
  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 -9
  16. package/lib/core/app-configuration/index.js +3 -19
  17. package/lib/core/bootstrap.js +3 -34
  18. package/lib/core/domain/content-type/index.js +3 -7
  19. package/lib/core/domain/module/index.js +8 -6
  20. package/lib/core/domain/module/validation.js +1 -4
  21. package/lib/core/loaders/admin.js +2 -2
  22. package/lib/core/loaders/apis.js +7 -7
  23. package/lib/core/loaders/components.js +3 -5
  24. package/lib/core/loaders/index.js +1 -0
  25. package/lib/core/loaders/middlewares.js +23 -123
  26. package/lib/core/loaders/plugins/get-enabled-plugins.js +48 -14
  27. package/lib/core/loaders/plugins/index.js +30 -14
  28. package/lib/core/loaders/policies.js +1 -1
  29. package/lib/core/loaders/src-index.js +39 -0
  30. package/lib/core/registries/apis.js +2 -16
  31. package/lib/core/registries/content-types.js +50 -6
  32. package/lib/core/registries/controllers.d.ts +7 -0
  33. package/lib/core/registries/controllers.js +74 -3
  34. package/lib/core/registries/hooks.d.ts +20 -0
  35. package/lib/core/registries/hooks.js +87 -0
  36. package/lib/core/registries/middlewares.d.ts +5 -0
  37. package/lib/core/registries/middlewares.js +61 -2
  38. package/lib/core/registries/modules.js +3 -3
  39. package/lib/core/registries/plugins.js +2 -2
  40. package/lib/core/registries/policies.d.ts +9 -0
  41. package/lib/core/registries/policies.js +57 -6
  42. package/lib/core/registries/services.d.ts +7 -0
  43. package/lib/core/registries/services.js +71 -15
  44. package/lib/core-api/controller/collection-type.js +38 -11
  45. package/lib/core-api/controller/index.d.ts +25 -0
  46. package/lib/core-api/controller/index.js +30 -11
  47. package/lib/core-api/controller/single-type.js +26 -7
  48. package/lib/core-api/controller/transform.js +28 -3
  49. package/lib/core-api/routes/index.js +71 -0
  50. package/lib/core-api/service/collection-type.js +22 -27
  51. package/lib/core-api/service/index.d.ts +21 -0
  52. package/lib/core-api/service/index.js +9 -19
  53. package/lib/core-api/service/pagination.js +7 -2
  54. package/lib/core-api/service/single-type.js +17 -20
  55. package/lib/factories.d.ts +48 -0
  56. package/lib/factories.js +84 -0
  57. package/lib/index.d.ts +10 -31
  58. package/lib/index.js +5 -1
  59. package/lib/middlewares/body.js +33 -0
  60. package/lib/middlewares/compression.js +8 -0
  61. package/lib/middlewares/cors.js +58 -0
  62. package/lib/middlewares/errors.js +40 -0
  63. package/lib/middlewares/favicon.js +19 -0
  64. package/lib/middlewares/index.d.ts +5 -0
  65. package/lib/middlewares/index.js +30 -116
  66. package/lib/middlewares/ip.js +8 -0
  67. package/lib/middlewares/logger.js +27 -0
  68. package/lib/middlewares/powered-by.js +20 -0
  69. package/lib/middlewares/public/index.js +98 -73
  70. package/lib/middlewares/query.js +46 -0
  71. package/lib/middlewares/response-time.js +15 -0
  72. package/lib/middlewares/responses.js +19 -0
  73. package/lib/middlewares/security.js +51 -0
  74. package/lib/middlewares/session/index.js +6 -6
  75. package/lib/migrations/draft-publish.js +57 -0
  76. package/lib/services/auth/index.js +87 -0
  77. package/lib/services/core-store.js +64 -49
  78. package/lib/services/cron.js +54 -0
  79. package/lib/services/entity-service/attributes/index.js +31 -0
  80. package/lib/services/entity-service/attributes/transforms.js +20 -0
  81. package/lib/services/entity-service/components.js +39 -15
  82. package/lib/services/entity-service/index.d.ts +91 -0
  83. package/lib/services/entity-service/index.js +118 -60
  84. package/lib/services/entity-service/params.js +48 -81
  85. package/lib/services/entity-validator/index.js +76 -43
  86. package/lib/services/entity-validator/validators.js +129 -43
  87. package/lib/services/errors.js +77 -0
  88. package/lib/services/fs.js +1 -1
  89. package/lib/services/metrics/index.js +38 -36
  90. package/lib/services/server/admin-api.js +14 -0
  91. package/lib/services/server/api.js +36 -0
  92. package/lib/services/server/compose-endpoint.js +141 -0
  93. package/lib/services/server/content-api.js +16 -0
  94. package/lib/{server.js → services/server/http-server.js} +0 -0
  95. package/lib/services/server/index.js +127 -0
  96. package/lib/services/server/koa.js +64 -0
  97. package/lib/services/server/middleware.js +122 -0
  98. package/lib/services/server/policy.js +32 -0
  99. package/lib/services/server/register-middlewares.js +110 -0
  100. package/lib/services/server/register-routes.js +106 -0
  101. package/lib/services/server/routing.js +120 -0
  102. package/lib/services/webhook-runner.js +1 -1
  103. package/lib/utils/ee.js +3 -3
  104. package/lib/utils/get-dirs.js +17 -0
  105. package/lib/utils/index.js +2 -0
  106. package/lib/utils/signals.js +24 -0
  107. package/lib/utils/update-notifier/index.js +2 -1
  108. package/package.json +93 -93
  109. package/lib/core/app-configuration/load-functions.js +0 -28
  110. package/lib/core-api/index.js +0 -39
  111. package/lib/middlewares/boom/defaults.json +0 -5
  112. package/lib/middlewares/boom/index.js +0 -147
  113. package/lib/middlewares/cors/index.js +0 -66
  114. package/lib/middlewares/cron/defaults.json +0 -5
  115. package/lib/middlewares/cron/index.js +0 -43
  116. package/lib/middlewares/favicon/defaults.json +0 -7
  117. package/lib/middlewares/favicon/index.js +0 -32
  118. package/lib/middlewares/gzip/defaults.json +0 -6
  119. package/lib/middlewares/gzip/index.js +0 -19
  120. package/lib/middlewares/helmet/defaults.json +0 -18
  121. package/lib/middlewares/helmet/index.js +0 -9
  122. package/lib/middlewares/ip/defaults.json +0 -7
  123. package/lib/middlewares/ip/index.js +0 -25
  124. package/lib/middlewares/language/defaults.json +0 -9
  125. package/lib/middlewares/language/index.js +0 -40
  126. package/lib/middlewares/logger/defaults.json +0 -5
  127. package/lib/middlewares/logger/index.js +0 -37
  128. package/lib/middlewares/parser/defaults.json +0 -11
  129. package/lib/middlewares/parser/index.js +0 -72
  130. package/lib/middlewares/poweredBy/defaults.json +0 -5
  131. package/lib/middlewares/poweredBy/index.js +0 -16
  132. package/lib/middlewares/public/defaults.json +0 -8
  133. package/lib/middlewares/responseTime/defaults.json +0 -5
  134. package/lib/middlewares/responseTime/index.js +0 -25
  135. package/lib/middlewares/responses/defaults.json +0 -5
  136. package/lib/middlewares/responses/index.js +0 -18
  137. package/lib/middlewares/router/defaults.json +0 -7
  138. package/lib/middlewares/router/index.js +0 -72
  139. package/lib/middlewares/router/utils/compose-endpoint.js +0 -169
  140. package/lib/utils/get-prefixed-dependencies.js +0 -7
@@ -0,0 +1,40 @@
1
+ 'use strict';
2
+
3
+ const { HttpError, ApplicationError } = require('@strapi/utils').errors;
4
+ const {
5
+ formatApplicationError,
6
+ formatHttpError,
7
+ formatInternalError,
8
+ } = require('../services/errors');
9
+
10
+ module.exports = (/* _, { strapi } */) => {
11
+ return async (ctx, next) => {
12
+ try {
13
+ await next();
14
+
15
+ if (!ctx.response._explicitStatus) {
16
+ return ctx.notFound();
17
+ }
18
+ } catch (error) {
19
+ if (error instanceof ApplicationError) {
20
+ const { status, body } = formatApplicationError(error);
21
+ ctx.status = status;
22
+ ctx.body = body;
23
+ return;
24
+ }
25
+
26
+ if (error instanceof HttpError) {
27
+ const { status, body } = formatHttpError(error);
28
+ ctx.status = status;
29
+ ctx.body = body;
30
+ return;
31
+ }
32
+
33
+ strapi.log.error(error);
34
+
35
+ const { status, body } = formatInternalError(error);
36
+ ctx.status = status;
37
+ ctx.body = body;
38
+ }
39
+ };
40
+ };
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ const { resolve } = require('path');
4
+ const { defaultsDeep } = require('lodash/fp');
5
+ const favicon = require('koa-favicon');
6
+
7
+ const defaults = {
8
+ path: 'favicon.ico',
9
+ maxAge: 86400000,
10
+ };
11
+
12
+ /**
13
+ * @type {import('./').MiddlewareFactory}
14
+ */
15
+ module.exports = (config, { strapi }) => {
16
+ const { maxAge, path: faviconPath } = defaultsDeep(defaults, config);
17
+
18
+ return favicon(resolve(strapi.dirs.root, faviconPath), { maxAge });
19
+ };
@@ -0,0 +1,5 @@
1
+ import { Strapi } from '../';
2
+ import { Middleware } from 'koa';
3
+
4
+ export type MiddlewareFactory = (config: any, ctx: { strapi: Strapi }) => Middleware | null;
5
+ export type Middleware = Middleware;
@@ -1,119 +1,33 @@
1
1
  'use strict';
2
2
 
3
- const { uniq, difference, get, isUndefined, merge } = require('lodash');
4
-
5
- const requiredMiddlewares = [
6
- 'responses',
7
- 'router',
8
- 'logger',
9
- 'boom',
10
- 'cors',
11
- 'cron',
12
- 'xframe',
13
- 'xss',
14
- 'public',
15
- 'favicon',
16
- ];
17
-
18
- module.exports = async function() {
19
- /** Utils */
20
- const middlewareConfig = this.config.middleware;
21
-
22
- // check if a middleware exists
23
- const middlewareExists = key => {
24
- return !isUndefined(this.middleware[key]);
25
- };
26
-
27
- // check if a middleware is enabled
28
- const middlewareEnabled = key => {
29
- return (
30
- requiredMiddlewares.includes(key) ||
31
- get(middlewareConfig, ['settings', key, 'enabled'], false) === true
32
- );
33
- };
34
-
35
- // list of enabled middlewares
36
- const enabledMiddlewares = Object.keys(this.middleware).filter(middlewareEnabled);
37
-
38
- // Method to initialize middlewares and emit an event.
39
- const initialize = middlewareKey => {
40
- if (this.middleware[middlewareKey].loaded === true) return;
41
-
42
- const module = this.middleware[middlewareKey].load;
43
-
44
- return new Promise((resolve, reject) => {
45
- const timeout = setTimeout(
46
- () => reject(`(middleware: ${middlewareKey}) is taking too long to load.`),
47
- middlewareConfig.timeout || 1000
48
- );
49
- this.middleware[middlewareKey] = merge(this.middleware[middlewareKey], module);
50
-
51
- Promise.resolve()
52
- .then(() => module.initialize())
53
- .then(() => {
54
- clearTimeout(timeout);
55
- this.middleware[middlewareKey].loaded = true;
56
- resolve();
57
- })
58
- .catch(err => {
59
- clearTimeout(timeout);
60
-
61
- if (err) {
62
- return reject(err);
63
- }
64
- });
65
- });
66
- };
67
-
68
- /**
69
- * Run init functions
70
- */
71
-
72
- // Run beforeInitialize of every middleware
73
- await Promise.all(
74
- enabledMiddlewares.map(key => {
75
- const { beforeInitialize } = this.middleware[key].load;
76
- if (typeof beforeInitialize === 'function') {
77
- return beforeInitialize();
78
- }
79
- })
80
- );
81
-
82
- // run the initialization of an array of middlewares sequentially
83
- const initMiddlewaresSeq = async middlewareArr => {
84
- for (let key of uniq(middlewareArr)) {
85
- await initialize(key);
86
- }
87
- };
88
-
89
- const middlewaresBefore = get(middlewareConfig, 'load.before', [])
90
- .filter(middlewareExists)
91
- .filter(middlewareEnabled);
92
-
93
- const middlewaresAfter = get(middlewareConfig, 'load.after', [])
94
- .filter(middlewareExists)
95
- .filter(middlewareEnabled);
96
-
97
- const middlewaresOrder = get(middlewareConfig, 'load.order', [])
98
- .filter(middlewareExists)
99
- .filter(middlewareEnabled);
100
-
101
- const unspecifiedMiddlewares = difference(
102
- enabledMiddlewares,
103
- middlewaresBefore,
104
- middlewaresOrder,
105
- middlewaresAfter
106
- );
107
-
108
- // before
109
- await initMiddlewaresSeq(middlewaresBefore);
110
-
111
- // ordered // rest of middlewares
112
- await Promise.all([
113
- initMiddlewaresSeq(middlewaresOrder),
114
- Promise.all(unspecifiedMiddlewares.map(initialize)),
115
- ]);
116
-
117
- // after
118
- await initMiddlewaresSeq(middlewaresAfter);
3
+ const compression = require('./compression');
4
+ const cors = require('./cors');
5
+ const errors = require('./errors');
6
+ const favicon = require('./favicon');
7
+ const ip = require('./ip');
8
+ const logger = require('./logger');
9
+ const poweredBy = require('./powered-by');
10
+ const body = require('./body');
11
+ const query = require('./query');
12
+ const responseTime = require('./response-time');
13
+ const responses = require('./responses');
14
+ const security = require('./security');
15
+ // TODO: add back ?
16
+ // session: require('./session'),
17
+ const publicStatic = require('./public');
18
+
19
+ module.exports = {
20
+ errors,
21
+ ip,
22
+ security,
23
+ cors,
24
+ responseTime,
25
+ poweredBy,
26
+ logger,
27
+ compression,
28
+ responses,
29
+ body,
30
+ query,
31
+ favicon,
32
+ public: publicStatic,
119
33
  };
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ const ip = require('koa-ip');
4
+
5
+ /**
6
+ * @type {import('./').MiddlewareFactory}
7
+ */
8
+ module.exports = config => ip(config);
@@ -0,0 +1,27 @@
1
+ 'use strict';
2
+ const chalk = require('chalk');
3
+
4
+ const codeToColor = code => {
5
+ return code >= 500
6
+ ? chalk.red(code)
7
+ : code >= 400
8
+ ? chalk.yellow(code)
9
+ : code >= 300
10
+ ? chalk.cyan(code)
11
+ : code >= 200
12
+ ? chalk.green(code)
13
+ : code;
14
+ };
15
+
16
+ /**
17
+ * @type {import('./').MiddlewareFactory}
18
+ */
19
+ module.exports = (_, { strapi }) => {
20
+ return async (ctx, next) => {
21
+ const start = Date.now();
22
+ await next();
23
+ const delta = Math.ceil(Date.now() - start);
24
+
25
+ strapi.log.http(`${ctx.method} ${ctx.url} (${delta} ms) ${codeToColor(ctx.status)}`);
26
+ };
27
+ };
@@ -0,0 +1,20 @@
1
+ 'use strict';
2
+
3
+ const { defaultsDeep } = require('lodash/fp');
4
+
5
+ const defaults = {
6
+ poweredBy: 'Strapi <strapi.io>',
7
+ };
8
+
9
+ /**
10
+ * @type {import('./').MiddlewareFactory}
11
+ */
12
+ module.exports = config => {
13
+ const { poweredBy } = defaultsDeep(defaults, config);
14
+
15
+ return async (ctx, next) => {
16
+ await next();
17
+
18
+ ctx.set('X-Powered-By', poweredBy);
19
+ };
20
+ };
@@ -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