@strapi/strapi 4.11.0-alpha.0 → 4.11.0-beta.1
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/ee/LICENSE.txt +1 -21
- package/lib/Strapi.js +1 -0
- package/lib/commands/actions/export/action.js +2 -4
- package/lib/commands/actions/import/action.js +5 -4
- package/lib/commands/actions/import/command.js +2 -2
- package/lib/commands/actions/transfer/action.js +5 -4
- package/lib/commands/actions/transfer/command.js +3 -3
- package/lib/commands/utils/commander.js +24 -18
- package/lib/commands/utils/data-transfer.js +87 -1
- package/lib/services/entity-service/index.js +45 -12
- package/lib/services/metrics/admin-user-hash.js +1 -1
- package/package.json +15 -15
package/ee/LICENSE.txt
CHANGED
|
@@ -1,21 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
In the event of a direct conflict between the terms of this EE Supplemental License and the terms of the Enterprise Agreement or the Subscription Agreement, as applicable, the terms of this EE Supplemental License will control. Except to the extent modified by this EE Supplemental License, the Enterprise Agreement or the Subscription Agreement, as applicable, remain in full force and effect in accordance with its terms.
|
|
4
|
-
|
|
5
|
-
By using the EE Software, You hereby agree to the below terms and conditions.
|
|
6
|
-
|
|
7
|
-
1. Notwithstanding any terms to the contrary in the Enterprise Agreement or Subscription Agreement, You may copy, modify and publish patches to the EE Software in a production environment (such copies, “Production Copies,” such modifications, “Production Modifications” and such patches, “Production Patches”) if and only if (a) You have agreed to, and are in full compliance with, the Enterprise Agreement or Subscription Agreement, as applicable, and (b) You have a valid license to the EE Software for the correct number of projects. You agree that Strapi and/or its licensors (as applicable) will own all right, title and interest in and to all such Production Copies, Production Modifications and Production Patches. You may display and/or distribute such Production Copies, Production Modifications and Production Patches if and only if (i) You have a valid license to the EE Software for the correct number of projects and (ii) You are in compliance with the Enterprise Agreement or Subscription Agreement, as applicable. You hereby assign to Strapi all right, title and interest in and to all Production Copies, Production Modifications and Production Patches, including all intellectual property rights embodied in or related to the foregoing.
|
|
8
|
-
|
|
9
|
-
2. Notwithstanding the foregoing, You may copy and modify the EE Software solely for development and testing purposes (such copies, “Development Copies” and such modifications, “Development Modifications”) with or without a license to the EE Software if your use is in compliance with this Section 2. You agree that Strapi and/or its licensors (as applicable) will own all right, title and interest in and to all Development Copies and Development Modifications and You hereby assign to Strapi all right, title and interest in and to all Development Copies and Development Modifications, including all intellectual property rights embodied in or related to the foregoing. If You do not have a license to the EE Software, then You further agree as follows:
|
|
10
|
-
|
|
11
|
-
Other than as expressly set forth in this Section 2, You may not (a) copy or modify the EE Software, (b) create derivative works of the EE Software, (c) remove or modify any notice of any patent, copyright, trademark, or other proprietary rights that appear on or in the EE Software, (d) reverse engineer, decompile, translate, disassemble, or discover the source code of all or any portion of the EE Software, (e) publicly display all or any part of the EE Software, (f) distribute, disclose, market, lease, publish, merge, resell, assign, loan, sublicense, rent, or transfer the EE Software to any third party, (g) use the EE Software for any dial-up, remote access, interactive, or other on-line or hosted service, or to provide a service bureau, time share, or other services to third parties, (h) merge the EE Software into another product, (i) disclose the results of any EE Software performance benchmarks or test results to any third party without Strapi’s prior written consent, (j) use any trademarks, logos, service marks, trade names of Strapi, or any portion thereof, without Strapi’s prior written consent, (k) use the EE Software, or any portion thereof, in a manner that does not comply with applicable law, regulations, or governmental orders, or (l) use or store the EE Software on equipment not owned or controlled by Customer.
|
|
12
|
-
|
|
13
|
-
THE EE SOFTWARE IS PROVIDED ON AN “AS IS” BASIS WITHOUT ANY REPRESENTATIONS, WARRANTIES, COVENANTS, OR CONDITIONS OF ANY KIND (EXPRESS OR IMPLIED, STATUTORY OR OTHERWISE), INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, TITLE, FITNESS FOR A PARTICULAR PURPOSE, OR NONINFRINGEMENT. FURTHER, STRAPI DOES NOT REPRESENT OR WARRANT THAT (A) THE ACCESS TO OR USE OF THE EE SOFTWARE WILL BE SECURE, TIMELY, UNINTERRUPTED, ERROR-FREE, OR OPERATE IN COMBINATION WITH ANY OTHER HARDWARE, SOFTWARE, SYSTEM, OR DATA, (B) THE EE SOFTWARE WILL MEET YOUR REQUIREMENTS OR EXPECTATIONS, OR OTHERWISE PRODUCE ANY PARTICULAR RESULTS, (C) ERRORS OR DEFECTS WILL BE CORRECTED, PATCHES OR WORKAROUNDS WILL BE PROVIDED, OR STRAPI WILL DETECT ANY BUG IN THE EE SOFTWARE, (D) THE SOFTWARE IS FREE OF VIRUSES OR OTHER HARMFUL COMPONENTS, OR (E) THIRD-PARTY DISRUPTIONS OR SECURITY BREACHES OF THE EE SOFTWARE WILL BE PREVENTED.
|
|
14
|
-
|
|
15
|
-
STRAPI WILL NOT BE LIABLE FOR ANY LOSS OF PROFITS OR ANY INDIRECT, SPECIAL, INCIDENTAL, RELIANCE, OR CONSEQUENTIAL DAMAGES OF ANY KIND, REGARDLESS OF THE FORM OF ACTION, WHETHER IN CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY, OR OTHERWISE, EVEN IF INFORMED OF THE POSSIBILITY OF SUCH DAMAGES IN ADVANCE.
|
|
16
|
-
|
|
17
|
-
STRAPI’S ENTIRE LIABILITY TO YOU FOR USE OF THE EE SOFTWARE WILL NOT EXCEED $100.
|
|
18
|
-
|
|
19
|
-
3. You are not granted any other rights beyond what is expressly stated herein and in the Enterprise Agreement or Subscription Agreement, as applicable.
|
|
20
|
-
|
|
21
|
-
4. This EE Supplemental License does not apply to Strapi software that is distributed as part of the Strapi Community Edition (CE) (the “CE Software”).
|
|
1
|
+
If you or the company you represent has entered into a written agreement referencing the Enterprise Edition of the Strapi source code available at https://github.com/strapi/strapi, then such agreement applies to your use of the Enterprise Edition of the Strapi Software. If you or the company you represent is using the Enterprise Edition of the Strapi Software in connection with a subscription to our cloud offering, then the agreement you have agreed to with respect to our cloud offering and the licenses included in such agreement apply to your use of the Enterprise Edition of the Strapi Software. Otherwise, the Strapi Enterprise Software License Agreement (found here https://strapi.io/enterprise-terms) applies to your use of the Enterprise Edition of the Strapi Software. BY ACCESSING OR USING THE ENTERPRISE EDITION OF THE STRAPI SOFTWARE, YOU ARE AGREEING TO BE BOUND BY THE RELEVANT REFERENCED AGREEMENT. IF YOU ARE NOT AUTHORIZED TO ACCEPT THESE TERMS ON BEHALF OF THE COMPANY YOU REPRESENT OR IF YOU DO NOT AGREE TO ALL OF THE RELEVANT TERMS AND CONDITIONS REFERENCED AND YOU HAVE NOT OTHERWISE EXECUTED A WRITTEN AGREEMENT WITH STRAPI, YOU ARE NOT AUTHORIZED TO ACCESS OR USE OR ALLOW ANY USER TO ACCESS OR USE ANY PART OF THE ENTERPRISE EDITION OF THE STRAPI SOFTWARE. YOUR ACCESS RIGHTS ARE CONDITIONAL ON YOUR CONSENT TO THE RELEVANT REFERENCED TERMS TO THE EXCLUSION OF ALL OTHER TERMS; IF THE RELEVANT REFERENCED TERMS ARE CONSIDERED AN OFFER BY YOU, ACCEPTANCE IS EXPRESSLY LIMITED TO THE RELEVANT REFERENCED TERMS.
|
package/lib/Strapi.js
CHANGED
|
@@ -255,6 +255,7 @@ class Strapi {
|
|
|
255
255
|
numberOfAllContentTypes: _.size(this.contentTypes), // TODO: V5: This event should be renamed numberOfContentTypes in V5 as the name is already taken to describe the number of content types using i18n.
|
|
256
256
|
numberOfComponents: _.size(this.components),
|
|
257
257
|
numberOfDynamicZones: getNumberOfDynamicZones(),
|
|
258
|
+
environment: strapi.config.environment,
|
|
258
259
|
// TODO: to add back
|
|
259
260
|
// providers: this.config.installedProviders,
|
|
260
261
|
},
|
|
@@ -25,6 +25,7 @@ const {
|
|
|
25
25
|
exitMessageText,
|
|
26
26
|
abortTransfer,
|
|
27
27
|
getTransferTelemetryPayload,
|
|
28
|
+
setSignalHandler,
|
|
28
29
|
} = require('../../utils/data-transfer');
|
|
29
30
|
const { exitWith } = require('../../utils/helpers');
|
|
30
31
|
|
|
@@ -115,10 +116,7 @@ module.exports = async (opts) => {
|
|
|
115
116
|
let outFile;
|
|
116
117
|
try {
|
|
117
118
|
// Abort transfer if user interrupts process
|
|
118
|
-
|
|
119
|
-
process.removeAllListeners(signal);
|
|
120
|
-
process.on(signal, () => abortTransfer({ engine, strapi }));
|
|
121
|
-
});
|
|
119
|
+
setSignalHandler(() => abortTransfer({ engine, strapi }));
|
|
122
120
|
|
|
123
121
|
results = await engine.transfer();
|
|
124
122
|
outFile = results.destination.file.path;
|
|
@@ -21,6 +21,8 @@ const {
|
|
|
21
21
|
exitMessageText,
|
|
22
22
|
abortTransfer,
|
|
23
23
|
getTransferTelemetryPayload,
|
|
24
|
+
setSignalHandler,
|
|
25
|
+
getDiffHandler,
|
|
24
26
|
} = require('../../utils/data-transfer');
|
|
25
27
|
const { exitWith } = require('../../utils/helpers');
|
|
26
28
|
|
|
@@ -111,6 +113,8 @@ module.exports = async (opts) => {
|
|
|
111
113
|
|
|
112
114
|
const { updateLoader } = loadersFactory();
|
|
113
115
|
|
|
116
|
+
engine.onSchemaDiff(getDiffHandler(engine, { force: opts.force, action: 'import' }));
|
|
117
|
+
|
|
114
118
|
progress.on(`stage::start`, ({ stage, data }) => {
|
|
115
119
|
updateLoader(stage, data).start();
|
|
116
120
|
});
|
|
@@ -134,10 +138,7 @@ module.exports = async (opts) => {
|
|
|
134
138
|
let results;
|
|
135
139
|
try {
|
|
136
140
|
// Abort transfer if user interrupts process
|
|
137
|
-
|
|
138
|
-
process.removeAllListeners(signal);
|
|
139
|
-
process.on(signal, () => abortTransfer({ engine, strapi }));
|
|
140
|
-
});
|
|
141
|
+
setSignalHandler(() => abortTransfer({ engine, strapi }));
|
|
141
142
|
|
|
142
143
|
results = await engine.transfer();
|
|
143
144
|
} catch (e) {
|
|
@@ -9,7 +9,7 @@ const {
|
|
|
9
9
|
throttleOption,
|
|
10
10
|
validateExcludeOnly,
|
|
11
11
|
} = require('../../utils/data-transfer');
|
|
12
|
-
const {
|
|
12
|
+
const { getCommanderConfirmMessage, forceOption } = require('../../utils/commander');
|
|
13
13
|
const { getLocalScript, exitWith } = require('../../utils/helpers');
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -88,7 +88,7 @@ module.exports = ({ command }) => {
|
|
|
88
88
|
})
|
|
89
89
|
.hook(
|
|
90
90
|
'preAction',
|
|
91
|
-
|
|
91
|
+
getCommanderConfirmMessage(
|
|
92
92
|
'The import will delete all assets and data in your database. Are you sure you want to proceed?',
|
|
93
93
|
{ failMessage: 'Import process aborted' }
|
|
94
94
|
)
|
|
@@ -22,6 +22,8 @@ const {
|
|
|
22
22
|
exitMessageText,
|
|
23
23
|
abortTransfer,
|
|
24
24
|
getTransferTelemetryPayload,
|
|
25
|
+
setSignalHandler,
|
|
26
|
+
getDiffHandler,
|
|
25
27
|
} = require('../../utils/data-transfer');
|
|
26
28
|
const { exitWith } = require('../../utils/helpers');
|
|
27
29
|
|
|
@@ -146,6 +148,8 @@ module.exports = async (opts) => {
|
|
|
146
148
|
|
|
147
149
|
const { updateLoader } = loadersFactory();
|
|
148
150
|
|
|
151
|
+
engine.onSchemaDiff(getDiffHandler(engine, { force: opts.force, action: 'transfer' }));
|
|
152
|
+
|
|
149
153
|
progress.on(`stage::start`, ({ stage, data }) => {
|
|
150
154
|
updateLoader(stage, data).start();
|
|
151
155
|
});
|
|
@@ -171,10 +175,7 @@ module.exports = async (opts) => {
|
|
|
171
175
|
let results;
|
|
172
176
|
try {
|
|
173
177
|
// Abort transfer if user interrupts process
|
|
174
|
-
|
|
175
|
-
process.removeAllListeners(signal);
|
|
176
|
-
process.on(signal, () => abortTransfer({ engine, strapi }));
|
|
177
|
-
});
|
|
178
|
+
setSignalHandler(() => abortTransfer({ engine, strapi }));
|
|
178
179
|
|
|
179
180
|
results = await engine.transfer();
|
|
180
181
|
} catch (e) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const inquirer = require('inquirer');
|
|
4
4
|
const { Option } = require('commander');
|
|
5
|
-
const {
|
|
5
|
+
const { getCommanderConfirmMessage, forceOption, parseURL } = require('../../utils/commander');
|
|
6
6
|
const {
|
|
7
7
|
getLocalScript,
|
|
8
8
|
exitWith,
|
|
@@ -76,7 +76,7 @@ module.exports = ({ command }) => {
|
|
|
76
76
|
thisCommand.opts().fromToken = answers.fromToken;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
await
|
|
79
|
+
await getCommanderConfirmMessage(
|
|
80
80
|
'The transfer will delete all the local Strapi assets and its database. Are you sure you want to proceed?',
|
|
81
81
|
{ failMessage: 'Transfer process aborted' }
|
|
82
82
|
)(thisCommand);
|
|
@@ -104,7 +104,7 @@ module.exports = ({ command }) => {
|
|
|
104
104
|
thisCommand.opts().toToken = answers.toToken;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
await
|
|
107
|
+
await getCommanderConfirmMessage(
|
|
108
108
|
'The transfer will delete all the remote Strapi assets and its database. Are you sure you want to proceed?',
|
|
109
109
|
{ failMessage: 'Transfer process aborted' }
|
|
110
110
|
)(thisCommand);
|
|
@@ -111,30 +111,35 @@ const promptEncryptionKey = async (thisCommand) => {
|
|
|
111
111
|
* @param {object} options Additional options
|
|
112
112
|
* @param {string|undefined} options.failMessage The message to display when prompt is not confirmed
|
|
113
113
|
*/
|
|
114
|
-
const
|
|
114
|
+
const getCommanderConfirmMessage = (message, { failMessage } = {}) => {
|
|
115
115
|
return async (command) => {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (opts?.force === true) {
|
|
119
|
-
// attempt to mimic the inquirer prompt exactly
|
|
120
|
-
console.log(`${green('?')} ${bold(message)} ${cyan('Yes')}`);
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const answers = await inquirer.prompt([
|
|
125
|
-
{
|
|
126
|
-
type: 'confirm',
|
|
127
|
-
message,
|
|
128
|
-
name: `confirm`,
|
|
129
|
-
default: false,
|
|
130
|
-
},
|
|
131
|
-
]);
|
|
132
|
-
if (!answers.confirm) {
|
|
116
|
+
const confirmed = await confirmMessage(message, { force: command.opts().force });
|
|
117
|
+
if (!confirmed) {
|
|
133
118
|
exitWith(1, failMessage);
|
|
134
119
|
}
|
|
135
120
|
};
|
|
136
121
|
};
|
|
137
122
|
|
|
123
|
+
const confirmMessage = async (message, { force } = {}) => {
|
|
124
|
+
// if we have a force option, respond yes
|
|
125
|
+
if (force === true) {
|
|
126
|
+
// attempt to mimic the inquirer prompt exactly
|
|
127
|
+
console.log(`${green('?')} ${bold(message)} ${cyan('Yes')}`);
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const answers = await inquirer.prompt([
|
|
132
|
+
{
|
|
133
|
+
type: 'confirm',
|
|
134
|
+
message,
|
|
135
|
+
name: `confirm`,
|
|
136
|
+
default: false,
|
|
137
|
+
},
|
|
138
|
+
]);
|
|
139
|
+
|
|
140
|
+
return answers.confirm;
|
|
141
|
+
};
|
|
142
|
+
|
|
138
143
|
const forceOption = new Option(
|
|
139
144
|
'--force',
|
|
140
145
|
`Automatically answer "yes" to all prompts, including potentially destructive requests, and run non-interactively.`
|
|
@@ -146,6 +151,7 @@ module.exports = {
|
|
|
146
151
|
parseURL,
|
|
147
152
|
parseInteger,
|
|
148
153
|
promptEncryptionKey,
|
|
154
|
+
getCommanderConfirmMessage,
|
|
149
155
|
confirmMessage,
|
|
150
156
|
forceOption,
|
|
151
157
|
};
|
|
@@ -12,9 +12,11 @@ const {
|
|
|
12
12
|
createLogger,
|
|
13
13
|
} = require('@strapi/logger');
|
|
14
14
|
const ora = require('ora');
|
|
15
|
+
const { TransferEngineInitializationError } = require('@strapi/data-transfer/dist/engine/errors');
|
|
16
|
+
const { merge } = require('lodash/fp');
|
|
15
17
|
const { readableBytes, exitWith } = require('./helpers');
|
|
16
18
|
const strapi = require('../../index');
|
|
17
|
-
const { getParseListWithChoices, parseInteger } = require('./commander');
|
|
19
|
+
const { getParseListWithChoices, parseInteger, confirmMessage } = require('./commander');
|
|
18
20
|
|
|
19
21
|
const exitMessageText = (process, error = false) => {
|
|
20
22
|
const processCapitalized = process[0].toUpperCase() + process.slice(1);
|
|
@@ -113,6 +115,15 @@ const abortTransfer = async ({ engine, strapi }) => {
|
|
|
113
115
|
return true;
|
|
114
116
|
};
|
|
115
117
|
|
|
118
|
+
const setSignalHandler = async (handler, signals = ['SIGINT', 'SIGTERM', 'SIGQUIT']) => {
|
|
119
|
+
signals.forEach((signal) => {
|
|
120
|
+
// We specifically remove ALL listeners because we have to clear the one added in Strapi bootstrap that has a process.exit
|
|
121
|
+
// TODO: Ideally Strapi bootstrap would not add that listener, and then this could be more flexible and add/remove only what it needs to
|
|
122
|
+
process.removeAllListeners(signal);
|
|
123
|
+
process.on(signal, handler);
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
|
|
116
127
|
const createStrapiInstance = async (opts = {}) => {
|
|
117
128
|
try {
|
|
118
129
|
const appContext = await strapi.compile();
|
|
@@ -257,6 +268,79 @@ const getTransferTelemetryPayload = (engine) => {
|
|
|
257
268
|
};
|
|
258
269
|
};
|
|
259
270
|
|
|
271
|
+
/**
|
|
272
|
+
* Get a transfer engine schema diff handler that confirms with the user before bypassing a schema check
|
|
273
|
+
*/
|
|
274
|
+
const getDiffHandler = (engine, { force, action }) => {
|
|
275
|
+
return async (context, next) => {
|
|
276
|
+
// if we abort here, we need to actually exit the process because of conflict with inquirer prompt
|
|
277
|
+
setSignalHandler(async () => {
|
|
278
|
+
await abortTransfer({ engine, strapi });
|
|
279
|
+
exitWith(1, exitMessageText(action, true));
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
let workflowsStatus;
|
|
283
|
+
const source = 'Schema Integrity';
|
|
284
|
+
|
|
285
|
+
Object.entries(context.diffs).forEach(([uid, diffs]) => {
|
|
286
|
+
for (const diff of diffs) {
|
|
287
|
+
const path = [uid].concat(diff.path).join('.');
|
|
288
|
+
const endPath = diff.path[diff.path.length - 1];
|
|
289
|
+
|
|
290
|
+
// Catch known features
|
|
291
|
+
if (
|
|
292
|
+
uid === 'admin::workflow' ||
|
|
293
|
+
uid === 'admin::workflow-stage' ||
|
|
294
|
+
endPath?.startsWith('strapi_reviewWorkflows_')
|
|
295
|
+
) {
|
|
296
|
+
workflowsStatus = diff.kind;
|
|
297
|
+
}
|
|
298
|
+
// handle generic cases
|
|
299
|
+
else if (diff.kind === 'added') {
|
|
300
|
+
engine.reportWarning(chalk.red(`${chalk.bold(path)} does not exist on source`), source);
|
|
301
|
+
} else if (diff.kind === 'deleted') {
|
|
302
|
+
engine.reportWarning(
|
|
303
|
+
chalk.red(`${chalk.bold(path)} does not exist on destination`),
|
|
304
|
+
source
|
|
305
|
+
);
|
|
306
|
+
} else if (diff.kind === 'modified') {
|
|
307
|
+
engine.reportWarning(chalk.red(`${chalk.bold(path)} has a different data type`), source);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
// output the known feature warnings
|
|
313
|
+
if (workflowsStatus === 'added') {
|
|
314
|
+
engine.reportWarning(chalk.red(`Review workflows feature does not exist on source`), source);
|
|
315
|
+
} else if (workflowsStatus === 'deleted') {
|
|
316
|
+
engine.reportWarning(
|
|
317
|
+
chalk.red(`Review workflows feature does not exist on destination`),
|
|
318
|
+
source
|
|
319
|
+
);
|
|
320
|
+
} else if (workflowsStatus === 'modified') {
|
|
321
|
+
engine.panic(
|
|
322
|
+
new TransferEngineInitializationError('Unresolved differences in schema [review workflows]')
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const confirmed = await confirmMessage(
|
|
327
|
+
'There are differences in schema between the source and destination, and the data listed above will be lost. Are you sure you want to continue?',
|
|
328
|
+
{
|
|
329
|
+
force,
|
|
330
|
+
}
|
|
331
|
+
);
|
|
332
|
+
|
|
333
|
+
// reset handler back to normal
|
|
334
|
+
setSignalHandler(() => abortTransfer({ engine, strapi }));
|
|
335
|
+
|
|
336
|
+
if (confirmed) {
|
|
337
|
+
context.ignoredDiffs = merge(context.diffs, context.ignoredDiffs);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return next(context);
|
|
341
|
+
};
|
|
342
|
+
};
|
|
343
|
+
|
|
260
344
|
module.exports = {
|
|
261
345
|
loadersFactory,
|
|
262
346
|
buildTransferTable,
|
|
@@ -271,4 +355,6 @@ module.exports = {
|
|
|
271
355
|
validateExcludeOnly,
|
|
272
356
|
formatDiagnostic,
|
|
273
357
|
abortTransfer,
|
|
358
|
+
setSignalHandler,
|
|
359
|
+
getDiffHandler,
|
|
274
360
|
};
|
|
@@ -59,6 +59,10 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
|
|
|
59
59
|
return options;
|
|
60
60
|
},
|
|
61
61
|
|
|
62
|
+
async wrapResult(result) {
|
|
63
|
+
return result;
|
|
64
|
+
},
|
|
65
|
+
|
|
62
66
|
async emitEvent(uid, event, entity) {
|
|
63
67
|
// Ignore audit log events to prevent infinite loops
|
|
64
68
|
if (uid === 'admin::audit-log') {
|
|
@@ -83,10 +87,12 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
|
|
|
83
87
|
const query = transformParamsToQuery(uid, wrappedParams);
|
|
84
88
|
|
|
85
89
|
if (kind === 'singleType') {
|
|
86
|
-
|
|
90
|
+
const entity = db.query(uid).findOne(query);
|
|
91
|
+
return this.wrapResult(entity, { uid, action: 'findOne' });
|
|
87
92
|
}
|
|
88
93
|
|
|
89
|
-
|
|
94
|
+
const entities = await db.query(uid).findMany(query);
|
|
95
|
+
return this.wrapResult(entities, { uid, action: 'findMany' });
|
|
90
96
|
},
|
|
91
97
|
|
|
92
98
|
async findPage(uid, opts) {
|
|
@@ -94,7 +100,11 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
|
|
|
94
100
|
|
|
95
101
|
const query = transformParamsToQuery(uid, wrappedParams);
|
|
96
102
|
|
|
97
|
-
|
|
103
|
+
const page = await db.query(uid).findPage(query);
|
|
104
|
+
return {
|
|
105
|
+
...page,
|
|
106
|
+
results: await this.wrapResult(page.results, { uid, action: 'findPage' }),
|
|
107
|
+
};
|
|
98
108
|
},
|
|
99
109
|
|
|
100
110
|
// TODO: streamline the logic based on the populate option
|
|
@@ -103,7 +113,11 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
|
|
|
103
113
|
|
|
104
114
|
const query = transformParamsToQuery(uid, wrappedParams);
|
|
105
115
|
|
|
106
|
-
|
|
116
|
+
const entities = await db.query(uid).findPage(query);
|
|
117
|
+
return {
|
|
118
|
+
...entities,
|
|
119
|
+
results: await this.wrapResult(entities.results, { uid, action: 'findWithRelationCounts' }),
|
|
120
|
+
};
|
|
107
121
|
},
|
|
108
122
|
|
|
109
123
|
async findWithRelationCounts(uid, opts) {
|
|
@@ -111,7 +125,8 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
|
|
|
111
125
|
|
|
112
126
|
const query = transformParamsToQuery(uid, wrappedParams);
|
|
113
127
|
|
|
114
|
-
|
|
128
|
+
const entities = await db.query(uid).findMany(query);
|
|
129
|
+
return this.wrapResult(entities, { uid, action: 'findWithRelationCounts' });
|
|
115
130
|
},
|
|
116
131
|
|
|
117
132
|
async findOne(uid, entityId, opts) {
|
|
@@ -119,7 +134,8 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
|
|
|
119
134
|
|
|
120
135
|
const query = transformParamsToQuery(uid, pickSelectionParams(wrappedParams));
|
|
121
136
|
|
|
122
|
-
|
|
137
|
+
const entity = await db.query(uid).findOne({ ...query, where: { id: entityId } });
|
|
138
|
+
return this.wrapResult(entity, { uid, action: 'findOne' });
|
|
123
139
|
},
|
|
124
140
|
|
|
125
141
|
async count(uid, opts) {
|
|
@@ -162,6 +178,8 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
|
|
|
162
178
|
entity = await this.findOne(uid, entity.id, wrappedParams);
|
|
163
179
|
}
|
|
164
180
|
|
|
181
|
+
entity = await this.wrapResult(entity, { uid, action: 'create' });
|
|
182
|
+
|
|
165
183
|
await this.emitEvent(uid, ENTRY_CREATE, entity);
|
|
166
184
|
|
|
167
185
|
return entity;
|
|
@@ -213,6 +231,8 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
|
|
|
213
231
|
entity = await this.findOne(uid, entity.id, wrappedParams);
|
|
214
232
|
}
|
|
215
233
|
|
|
234
|
+
entity = await this.wrapResult(entity, { uid, action: 'update' });
|
|
235
|
+
|
|
216
236
|
await this.emitEvent(uid, ENTRY_UPDATE, entity);
|
|
217
237
|
|
|
218
238
|
return entity;
|
|
@@ -224,7 +244,7 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
|
|
|
224
244
|
// select / populate
|
|
225
245
|
const query = transformParamsToQuery(uid, pickSelectionParams(wrappedParams));
|
|
226
246
|
|
|
227
|
-
|
|
247
|
+
let entityToDelete = await db.query(uid).findOne({
|
|
228
248
|
...query,
|
|
229
249
|
where: { id: entityId },
|
|
230
250
|
});
|
|
@@ -238,6 +258,8 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
|
|
|
238
258
|
await db.query(uid).delete({ where: { id: entityToDelete.id } });
|
|
239
259
|
await deleteComponents(uid, componentsToDelete, { loadComponents: false });
|
|
240
260
|
|
|
261
|
+
entityToDelete = await this.wrapResult(entityToDelete, { uid, action: 'delete' });
|
|
262
|
+
|
|
241
263
|
await this.emitEvent(uid, ENTRY_DELETE, entityToDelete);
|
|
242
264
|
|
|
243
265
|
return entityToDelete;
|
|
@@ -250,7 +272,7 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
|
|
|
250
272
|
// select / populate
|
|
251
273
|
const query = transformParamsToQuery(uid, wrappedParams);
|
|
252
274
|
|
|
253
|
-
|
|
275
|
+
let entitiesToDelete = await db.query(uid).findMany(query);
|
|
254
276
|
|
|
255
277
|
if (!entitiesToDelete.length) {
|
|
256
278
|
return null;
|
|
@@ -265,21 +287,27 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
|
|
|
265
287
|
componentsToDelete.map((compos) => deleteComponents(uid, compos, { loadComponents: false }))
|
|
266
288
|
);
|
|
267
289
|
|
|
290
|
+
entitiesToDelete = await this.wrapResult(entitiesToDelete, { uid, action: 'delete' });
|
|
291
|
+
|
|
268
292
|
// Trigger webhooks. One for each entity
|
|
269
293
|
await Promise.all(entitiesToDelete.map((entity) => this.emitEvent(uid, ENTRY_DELETE, entity)));
|
|
270
294
|
|
|
271
295
|
return deletedEntities;
|
|
272
296
|
},
|
|
273
297
|
|
|
274
|
-
load(uid, entity, field, params = {}) {
|
|
298
|
+
async load(uid, entity, field, params = {}) {
|
|
275
299
|
if (!_.isString(field)) {
|
|
276
300
|
throw new Error(`Invalid load. Expected "${field}" to be a string`);
|
|
277
301
|
}
|
|
278
302
|
|
|
279
|
-
|
|
303
|
+
const loadedEntity = await db
|
|
304
|
+
.query(uid)
|
|
305
|
+
.load(entity, field, transformLoadParamsToQuery(uid, field, params));
|
|
306
|
+
|
|
307
|
+
return this.wrapResult(loadedEntity, { uid, field, action: 'load' });
|
|
280
308
|
},
|
|
281
309
|
|
|
282
|
-
loadPages(uid, entity, field, params = {}, pagination = {}) {
|
|
310
|
+
async loadPages(uid, entity, field, params = {}, pagination = {}) {
|
|
283
311
|
if (!_.isString(field)) {
|
|
284
312
|
throw new Error(`Invalid load. Expected "${field}" to be a string`);
|
|
285
313
|
}
|
|
@@ -293,7 +321,12 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
|
|
|
293
321
|
|
|
294
322
|
const query = transformLoadParamsToQuery(uid, field, params, pagination);
|
|
295
323
|
|
|
296
|
-
|
|
324
|
+
const loadedPage = await db.query(uid).loadPages(entity, field, query);
|
|
325
|
+
|
|
326
|
+
return {
|
|
327
|
+
...loadedPage,
|
|
328
|
+
results: await this.wrapResult(loadedPage.results, { uid, field, action: 'load' }),
|
|
329
|
+
};
|
|
297
330
|
},
|
|
298
331
|
});
|
|
299
332
|
|
|
@@ -10,7 +10,7 @@ const crypto = require('crypto');
|
|
|
10
10
|
*/
|
|
11
11
|
const generateAdminUserHash = (strapi) => {
|
|
12
12
|
const ctx = strapi?.requestContext?.get();
|
|
13
|
-
if (!ctx?.state?.user) {
|
|
13
|
+
if (!ctx?.state?.user?.email) {
|
|
14
14
|
return '';
|
|
15
15
|
}
|
|
16
16
|
return crypto.createHash('sha256').update(ctx.state.user.email).digest('hex');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strapi/strapi",
|
|
3
|
-
"version": "4.11.0-
|
|
3
|
+
"version": "4.11.0-beta.1",
|
|
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",
|
|
@@ -81,19 +81,19 @@
|
|
|
81
81
|
"dependencies": {
|
|
82
82
|
"@koa/cors": "3.4.3",
|
|
83
83
|
"@koa/router": "10.1.1",
|
|
84
|
-
"@strapi/admin": "4.11.0-
|
|
85
|
-
"@strapi/data-transfer": "4.11.0-
|
|
86
|
-
"@strapi/database": "4.11.0-
|
|
87
|
-
"@strapi/generate-new": "4.11.0-
|
|
88
|
-
"@strapi/generators": "4.11.0-
|
|
89
|
-
"@strapi/logger": "4.11.0-
|
|
90
|
-
"@strapi/permissions": "4.11.0-
|
|
91
|
-
"@strapi/plugin-content-manager": "4.11.0-
|
|
92
|
-
"@strapi/plugin-content-type-builder": "4.11.0-
|
|
93
|
-
"@strapi/plugin-email": "4.11.0-
|
|
94
|
-
"@strapi/plugin-upload": "4.11.0-
|
|
95
|
-
"@strapi/typescript-utils": "4.11.0-
|
|
96
|
-
"@strapi/utils": "4.11.0-
|
|
84
|
+
"@strapi/admin": "4.11.0-beta.1",
|
|
85
|
+
"@strapi/data-transfer": "4.11.0-beta.1",
|
|
86
|
+
"@strapi/database": "4.11.0-beta.1",
|
|
87
|
+
"@strapi/generate-new": "4.11.0-beta.1",
|
|
88
|
+
"@strapi/generators": "4.11.0-beta.1",
|
|
89
|
+
"@strapi/logger": "4.11.0-beta.1",
|
|
90
|
+
"@strapi/permissions": "4.11.0-beta.1",
|
|
91
|
+
"@strapi/plugin-content-manager": "4.11.0-beta.1",
|
|
92
|
+
"@strapi/plugin-content-type-builder": "4.11.0-beta.1",
|
|
93
|
+
"@strapi/plugin-email": "4.11.0-beta.1",
|
|
94
|
+
"@strapi/plugin-upload": "4.11.0-beta.1",
|
|
95
|
+
"@strapi/typescript-utils": "4.11.0-beta.1",
|
|
96
|
+
"@strapi/utils": "4.11.0-beta.1",
|
|
97
97
|
"bcryptjs": "2.4.3",
|
|
98
98
|
"boxen": "5.1.2",
|
|
99
99
|
"chalk": "4.1.2",
|
|
@@ -142,5 +142,5 @@
|
|
|
142
142
|
"node": ">=14.19.1 <=18.x.x",
|
|
143
143
|
"npm": ">=6.0.0"
|
|
144
144
|
},
|
|
145
|
-
"gitHead": "
|
|
145
|
+
"gitHead": "a5fa3bd7e1c4680dd350580620d383612597d25d"
|
|
146
146
|
}
|