@strapi/admin 4.12.6 → 4.13.0-alpha.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.
- package/admin/src/StrapiApp.js +1 -1
- package/admin/src/components/AuthenticatedApp/index.js +118 -0
- package/admin/src/components/AuthenticatedApp/utils/api.js +85 -0
- package/admin/src/components/AuthenticatedApp/utils/checkLatestStrapiVersion.js +11 -0
- package/admin/src/components/GuidedTour/Modal/index.js +3 -1
- package/admin/src/components/NpsSurvey/hooks/useNpsSurveySettings.js +17 -0
- package/admin/src/components/NpsSurvey/index.js +365 -0
- package/admin/src/components/PluginsInitializer/index.js +68 -0
- package/admin/src/components/PluginsInitializer/init.js +11 -0
- package/admin/src/components/PluginsInitializer/reducer.js +22 -0
- package/admin/src/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/getTableColumns.js +2 -0
- package/admin/src/content-manager/components/DynamicZone/components/DynamicZoneLabel.js +1 -1
- package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +8 -1
- package/admin/src/content-manager/components/Filter/CustomInputs/AdminUsersFilter.js +42 -0
- package/admin/src/content-manager/components/Filter/Filter.js +54 -0
- package/admin/src/content-manager/components/Filter/index.js +1 -0
- package/admin/src/content-manager/components/InputUID/index.js +222 -216
- package/admin/src/content-manager/components/RelationInput/RelationInput.js +4 -0
- package/admin/src/content-manager/components/RepeatableComponent/index.js +32 -2
- package/admin/src/content-manager/components/Wysiwyg/Editor.js +432 -68
- package/admin/src/content-manager/components/Wysiwyg/WysiwygStyles.js +0 -7
- package/admin/src/content-manager/components/Wysiwyg/index.js +147 -152
- package/admin/src/content-manager/hooks/useAllowedAttributes.js +47 -0
- package/admin/src/content-manager/pages/App/index.js +16 -5
- package/admin/src/content-manager/pages/EditView/Information/index.js +9 -8
- package/admin/src/content-manager/pages/ListSettingsView/components/Settings.js +40 -7
- package/admin/src/content-manager/pages/ListSettingsView/index.js +6 -2
- package/admin/src/content-manager/pages/ListView/components/BulkActionButtons/SelectedEntriesModal/index.js +2 -2
- package/admin/src/content-manager/pages/ListView/components/FieldPicker/index.js +67 -69
- package/admin/src/content-manager/pages/ListView/components/TableRows/index.js +1 -1
- package/admin/src/content-manager/pages/ListView/components/ViewSettingsMenu/index.js +80 -0
- package/admin/src/content-manager/pages/ListView/index.js +236 -67
- package/admin/src/content-manager/utils/getDisplayName.js +33 -0
- package/admin/src/content-manager/utils/index.js +1 -0
- package/admin/src/hooks/useSettingsForm/index.js +3 -14
- package/admin/src/hooks/useSettingsMenu/index.js +2 -2
- package/admin/src/hooks/useSettingsMenu/utils/formatLinks.js +3 -1
- package/admin/src/hooks/useSettingsMenu/utils/sortLinks.js +3 -1
- package/admin/src/index.js +1 -1
- package/admin/src/layouts/AppLayout/index.js +33 -0
- package/admin/src/pages/Admin/Onboarding/index.js +3 -1
- package/admin/src/pages/Admin/index.js +73 -77
- package/admin/src/pages/App/constants.js +1 -1
- package/admin/src/pages/App/index.js +122 -160
- package/admin/src/pages/AuthPage/components/Register/index.js +5 -0
- package/admin/src/pages/AuthPage/index.js +4 -2
- package/admin/src/pages/HomePage/index.js +3 -1
- package/admin/src/pages/InstalledPluginsPage/index.js +3 -1
- package/admin/src/pages/{InternalErrorPage.js → InternalErrorPage/index.js} +4 -3
- package/admin/src/pages/{NotFoundPage.js → NotFoundPage/index.js} +3 -1
- package/admin/src/pages/ProfilePage/index.js +4 -2
- package/admin/src/pages/SettingsPage/constants.js +132 -67
- package/admin/src/pages/SettingsPage/index.js +18 -23
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/Users/EditPage/index.js +1 -2
- package/admin/src/pages/SettingsPage/pages/Users/ListPage/DynamicTable/TableRows/index.js +1 -1
- package/admin/src/pages/UseCasePage/index.js +175 -0
- package/admin/src/plugins.js +7 -8
- package/admin/src/translations/en.json +10 -1
- package/admin/src/utils/checkFormValidity.js +15 -0
- package/admin/src/utils/createRoute.js +7 -5
- package/admin/src/utils/formatAPIErrors.js +3 -1
- package/admin/src/utils/getAttributesToDisplay.js +19 -0
- package/admin/src/utils/getExistingActions.js +32 -0
- package/admin/src/utils/getFullName.js +1 -1
- package/admin/src/utils/index.js +9 -0
- package/admin/src/utils/makeUniqueRoutes.js +6 -0
- package/admin/src/utils/sortLinks.js +3 -1
- package/admin/src/utils/uniqueAdminHash.js +9 -2
- package/build/{1049.9d69d231.chunk.js → 1049.ec69f5e0.chunk.js} +1 -1
- package/build/1227.9f37e1dc.chunk.js +1 -0
- package/build/1386.ea73b677.chunk.js +7 -0
- package/build/{2225.33287e1b.chunk.js → 2225.649fb7bc.chunk.js} +2 -2
- package/build/{2237.03792b63.chunk.js → 2237.b832ae6e.chunk.js} +4 -4
- package/build/{2379.401f56f3.chunk.js → 2379.1f98a31a.chunk.js} +1 -1
- package/build/{2395.e6a79fbb.chunk.js → 2395.0e5e8ded.chunk.js} +1 -1
- package/build/{2801.31393ffe.chunk.js → 2801.8e1aa82a.chunk.js} +1 -1
- package/build/3483.19381b40.chunk.js +1 -0
- package/build/3739.63e352f1.chunk.js +103 -0
- package/build/4174.f1f39e40.chunk.js +1 -0
- package/build/448.829e1344.chunk.js +1 -0
- package/build/4546.a5946d22.chunk.js +1 -0
- package/build/4724.aea5c8c1.chunk.js +6 -0
- package/build/{502.8dd074ff.chunk.js → 502.7bba43b1.chunk.js} +1 -1
- package/build/6158.c3c13c20.chunk.js +1 -0
- package/build/6691.4985ef22.chunk.js +105 -0
- package/build/{7464.592a9295.chunk.js → 7464.eb057bec.chunk.js} +1 -1
- package/build/78.dcc6df5c.chunk.js +1 -0
- package/build/{8276.e519a707.chunk.js → 8276.be3ed581.chunk.js} +2 -2
- package/build/{2747.d1442a90.chunk.js → 9806.5d5a0e8d.chunk.js} +64 -72
- package/build/9944.7af075a5.chunk.js +26 -0
- package/build/Admin-authenticatedApp.43b6ec9a.chunk.js +79 -0
- package/build/Admin_InternalErrorPage.38155af3.chunk.js +1 -0
- package/build/Admin_homePage.6f128523.chunk.js +81 -0
- package/build/Admin_marketplace.061a6e5a.chunk.js +55 -0
- package/build/Admin_pluginsPage.16f837b8.chunk.js +6 -0
- package/build/Admin_profilePage.678bce24.chunk.js +13 -0
- package/build/Admin_settingsPage.af7309e4.chunk.js +111 -0
- package/build/{Upload_ConfigureTheView.345ac1e0.chunk.js → Upload_ConfigureTheView.3fc1c100.chunk.js} +1 -1
- package/build/admin-app.d63bd229.chunk.js +36 -0
- package/build/{admin-edit-roles-page.24bdf746.chunk.js → admin-edit-roles-page.38a6c863.chunk.js} +3 -3
- package/build/admin-edit-users.545fc882.chunk.js +10 -0
- package/build/{admin-roles-list.23ddff26.chunk.js → admin-roles-list.1e2e814d.chunk.js} +1 -1
- package/build/admin-users.b8ea5677.chunk.js +11 -0
- package/build/{api-tokens-create-page.46c2ea84.chunk.js → api-tokens-create-page.e0c15627.chunk.js} +1 -1
- package/build/{api-tokens-edit-page.58139df9.chunk.js → api-tokens-edit-page.9f2dce47.chunk.js} +1 -1
- package/build/{api-tokens-list-page.0af7d431.chunk.js → api-tokens-list-page.d747051c.chunk.js} +2 -2
- package/build/{audit-logs-settings-page.0f73ccf8.chunk.js → audit-logs-settings-page.96f9d608.chunk.js} +1 -1
- package/build/content-manager.ccff1078.chunk.js +1097 -0
- package/build/{content-type-builder-list-view.bf9be456.chunk.js → content-type-builder-list-view.b71cf240.chunk.js} +1 -1
- package/build/{content-type-builder.66066281.chunk.js → content-type-builder.e5669749.chunk.js} +18 -18
- package/build/{email-settings-page.2f7e35c0.chunk.js → email-settings-page.2809f0bf.chunk.js} +1 -1
- package/build/en-json.e12fd5fc.chunk.js +1 -0
- package/build/{i18n-settings-page.47f78016.chunk.js → i18n-settings-page.5f716172.chunk.js} +1 -1
- package/build/index.html +1 -1
- package/build/main.c6c9e04c.js +2859 -0
- package/build/{review-workflows-settings-create-view.d24a32b9.chunk.js → review-workflows-settings-create-view.4a156a19.chunk.js} +1 -1
- package/build/{review-workflows-settings-edit-view.6044b022.chunk.js → review-workflows-settings-edit-view.ce984d1f.chunk.js} +1 -1
- package/build/{review-workflows-settings-list-view.3f0ef4bc.chunk.js → review-workflows-settings-list-view.419b8deb.chunk.js} +2 -2
- package/build/runtime~main.dcf1cb45.js +2 -0
- package/build/{sso-settings-page.4dba0670.chunk.js → sso-settings-page.45153df5.chunk.js} +1 -1
- package/build/{transfer-tokens-create-page.1597e6ab.chunk.js → transfer-tokens-create-page.ebba16d8.chunk.js} +1 -1
- package/build/{transfer-tokens-edit-page.8741529f.chunk.js → transfer-tokens-edit-page.d7bb2b3e.chunk.js} +1 -1
- package/build/{transfer-tokens-list-page.d6986b03.chunk.js → transfer-tokens-list-page.cfe1736c.chunk.js} +2 -2
- package/build/{upload-settings.7f93d4c0.chunk.js → upload-settings.cc5ad813.chunk.js} +1 -1
- package/build/{upload.37488080.chunk.js → upload.756efc28.chunk.js} +1 -1
- package/build/{users-advanced-settings-page.17052d72.chunk.js → users-advanced-settings-page.818d84eb.chunk.js} +1 -1
- package/build/{users-email-settings-page.3de8ea50.chunk.js → users-email-settings-page.c1967c09.chunk.js} +1 -1
- package/build/{users-providers-settings-page.0eaa916d.chunk.js → users-providers-settings-page.11893e08.chunk.js} +1 -1
- package/build/{users-roles-settings-page.957ad48b.chunk.js → users-roles-settings-page.2b051e6a.chunk.js} +1 -1
- package/build/webhook-edit-page.de45c635.chunk.js +33 -0
- package/build/{webhook-list-page.65e1b5bb.chunk.js → webhook-list-page.ca91df8b.chunk.js} +1 -1
- package/ee/admin/content-manager/components/Filter/CustomInputs/ReviewWorkflows/AssigneeFilter.js +42 -0
- package/ee/admin/content-manager/components/Filter/CustomInputs/ReviewWorkflows/StageFilter.js +70 -0
- package/ee/admin/content-manager/components/Filter/CustomInputs/ReviewWorkflows/constants.js +71 -0
- package/ee/admin/content-manager/pages/EditView/InformationBox/InformationBoxEE.js +9 -217
- package/ee/admin/content-manager/pages/EditView/InformationBox/components/AssigneeSelect/AssigneeSelect.js +147 -0
- package/ee/admin/content-manager/pages/EditView/InformationBox/components/AssigneeSelect/index.js +1 -0
- package/ee/admin/content-manager/pages/EditView/InformationBox/components/StageSelect/StageSelect.js +243 -0
- package/ee/admin/content-manager/pages/EditView/InformationBox/components/StageSelect/index.js +1 -0
- package/ee/admin/content-manager/pages/EditView/InformationBox/constants.js +2 -0
- package/ee/admin/content-manager/pages/ListSettingsView/constants.js +7 -0
- package/ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn/ReviewWorkflowsAssigneeEE.js +21 -0
- package/ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn/constants.js +44 -17
- package/ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn/index.js +1 -0
- package/ee/admin/pages/App/constants.js +5 -6
- package/ee/admin/pages/SettingsPage/constants.js +42 -27
- package/ee/server/constants/workflows.js +1 -0
- package/ee/server/controllers/index.js +1 -0
- package/ee/server/controllers/workflows/assignees/index.js +44 -0
- package/ee/server/routes/review-workflows.js +17 -0
- package/ee/server/services/index.js +1 -0
- package/ee/server/services/review-workflows/assignees.js +54 -0
- package/ee/server/services/review-workflows/metrics/index.js +5 -0
- package/ee/server/services/review-workflows/review-workflows.js +20 -11
- package/ee/server/validation/review-workflows.js +8 -0
- package/index.js +2 -6
- package/package.json +9 -9
- package/scripts/build.js +15 -15
- package/scripts/create-dev-plugins-file.js +5 -38
- package/server/controllers/role.js +2 -0
- package/server/controllers/user.js +2 -0
- package/server/services/permission/permissions-manager/index.js +3 -1
- package/server/services/permission/permissions-manager/sanitize.js +19 -7
- package/server/services/permission/permissions-manager/validate.js +218 -0
- package/utils/create-cache-dir.js +62 -16
- package/utils/create-plugins-exclude-path.js +3 -23
- package/utils/get-plugins.js +110 -0
- package/utils/index.js +1 -1
- package/webpack.config.js +10 -13
- package/admin/src/components/AuthenticatedApp.js +0 -229
- package/admin/src/content-manager/components/AttributeFilter/Filters.js +0 -58
- package/admin/src/content-manager/components/AttributeFilter/hooks/useAllowedAttributes.js +0 -42
- package/admin/src/content-manager/components/AttributeFilter/index.js +0 -40
- package/admin/src/content-manager/components/Wysiwyg/EditorStylesContainer.js +0 -344
- package/admin/src/pages/UseCasePage.js +0 -174
- package/build/2166.c837469a.chunk.js +0 -1
- package/build/3483.8517171f.chunk.js +0 -1
- package/build/3984.dda474f7.chunk.js +0 -1
- package/build/4546.7a3c0d03.chunk.js +0 -1
- package/build/5483.5bfbb00d.chunk.js +0 -6
- package/build/6158.c974fd83.chunk.js +0 -1
- package/build/748.fd2e5afd.chunk.js +0 -105
- package/build/773.6381d62d.chunk.js +0 -18
- package/build/7826.399afe81.chunk.js +0 -103
- package/build/8261.2525d35c.chunk.js +0 -7
- package/build/8299.62b67c72.chunk.js +0 -1
- package/build/Admin-AuthPage.90d64342.chunk.js +0 -35
- package/build/Admin-AuthenticatedApp.379ac945.chunk.js +0 -24
- package/build/Admin-UseCasePage.1f757db5.chunk.js +0 -13
- package/build/Admin_GuidedTourModal.8ccf1fbc.chunk.js +0 -12
- package/build/Admin_InternalErrorPage.9de92c6d.chunk.js +0 -9
- package/build/Admin_NotFoundPage.21620424.chunk.js +0 -9
- package/build/Admin_Onboarding.dbfa32f6.chunk.js +0 -43
- package/build/Admin_homePage.2000cbe9.chunk.js +0 -86
- package/build/Admin_marketplace.ec80e29b.chunk.js +0 -63
- package/build/Admin_pluginsPage.0c6851f8.chunk.js +0 -14
- package/build/Admin_profilePage.78cd8495.chunk.js +0 -21
- package/build/Admin_settingsPage.1760c3ce.chunk.js +0 -119
- package/build/StrapiApp.221fac30.chunk.js +0 -5
- package/build/admin-edit-users.5d10d444.chunk.js +0 -10
- package/build/admin-users.2b3e4305.chunk.js +0 -11
- package/build/content-manager.fb0833bd.chunk.js +0 -1099
- package/build/en-json.08c05fcf.chunk.js +0 -1
- package/build/main.ee3c1938.js +0 -2859
- package/build/runtime~main.397ee447.js +0 -2
- package/build/webhook-edit-page.665210af.chunk.js +0 -33
- package/scripts/create-plugins-file.js +0 -92
- package/utils/get-plugins-path.js +0 -41
- /package/server/services/permission/permissions-manager/{query-builers.js → query-builders.js} +0 -0
|
@@ -8,6 +8,8 @@ const defaultStages = require('../../constants/default-stages.json');
|
|
|
8
8
|
const defaultWorkflow = require('../../constants/default-workflow.json');
|
|
9
9
|
const {
|
|
10
10
|
ENTITY_STAGE_ATTRIBUTE,
|
|
11
|
+
ENTITY_ASSIGNEE_ATTRIBUTE,
|
|
12
|
+
STAGE_MODEL_UID,
|
|
11
13
|
MAX_WORKFLOWS,
|
|
12
14
|
MAX_STAGES_PER_WORKFLOW,
|
|
13
15
|
} = require('../../constants/workflows');
|
|
@@ -52,19 +54,26 @@ function extendReviewWorkflowContentTypes({ strapi }) {
|
|
|
52
54
|
);
|
|
53
55
|
return contentType;
|
|
54
56
|
};
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
|
|
58
|
+
const setRelation = (path, target) =>
|
|
59
|
+
set(path, {
|
|
60
|
+
writable: true,
|
|
61
|
+
private: false,
|
|
62
|
+
configurable: false,
|
|
63
|
+
visible: false,
|
|
64
|
+
useJoinTable: true, // We want a join table to persist data when downgrading to CE
|
|
65
|
+
type: 'relation',
|
|
66
|
+
relation: 'oneToOne',
|
|
67
|
+
target,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const setReviewWorkflowAttributes = pipe([
|
|
71
|
+
setRelation(`attributes.${ENTITY_STAGE_ATTRIBUTE}`, STAGE_MODEL_UID),
|
|
72
|
+
setRelation(`attributes.${ENTITY_ASSIGNEE_ATTRIBUTE}`, 'admin::user'),
|
|
73
|
+
]);
|
|
65
74
|
|
|
66
75
|
const extendContentTypeIfCompatible = cond([
|
|
67
|
-
[assertContentTypeCompatibility,
|
|
76
|
+
[assertContentTypeCompatibility, setReviewWorkflowAttributes],
|
|
68
77
|
[stubTrue, incompatibleContentTypeAlert],
|
|
69
78
|
]);
|
|
70
79
|
strapi.container.get('content-types').extend(contentTypeUID, extendContentTypeIfCompatible);
|
|
@@ -66,8 +66,16 @@ const validateWorkflowUpdateSchema = yup.object().shape({
|
|
|
66
66
|
contentTypes: validateContentTypes,
|
|
67
67
|
});
|
|
68
68
|
|
|
69
|
+
const validateUpdateAssigneeOnEntity = yup
|
|
70
|
+
.object()
|
|
71
|
+
.shape({
|
|
72
|
+
id: yup.number().integer().min(1).nullable(),
|
|
73
|
+
})
|
|
74
|
+
.required();
|
|
75
|
+
|
|
69
76
|
module.exports = {
|
|
70
77
|
validateWorkflowCreate: validateYupSchema(validateWorkflowCreateSchema),
|
|
71
78
|
validateUpdateStageOnEntity: validateYupSchema(validateUpdateStageOnEntity),
|
|
79
|
+
validateUpdateAssigneeOnEntity: validateYupSchema(validateUpdateAssigneeOnEntity),
|
|
72
80
|
validateWorkflowUpdate: validateYupSchema(validateWorkflowUpdateSchema),
|
|
73
81
|
};
|
package/index.js
CHANGED
|
@@ -30,7 +30,6 @@ async function build({ appDir, buildDestDir, env, forceBuild, optimize, options,
|
|
|
30
30
|
const entry = path.resolve(cacheDir, 'admin', 'src');
|
|
31
31
|
const dest = path.resolve(buildDestDir, 'build');
|
|
32
32
|
|
|
33
|
-
const pluginsPath = Object.keys(plugins).map((pluginName) => plugins[pluginName].pathToPlugin);
|
|
34
33
|
const enforceSourceMaps = process.env.STRAPI_ENFORCE_SOURCEMAPS === 'true' ?? false;
|
|
35
34
|
|
|
36
35
|
// Either use the tsconfig file from the generated app or the one inside the .cache folder
|
|
@@ -41,14 +40,13 @@ async function build({ appDir, buildDestDir, env, forceBuild, optimize, options,
|
|
|
41
40
|
|
|
42
41
|
const config = getCustomWebpackConfig(appDir, {
|
|
43
42
|
appDir,
|
|
44
|
-
cacheDir,
|
|
45
43
|
dest,
|
|
46
44
|
enforceSourceMaps,
|
|
47
45
|
entry,
|
|
48
46
|
env,
|
|
49
47
|
optimize,
|
|
50
48
|
options,
|
|
51
|
-
|
|
49
|
+
plugins,
|
|
52
50
|
tsConfigFilePath,
|
|
53
51
|
});
|
|
54
52
|
|
|
@@ -100,8 +98,6 @@ async function watchAdmin({ appDir, browser, buildDestDir, host, options, plugin
|
|
|
100
98
|
const dest = path.join(buildDestDir, 'build');
|
|
101
99
|
const env = 'development';
|
|
102
100
|
|
|
103
|
-
const pluginsPath = Object.keys(plugins).map((pluginName) => plugins[pluginName].pathToPlugin);
|
|
104
|
-
|
|
105
101
|
// Either use the tsconfig file from the generated app or the one inside the .cache folder
|
|
106
102
|
// so we can develop plugins in TS while being in a JS app
|
|
107
103
|
const tsConfigFilePath = useTypeScript
|
|
@@ -115,7 +111,7 @@ async function watchAdmin({ appDir, browser, buildDestDir, host, options, plugin
|
|
|
115
111
|
entry,
|
|
116
112
|
env,
|
|
117
113
|
options,
|
|
118
|
-
|
|
114
|
+
plugins,
|
|
119
115
|
devServer: {
|
|
120
116
|
port,
|
|
121
117
|
client: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strapi/admin",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.13.0-alpha.0",
|
|
4
4
|
"description": "Strapi Admin",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -42,15 +42,15 @@
|
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@casl/ability": "^5.4.3",
|
|
44
44
|
"@pmmmwh/react-refresh-webpack-plugin": "0.5.10",
|
|
45
|
-
"@strapi/data-transfer": "4.
|
|
45
|
+
"@strapi/data-transfer": "4.13.0-alpha.0",
|
|
46
46
|
"@strapi/design-system": "1.9.0",
|
|
47
|
-
"@strapi/helper-plugin": "4.
|
|
47
|
+
"@strapi/helper-plugin": "4.13.0-alpha.0",
|
|
48
48
|
"@strapi/icons": "1.9.0",
|
|
49
|
-
"@strapi/permissions": "4.
|
|
50
|
-
"@strapi/provider-audit-logs-local": "4.
|
|
51
|
-
"@strapi/typescript-utils": "4.
|
|
52
|
-
"@strapi/utils": "4.
|
|
53
|
-
"axios": "1.
|
|
49
|
+
"@strapi/permissions": "4.13.0-alpha.0",
|
|
50
|
+
"@strapi/provider-audit-logs-local": "4.13.0-alpha.0",
|
|
51
|
+
"@strapi/typescript-utils": "4.13.0-alpha.0",
|
|
52
|
+
"@strapi/utils": "4.13.0-alpha.0",
|
|
53
|
+
"axios": "1.5.0",
|
|
54
54
|
"bcryptjs": "2.4.3",
|
|
55
55
|
"browserslist": "^4.17.3",
|
|
56
56
|
"browserslist-to-esbuild": "1.2.0",
|
|
@@ -154,5 +154,5 @@
|
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
},
|
|
157
|
-
"gitHead": "
|
|
157
|
+
"gitHead": "41844c2867621a1f47dd6ae6ac83283aa54b22f8"
|
|
158
158
|
}
|
package/scripts/build.js
CHANGED
|
@@ -7,14 +7,8 @@ const { isObject } = require('lodash');
|
|
|
7
7
|
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
|
|
8
8
|
|
|
9
9
|
const webpackConfig = require('../webpack.config');
|
|
10
|
-
const
|
|
11
|
-
const {
|
|
12
|
-
getCorePluginsPath,
|
|
13
|
-
getPluginToInstallPath,
|
|
14
|
-
createPluginsFile,
|
|
15
|
-
} = require('./create-plugins-file');
|
|
16
|
-
|
|
17
|
-
const PLUGINS_TO_INSTALL = ['i18n', 'users-permissions'];
|
|
10
|
+
const { getPlugins } = require('../utils/get-plugins');
|
|
11
|
+
const { createPluginsJs } = require('../utils/create-cache-dir');
|
|
18
12
|
|
|
19
13
|
// Wrapper that outputs the webpack speed
|
|
20
14
|
const smp = new SpeedMeasurePlugin();
|
|
@@ -24,18 +18,24 @@ const buildAdmin = async () => {
|
|
|
24
18
|
const dest = path.join(__dirname, '..', 'build');
|
|
25
19
|
const tsConfigFilePath = path.join(__dirname, '..', 'admin', 'src', 'tsconfig.json');
|
|
26
20
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
/**
|
|
22
|
+
* We _always_ install these FE plugins, they're considered "core"
|
|
23
|
+
* and are typically marked as `required` in their package.json
|
|
24
|
+
*/
|
|
25
|
+
const plugins = getPlugins([
|
|
26
|
+
'@strapi/plugin-content-type-builder',
|
|
27
|
+
'@strapi/plugin-email',
|
|
28
|
+
'@strapi/plugin-upload',
|
|
29
|
+
'@strapi/plugin-i18n',
|
|
30
|
+
'@strapi/plugin-users-permissions',
|
|
31
|
+
]);
|
|
31
32
|
|
|
32
|
-
await
|
|
33
|
+
await createPluginsJs(plugins, path.join(__dirname, '..'));
|
|
33
34
|
|
|
34
35
|
const args = {
|
|
35
36
|
entry,
|
|
36
37
|
dest,
|
|
37
|
-
|
|
38
|
-
pluginsPath,
|
|
38
|
+
plugins,
|
|
39
39
|
env: 'production',
|
|
40
40
|
optimize: true,
|
|
41
41
|
options: {
|
|
@@ -1,40 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { join
|
|
4
|
-
const { promisify } = require('util');
|
|
5
|
-
|
|
6
|
-
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
7
|
-
const glob = promisify(require('glob').glob);
|
|
3
|
+
const { join } = require('path');
|
|
8
4
|
const fs = require('fs-extra');
|
|
9
|
-
const {
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Retrieve all plugins that are inside the plugins folder
|
|
13
|
-
* @returns Object the plugins
|
|
14
|
-
*/
|
|
15
|
-
const getPluginsPackages = async () => {
|
|
16
|
-
const pathToPackages = resolve(__dirname, '..', '..', '..', 'plugins', '*');
|
|
17
|
-
const pluginsPackageDirs = await glob(pathToPackages);
|
|
18
|
-
|
|
19
|
-
return pluginsPackageDirs
|
|
20
|
-
.filter((pluginDir) => {
|
|
21
|
-
return fs.existsSync(join(pluginDir, 'admin', 'src', 'index.js'));
|
|
22
|
-
})
|
|
23
|
-
.reduce((acc, current) => {
|
|
24
|
-
const depName = current.replace(/\\/g, '/').split('/').slice(-1)[0];
|
|
25
|
-
|
|
26
|
-
const adminEntryPoint = join(__dirname, '..', 'admin', 'src');
|
|
27
|
-
|
|
28
|
-
const pathToPlugin = join(relative(adminEntryPoint, current), 'admin', 'src').replace(
|
|
29
|
-
/\\/g,
|
|
30
|
-
'/'
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
acc[depName] = pathToPlugin;
|
|
34
|
-
|
|
35
|
-
return acc;
|
|
36
|
-
}, {});
|
|
37
|
-
};
|
|
5
|
+
const { getPlugins } = require('../utils/get-plugins');
|
|
6
|
+
const { createPluginsJs } = require('../utils/create-cache-dir');
|
|
38
7
|
|
|
39
8
|
/**
|
|
40
9
|
* Write the plugins.js file or copy the plugins-dev.js file if it exists
|
|
@@ -49,11 +18,9 @@ const createFile = async () => {
|
|
|
49
18
|
return;
|
|
50
19
|
}
|
|
51
20
|
|
|
52
|
-
const
|
|
53
|
-
const plugins = await getPluginsPackages();
|
|
54
|
-
const allPlugins = { ...corePlugins, ...plugins };
|
|
21
|
+
const plugins = getPlugins();
|
|
55
22
|
|
|
56
|
-
return
|
|
23
|
+
return createPluginsJs(plugins, join(__dirname, '..'));
|
|
57
24
|
};
|
|
58
25
|
|
|
59
26
|
createFile()
|
|
@@ -55,6 +55,8 @@ module.exports = {
|
|
|
55
55
|
ability: ctx.state.userAbility,
|
|
56
56
|
model: 'admin::role',
|
|
57
57
|
});
|
|
58
|
+
|
|
59
|
+
await permissionsManager.validateQuery(query);
|
|
58
60
|
const sanitizedQuery = await permissionsManager.sanitizeQuery(query);
|
|
59
61
|
|
|
60
62
|
const roles = await getService('role').findAllWithUsersCount(sanitizedQuery);
|
|
@@ -52,6 +52,8 @@ module.exports = {
|
|
|
52
52
|
ability: ctx.state.userAbility,
|
|
53
53
|
model: 'admin::user',
|
|
54
54
|
});
|
|
55
|
+
|
|
56
|
+
await permissionsManager.validateQuery(ctx.query);
|
|
55
57
|
const sanitizedQuery = await permissionsManager.sanitizeQuery(ctx.query);
|
|
56
58
|
|
|
57
59
|
const { results, pagination } = await userService.findPage(sanitizedQuery);
|
|
@@ -4,8 +4,9 @@ const _ = require('lodash');
|
|
|
4
4
|
const { cloneDeep, isPlainObject } = require('lodash/fp');
|
|
5
5
|
const { subject: asSubject } = require('@casl/ability');
|
|
6
6
|
const createSanitizeHelpers = require('./sanitize');
|
|
7
|
+
const createValidateHelpers = require('./validate');
|
|
7
8
|
|
|
8
|
-
const { buildStrapiQuery, buildCaslQuery } = require('./query-
|
|
9
|
+
const { buildStrapiQuery, buildCaslQuery } = require('./query-builders');
|
|
9
10
|
|
|
10
11
|
module.exports = ({ ability, action, model }) => ({
|
|
11
12
|
ability,
|
|
@@ -48,4 +49,5 @@ module.exports = ({ ability, action, model }) => ({
|
|
|
48
49
|
},
|
|
49
50
|
|
|
50
51
|
...createSanitizeHelpers({ action, ability, model }),
|
|
52
|
+
...createValidateHelpers({ action, ability, model }),
|
|
51
53
|
});
|
|
@@ -45,7 +45,7 @@ const STATIC_FIELDS = [ID_ATTRIBUTE];
|
|
|
45
45
|
module.exports = ({ action, ability, model }) => {
|
|
46
46
|
const schema = strapi.getModel(model);
|
|
47
47
|
|
|
48
|
-
const {
|
|
48
|
+
const { removeDisallowedFields } = sanitize.visitors;
|
|
49
49
|
|
|
50
50
|
const createSanitizeQuery = (options = {}) => {
|
|
51
51
|
const { fields } = options;
|
|
@@ -54,8 +54,9 @@ module.exports = ({ action, ability, model }) => {
|
|
|
54
54
|
const permittedFields = fields.shouldIncludeAll ? null : getQueryFields(fields.permitted);
|
|
55
55
|
|
|
56
56
|
const sanitizeFilters = pipeAsync(
|
|
57
|
-
traverse.traverseQueryFilters(
|
|
57
|
+
traverse.traverseQueryFilters(removeDisallowedFields(permittedFields), { schema }),
|
|
58
58
|
traverse.traverseQueryFilters(omitDisallowedAdminUserFields, { schema }),
|
|
59
|
+
traverse.traverseQueryFilters(omitHiddenFields, { schema }),
|
|
59
60
|
traverse.traverseQueryFilters(removePassword, { schema }),
|
|
60
61
|
traverse.traverseQueryFilters(
|
|
61
62
|
({ key, value }, { remove }) => {
|
|
@@ -68,8 +69,9 @@ module.exports = ({ action, ability, model }) => {
|
|
|
68
69
|
);
|
|
69
70
|
|
|
70
71
|
const sanitizeSort = pipeAsync(
|
|
71
|
-
traverse.traverseQuerySort(
|
|
72
|
+
traverse.traverseQuerySort(removeDisallowedFields(permittedFields), { schema }),
|
|
72
73
|
traverse.traverseQuerySort(omitDisallowedAdminUserFields, { schema }),
|
|
74
|
+
traverse.traverseQuerySort(omitHiddenFields, { schema }),
|
|
73
75
|
traverse.traverseQuerySort(removePassword, { schema }),
|
|
74
76
|
traverse.traverseQuerySort(
|
|
75
77
|
({ key, attribute, value }, { remove }) => {
|
|
@@ -82,13 +84,15 @@ module.exports = ({ action, ability, model }) => {
|
|
|
82
84
|
);
|
|
83
85
|
|
|
84
86
|
const sanitizePopulate = pipeAsync(
|
|
85
|
-
traverse.traverseQueryPopulate(
|
|
87
|
+
traverse.traverseQueryPopulate(removeDisallowedFields(permittedFields), { schema }),
|
|
86
88
|
traverse.traverseQueryPopulate(omitDisallowedAdminUserFields, { schema }),
|
|
89
|
+
traverse.traverseQueryPopulate(omitHiddenFields, { schema }),
|
|
87
90
|
traverse.traverseQueryPopulate(removePassword, { schema })
|
|
88
91
|
);
|
|
89
92
|
|
|
90
93
|
const sanitizeFields = pipeAsync(
|
|
91
|
-
traverse.traverseQueryFields(
|
|
94
|
+
traverse.traverseQueryFields(removeDisallowedFields(permittedFields), { schema }),
|
|
95
|
+
traverse.traverseQueryFields(omitHiddenFields, { schema }),
|
|
92
96
|
traverse.traverseQueryFields(removePassword, { schema })
|
|
93
97
|
);
|
|
94
98
|
|
|
@@ -126,7 +130,7 @@ module.exports = ({ action, ability, model }) => {
|
|
|
126
130
|
// Remove unallowed fields from admin::user relations
|
|
127
131
|
traverseEntity(pickAllowedAdminUserFields, { schema }),
|
|
128
132
|
// Remove not allowed fields (RBAC)
|
|
129
|
-
traverseEntity(
|
|
133
|
+
traverseEntity(removeDisallowedFields(permittedFields), { schema }),
|
|
130
134
|
// Remove all fields of type 'password'
|
|
131
135
|
sanitize.sanitizers.sanitizePasswords(schema)
|
|
132
136
|
);
|
|
@@ -141,7 +145,7 @@ module.exports = ({ action, ability, model }) => {
|
|
|
141
145
|
// Remove fields hidden from the admin
|
|
142
146
|
traverseEntity(omitHiddenFields, { schema }),
|
|
143
147
|
// Remove not allowed fields (RBAC)
|
|
144
|
-
traverseEntity(
|
|
148
|
+
traverseEntity(removeDisallowedFields(permittedFields), { schema }),
|
|
145
149
|
// Remove roles from createdBy & updateBy fields
|
|
146
150
|
omitCreatorRoles
|
|
147
151
|
);
|
|
@@ -256,13 +260,21 @@ module.exports = ({ action, ability, model }) => {
|
|
|
256
260
|
};
|
|
257
261
|
|
|
258
262
|
const getQueryFields = (fields = []) => {
|
|
263
|
+
const nonVisibleAttributes = getNonVisibleAttributes(schema);
|
|
264
|
+
const writableAttributes = getWritableAttributes(schema);
|
|
265
|
+
|
|
266
|
+
const nonVisibleWritableAttributes = intersection(nonVisibleAttributes, writableAttributes);
|
|
267
|
+
|
|
259
268
|
return uniq([
|
|
260
269
|
...fields,
|
|
261
270
|
...STATIC_FIELDS,
|
|
262
271
|
...COMPONENT_FIELDS,
|
|
272
|
+
...nonVisibleWritableAttributes,
|
|
263
273
|
CREATED_AT_ATTRIBUTE,
|
|
264
274
|
UPDATED_AT_ATTRIBUTE,
|
|
265
275
|
PUBLISHED_AT_ATTRIBUTE,
|
|
276
|
+
CREATED_BY_ATTRIBUTE,
|
|
277
|
+
UPDATED_BY_ATTRIBUTE,
|
|
266
278
|
]);
|
|
267
279
|
};
|
|
268
280
|
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { subject: asSubject, detectSubjectType } = require('@casl/ability');
|
|
4
|
+
const { permittedFieldsOf } = require('@casl/ability/extra');
|
|
5
|
+
const {
|
|
6
|
+
defaults,
|
|
7
|
+
omit,
|
|
8
|
+
isArray,
|
|
9
|
+
isEmpty,
|
|
10
|
+
isNil,
|
|
11
|
+
flatMap,
|
|
12
|
+
some,
|
|
13
|
+
prop,
|
|
14
|
+
uniq,
|
|
15
|
+
intersection,
|
|
16
|
+
getOr,
|
|
17
|
+
isObject,
|
|
18
|
+
} = require('lodash/fp');
|
|
19
|
+
|
|
20
|
+
const {
|
|
21
|
+
contentTypes,
|
|
22
|
+
traverseEntity,
|
|
23
|
+
traverse,
|
|
24
|
+
validate,
|
|
25
|
+
pipeAsync,
|
|
26
|
+
errors: { ValidationError },
|
|
27
|
+
} = require('@strapi/utils');
|
|
28
|
+
|
|
29
|
+
const { throwPassword, throwDisallowedFields } = validate.visitors;
|
|
30
|
+
const { ADMIN_USER_ALLOWED_FIELDS } = require('../../../domain/user');
|
|
31
|
+
|
|
32
|
+
const { constants, isScalarAttribute, getNonVisibleAttributes, getWritableAttributes } =
|
|
33
|
+
contentTypes;
|
|
34
|
+
const {
|
|
35
|
+
ID_ATTRIBUTE,
|
|
36
|
+
CREATED_AT_ATTRIBUTE,
|
|
37
|
+
UPDATED_AT_ATTRIBUTE,
|
|
38
|
+
PUBLISHED_AT_ATTRIBUTE,
|
|
39
|
+
CREATED_BY_ATTRIBUTE,
|
|
40
|
+
UPDATED_BY_ATTRIBUTE,
|
|
41
|
+
} = constants;
|
|
42
|
+
|
|
43
|
+
const COMPONENT_FIELDS = ['__component'];
|
|
44
|
+
|
|
45
|
+
const STATIC_FIELDS = [ID_ATTRIBUTE];
|
|
46
|
+
|
|
47
|
+
const throwInvalidParam = ({ key }) => {
|
|
48
|
+
throw new ValidationError(`Invalid parameter ${key}`);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
module.exports = ({ action, ability, model }) => {
|
|
52
|
+
const schema = strapi.getModel(model);
|
|
53
|
+
|
|
54
|
+
const createValidateQuery = (options = {}) => {
|
|
55
|
+
const { fields } = options;
|
|
56
|
+
|
|
57
|
+
// TODO: validate relations to admin users in all validators
|
|
58
|
+
const permittedFields = fields.shouldIncludeAll ? null : getQueryFields(fields.permitted);
|
|
59
|
+
|
|
60
|
+
const validateFilters = pipeAsync(
|
|
61
|
+
traverse.traverseQueryFilters(throwDisallowedFields(permittedFields), { schema }),
|
|
62
|
+
traverse.traverseQueryFilters(throwDisallowedAdminUserFields, { schema }),
|
|
63
|
+
traverse.traverseQueryFilters(throwPassword, { schema }),
|
|
64
|
+
traverse.traverseQueryFilters(
|
|
65
|
+
({ key, value }) => {
|
|
66
|
+
if (isObject(value) && isEmpty(value)) {
|
|
67
|
+
throwInvalidParam({ key });
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
{ schema }
|
|
71
|
+
)
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const validateSort = pipeAsync(
|
|
75
|
+
traverse.traverseQuerySort(throwDisallowedFields(permittedFields), { schema }),
|
|
76
|
+
traverse.traverseQuerySort(throwDisallowedAdminUserFields, { schema }),
|
|
77
|
+
traverse.traverseQuerySort(throwPassword, { schema }),
|
|
78
|
+
traverse.traverseQuerySort(
|
|
79
|
+
({ key, attribute, value }) => {
|
|
80
|
+
if (!isScalarAttribute(attribute) && isEmpty(value)) {
|
|
81
|
+
throwInvalidParam({ key });
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
{ schema }
|
|
85
|
+
)
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const validateFields = pipeAsync(
|
|
89
|
+
traverse.traverseQueryFields(throwDisallowedFields(permittedFields), { schema }),
|
|
90
|
+
traverse.traverseQueryFields(throwPassword, { schema })
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
return async (query) => {
|
|
94
|
+
if (query.filters) {
|
|
95
|
+
await validateFilters(query.filters);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (query.sort) {
|
|
99
|
+
await validateSort(query.sort);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (query.fields) {
|
|
103
|
+
await validateFields(query.fields);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return true;
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const createValidateInput = (options = {}) => {
|
|
111
|
+
const { fields } = options;
|
|
112
|
+
|
|
113
|
+
const permittedFields = fields.shouldIncludeAll ? null : getInputFields(fields.permitted);
|
|
114
|
+
|
|
115
|
+
return pipeAsync(
|
|
116
|
+
// Remove fields hidden from the admin
|
|
117
|
+
traverseEntity(throwHiddenFields, { schema }),
|
|
118
|
+
// Remove not allowed fields (RBAC)
|
|
119
|
+
traverseEntity(throwDisallowedFields(permittedFields), { schema }),
|
|
120
|
+
// Remove roles from createdBy & updatedBy fields
|
|
121
|
+
omitCreatorRoles
|
|
122
|
+
);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const wrapValidate = (createValidateFunction) => {
|
|
126
|
+
const wrappedValidate = async (data, options = {}) => {
|
|
127
|
+
if (isArray(data)) {
|
|
128
|
+
return Promise.all(data.map((entity) => wrappedValidate(entity, options)));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const { subject, action: actionOverride } = getDefaultOptions(data, options);
|
|
132
|
+
|
|
133
|
+
const permittedFields = permittedFieldsOf(ability, actionOverride, subject, {
|
|
134
|
+
fieldsFrom: (rule) => rule.fields || [],
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const hasAtLeastOneRegistered = some(
|
|
138
|
+
(fields) => !isNil(fields),
|
|
139
|
+
flatMap(prop('fields'), ability.rulesFor(actionOverride, detectSubjectType(subject)))
|
|
140
|
+
);
|
|
141
|
+
const shouldIncludeAllFields = isEmpty(permittedFields) && !hasAtLeastOneRegistered;
|
|
142
|
+
|
|
143
|
+
const validateOptions = {
|
|
144
|
+
...options,
|
|
145
|
+
fields: {
|
|
146
|
+
shouldIncludeAll: shouldIncludeAllFields,
|
|
147
|
+
permitted: permittedFields,
|
|
148
|
+
hasAtLeastOneRegistered,
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const validateFunction = createValidateFunction(validateOptions);
|
|
153
|
+
|
|
154
|
+
return validateFunction(data);
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
return wrappedValidate;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const getDefaultOptions = (data, options) => {
|
|
161
|
+
return defaults({ subject: asSubject(model, data), action }, options);
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Omit creator fields' (createdBy & updatedBy) roles from the admin API responses
|
|
166
|
+
*/
|
|
167
|
+
const omitCreatorRoles = omit([`${CREATED_BY_ATTRIBUTE}.roles`, `${UPDATED_BY_ATTRIBUTE}.roles`]);
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Visitor used to remove hidden fields from the admin API responses
|
|
171
|
+
*/
|
|
172
|
+
const throwHiddenFields = ({ key, schema }) => {
|
|
173
|
+
const isHidden = getOr(false, ['config', 'attributes', key, 'hidden'], schema);
|
|
174
|
+
|
|
175
|
+
if (isHidden) {
|
|
176
|
+
throwInvalidParam({ key });
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Visitor used to omit disallowed fields from the admin users entities & avoid leaking sensitive information
|
|
182
|
+
*/
|
|
183
|
+
const throwDisallowedAdminUserFields = ({ key, attribute, schema }) => {
|
|
184
|
+
if (schema.uid === 'admin::user' && attribute && !ADMIN_USER_ALLOWED_FIELDS.includes(key)) {
|
|
185
|
+
throwInvalidParam({ key });
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
const getInputFields = (fields = []) => {
|
|
190
|
+
const nonVisibleAttributes = getNonVisibleAttributes(schema);
|
|
191
|
+
const writableAttributes = getWritableAttributes(schema);
|
|
192
|
+
|
|
193
|
+
const nonVisibleWritableAttributes = intersection(nonVisibleAttributes, writableAttributes);
|
|
194
|
+
|
|
195
|
+
return uniq([
|
|
196
|
+
...fields,
|
|
197
|
+
...STATIC_FIELDS,
|
|
198
|
+
...COMPONENT_FIELDS,
|
|
199
|
+
...nonVisibleWritableAttributes,
|
|
200
|
+
]);
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const getQueryFields = (fields = []) => {
|
|
204
|
+
return uniq([
|
|
205
|
+
...fields,
|
|
206
|
+
...STATIC_FIELDS,
|
|
207
|
+
...COMPONENT_FIELDS,
|
|
208
|
+
CREATED_AT_ATTRIBUTE,
|
|
209
|
+
UPDATED_AT_ATTRIBUTE,
|
|
210
|
+
PUBLISHED_AT_ATTRIBUTE,
|
|
211
|
+
]);
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
validateQuery: wrapValidate(createValidateQuery),
|
|
216
|
+
validateInput: wrapValidate(createValidateInput),
|
|
217
|
+
};
|
|
218
|
+
};
|