@strapi/strapi 4.4.0-rc.1 → 4.5.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/lib/Strapi.js CHANGED
@@ -23,8 +23,6 @@ const entityValidator = require('./services/entity-validator');
23
23
  const createTelemetry = require('./services/metrics');
24
24
  const requestContext = require('./services/request-context');
25
25
  const createAuth = require('./services/auth');
26
- const createCustomFields = require('./services/custom-fields');
27
- const createContentAPI = require('./services/content-api');
28
26
  const createUpdateNotifier = require('./utils/update-notifier');
29
27
  const createStartupLogger = require('./utils/startup-logger');
30
28
  const { LIFECYCLES } = require('./utils/lifecycles');
@@ -37,14 +35,12 @@ const hooksRegistry = require('./core/registries/hooks');
37
35
  const controllersRegistry = require('./core/registries/controllers');
38
36
  const modulesRegistry = require('./core/registries/modules');
39
37
  const pluginsRegistry = require('./core/registries/plugins');
40
- const customFieldsRegistry = require('./core/registries/custom-fields');
41
38
  const createConfigProvider = require('./core/registries/config');
42
39
  const apisRegistry = require('./core/registries/apis');
43
40
  const bootstrap = require('./core/bootstrap');
44
41
  const loaders = require('./core/loaders');
45
42
  const { destroyOnSignal } = require('./utils/signals');
46
43
  const sanitizersRegistry = require('./core/registries/sanitizers');
47
- const convertCustomFieldType = require('./utils/convert-custom-field-type');
48
44
 
49
45
  // TODO: move somewhere else
50
46
  const draftAndPublishSync = require('./migrations/draft-publish');
