@strapi/strapi 4.1.10-beta.0 → 4.1.12

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.
package/lib/Strapi.js CHANGED
@@ -37,6 +37,7 @@ const apisRegistry = require('./core/registries/apis');
37
37
  const bootstrap = require('./core/bootstrap');
38
38
  const loaders = require('./core/loaders');
39
39
  const { destroyOnSignal } = require('./utils/signals');
40
+ const sanitizersRegistry = require('./core/registries/sanitizers');
40
41
 
41
42
  // TODO: move somewhere else
42
43
  const draftAndPublishSync = require('./migrations/draft-publish');
@@ -64,6 +65,7 @@ class Strapi {
64
65
  this.container.register('plugins', pluginsRegistry(this));
65
66
  this.container.register('apis', apisRegistry(this));
66
67
  this.container.register('auth', createAuth(this));
68
+ this.container.register('sanitizers', sanitizersRegistry(this));
67
69
 
68
70
  this.dirs = utils.getDirs(rootDir, { strapi: this });
69
71
 
@@ -157,6 +159,10 @@ class Strapi {
157
159
  return this.container.get('auth');
158
160
  }
159
161
 
162
+ get sanitizers() {
163
+ return this.container.get('sanitizers');
164
+ }
165
+
160
166
  async start() {
161
167
  try {
162
168
  if (!this.isLoaded) {
@@ -304,6 +310,10 @@ class Strapi {
304
310
  this.app = await loaders.loadSrcIndex(this);
305
311
  }
306
312
 
313
+ async loadSanitizers() {
314
+ await loaders.loadSanitizers(this);
315
+ }
316
+
307
317
  registerInternalHooks() {
308
318
  this.container.get('hooks').set('strapi::content-types.beforeSync', createAsyncParallelHook());
309
319
  this.container.get('hooks').set('strapi::content-types.afterSync', createAsyncParallelHook());
@@ -315,6 +325,7 @@ class Strapi {
315
325
  async register() {
316
326
  await Promise.all([
317
327
  this.loadApp(),
328
+ this.loadSanitizers(),
318
329
  this.loadPlugins(),
319
330
  this.loadAdmin(),
320
331
  this.loadAPIs(),
@@ -6,31 +6,35 @@ const _ = require('lodash');
6
6
  const fse = require('fs-extra');
7
7
  const { isKebabCase } = require('@strapi/utils');
8
8
 
9
- // to handle names with numbers in it we first check if it is already in kebabCase
10
- const normalizeName = name => (isKebabCase(name) ? name : _.kebabCase(name));
11
-
12
9
  const DEFAULT_CONTENT_TYPE = {
13
10
  schema: {},
14
11
  actions: {},
15
12
  lifecycles: {},
16
13
  };
17
14
 
15
+ // to handle names with numbers in it we first check if it is already in kebabCase
16
+ const normalizeName = name => (isKebabCase(name) ? name : _.kebabCase(name));
17
+
18
+ const isDirectory = fd => fd.isDirectory();
19
+ const isDotFile = fd => fd.name.startsWith('.');
20
+
18
21
  module.exports = async strapi => {
19
22
  if (!existsSync(strapi.dirs.api)) {
20
23
  throw new Error('Missing api folder. Please create one at `./src/api`');
21
24
  }
22
25
 
23
- const apisFDs = await fse.readdir(strapi.dirs.api, { withFileTypes: true });
26
+ const apisFDs = await (await fse.readdir(strapi.dirs.api, { withFileTypes: true }))
27
+ .filter(isDirectory)
28
+ .filter(_.negate(isDotFile));
29
+
24
30
  const apis = {};
25
31
 
26
32
  // only load folders
27
33
  for (const apiFD of apisFDs) {
28
- if (apiFD.isDirectory()) {
29
- const apiName = normalizeName(apiFD.name);
30
- const api = await loadAPI(join(strapi.dirs.api, apiFD.name));
34
+ const apiName = normalizeName(apiFD.name);
35
+ const api = await loadAPI(join(strapi.dirs.api, apiFD.name));
31
36
 
32
- apis[apiName] = api;
33
- }
37
+ apis[apiName] = api;
34
38
  }
35
39
 
36
40
  validateContentTypesUnicity(apis);
@@ -8,4 +8,5 @@ module.exports = {
8
8
  loadPolicies: require('./policies'),
9
9
  loadPlugins: require('./plugins'),
10
10
  loadAdmin: require('./admin'),
11
+ loadSanitizers: require('./sanitizers'),
11
12
  };
@@ -0,0 +1,5 @@
1
+ 'use strict';
2
+
3
+ module.exports = strapi => {
4
+ strapi.container.get('sanitizers').set('content-api', { input: [], output: [] });
5
+ };
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ const _ = require('lodash');
4
+
5
+ const sanitizersRegistry = () => {
6
+ const sanitizers = {};
7
+
8
+ return {
9
+ get(path) {
10
+ return _.get(sanitizers, path, []);
11
+ },
12
+ add(path, sanitizer) {
13
+ this.get(path).push(sanitizer);
14
+ return this;
15
+ },
16
+ set(path, value = []) {
17
+ _.set(sanitizers, path, value);
18
+ return this;
19
+ },
20
+ has(path) {
21
+ return _.has(sanitizers, path);
22
+ },
23
+ };
24
+ };
25
+
26
+ module.exports = sanitizersRegistry;
@@ -3,12 +3,23 @@
3
3
  const fse = require('fs-extra');
4
4
  const { defaultsDeep, get } = require('lodash/fp');
5
5
  const body = require('koa-body');
6
+ const mime = require('mime-types');
6
7
 
7
8
  const defaults = {
8
9
  multipart: true,
9
10
  patchKoa: true,
10
11
  };
11
12
 
13
+ function ensureFileMimeType(file) {
14
+ if (!file.type) {
15
+ file.type = mime.lookup(file.name) || 'application/octet-stream';
16
+ }
17
+ }
18
+
19
+ function getFiles(ctx) {
20
+ return get('request.files.files', ctx);
21
+ }
22
+
12
23
  /**
13
24
  * @type {import('./').MiddlewareFactory}
14
25
  */
@@ -18,21 +29,38 @@ module.exports = config => {
18
29
  return async (ctx, next) => {
19
30
  // TODO: find a better way later
20
31
  if (ctx.url === '/graphql') {
21
- return next();
22
- }
32
+ await next();
33
+ } else {
34
+ try {
35
+ await body({ patchKoa: true, ...bodyConfig })(ctx, () => {});
23
36
 
24
- try {
25
- await body({ patchKoa: true, ...bodyConfig })(ctx, next);
26
- } catch (e) {
27
- if ((e || {}).message && e.message.includes('maxFileSize exceeded')) {
28
- return ctx.payloadTooLarge('FileTooBig');
29
- }
37
+ const files = getFiles(ctx);
30
38
 
31
- throw e;
39
+ /**
40
+ * in case the mime-type wasn't sent, Strapi tries to guess it
41
+ * from the file extension, to avoid a corrupt database state
42
+ */
43
+ if (files) {
44
+ if (Array.isArray(files)) {
45
+ files.forEach(ensureFileMimeType);
46
+ } else {
47
+ ensureFileMimeType(files);
48
+ }
49
+ }
50
+
51
+ await next();
52
+ } catch (e) {
53
+ if ((e || {}).message && e.message.includes('maxFileSize exceeded')) {
54
+ return ctx.payloadTooLarge('FileTooBig');
55
+ }
56
+
57
+ throw e;
58
+ }
32
59
  }
33
60
 
61
+ const files = getFiles(ctx);
62
+
34
63
  // clean any file that was uploaded
35
- const files = get('request.files.files', ctx);
36
64
  if (files) {
37
65
  if (Array.isArray(files)) {
38
66
  // not awaiting to not slow the request
@@ -166,7 +166,9 @@ const stringValidator = composeValidators(
166
166
  addUniqueValidator
167
167
  );
168
168
 
169
- const emailValidator = composeValidators(stringValidator, validator => validator.email());
169
+ const emailValidator = composeValidators(stringValidator, validator =>
170
+ validator.email().min(1, '${path} cannot be empty')
171
+ );
170
172
 
171
173
  const uidValidator = composeValidators(stringValidator, validator =>
172
174
  validator.matches(new RegExp('^[A-Za-z0-9-_.~]*$'))
@@ -20,7 +20,7 @@ const boxenOptions = {
20
20
  borderStyle: 'round',
21
21
  };
22
22
 
23
- const geUpdatetMessage = (newVersion, currentVersion) => {
23
+ const getUpdateMessage = (newVersion, currentVersion) => {
24
24
  const currentVersionLog = chalk.dim(currentVersion);
25
25
  const newVersionLog = chalk.green(newVersion);
26
26
  const releaseLink = chalk.bold('https://github.com/strapi/strapi/releases');
@@ -78,7 +78,7 @@ const createUpdateNotifier = strapi => {
78
78
  return;
79
79
  }
80
80
 
81
- const message = boxen(geUpdatetMessage(latestVersion, pkg.version), boxenOptions);
81
+ const message = boxen(getUpdateMessage(latestVersion, pkg.version), boxenOptions);
82
82
  config.set('lastNotification', now);
83
83
  console.log(message);
84
84
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/strapi",
3
- "version": "4.1.10-beta.0",
3
+ "version": "4.1.12",
4
4
  "description": "An open source headless CMS solution to create and manage your own API. It provides a powerful dashboard and features to make your life easier. Databases supported: MySQL, MariaDB, PostgreSQL, SQLite",
5
5
  "keywords": [
6
6
  "strapi",
@@ -80,16 +80,16 @@
80
80
  "dependencies": {
81
81
  "@koa/cors": "3.1.0",
82
82
  "@koa/router": "10.1.1",
83
- "@strapi/admin": "4.1.10-beta.0",
84
- "@strapi/database": "4.1.10-beta.0",
85
- "@strapi/generate-new": "4.1.10-beta.0",
86
- "@strapi/generators": "4.1.10-beta.0",
87
- "@strapi/logger": "4.1.10-beta.0",
88
- "@strapi/plugin-content-manager": "4.1.10-beta.0",
89
- "@strapi/plugin-content-type-builder": "4.1.10-beta.0",
90
- "@strapi/plugin-email": "4.1.10-beta.0",
91
- "@strapi/plugin-upload": "4.1.10-beta.0",
92
- "@strapi/utils": "4.1.10-beta.0",
83
+ "@strapi/admin": "4.1.12",
84
+ "@strapi/database": "4.1.12",
85
+ "@strapi/generate-new": "4.1.12",
86
+ "@strapi/generators": "4.1.12",
87
+ "@strapi/logger": "4.1.12",
88
+ "@strapi/plugin-content-manager": "4.1.12",
89
+ "@strapi/plugin-content-type-builder": "4.1.12",
90
+ "@strapi/plugin-email": "4.1.12",
91
+ "@strapi/plugin-upload": "4.1.12",
92
+ "@strapi/utils": "4.1.12",
93
93
  "bcryptjs": "2.4.3",
94
94
  "boxen": "5.1.2",
95
95
  "chalk": "4.1.2",
@@ -117,6 +117,7 @@
117
117
  "koa-session": "6.2.0",
118
118
  "koa-static": "5.0.0",
119
119
  "lodash": "4.17.21",
120
+ "mime-types": "2.1.35",
120
121
  "node-fetch": "2.6.7",
121
122
  "node-machine-id": "1.1.12",
122
123
  "node-schedule": "2.0.0",
@@ -136,5 +137,5 @@
136
137
  "node": ">=12.22.0 <=16.x.x",
137
138
  "npm": ">=6.0.0"
138
139
  },
139
- "gitHead": "a9082d9a3b26bf0abeb8e45d4507d5329e9ae733"
140
+ "gitHead": "ab698015cfc4f43fa0ce2ae94ec59e00a67e4cda"
140
141
  }