@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 +11 -0
- package/lib/core/loaders/apis.js +13 -9
- package/lib/core/loaders/index.js +1 -0
- package/lib/core/loaders/sanitizers.js +5 -0
- package/lib/core/registries/sanitizers.js +26 -0
- package/lib/middlewares/body.js +38 -10
- package/lib/services/entity-validator/validators.js +3 -1
- package/lib/utils/update-notifier/index.js +2 -2
- package/package.json +13 -12
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(),
|
package/lib/core/loaders/apis.js
CHANGED
|
@@ -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
|
-
|
|
29
|
-
|
|
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
|
-
|
|
33
|
-
}
|
|
37
|
+
apis[apiName] = api;
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
validateContentTypesUnicity(apis);
|
|
@@ -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;
|
package/lib/middlewares/body.js
CHANGED
|
@@ -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
|
-
|
|
22
|
-
}
|
|
32
|
+
await next();
|
|
33
|
+
} else {
|
|
34
|
+
try {
|
|
35
|
+
await body({ patchKoa: true, ...bodyConfig })(ctx, () => {});
|
|
23
36
|
|
|
24
|
-
|
|
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
|
-
|
|
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 =>
|
|
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
|
|
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(
|
|
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.
|
|
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.
|
|
84
|
-
"@strapi/database": "4.1.
|
|
85
|
-
"@strapi/generate-new": "4.1.
|
|
86
|
-
"@strapi/generators": "4.1.
|
|
87
|
-
"@strapi/logger": "4.1.
|
|
88
|
-
"@strapi/plugin-content-manager": "4.1.
|
|
89
|
-
"@strapi/plugin-content-type-builder": "4.1.
|
|
90
|
-
"@strapi/plugin-email": "4.1.
|
|
91
|
-
"@strapi/plugin-upload": "4.1.
|
|
92
|
-
"@strapi/utils": "4.1.
|
|
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": "
|
|
140
|
+
"gitHead": "ab698015cfc4f43fa0ce2ae94ec59e00a67e4cda"
|
|
140
141
|
}
|