@@ -79,7 +75,7 @@ class Strapi {
79
75
  // Load the app configuration from the dist directory
80
76
  const appConfig = loadConfiguration({ appDir: rootDirs.app, distDir: rootDirs.dist }, opts);
81
77
 
82
- // Instantiate the Strapi container
78
+ // Instanciate the Strapi container
83
79
  this.container = createContainer(this);
84
80
 
85
81
  // Register every Strapi registry in the container
@@ -92,10 +88,8 @@ class Strapi {
92
88
  this.container.register('controllers', controllersRegistry(this));
93
89
  this.container.register('modules', modulesRegistry(this));
94
90
  this.container.register('plugins', pluginsRegistry(this));
95
- this.container.register('custom-fields', customFieldsRegistry(this));
96
91
  this.container.register('apis', apisRegistry(this));
97
92
  this.container.register('auth', createAuth(this));
98
- this.container.register('content-api', createContentAPI(this));
99
93
  this.container.register('sanitizers', sanitizersRegistry(this));
100
94
 
101
95
  // Create a mapping of every useful directory (for the app, dist and static directories)
@@ -105,7 +99,7 @@ class Strapi {
105
99
  this.isLoaded = false;
106
100
  this.reload = this.reload();
107
101
 
108
- // Instantiate the Koa app & the HTTP server
102
+ // Instanciate the Koa app & the HTTP server
109
103
  this.server = createServer(this);
110
104
 
111
105
  // Strapi utils instanciation
@@ -117,8 +111,6 @@ class Strapi {
117
111
  this.telemetry = createTelemetry(this);
118
112
  this.requestContext = requestContext;
119
113
 
120
- this.customFields = createCustomFields(this);
121
-
122
114
  createUpdateNotifier(this).notify();
123
115
  }
124
116
 
@@ -198,10 +190,6 @@ class Strapi {
198
190
  return this.container.get('auth');
199
191
  }
200
192
 
201
- get contentAPI() {
202
- return this.container.get('content-api');
203
- }
204
-
205
193
  get sanitizers() {
206
194
  return this.container.get('sanitizers');
207
195
  }
@@ -391,8 +379,6 @@ class Strapi {
391
379
  this.telemetry.register();
392
380
 
393
381
  await this.runLifecyclesFunctions(LIFECYCLES.REGISTER);
394
- // NOTE: Swap type customField for underlying data type
395
- convertCustomFieldType(this);
396
382
 
397
383
  return this;
398
384
  }
@@ -461,8 +447,6 @@ class Strapi {
461
447
  await this.server.initMiddlewares();
462
448
  await this.server.initRouting();
463
449
 
464
- await this.contentAPI.permissions.registerActions();
465
-
466
450
  await this.runLifecyclesFunctions(LIFECYCLES.BOOTSTRAP);
467
451
 
468
452
  this.cron.start();
@@ -32,7 +32,6 @@ const createAuthentication = () => {
32
32
 
33
33
  return this;
34
34
  },
35
-
36
35
  async authenticate(ctx, next) {
37
36
  const { route } = ctx.state;
38
37
 
@@ -48,7 +47,7 @@ const createAuthentication = () => {
48
47
  for (const strategy of strategiesToUse) {
49
48
  const result = await strategy.authenticate(ctx);
50
49
 
51
- const { authenticated = false, credentials, ability = null, error = null } = result || {};
50
+ const { authenticated = false, error = null, credentials } = result || {};
52
51
 
53
52
  if (error !== null) {
54
53
  return ctx.unauthorized(error);
@@ -59,7 +58,6 @@ const createAuthentication = () => {
59
58
  ctx.state.auth = {
60
59
  strategy,
61
60
  credentials,
62
- ability,
63
61
  };
64
62
 
65
63
  return next();
@@ -68,7 +66,6 @@ const createAuthentication = () => {
68
66
 
69
67
  return ctx.unauthorized('Missing or invalid credentials');
70
68
  },
71
-
72
69
  async verify(auth, config = {}) {
73
70
  if (config === false) {
74
71
  return;
@@ -48,11 +48,10 @@ const createComponents = async (uid, data) => {
48
48
  );
49
49
 
50
50
  // TODO: add order
51
- componentBody[attributeName] = components.map(({ id }, idx) => {
51
+ componentBody[attributeName] = components.map(({ id }) => {
52
52
  return {
53
53
  id,
54
54
  __pivot: {
55
- order: idx + 1,
56
55
  field: attributeName,
57
56
  component_type: componentUID,
58
57
  },
@@ -63,7 +62,6 @@ const createComponents = async (uid, data) => {
63
62
  componentBody[attributeName] = {
64
63
  id: component.id,
65
64
  __pivot: {
66
- order: 1,
67
65
  field: attributeName,
68
66
  component_type: componentUID,
69
67
  },
@@ -81,13 +79,12 @@ const createComponents = async (uid, data) => {
81
79
  }
82
80
 
83
81
  componentBody[attributeName] = await Promise.all(
84
- dynamiczoneValues.map(async (value, idx) => {
82
+ dynamiczoneValues.map(async (value) => {
85
83
  const { id } = await createComponent(value.__component, value);
86
84
  return {
87
85
  id,
88
86
  __component: value.__component,
89
87
  __pivot: {
90
- order: idx + 1,
91
88
  field: attributeName,
92
89
  },
93
90
  };
@@ -145,11 +142,10 @@ const updateComponents = async (uid, entityToUpdate, data) => {
145
142
  componentValue.map((value) => updateOrCreateComponent(componentUID, value))
146
143
  );
147
144
 
148
- componentBody[attributeName] = components.filter(_.negate(_.isNil)).map(({ id }, idx) => {
145
+ componentBody[attributeName] = components.filter(_.negate(_.isNil)).map(({ id }) => {
149
146
  return {
150
147
  id,
151
148
  __pivot: {
152
- order: idx + 1,
153
149
  field: attributeName,
154
150
  component_type: componentUID,
155
151
  },
@@ -160,7 +156,6 @@ const updateComponents = async (uid, entityToUpdate, data) => {
160
156
  componentBody[attributeName] = component && {
161
157
  id: component.id,
162
158
  __pivot: {
163
- order: 1,
164
159
  field: attributeName,
165
160
  component_type: componentUID,
166
161
  },
@@ -180,14 +175,13 @@ const updateComponents = async (uid, entityToUpdate, data) => {
180
175
  }
181
176
 
182
177
  componentBody[attributeName] = await Promise.all(
183
- dynamiczoneValues.map(async (value, idx) => {
178
+ dynamiczoneValues.map(async (value) => {
184
179
  const { id } = await updateOrCreateComponent(value.__component, value);
185
180
 
186
181
  return {
187
182
  id,
188
183
  __component: value.__component,
189
184
  __pivot: {
190
- order: idx + 1,
191
185
  field: attributeName,
192
186
  },
193
187
  };
@@ -10,6 +10,7 @@ const {
10
10
  sanitize,
11
11
  } = require('@strapi/utils');
12
12
  const { ValidationError } = require('@strapi/utils').errors;
13
+ const { transformParamsToQuery } = require('@strapi/utils').convertQueryParams;
13
14
  const uploadFiles = require('../utils/upload-files');
14
15
 
15
16
  const {
@@ -19,7 +20,7 @@ const {
19
20
  updateComponents,
20
21
  deleteComponents,
21
22
  } = require('./components');
22
- const { transformParamsToQuery, pickSelectionParams } = require('./params');
23
+ const { pickSelectionParams } = require('./params');
23
24
  const { applyTransforms } = require('./attributes');
24
25
 
25
26
  // TODO: those should be strapi events used by the webhooks not the other way arround
@@ -83,12 +84,7 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
83
84
 
84
85
  const query = transformParamsToQuery(uid, wrappedParams);
85
86
 
86
- const { results, pagination } = await db.query(uid).findPage(query);
87
-
88
- return {
89
- results,
90
- pagination,
91
- };
87
+ return db.query(uid).findPage(query);
92
88
  },
93
89
 
94
90
  async findWithRelationCounts(uid, opts) {
@@ -96,9 +92,7 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
96
92
 
97
93
  const query = transformParamsToQuery(uid, wrappedParams);
98
94
 
99
- const results = await db.query(uid).findMany(query);
100
-
101
- return results;
95
+ return db.query(uid).findMany(query);
102
96
  },
103
97
 
104
98
  async findOne(uid, entityId, opts) {
@@ -1,95 +1,9 @@
1
1
  'use strict';
2
2
 
3
- const { pick, isNil, toNumber, isInteger } = require('lodash/fp');
4
- const { PaginationError } = require('@strapi/utils').errors;
5
-
6
- const {
7
- convertSortQueryParams,
8
- convertLimitQueryParams,
9
- convertStartQueryParams,
10
- convertPopulateQueryParams,
11
- convertFiltersQueryParams,
12
- convertFieldsQueryParams,
13
- convertPublicationStateParams,
14
- } = require('@strapi/utils/lib/convert-query-params');
3
+ const { pick } = require('lodash/fp');
15
4
 
16
5
  const pickSelectionParams = pick(['fields', 'populate']);
17
6
 
18
- const transformParamsToQuery = (uid, params) => {
19
- // NOTE: can be a CT, a Compo or nothing in the case of polymorphism (DZ & morph relations)
20
- const schema = strapi.getModel(uid);
21
-
22
- const query = {};
23
-
24
- const { _q, sort, filters, fields, populate, page, pageSize, start, limit } = params;
25
-
26
- if (!isNil(_q)) {
27
- query._q = _q;
28
- }
29
-
30
- if (!isNil(sort)) {
31
- query.orderBy = convertSortQueryParams(sort);
32
- }
33
-
34
- if (!isNil(filters)) {
35
- query.where = convertFiltersQueryParams(filters, schema);
36
- }
37
-
38
- if (!isNil(fields)) {
39
- query.select = convertFieldsQueryParams(fields);
40
- }
41
-
42
- if (!isNil(populate)) {
43
- query.populate = convertPopulateQueryParams(populate, schema);
44
- }
45
-
46
- const isPagePagination = !isNil(page) || !isNil(pageSize);
47
- const isOffsetPagination = !isNil(start) || !isNil(limit);
48
-
49
- if (isPagePagination && isOffsetPagination) {
50
- throw new PaginationError(
51
- 'Invalid pagination attributes. You cannot use page and offset pagination in the same query'
52
- );
53
- }
54
-
55
- if (!isNil(page)) {
56
- const pageVal = toNumber(page);
57
-
58
- if (!isInteger(pageVal) || pageVal <= 0) {
59
- throw new PaginationError(
60
- `Invalid 'page' parameter. Expected an integer > 0, received: ${page}`
61
- );
62
- }
63
-
64
- query.page = pageVal;
65
- }
66
-
67
- if (!isNil(pageSize)) {
68
- const pageSizeVal = toNumber(pageSize);
69
-
70
- if (!isInteger(pageSizeVal) || pageSizeVal <= 0) {
71
- throw new PaginationError(
72
- `Invalid 'pageSize' parameter. Expected an integer > 0, received: ${page}`
73
- );
74
- }
75
-
76
- query.pageSize = pageSizeVal;
77
- }
78
-
79
- if (!isNil(start)) {
80
- query.offset = convertStartQueryParams(start);
81
- }
82
-
83
- if (!isNil(limit)) {
84
- query.limit = convertLimitQueryParams(limit);
85
- }
86
-
87
- convertPublicationStateParams(schema, params, query);
88
-
89
- return query;
90
- };
91
-
92
7
  module.exports = {
93
- transformParamsToQuery,
94
8
  pickSelectionParams,
95
9
  };
@@ -29,9 +29,6 @@ export type NonUniqueAttribute = { unique: false };
29
29
  export type ConfigurableAttribute = { configurable: true };
30
30
  export type NonConfigurableAttribute = { configurable: false };
31
31
 
32
- // custom field
33
- export type CustomField<T extends string, P extends object = undefined> = { customField: T, options?: P };
34
-
35
32
  // min/max
36
33
  export type SetMinMax<T extends MinMaxOption<U>, U = number> = T;
37
34
 
@@ -5,28 +5,6 @@ import type { StringMap } from './utils';
5
5
  import type { GenericController } from '../../../core-api/controller'
6
6
  import type { GenericService } from '../../../core-api/service'
7
7
 
8
- // TODO move custom fields types to a separate file
9
- interface CustomFieldServerOptions {
10
- /**
11
- * The name of the custom field
12
- */
13
- name: string;
14
-
15
- /**
16
- * The name of the plugin creating the custom field
17
- */
18
- plugin?: string;
19
-
20
- /**
21
- * The existing Strapi data type the custom field uses
22
- */
23
- type: string;
24
- }
25
-
26
- interface CustomFields {
27
- register: (customFields: CustomFieldServerOptions[] | CustomFieldServerOptions) => void;
28
- }
29
-
30
8
  /**
31
9
  * The Strapi interface implemented by the main Strapi class.
32
10
  */
@@ -46,11 +24,6 @@ export interface Strapi {
46
24
  */
47
25
  readonly auth: any;
48
26
 
49
- /**
50
- * Getter for the Strapi content API container
51
- */
52
- readonly contentAPI: any;
53
-
54
27
  /**
55
28
  * Getter for the Strapi sanitizers container
56
29
  */
@@ -92,13 +65,6 @@ export interface Strapi {
92
65
  */
93
66
  contentType(uid: string): any;
94
67
 
95
- /**
96
- * The custom fields registry
97
- *
98
- * It returns the custom fields interface
99
- */
100
- readonly customFields: CustomFields;
101
-
102
68
  /**
103
69
  * Getter for the Strapi policies container
104
70
  *
@@ -229,7 +195,7 @@ export interface Strapi {
229
195
  /**
230
196
  * Restart the server and reload all the configuration.
231
197
  * It re-runs all the lifecycles phases.
232
- *
198
+ *
233
199
  * @example
234
200
  * ``` ts
235
201
  * setImmediate(() => strapi.reload());
@@ -257,13 +223,13 @@ export interface Strapi {
257
223
  /**
258
224
  * Opent he administration panel in a browser if the option is enabled.
259
225
  * You can disable it using the admin.autoOpen configuration variable.
260
- *
226
+ *
261
227
  * Note: It only works in development envs.
262
228
  */
263
229
  openAdmin(options: { isInitialized: boolean }): Promise<void>;
264
230
 
265
231
  /**
266
- * Load the admin panel server logic into the server code and initialize its configuration.
232
+ * Load the admin panel server logic into the server code and initialize its configuration.
267
233
  */
268
234
  loadAdmin(): Promise<void>;
269
235
 
@@ -322,7 +288,7 @@ export interface Strapi {
322
288
  container: any;
323
289
 
324
290
  /**
325
- * References to all the directories handled by Strapi
291
+ * References to all the directories handled by Strapi
326
292
  */
327
293
  dirs: StrapiDirectories;
328
294
 
@@ -357,7 +323,7 @@ export interface Strapi {
357
323
  startupLogger: any;
358
324
 
359
325
  /**
360
- * Strapi logger used to send errors, warning or information messages
326
+ * Strapi logger used to send errors, warning or information messages
361
327
  */
362
328
  log: any;
363
329
 
@@ -390,7 +356,7 @@ export interface Strapi {
390
356
  /**
391
357
  * Entity Service instance
392
358
  */
393
- entityService: any;
359
+ entityService: any;
394
360
  }
395
361
 
396
362
  export interface Lifecycles {
@@ -423,4 +389,4 @@ export interface StrapiDirectories {
423
389
  middlewares: string;
424
390
  config: string;
425
391
  };
426
- }
392
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/strapi",
3
- "version": "4.4.0-rc.1",
3
+ "version": "4.5.0-alpha.0",
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,18 +80,17 @@
80
80
  "dependencies": {
81
81
  "@koa/cors": "3.4.1",
82
82
  "@koa/router": "10.1.1",
83
- "@strapi/admin": "4.4.0-rc.1",
84
- "@strapi/database": "4.4.0-rc.1",
85
- "@strapi/generate-new": "4.4.0-rc.1",
86
- "@strapi/generators": "4.4.0-rc.1",
87
- "@strapi/logger": "4.4.0-rc.1",
88
- "@strapi/permissions": "4.4.0-rc.1",
89
- "@strapi/plugin-content-manager": "4.4.0-rc.1",
90
- "@strapi/plugin-content-type-builder": "4.4.0-rc.1",
91
- "@strapi/plugin-email": "4.4.0-rc.1",
92
- "@strapi/plugin-upload": "4.4.0-rc.1",
93
- "@strapi/typescript-utils": "4.4.0-rc.1",
94
- "@strapi/utils": "4.4.0-rc.1",
83
+ "@strapi/admin": "4.5.0-alpha.0",
84
+ "@strapi/database": "4.5.0-alpha.0",
85
+ "@strapi/generate-new": "4.5.0-alpha.0",
86
+ "@strapi/generators": "4.5.0-alpha.0",
87
+ "@strapi/logger": "4.5.0-alpha.0",
88
+ "@strapi/plugin-content-manager": "4.5.0-alpha.0",
89
+ "@strapi/plugin-content-type-builder": "4.5.0-alpha.0",
90
+ "@strapi/plugin-email": "4.5.0-alpha.0",
91
+ "@strapi/plugin-upload": "4.5.0-alpha.0",
92
+ "@strapi/typescript-utils": "4.5.0-alpha.0",
93
+ "@strapi/utils": "4.5.0-alpha.0",
95
94
  "bcryptjs": "2.4.3",
96
95
  "boxen": "5.1.2",
97
96
  "chalk": "4.1.2",
@@ -140,5 +139,5 @@
140
139
  "node": ">=14.19.1 <=18.x.x",
141
140
  "npm": ">=6.0.0"
142
141
  },
143
- "gitHead": "00c788873a5b25b63ccdeaad6b0781d26c26d90d"
142
+ "gitHead": "c9a98c4dbcf3c4f2a449f8d96e7cbe4cd9b1e0f5"
144
143
  }
@@ -1,54 +0,0 @@
1
- 'use strict';
2
-
3
- const { has } = require('lodash/fp');
4
- const validators = require('../../services/entity-validator/validators');
5
-
6
- const customFieldsRegistry = (strapi) => {
7
- const customFields = {};
8
-
9
- return {
10
- getAll() {
11
- return customFields;
12
- },
13
- get(customField) {
14
- const registeredCustomField = customFields[customField];
15
- if (!registeredCustomField) {
16
- throw new Error(`Could not find Custom Field: ${customField}`);
17
- }
18
-
19
- return registeredCustomField;
20
- },
21
- add(customField) {
22
- const customFieldList = Array.isArray(customField) ? customField : [customField];
23
-
24
- for (const cf of customFieldList) {
25
- if (!has('name', cf) || !has('type', cf)) {
26
- throw new Error(`Custom fields require a 'name' and 'type' key`);
27
- }
28
-
29
- const { name, plugin, type } = cf;
30
- if (!has(type, validators)) {
31
- throw new Error(
32
- `Custom field type: '${type}' is not a valid Strapi type or it can't be used with a Custom Field`
33
- );
34
- }
35
-
36
- const isValidObjectKey = /^(?![0-9])[a-zA-Z0-9$_-]+$/g;
37
- if (!isValidObjectKey.test(name)) {
38
- throw new Error(`Custom field name: '${name}' is not a valid object key`);
39
- }
40
-
41
- // When no plugin is specified, or it isn't found in Strapi, default to global
42
- const uid = strapi.plugin(plugin) ? `plugin::${plugin}.${name}` : `global::${name}`;
43
-
44
- if (has(uid, customFields)) {
45
- throw new Error(`Custom field: '${uid}' has already been registered`);
46
- }
47
-
48
- customFields[uid] = cf;
49
- }
50
- },
51
- };
52
- };
53
-
54
- module.exports = customFieldsRegistry;
@@ -1,74 +0,0 @@
1
- 'use strict';
2
-
3
- const _ = require('lodash');
4
- const instantiatePermissionsUtilities = require('./permissions');
5
-
6
- const transformRoutePrefixFor = (pluginName) => (route) => {
7
- const prefix = route.config && route.config.prefix;
8
- const path = prefix !== undefined ? `${prefix}${route.path}` : `/${pluginName}${route.path}`;
9
-
10
- return {
11
- ...route,
12
- path,
13
- };
14
- };
15
-
16
- /**
17
- * Create a content API container that holds logic, tools and utils. (eg: permissions, ...)
18
- */
19
- const createContentAPI = (strapi) => {
20
- const getRoutesMap = async () => {
21
- const routesMap = {};
22
-
23
- _.forEach(strapi.api, (api, apiName) => {
24
- const routes = _.flatMap(api.routes, (route) => {
25
- if (_.has(route, 'routes')) {
26
- return route.routes;
27
- }
28
-
29
- return route;
30
- }).filter((route) => route.info.type === 'content-api');
31
-
32
- if (routes.length === 0) {
33
- return;
34
- }
35
-
36
- const apiPrefix = strapi.config.get('api.rest.prefix');
37
- routesMap[`api::${apiName}`] = routes.map((route) => ({
38
- ...route,
39
- path: `${apiPrefix}${route.path}`,
40
- }));
41
- });
42
-
43
- _.forEach(strapi.plugins, (plugin, pluginName) => {
44
- const transformPrefix = transformRoutePrefixFor(pluginName);
45
-
46
- const routes = _.flatMap(plugin.routes, (route) => {
47
- if (_.has(route, 'routes')) {
48
- return route.routes.map(transformPrefix);
49
- }
50
-
51
- return transformPrefix(route);
52
- }).filter((route) => route.info.type === 'content-api');
53
-
54
- if (routes.length === 0) {
55
- return;
56
- }
57
-
58
- const apiPrefix = strapi.config.get('api.rest.prefix');
59
- routesMap[`plugin::${pluginName}`] = routes.map((route) => ({
60
- ...route,
61
- path: `${apiPrefix}${route.path}`,
62
- }));
63
- });
64
-
65
- return routesMap;
66
- };
67
-
68
- return {
69
- permissions: instantiatePermissionsUtilities(strapi),
70
- getRoutesMap,
71
- };
72
- };
73
-
74
- module.exports = createContentAPI;
@@ -1,5 +0,0 @@
1
- 'use strict';
2
-
3
- const permissions = require('@strapi/permissions');
4
-
5
- module.exports = ({ providers }) => permissions.engine.new({ providers });
@@ -1,148 +0,0 @@
1
- 'use strict';
2
-
3
- const _ = require('lodash');
4
- const { createActionProvider, createConditionProvider } = require('./providers');
5
- const createPermissionEngine = require('./engine');
6
-
7
- /**
8
- * Creates an handler that checks if the permission's action exists in the action registry
9
- */
10
- const createValidatePermissionHandler =
11
- (actionProvider) =>
12
- ({ permission }) => {
13
- const action = actionProvider.get(permission.action);
14
-
15
- // If the action isn't registered into the action provider, then ignore the permission and warn the user
16
- if (!action) {
17
- strapi.log.debug(
18
- `Unknown action "${permission.action}" supplied when registering a new permission`
19
- );
20
- return false;
21
- }
22
- };
23
-
24
- /**
25
- * Create instances of providers and permission engine for the core content-API service.
26
- * Also, expose utilities to get informations about available actions and such.
27
- *
28
- * @param {Strapi.Strapi} strapi
29
- */
30
- module.exports = (strapi) => {
31
- // NOTE: Here we define both an action and condition provider,
32
- // but at the moment, we're only using the action one.
33
- const providers = {
34
- action: createActionProvider(),
35
- condition: createConditionProvider(),
36
- };
37
-
38
- /**
39
- * Get a tree representation of the available Content API actions
40
- * based on the methods of the Content API controllers.
41
- *
42
- * @note Only actions bound to a content-API route are returned.
43
- *
44
- * @return {{ [api: string]: { [controller: string]: string[] }}}
45
- */
46
- const getActionsMap = () => {
47
- const actionMap = {};
48
-
49
- /**
50
- * Check if a controller's action is bound to the
51
- * content-api by looking at a potential __type__ symbol
52
- *
53
- * @param {object} action
54
- *
55
- * @return {boolean}
56
- */
57
- const isContentApi = (action) => {
58
- if (!_.has(action, Symbol.for('__type__'))) {
59
- return false;
60
- }
61
-
62
- return action[Symbol.for('__type__')].includes('content-api');
63
- };
64
-
65
- /**
66
- * Register actions from a specific API source into the result tree
67
- *
68
- * @param {{ [apiName]: { controllers: { [controller]: object } }}} apis The API container
69
- * @param {string} source The prefix to use in front the API name
70
- *
71
- * @return {void}
72
- */
73
- const registerAPIsActions = (apis, source) => {
74
- _.forEach(apis, (api, apiName) => {
75
- const controllers = _.reduce(
76
- api.controllers,
77
- (acc, controller, controllerName) => {
78
- const contentApiActions = _.pickBy(controller, isContentApi);
79
-
80
- if (_.isEmpty(contentApiActions)) {
81
- return acc;
82
- }
83
-
84
- acc[controllerName] = Object.keys(contentApiActions);
85
-
86
- return acc;
87
- },
88
- {}
89
- );
90
-
91
- if (!_.isEmpty(controllers)) {
92
- actionMap[`${source}::${apiName}`] = { controllers };
93
- }
94
- });
95
- };
96
-
97
- registerAPIsActions(strapi.api, 'api');
98
- registerAPIsActions(strapi.plugins, 'plugin');
99
-
100
- return actionMap;
101
- };
102
-
103
- /**
104
- * Register all the content-API's controllers actions into the action provider.
105
- * This method make use of the {@link getActionsMap} to generate the list of actions to register.
106
- *
107
- * @return {void}
108
- */
109
- const registerActions = async () => {
110
- const actionsMap = getActionsMap();
111
-
112
- // For each API
113
- for (const [api, value] of Object.entries(actionsMap)) {
114
- const { controllers } = value;
115
-
116
- // Register controllers methods as actions
117
- for (const [controller, actions] of Object.entries(controllers)) {
118
- // Register each action individually
119
- await Promise.all(
120
- actions.map((action) => {
121
- const actionUID = `${api}.${controller}.${action}`;
122
-
123
- return providers.action.register(actionUID, {
124
- api,
125
- controller,
126
- action,
127
- uid: actionUID,
128
- });
129
- })
130
- );
131
- }
132
- }
133
- };
134
-
135
- // Create an instance of a content-API permission engine
136
- // and binds a custom validation handler to it
137
- const engine = createPermissionEngine({ providers }).on(
138
- 'before-format::validate.permission',
139
- createValidatePermissionHandler(providers.action)
140
- );
141
-
142
- return {
143
- engine,
144
- providers,
145
- registerActions,
146
- getActionsMap,
147
- };
148
- };
@@ -1,19 +0,0 @@
1
- 'use strict';
2
-
3
- const { providerFactory } = require('@strapi/utils');
4
-
5
- module.exports = (options = {}) => {
6
- const provider = providerFactory(options);
7
-
8
- return {
9
- ...provider,
10
-
11
- async register(action, payload) {
12
- if (strapi.isLoaded) {
13
- throw new Error(`You can't register new actions outside the bootstrap function.`);
14
- }
15
-
16
- return provider.register(action, payload);
17
- },
18
- };
19
- };
@@ -1,19 +0,0 @@
1
- 'use strict';
2
-
3
- const { providerFactory } = require('@strapi/utils');
4
-
5
- module.exports = (options = {}) => {
6
- const provider = providerFactory(options);
7
-
8
- return {
9
- ...provider,
10
-
11
- async register(condition) {
12
- if (strapi.isLoaded) {
13
- throw new Error(`You can't register new conditions outside the bootstrap function.`);
14
- }
15
-
16
- return provider.register(condition.name, condition);
17
- },
18
- };
19
- };
@@ -1,9 +0,0 @@
1
- 'use strict';
2
-
3
- const createActionProvider = require('./action');
4
- const createConditionProvider = require('./condition');
5
-
6
- module.exports = {
7
- createActionProvider,
8
- createConditionProvider,
9
- };
@@ -1,11 +0,0 @@
1
- 'use strict';
2
-
3
- const createCustomFields = (strapi) => {
4
- return {
5
- register(customField) {
6
- strapi.container.get('custom-fields').add(customField);
7
- },
8
- };
9
- };
10
-
11
- module.exports = createCustomFields;
@@ -1,22 +0,0 @@
1
- 'use strict';
2
-
3
- const convertCustomFieldType = (strapi) => {
4
- const allContentTypeSchemaAttributes = Object.values(strapi.contentTypes).map(
5
- (schema) => schema.attributes
6
- );
7
- const allComponentSchemaAttributes = Object.values(strapi.components).map(
8
- (schema) => schema.attributes
9
- );
10
- const allSchemasAttributes = [...allContentTypeSchemaAttributes, ...allComponentSchemaAttributes];
11
-
12
- for (const schemaAttrbutes of allSchemasAttributes) {
13
- for (const attribute of Object.values(schemaAttrbutes)) {
14
- if (attribute.type === 'customField') {
15
- const customField = strapi.container.get('custom-fields').get(attribute.customField);
16
- attribute.type = customField.type;
17
- }
18
- }
19
- }
20
- };
21
-
22
- module.exports = convertCustomFieldType;