From e4e3825def91de569d60fae009bfef1542a29669 Mon Sep 17 00:00:00 2001 From: Boaz Poolman Date: Mon, 5 Aug 2024 18:37:56 +0200 Subject: [PATCH 1/2] chore: setup components in the playground --- playground/.strapi/client/app.js | 16 + playground/.strapi/client/index.html | 62 ++ playground/config/plugins.js | 13 +- .../api/home/content-types/home/schema.json | 28 + playground/src/api/home/controllers/home.js | 9 + playground/src/api/home/routes/home.js | 9 + playground/src/api/home/services/home.js | 9 + .../api/page/content-types/page/schema.json | 19 + playground/src/api/page/controllers/page.js | 9 + playground/src/api/page/routes/page.js | 9 + playground/src/api/page/services/page.js | 9 + .../src/components/core/contact-info.json | 15 + playground/src/components/core/profile.json | 18 + playground/types/generated/components.d.ts | 33 + playground/types/generated/contentTypes.d.ts | 858 ++++++++++++++++++ 15 files changed, 1115 insertions(+), 1 deletion(-) create mode 100644 playground/.strapi/client/app.js create mode 100644 playground/.strapi/client/index.html create mode 100644 playground/src/api/home/content-types/home/schema.json create mode 100644 playground/src/api/home/controllers/home.js create mode 100644 playground/src/api/home/routes/home.js create mode 100644 playground/src/api/home/services/home.js create mode 100644 playground/src/api/page/content-types/page/schema.json create mode 100644 playground/src/api/page/controllers/page.js create mode 100644 playground/src/api/page/routes/page.js create mode 100644 playground/src/api/page/services/page.js create mode 100644 playground/src/components/core/contact-info.json create mode 100644 playground/src/components/core/profile.json create mode 100644 playground/types/generated/components.d.ts create mode 100644 playground/types/generated/contentTypes.d.ts diff --git a/playground/.strapi/client/app.js b/playground/.strapi/client/app.js new file mode 100644 index 0000000..1996af5 --- /dev/null +++ b/playground/.strapi/client/app.js @@ -0,0 +1,16 @@ +/** + * This file was automatically generated by Strapi. + * Any modifications made will be discarded. + */ +import i18N from "@strapi/plugin-i18n/strapi-admin"; +import usersPermissions from "@strapi/plugin-users-permissions/strapi-admin"; +import configSync from "strapi-plugin-config-sync/strapi-admin"; +import { renderAdmin } from "@strapi/strapi/admin"; + +renderAdmin(document.getElementById("strapi"), { + plugins: { + i18n: i18N, + "users-permissions": usersPermissions, + "config-sync": configSync, + }, +}); diff --git a/playground/.strapi/client/index.html b/playground/.strapi/client/index.html new file mode 100644 index 0000000..08d9c27 --- /dev/null +++ b/playground/.strapi/client/index.html @@ -0,0 +1,62 @@ + + + + + + + + + Strapi Admin + + + +
+ + + diff --git a/playground/config/plugins.js b/playground/config/plugins.js index e321c68..ed733d3 100644 --- a/playground/config/plugins.js +++ b/playground/config/plugins.js @@ -3,7 +3,18 @@ module.exports = { enabled: true, config: { importOnBootstrap: false, - minify: true, + minify: false, + customTypes: [ + { + configName: "home", + queryString: "api::home.home", + uid: ["slug"], + components: [ + "Profile", + "Profile.ContactInfo", + ], + } + ] }, }, }; diff --git a/playground/src/api/home/content-types/home/schema.json b/playground/src/api/home/content-types/home/schema.json new file mode 100644 index 0000000..4f55a03 --- /dev/null +++ b/playground/src/api/home/content-types/home/schema.json @@ -0,0 +1,28 @@ +{ + "kind": "singleType", + "collectionName": "homes", + "info": { + "singularName": "home", + "pluralName": "homes", + "displayName": "Home", + "description": "" + }, + "options": { + "draftAndPublish": false + }, + "pluginOptions": {}, + "attributes": { + "title": { + "type": "string" + }, + "Profile": { + "type": "component", + "repeatable": false, + "component": "core.profile" + }, + "slug": { + "type": "uid", + "targetField": "title" + } + } +} diff --git a/playground/src/api/home/controllers/home.js b/playground/src/api/home/controllers/home.js new file mode 100644 index 0000000..b4dc6c0 --- /dev/null +++ b/playground/src/api/home/controllers/home.js @@ -0,0 +1,9 @@ +'use strict'; + +/** + * home controller + */ + +const { createCoreController } = require('@strapi/strapi').factories; + +module.exports = createCoreController('api::home.home'); diff --git a/playground/src/api/home/routes/home.js b/playground/src/api/home/routes/home.js new file mode 100644 index 0000000..63ca7fd --- /dev/null +++ b/playground/src/api/home/routes/home.js @@ -0,0 +1,9 @@ +'use strict'; + +/** + * home router + */ + +const { createCoreRouter } = require('@strapi/strapi').factories; + +module.exports = createCoreRouter('api::home.home'); diff --git a/playground/src/api/home/services/home.js b/playground/src/api/home/services/home.js new file mode 100644 index 0000000..64e6d32 --- /dev/null +++ b/playground/src/api/home/services/home.js @@ -0,0 +1,9 @@ +'use strict'; + +/** + * home service + */ + +const { createCoreService } = require('@strapi/strapi').factories; + +module.exports = createCoreService('api::home.home'); diff --git a/playground/src/api/page/content-types/page/schema.json b/playground/src/api/page/content-types/page/schema.json new file mode 100644 index 0000000..f5c7e93 --- /dev/null +++ b/playground/src/api/page/content-types/page/schema.json @@ -0,0 +1,19 @@ +{ + "kind": "collectionType", + "collectionName": "pages", + "info": { + "singularName": "page", + "pluralName": "pages", + "displayName": "Page" + }, + "options": { + "draftAndPublish": false + }, + "pluginOptions": {}, + "attributes": { + "title": { + "type": "string", + "required": true + } + } +} diff --git a/playground/src/api/page/controllers/page.js b/playground/src/api/page/controllers/page.js new file mode 100644 index 0000000..61fe8a7 --- /dev/null +++ b/playground/src/api/page/controllers/page.js @@ -0,0 +1,9 @@ +'use strict'; + +/** + * page controller + */ + +const { createCoreController } = require('@strapi/strapi').factories; + +module.exports = createCoreController('api::page.page'); diff --git a/playground/src/api/page/routes/page.js b/playground/src/api/page/routes/page.js new file mode 100644 index 0000000..258307a --- /dev/null +++ b/playground/src/api/page/routes/page.js @@ -0,0 +1,9 @@ +'use strict'; + +/** + * page router + */ + +const { createCoreRouter } = require('@strapi/strapi').factories; + +module.exports = createCoreRouter('api::page.page'); diff --git a/playground/src/api/page/services/page.js b/playground/src/api/page/services/page.js new file mode 100644 index 0000000..d5abde4 --- /dev/null +++ b/playground/src/api/page/services/page.js @@ -0,0 +1,9 @@ +'use strict'; + +/** + * page service + */ + +const { createCoreService } = require('@strapi/strapi').factories; + +module.exports = createCoreService('api::page.page'); diff --git a/playground/src/components/core/contact-info.json b/playground/src/components/core/contact-info.json new file mode 100644 index 0000000..ba435db --- /dev/null +++ b/playground/src/components/core/contact-info.json @@ -0,0 +1,15 @@ +{ + "collectionName": "components_core_contact_infos", + "info": { + "displayName": "ContactInfo" + }, + "options": {}, + "attributes": { + "Phonenumber": { + "type": "string" + }, + "Email": { + "type": "string" + } + } +} diff --git a/playground/src/components/core/profile.json b/playground/src/components/core/profile.json new file mode 100644 index 0000000..18848ef --- /dev/null +++ b/playground/src/components/core/profile.json @@ -0,0 +1,18 @@ +{ + "collectionName": "components_core_profiles", + "info": { + "displayName": "Profile", + "description": "" + }, + "options": {}, + "attributes": { + "title": { + "type": "string" + }, + "ContactInfo": { + "type": "component", + "repeatable": true, + "component": "core.contact-info" + } + } +} diff --git a/playground/types/generated/components.d.ts b/playground/types/generated/components.d.ts new file mode 100644 index 0000000..7fb9838 --- /dev/null +++ b/playground/types/generated/components.d.ts @@ -0,0 +1,33 @@ +import type { Schema, Attribute } from '@strapi/strapi'; + +export interface CoreProfile extends Schema.Component { + collectionName: 'components_core_profiles'; + info: { + displayName: 'Profile'; + description: ''; + }; + attributes: { + title: Attribute.String; + ContactInfo: Attribute.Component<'core.contact-info', true>; + }; +} + +export interface CoreContactInfo extends Schema.Component { + collectionName: 'components_core_contact_infos'; + info: { + displayName: 'ContactInfo'; + }; + attributes: { + Phonenumber: Attribute.String; + Email: Attribute.String; + }; +} + +declare module '@strapi/types' { + export module Shared { + export interface Components { + 'core.profile': CoreProfile; + 'core.contact-info': CoreContactInfo; + } + } +} diff --git a/playground/types/generated/contentTypes.d.ts b/playground/types/generated/contentTypes.d.ts new file mode 100644 index 0000000..64d1520 --- /dev/null +++ b/playground/types/generated/contentTypes.d.ts @@ -0,0 +1,858 @@ +import type { Schema, Attribute } from '@strapi/strapi'; + +export interface AdminPermission extends Schema.CollectionType { + collectionName: 'admin_permissions'; + info: { + name: 'Permission'; + description: ''; + singularName: 'permission'; + pluralName: 'permissions'; + displayName: 'Permission'; + }; + pluginOptions: { + 'content-manager': { + visible: false; + }; + 'content-type-builder': { + visible: false; + }; + }; + attributes: { + action: Attribute.String & + Attribute.Required & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + actionParameters: Attribute.JSON & Attribute.DefaultTo<{}>; + subject: Attribute.String & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + properties: Attribute.JSON & Attribute.DefaultTo<{}>; + conditions: Attribute.JSON & Attribute.DefaultTo<[]>; + role: Attribute.Relation<'admin::permission', 'manyToOne', 'admin::role'>; + createdAt: Attribute.DateTime; + updatedAt: Attribute.DateTime; + createdBy: Attribute.Relation< + 'admin::permission', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + updatedBy: Attribute.Relation< + 'admin::permission', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + }; +} + +export interface AdminUser extends Schema.CollectionType { + collectionName: 'admin_users'; + info: { + name: 'User'; + description: ''; + singularName: 'user'; + pluralName: 'users'; + displayName: 'User'; + }; + pluginOptions: { + 'content-manager': { + visible: false; + }; + 'content-type-builder': { + visible: false; + }; + }; + attributes: { + firstname: Attribute.String & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + lastname: Attribute.String & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + username: Attribute.String; + email: Attribute.Email & + Attribute.Required & + Attribute.Private & + Attribute.Unique & + Attribute.SetMinMaxLength<{ + minLength: 6; + }>; + password: Attribute.Password & + Attribute.Private & + Attribute.SetMinMaxLength<{ + minLength: 6; + }>; + resetPasswordToken: Attribute.String & Attribute.Private; + registrationToken: Attribute.String & Attribute.Private; + isActive: Attribute.Boolean & + Attribute.Private & + Attribute.DefaultTo; + roles: Attribute.Relation<'admin::user', 'manyToMany', 'admin::role'> & + Attribute.Private; + blocked: Attribute.Boolean & Attribute.Private & Attribute.DefaultTo; + preferedLanguage: Attribute.String; + createdAt: Attribute.DateTime; + updatedAt: Attribute.DateTime; + createdBy: Attribute.Relation<'admin::user', 'oneToOne', 'admin::user'> & + Attribute.Private; + updatedBy: Attribute.Relation<'admin::user', 'oneToOne', 'admin::user'> & + Attribute.Private; + }; +} + +export interface AdminRole extends Schema.CollectionType { + collectionName: 'admin_roles'; + info: { + name: 'Role'; + description: ''; + singularName: 'role'; + pluralName: 'roles'; + displayName: 'Role'; + }; + pluginOptions: { + 'content-manager': { + visible: false; + }; + 'content-type-builder': { + visible: false; + }; + }; + attributes: { + name: Attribute.String & + Attribute.Required & + Attribute.Unique & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + code: Attribute.String & + Attribute.Required & + Attribute.Unique & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + description: Attribute.String; + users: Attribute.Relation<'admin::role', 'manyToMany', 'admin::user'>; + permissions: Attribute.Relation< + 'admin::role', + 'oneToMany', + 'admin::permission' + >; + createdAt: Attribute.DateTime; + updatedAt: Attribute.DateTime; + createdBy: Attribute.Relation<'admin::role', 'oneToOne', 'admin::user'> & + Attribute.Private; + updatedBy: Attribute.Relation<'admin::role', 'oneToOne', 'admin::user'> & + Attribute.Private; + }; +} + +export interface AdminApiToken extends Schema.CollectionType { + collectionName: 'strapi_api_tokens'; + info: { + name: 'Api Token'; + singularName: 'api-token'; + pluralName: 'api-tokens'; + displayName: 'Api Token'; + description: ''; + }; + pluginOptions: { + 'content-manager': { + visible: false; + }; + 'content-type-builder': { + visible: false; + }; + }; + attributes: { + name: Attribute.String & + Attribute.Required & + Attribute.Unique & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + description: Attribute.String & + Attribute.SetMinMaxLength<{ + minLength: 1; + }> & + Attribute.DefaultTo<''>; + type: Attribute.Enumeration<['read-only', 'full-access', 'custom']> & + Attribute.Required & + Attribute.DefaultTo<'read-only'>; + accessKey: Attribute.String & + Attribute.Required & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + lastUsedAt: Attribute.DateTime; + permissions: Attribute.Relation< + 'admin::api-token', + 'oneToMany', + 'admin::api-token-permission' + >; + expiresAt: Attribute.DateTime; + lifespan: Attribute.BigInteger; + createdAt: Attribute.DateTime; + updatedAt: Attribute.DateTime; + createdBy: Attribute.Relation< + 'admin::api-token', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + updatedBy: Attribute.Relation< + 'admin::api-token', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + }; +} + +export interface AdminApiTokenPermission extends Schema.CollectionType { + collectionName: 'strapi_api_token_permissions'; + info: { + name: 'API Token Permission'; + description: ''; + singularName: 'api-token-permission'; + pluralName: 'api-token-permissions'; + displayName: 'API Token Permission'; + }; + pluginOptions: { + 'content-manager': { + visible: false; + }; + 'content-type-builder': { + visible: false; + }; + }; + attributes: { + action: Attribute.String & + Attribute.Required & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + token: Attribute.Relation< + 'admin::api-token-permission', + 'manyToOne', + 'admin::api-token' + >; + createdAt: Attribute.DateTime; + updatedAt: Attribute.DateTime; + createdBy: Attribute.Relation< + 'admin::api-token-permission', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + updatedBy: Attribute.Relation< + 'admin::api-token-permission', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + }; +} + +export interface AdminTransferToken extends Schema.CollectionType { + collectionName: 'strapi_transfer_tokens'; + info: { + name: 'Transfer Token'; + singularName: 'transfer-token'; + pluralName: 'transfer-tokens'; + displayName: 'Transfer Token'; + description: ''; + }; + pluginOptions: { + 'content-manager': { + visible: false; + }; + 'content-type-builder': { + visible: false; + }; + }; + attributes: { + name: Attribute.String & + Attribute.Required & + Attribute.Unique & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + description: Attribute.String & + Attribute.SetMinMaxLength<{ + minLength: 1; + }> & + Attribute.DefaultTo<''>; + accessKey: Attribute.String & + Attribute.Required & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + lastUsedAt: Attribute.DateTime; + permissions: Attribute.Relation< + 'admin::transfer-token', + 'oneToMany', + 'admin::transfer-token-permission' + >; + expiresAt: Attribute.DateTime; + lifespan: Attribute.BigInteger; + createdAt: Attribute.DateTime; + updatedAt: Attribute.DateTime; + createdBy: Attribute.Relation< + 'admin::transfer-token', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + updatedBy: Attribute.Relation< + 'admin::transfer-token', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + }; +} + +export interface AdminTransferTokenPermission extends Schema.CollectionType { + collectionName: 'strapi_transfer_token_permissions'; + info: { + name: 'Transfer Token Permission'; + description: ''; + singularName: 'transfer-token-permission'; + pluralName: 'transfer-token-permissions'; + displayName: 'Transfer Token Permission'; + }; + pluginOptions: { + 'content-manager': { + visible: false; + }; + 'content-type-builder': { + visible: false; + }; + }; + attributes: { + action: Attribute.String & + Attribute.Required & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + token: Attribute.Relation< + 'admin::transfer-token-permission', + 'manyToOne', + 'admin::transfer-token' + >; + createdAt: Attribute.DateTime; + updatedAt: Attribute.DateTime; + createdBy: Attribute.Relation< + 'admin::transfer-token-permission', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + updatedBy: Attribute.Relation< + 'admin::transfer-token-permission', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + }; +} + +export interface PluginUploadFile extends Schema.CollectionType { + collectionName: 'files'; + info: { + singularName: 'file'; + pluralName: 'files'; + displayName: 'File'; + description: ''; + }; + pluginOptions: { + 'content-manager': { + visible: false; + }; + 'content-type-builder': { + visible: false; + }; + }; + attributes: { + name: Attribute.String & Attribute.Required; + alternativeText: Attribute.String; + caption: Attribute.String; + width: Attribute.Integer; + height: Attribute.Integer; + formats: Attribute.JSON; + hash: Attribute.String & Attribute.Required; + ext: Attribute.String; + mime: Attribute.String & Attribute.Required; + size: Attribute.Decimal & Attribute.Required; + url: Attribute.String & Attribute.Required; + previewUrl: Attribute.String; + provider: Attribute.String & Attribute.Required; + provider_metadata: Attribute.JSON; + related: Attribute.Relation<'plugin::upload.file', 'morphToMany'>; + folder: Attribute.Relation< + 'plugin::upload.file', + 'manyToOne', + 'plugin::upload.folder' + > & + Attribute.Private; + folderPath: Attribute.String & + Attribute.Required & + Attribute.Private & + Attribute.SetMinMax< + { + min: 1; + }, + number + >; + createdAt: Attribute.DateTime; + updatedAt: Attribute.DateTime; + createdBy: Attribute.Relation< + 'plugin::upload.file', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + updatedBy: Attribute.Relation< + 'plugin::upload.file', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + }; +} + +export interface PluginUploadFolder extends Schema.CollectionType { + collectionName: 'upload_folders'; + info: { + singularName: 'folder'; + pluralName: 'folders'; + displayName: 'Folder'; + }; + pluginOptions: { + 'content-manager': { + visible: false; + }; + 'content-type-builder': { + visible: false; + }; + }; + attributes: { + name: Attribute.String & + Attribute.Required & + Attribute.SetMinMax< + { + min: 1; + }, + number + >; + pathId: Attribute.Integer & Attribute.Required & Attribute.Unique; + parent: Attribute.Relation< + 'plugin::upload.folder', + 'manyToOne', + 'plugin::upload.folder' + >; + children: Attribute.Relation< + 'plugin::upload.folder', + 'oneToMany', + 'plugin::upload.folder' + >; + files: Attribute.Relation< + 'plugin::upload.folder', + 'oneToMany', + 'plugin::upload.file' + >; + path: Attribute.String & + Attribute.Required & + Attribute.SetMinMax< + { + min: 1; + }, + number + >; + createdAt: Attribute.DateTime; + updatedAt: Attribute.DateTime; + createdBy: Attribute.Relation< + 'plugin::upload.folder', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + updatedBy: Attribute.Relation< + 'plugin::upload.folder', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + }; +} + +export interface PluginContentReleasesRelease extends Schema.CollectionType { + collectionName: 'strapi_releases'; + info: { + singularName: 'release'; + pluralName: 'releases'; + displayName: 'Release'; + }; + options: { + draftAndPublish: false; + }; + pluginOptions: { + 'content-manager': { + visible: false; + }; + 'content-type-builder': { + visible: false; + }; + }; + attributes: { + name: Attribute.String & Attribute.Required; + releasedAt: Attribute.DateTime; + scheduledAt: Attribute.DateTime; + timezone: Attribute.String; + status: Attribute.Enumeration< + ['ready', 'blocked', 'failed', 'done', 'empty'] + > & + Attribute.Required; + actions: Attribute.Relation< + 'plugin::content-releases.release', + 'oneToMany', + 'plugin::content-releases.release-action' + >; + createdAt: Attribute.DateTime; + updatedAt: Attribute.DateTime; + createdBy: Attribute.Relation< + 'plugin::content-releases.release', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + updatedBy: Attribute.Relation< + 'plugin::content-releases.release', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + }; +} + +export interface PluginContentReleasesReleaseAction + extends Schema.CollectionType { + collectionName: 'strapi_release_actions'; + info: { + singularName: 'release-action'; + pluralName: 'release-actions'; + displayName: 'Release Action'; + }; + options: { + draftAndPublish: false; + }; + pluginOptions: { + 'content-manager': { + visible: false; + }; + 'content-type-builder': { + visible: false; + }; + }; + attributes: { + type: Attribute.Enumeration<['publish', 'unpublish']> & Attribute.Required; + entry: Attribute.Relation< + 'plugin::content-releases.release-action', + 'morphToOne' + >; + contentType: Attribute.String & Attribute.Required; + locale: Attribute.String; + release: Attribute.Relation< + 'plugin::content-releases.release-action', + 'manyToOne', + 'plugin::content-releases.release' + >; + isEntryValid: Attribute.Boolean; + createdAt: Attribute.DateTime; + updatedAt: Attribute.DateTime; + createdBy: Attribute.Relation< + 'plugin::content-releases.release-action', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + updatedBy: Attribute.Relation< + 'plugin::content-releases.release-action', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + }; +} + +export interface PluginI18NLocale extends Schema.CollectionType { + collectionName: 'i18n_locale'; + info: { + singularName: 'locale'; + pluralName: 'locales'; + collectionName: 'locales'; + displayName: 'Locale'; + description: ''; + }; + options: { + draftAndPublish: false; + }; + pluginOptions: { + 'content-manager': { + visible: false; + }; + 'content-type-builder': { + visible: false; + }; + }; + attributes: { + name: Attribute.String & + Attribute.SetMinMax< + { + min: 1; + max: 50; + }, + number + >; + code: Attribute.String & Attribute.Unique; + createdAt: Attribute.DateTime; + updatedAt: Attribute.DateTime; + createdBy: Attribute.Relation< + 'plugin::i18n.locale', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + updatedBy: Attribute.Relation< + 'plugin::i18n.locale', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + }; +} + +export interface PluginUsersPermissionsPermission + extends Schema.CollectionType { + collectionName: 'up_permissions'; + info: { + name: 'permission'; + description: ''; + singularName: 'permission'; + pluralName: 'permissions'; + displayName: 'Permission'; + }; + pluginOptions: { + 'content-manager': { + visible: false; + }; + 'content-type-builder': { + visible: false; + }; + }; + attributes: { + action: Attribute.String & Attribute.Required; + role: Attribute.Relation< + 'plugin::users-permissions.permission', + 'manyToOne', + 'plugin::users-permissions.role' + >; + createdAt: Attribute.DateTime; + updatedAt: Attribute.DateTime; + createdBy: Attribute.Relation< + 'plugin::users-permissions.permission', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + updatedBy: Attribute.Relation< + 'plugin::users-permissions.permission', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + }; +} + +export interface PluginUsersPermissionsRole extends Schema.CollectionType { + collectionName: 'up_roles'; + info: { + name: 'role'; + description: ''; + singularName: 'role'; + pluralName: 'roles'; + displayName: 'Role'; + }; + pluginOptions: { + 'content-manager': { + visible: false; + }; + 'content-type-builder': { + visible: false; + }; + }; + attributes: { + name: Attribute.String & + Attribute.Required & + Attribute.SetMinMaxLength<{ + minLength: 3; + }>; + description: Attribute.String; + type: Attribute.String & Attribute.Unique; + permissions: Attribute.Relation< + 'plugin::users-permissions.role', + 'oneToMany', + 'plugin::users-permissions.permission' + >; + users: Attribute.Relation< + 'plugin::users-permissions.role', + 'oneToMany', + 'plugin::users-permissions.user' + >; + createdAt: Attribute.DateTime; + updatedAt: Attribute.DateTime; + createdBy: Attribute.Relation< + 'plugin::users-permissions.role', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + updatedBy: Attribute.Relation< + 'plugin::users-permissions.role', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + }; +} + +export interface PluginUsersPermissionsUser extends Schema.CollectionType { + collectionName: 'up_users'; + info: { + name: 'user'; + description: ''; + singularName: 'user'; + pluralName: 'users'; + displayName: 'User'; + }; + options: { + draftAndPublish: false; + timestamps: true; + }; + attributes: { + username: Attribute.String & + Attribute.Required & + Attribute.Unique & + Attribute.SetMinMaxLength<{ + minLength: 3; + }>; + email: Attribute.Email & + Attribute.Required & + Attribute.SetMinMaxLength<{ + minLength: 6; + }>; + provider: Attribute.String; + password: Attribute.Password & + Attribute.Private & + Attribute.SetMinMaxLength<{ + minLength: 6; + }>; + resetPasswordToken: Attribute.String & Attribute.Private; + confirmationToken: Attribute.String & Attribute.Private; + confirmed: Attribute.Boolean & Attribute.DefaultTo; + blocked: Attribute.Boolean & Attribute.DefaultTo; + role: Attribute.Relation< + 'plugin::users-permissions.user', + 'manyToOne', + 'plugin::users-permissions.role' + >; + createdAt: Attribute.DateTime; + updatedAt: Attribute.DateTime; + createdBy: Attribute.Relation< + 'plugin::users-permissions.user', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + updatedBy: Attribute.Relation< + 'plugin::users-permissions.user', + 'oneToOne', + 'admin::user' + > & + Attribute.Private; + }; +} + +export interface ApiHomeHome extends Schema.SingleType { + collectionName: 'homes'; + info: { + singularName: 'home'; + pluralName: 'homes'; + displayName: 'Home'; + description: ''; + }; + options: { + draftAndPublish: false; + }; + attributes: { + title: Attribute.String; + Profile: Attribute.Component<'core.profile'>; + slug: Attribute.UID<'api::home.home', 'title'>; + createdAt: Attribute.DateTime; + updatedAt: Attribute.DateTime; + createdBy: Attribute.Relation<'api::home.home', 'oneToOne', 'admin::user'> & + Attribute.Private; + updatedBy: Attribute.Relation<'api::home.home', 'oneToOne', 'admin::user'> & + Attribute.Private; + }; +} + +export interface ApiPagePage extends Schema.CollectionType { + collectionName: 'pages'; + info: { + singularName: 'page'; + pluralName: 'pages'; + displayName: 'Page'; + }; + options: { + draftAndPublish: false; + }; + attributes: { + title: Attribute.String & Attribute.Required; + createdAt: Attribute.DateTime; + updatedAt: Attribute.DateTime; + createdBy: Attribute.Relation<'api::page.page', 'oneToOne', 'admin::user'> & + Attribute.Private; + updatedBy: Attribute.Relation<'api::page.page', 'oneToOne', 'admin::user'> & + Attribute.Private; + }; +} + +declare module '@strapi/types' { + export module Shared { + export interface ContentTypes { + 'admin::permission': AdminPermission; + 'admin::user': AdminUser; + 'admin::role': AdminRole; + 'admin::api-token': AdminApiToken; + 'admin::api-token-permission': AdminApiTokenPermission; + 'admin::transfer-token': AdminTransferToken; + 'admin::transfer-token-permission': AdminTransferTokenPermission; + 'plugin::upload.file': PluginUploadFile; + 'plugin::upload.folder': PluginUploadFolder; + 'plugin::content-releases.release': PluginContentReleasesRelease; + 'plugin::content-releases.release-action': PluginContentReleasesReleaseAction; + 'plugin::i18n.locale': PluginI18NLocale; + 'plugin::users-permissions.permission': PluginUsersPermissionsPermission; + 'plugin::users-permissions.role': PluginUsersPermissionsRole; + 'plugin::users-permissions.user': PluginUsersPermissionsUser; + 'api::home.home': ApiHomeHome; + 'api::page.page': ApiPagePage; + } + } +} From 75634a30d210757629a1e4a1624f1459dba5c4ae Mon Sep 17 00:00:00 2001 From: Boaz Poolman Date: Thu, 8 Aug 2024 12:35:57 +0200 Subject: [PATCH 2/2] fix: recursively santize all config except for content_manager_configuration items --- server/config/type.js | 15 +++++++++------ server/utils/index.js | 27 ++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/server/config/type.js b/server/config/type.js index 3bb3b46..468a8e3 100644 --- a/server/config/type.js +++ b/server/config/type.js @@ -109,7 +109,10 @@ const ConfigType = class ConfigType { if (softImport && !force) return false; // Format JSON fields. - configContent = sanitizeConfig(configContent); + configContent = sanitizeConfig({ + config: configContent, + configName, + }); const query = { ...configContent }; this.jsonFields.map((field) => query[field] = JSON.stringify(configContent[field])); @@ -120,8 +123,8 @@ const ConfigType = class ConfigType { // Delete/create relations. await Promise.all(this.relations.map(async ({ queryString, relationName, parentName, relationSortFields }) => { const relationQueryApi = strapi.query(queryString); - existingConfig = sanitizeConfig(existingConfig, relationName, relationSortFields); - configContent = sanitizeConfig(configContent, relationName, relationSortFields); + existingConfig = sanitizeConfig({ config: existingConfig, configName, relation: relationName, relationSortFields }); + configContent = sanitizeConfig({ config: configContent, configName, relation: relationName, relationSortFields }); const configToAdd = difference(configContent[relationName], existingConfig[relationName], relationSortFields); const configToDelete = difference(existingConfig[relationName], configContent[relationName], relationSortFields); @@ -201,7 +204,7 @@ const ConfigType = class ConfigType { }); const configs = {}; - await Promise.all(Object.values(AllConfig).map(async (config) => { + await Promise.all(Object.entries(AllConfig).map(async ([configName, config]) => { const combinedUid = getCombinedUid(this.uidKeys, config); const combinedUidWhereFilter = getCombinedUidWhereFilter(this.uidKeys, config); @@ -214,13 +217,13 @@ const ConfigType = class ConfigType { const shouldExclude = !isEmpty(strapi.config.get('plugin.config-sync.excludedConfig').filter((option) => `${this.configPrefix}.${combinedUid}`.startsWith(option))); if (shouldExclude) return; - const formattedConfig = { ...sanitizeConfig(config) }; + const formattedConfig = { ...sanitizeConfig({ config, configName }) }; await Promise.all(this.relations.map(async ({ queryString, relationName, relationSortFields, parentName }) => { const relations = await noLimit(strapi.query(queryString), { where: { [parentName]: combinedUidWhereFilter }, }); - relations.map((relation) => sanitizeConfig(relation)); + relations.map((relation) => sanitizeConfig({ config: relation, configName: relationName })); relationSortFields.map((sortField) => { relations.sort(dynamicSort(sortField)); }); diff --git a/server/utils/index.js b/server/utils/index.js index 4a6c6f9..b29c2a8 100644 --- a/server/utils/index.js +++ b/server/utils/index.js @@ -46,7 +46,12 @@ const dynamicSort = (property) => { }; }; -const sanitizeConfig = (config, relation, relationSortFields) => { +const sanitizeConfig = ({ + config, + relation, + relationSortFields, + configName, +}) => { delete config._id; delete config.id; delete config.updatedAt; @@ -74,6 +79,26 @@ const sanitizeConfig = (config, relation, relationSortFields) => { config[relation] = formattedRelations; } + // We recursively sanitize the config to remove environment specific data. + // Except for the plugin_content_manager_configuration. + // This is because that stores the "edit the view" data which includes only configuration, not content. + if (configName && !configName.startsWith('plugin_content_manager_configuration_')) { + const recursiveSanitizeConfig = (recursivedSanitizedConfig) => { + delete recursivedSanitizedConfig._id; + delete recursivedSanitizedConfig.id; + delete recursivedSanitizedConfig.updatedAt; + delete recursivedSanitizedConfig.createdAt; + + Object.keys(recursivedSanitizedConfig).map((key, index) => { + if (recursivedSanitizedConfig[key] && typeof recursivedSanitizedConfig[key] === "object") { + recursiveSanitizeConfig(recursivedSanitizedConfig[key]); + } + }); + }; + + recursiveSanitizeConfig(config); + } + return config; };