@strapi/data-transfer 5.52.2 → 5.53.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/dist/strapi/index.d.ts +1 -0
- package/dist/strapi/index.d.ts.map +1 -1
- package/dist/strapi/index.js +9 -0
- package/dist/strapi/index.js.map +1 -1
- package/dist/strapi/index.mjs +1 -0
- package/dist/strapi/index.mjs.map +1 -1
- package/dist/strapi/providers/local-destination/strategies/restore/configuration.js +2 -2
- package/dist/strapi/providers/local-destination/strategies/restore/configuration.js.map +1 -1
- package/dist/strapi/providers/local-destination/strategies/restore/configuration.mjs +2 -2
- package/dist/strapi/providers/local-destination/strategies/restore/configuration.mjs.map +1 -1
- package/dist/strapi/providers/local-destination/strategies/restore/index.d.ts.map +1 -1
- package/dist/strapi/providers/local-destination/strategies/restore/index.js +1 -1
- package/dist/strapi/providers/local-destination/strategies/restore/index.js.map +1 -1
- package/dist/strapi/providers/local-destination/strategies/restore/index.mjs +1 -1
- package/dist/strapi/providers/local-destination/strategies/restore/index.mjs.map +1 -1
- package/dist/strapi/remote/handlers/push.d.ts +14 -0
- package/dist/strapi/remote/handlers/push.d.ts.map +1 -1
- package/dist/strapi/remote/handlers/push.js +104 -9
- package/dist/strapi/remote/handlers/push.js.map +1 -1
- package/dist/strapi/remote/handlers/push.mjs +103 -10
- package/dist/strapi/remote/handlers/push.mjs.map +1 -1
- package/dist/strapi/transfer-policy.d.ts +12 -0
- package/dist/strapi/transfer-policy.d.ts.map +1 -0
- package/dist/strapi/transfer-policy.js +163 -0
- package/dist/strapi/transfer-policy.js.map +1 -0
- package/dist/strapi/transfer-policy.mjs +154 -0
- package/dist/strapi/transfer-policy.mjs.map +1 -0
- package/package.json +6 -6
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var providers = require('../errors/providers.js');
|
|
4
|
+
|
|
5
|
+
const ADMIN_UID_PREFIX = 'admin::';
|
|
6
|
+
const OFFICIAL_TRANSFER_IGNORED_TYPES = [
|
|
7
|
+
'plugin::content-releases.release',
|
|
8
|
+
'plugin::content-releases.release-action'
|
|
9
|
+
];
|
|
10
|
+
const isRecord = (value)=>typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
11
|
+
const isProtectedRemotePushType = (uid)=>uid.startsWith(ADMIN_UID_PREFIX);
|
|
12
|
+
const isIgnoredOfficialTransferType = (uid)=>isProtectedRemotePushType(uid) || OFFICIAL_TRANSFER_IGNORED_TYPES.includes(uid);
|
|
13
|
+
const getIgnoredOfficialTransferTypes = ()=>[
|
|
14
|
+
...OFFICIAL_TRANSFER_IGNORED_TYPES
|
|
15
|
+
];
|
|
16
|
+
const getProtectedTransferUIDs = (strapi)=>{
|
|
17
|
+
const contentTypes = Object.keys(strapi.contentTypes);
|
|
18
|
+
const models = strapi.get('models').get();
|
|
19
|
+
return [
|
|
20
|
+
...new Set([
|
|
21
|
+
...contentTypes,
|
|
22
|
+
...models.map(({ uid })=>uid)
|
|
23
|
+
].filter(isProtectedRemotePushType))
|
|
24
|
+
];
|
|
25
|
+
};
|
|
26
|
+
const normalizeRemoteRestoreOptions = (strapi, restore = {})=>{
|
|
27
|
+
const protectedUIDs = getProtectedTransferUIDs(strapi);
|
|
28
|
+
const entities = {
|
|
29
|
+
...restore.entities
|
|
30
|
+
};
|
|
31
|
+
delete entities.filters;
|
|
32
|
+
return {
|
|
33
|
+
...restore,
|
|
34
|
+
entities: {
|
|
35
|
+
...entities,
|
|
36
|
+
...entities.include ? {
|
|
37
|
+
include: entities.include.filter((uid)=>!isProtectedRemotePushType(uid))
|
|
38
|
+
} : {},
|
|
39
|
+
exclude: [
|
|
40
|
+
...new Set([
|
|
41
|
+
...entities.exclude ?? [],
|
|
42
|
+
...protectedUIDs
|
|
43
|
+
])
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
const protectedTypeError = (uid, path)=>new providers.ProviderTransferError(`Remote push cannot transfer protected type "${uid}" at ${path}`);
|
|
49
|
+
const invalidPayloadError = (path, reason)=>new providers.ProviderTransferError(`Remote push received invalid relation payload at ${path}: ${reason}`);
|
|
50
|
+
const getSchema = (strapi, uid, path)=>{
|
|
51
|
+
const schema = strapi.getModel(uid);
|
|
52
|
+
if (!schema) {
|
|
53
|
+
throw invalidPayloadError(path, `unknown schema "${uid}"`);
|
|
54
|
+
}
|
|
55
|
+
return schema;
|
|
56
|
+
};
|
|
57
|
+
const getDatabaseSchema = (strapi, uid, path)=>{
|
|
58
|
+
const schema = strapi.db.metadata.get(uid);
|
|
59
|
+
if (!schema) {
|
|
60
|
+
throw invalidPayloadError(path, `unknown database schema "${uid}"`);
|
|
61
|
+
}
|
|
62
|
+
return schema;
|
|
63
|
+
};
|
|
64
|
+
const assertPolymorphicValueAllowed = (value, typeField, path)=>{
|
|
65
|
+
const values = Array.isArray(value) ? value : [
|
|
66
|
+
value
|
|
67
|
+
];
|
|
68
|
+
for (const entry of values){
|
|
69
|
+
if (!isRecord(entry) || typeof entry[typeField] !== 'string') {
|
|
70
|
+
throw invalidPayloadError(path, `missing polymorphic discriminator "${typeField}"`);
|
|
71
|
+
}
|
|
72
|
+
const target = entry[typeField];
|
|
73
|
+
if (isProtectedRemotePushType(target)) {
|
|
74
|
+
throw protectedTypeError(target, path);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const assertComponentValueAllowed = (strapi, componentUID, value, path, repeatable)=>{
|
|
79
|
+
if (!repeatable && value === null) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const values = repeatable ? value : [
|
|
83
|
+
value
|
|
84
|
+
];
|
|
85
|
+
if (repeatable && !Array.isArray(value) || !Array.isArray(values)) {
|
|
86
|
+
throw invalidPayloadError(path, 'expected component value');
|
|
87
|
+
}
|
|
88
|
+
for (const entry of values){
|
|
89
|
+
if (!isRecord(entry)) {
|
|
90
|
+
throw invalidPayloadError(path, 'expected component object');
|
|
91
|
+
}
|
|
92
|
+
assertSchemaDataAllowed(strapi, componentUID, entry, path);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
const assertDynamicZoneValueAllowed = (strapi, componentUIDs, value, path)=>{
|
|
96
|
+
if (!Array.isArray(value)) {
|
|
97
|
+
throw invalidPayloadError(path, 'expected dynamic zone array');
|
|
98
|
+
}
|
|
99
|
+
for (const entry of value){
|
|
100
|
+
if (!isRecord(entry) || typeof entry.__component !== 'string') {
|
|
101
|
+
throw invalidPayloadError(path, 'missing dynamic zone component discriminator');
|
|
102
|
+
}
|
|
103
|
+
const componentUID = entry.__component;
|
|
104
|
+
if (!componentUIDs.includes(componentUID)) {
|
|
105
|
+
throw invalidPayloadError(path, `unsupported dynamic zone component "${componentUID}"`);
|
|
106
|
+
}
|
|
107
|
+
assertSchemaDataAllowed(strapi, componentUID, entry, path);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
const assertSchemaDataAllowed = (strapi, uid, data, path)=>{
|
|
111
|
+
const schema = getSchema(strapi, uid, path);
|
|
112
|
+
const databaseSchema = getDatabaseSchema(strapi, uid, path);
|
|
113
|
+
for (const [field, value] of Object.entries(data)){
|
|
114
|
+
const attribute = schema.attributes?.[field];
|
|
115
|
+
if (!attribute) {
|
|
116
|
+
const protectedOwnerRelation = Object.values(databaseSchema.attributes ?? {}).find((candidate)=>candidate.type === 'relation' && candidate.owner === true && candidate.target && isProtectedRemotePushType(candidate.target) && candidate.joinColumn?.name === field);
|
|
117
|
+
if (protectedOwnerRelation?.target) {
|
|
118
|
+
throw protectedTypeError(protectedOwnerRelation.target, `${path}.${field}`);
|
|
119
|
+
}
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
const fieldPath = `${path}.${field}`;
|
|
123
|
+
if (attribute.type === 'relation') {
|
|
124
|
+
if (attribute.target && isProtectedRemotePushType(attribute.target)) {
|
|
125
|
+
throw protectedTypeError(attribute.target, fieldPath);
|
|
126
|
+
}
|
|
127
|
+
if (attribute.relation?.startsWith('morph')) {
|
|
128
|
+
assertPolymorphicValueAllowed(value, attribute.morphColumn?.typeField ?? '__type', fieldPath);
|
|
129
|
+
}
|
|
130
|
+
} else if (attribute.type === 'component' && attribute.component) {
|
|
131
|
+
assertComponentValueAllowed(strapi, attribute.component, value, fieldPath, attribute.repeatable === true);
|
|
132
|
+
} else if (attribute.type === 'dynamiczone') {
|
|
133
|
+
assertDynamicZoneValueAllowed(strapi, attribute.components ?? [], value, fieldPath);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
const assertRemoteEntityAllowed = (strapi, entity)=>{
|
|
138
|
+
if (isProtectedRemotePushType(entity.type)) {
|
|
139
|
+
throw protectedTypeError(entity.type, entity.type);
|
|
140
|
+
}
|
|
141
|
+
if (!isRecord(entity.data)) {
|
|
142
|
+
throw invalidPayloadError(entity.type, 'expected entity data object');
|
|
143
|
+
}
|
|
144
|
+
assertSchemaDataAllowed(strapi, entity.type, entity.data, entity.type);
|
|
145
|
+
};
|
|
146
|
+
const assertRemoteLinkAllowed = (link)=>{
|
|
147
|
+
if (isProtectedRemotePushType(link.left.type)) {
|
|
148
|
+
throw protectedTypeError(link.left.type, 'link.left');
|
|
149
|
+
}
|
|
150
|
+
if (isProtectedRemotePushType(link.right.type)) {
|
|
151
|
+
throw protectedTypeError(link.right.type, 'link.right');
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
exports.OFFICIAL_TRANSFER_IGNORED_TYPES = OFFICIAL_TRANSFER_IGNORED_TYPES;
|
|
156
|
+
exports.assertRemoteEntityAllowed = assertRemoteEntityAllowed;
|
|
157
|
+
exports.assertRemoteLinkAllowed = assertRemoteLinkAllowed;
|
|
158
|
+
exports.getIgnoredOfficialTransferTypes = getIgnoredOfficialTransferTypes;
|
|
159
|
+
exports.getProtectedTransferUIDs = getProtectedTransferUIDs;
|
|
160
|
+
exports.isIgnoredOfficialTransferType = isIgnoredOfficialTransferType;
|
|
161
|
+
exports.isProtectedRemotePushType = isProtectedRemotePushType;
|
|
162
|
+
exports.normalizeRemoteRestoreOptions = normalizeRemoteRestoreOptions;
|
|
163
|
+
//# sourceMappingURL=transfer-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transfer-policy.js","sources":["../../src/strapi/transfer-policy.ts"],"sourcesContent":["import type { Core, UID } from '@strapi/types';\n\nimport { ProviderTransferError } from '../errors/providers';\nimport type { IEntity, ILink } from '../types';\nimport type { IRestoreOptions } from './providers/local-destination/strategies/restore';\n\nconst ADMIN_UID_PREFIX = 'admin::';\n\nexport const OFFICIAL_TRANSFER_IGNORED_TYPES = [\n 'plugin::content-releases.release',\n 'plugin::content-releases.release-action',\n] as const;\n\ntype SchemaAttribute = {\n type?: string;\n target?: string;\n relation?: string;\n component?: string;\n components?: string[];\n repeatable?: boolean;\n morphColumn?: { typeField?: string };\n owner?: boolean;\n joinColumn?: { name?: string };\n};\n\ntype Schema = { attributes?: Record<string, SchemaAttribute> };\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nexport const isProtectedRemotePushType = (uid: string): boolean => uid.startsWith(ADMIN_UID_PREFIX);\n\nexport const isIgnoredOfficialTransferType = (uid: string): boolean =>\n isProtectedRemotePushType(uid) ||\n OFFICIAL_TRANSFER_IGNORED_TYPES.includes(uid as (typeof OFFICIAL_TRANSFER_IGNORED_TYPES)[number]);\n\nexport const getIgnoredOfficialTransferTypes = (): string[] => [...OFFICIAL_TRANSFER_IGNORED_TYPES];\n\nexport const getProtectedTransferUIDs = (strapi: Core.Strapi): string[] => {\n const contentTypes = Object.keys(strapi.contentTypes);\n const models = strapi.get('models').get() as Array<{ uid: string }>;\n\n return [\n ...new Set(\n [...contentTypes, ...models.map(({ uid }) => uid)].filter(isProtectedRemotePushType)\n ),\n ];\n};\n\nexport const normalizeRemoteRestoreOptions = (\n strapi: Core.Strapi,\n restore: IRestoreOptions = {}\n): IRestoreOptions => {\n const protectedUIDs = getProtectedTransferUIDs(strapi);\n const entities = { ...restore.entities };\n\n delete entities.filters;\n\n return {\n ...restore,\n entities: {\n ...entities,\n ...(entities.include\n ? { include: entities.include.filter((uid) => !isProtectedRemotePushType(uid)) }\n : {}),\n exclude: [...new Set([...(entities.exclude ?? []), ...protectedUIDs])],\n },\n };\n};\n\nconst protectedTypeError = (uid: string, path: string) =>\n new ProviderTransferError(`Remote push cannot transfer protected type \"${uid}\" at ${path}`);\n\nconst invalidPayloadError = (path: string, reason: string) =>\n new ProviderTransferError(`Remote push received invalid relation payload at ${path}: ${reason}`);\n\nconst getSchema = (strapi: Core.Strapi, uid: string, path: string): Schema => {\n const schema = strapi.getModel(uid as UID.Schema) as Schema | undefined;\n\n if (!schema) {\n throw invalidPayloadError(path, `unknown schema \"${uid}\"`);\n }\n\n return schema;\n};\n\nconst getDatabaseSchema = (strapi: Core.Strapi, uid: string, path: string): Schema => {\n const schema = strapi.db.metadata.get(uid as UID.Schema) as Schema | undefined;\n\n if (!schema) {\n throw invalidPayloadError(path, `unknown database schema \"${uid}\"`);\n }\n\n return schema;\n};\n\nconst assertPolymorphicValueAllowed = (value: unknown, typeField: string, path: string) => {\n const values = Array.isArray(value) ? value : [value];\n\n for (const entry of values) {\n if (!isRecord(entry) || typeof entry[typeField] !== 'string') {\n throw invalidPayloadError(path, `missing polymorphic discriminator \"${typeField}\"`);\n }\n\n const target = entry[typeField];\n if (isProtectedRemotePushType(target)) {\n throw protectedTypeError(target, path);\n }\n }\n};\n\nconst assertComponentValueAllowed = (\n strapi: Core.Strapi,\n componentUID: string,\n value: unknown,\n path: string,\n repeatable: boolean\n) => {\n if (!repeatable && value === null) {\n return;\n }\n\n const values = repeatable ? value : [value];\n\n if ((repeatable && !Array.isArray(value)) || !Array.isArray(values)) {\n throw invalidPayloadError(path, 'expected component value');\n }\n\n for (const entry of values) {\n if (!isRecord(entry)) {\n throw invalidPayloadError(path, 'expected component object');\n }\n assertSchemaDataAllowed(strapi, componentUID, entry, path);\n }\n};\n\nconst assertDynamicZoneValueAllowed = (\n strapi: Core.Strapi,\n componentUIDs: string[],\n value: unknown,\n path: string\n) => {\n if (!Array.isArray(value)) {\n throw invalidPayloadError(path, 'expected dynamic zone array');\n }\n\n for (const entry of value) {\n if (!isRecord(entry) || typeof entry.__component !== 'string') {\n throw invalidPayloadError(path, 'missing dynamic zone component discriminator');\n }\n\n const componentUID = entry.__component;\n if (!componentUIDs.includes(componentUID)) {\n throw invalidPayloadError(path, `unsupported dynamic zone component \"${componentUID}\"`);\n }\n\n assertSchemaDataAllowed(strapi, componentUID, entry, path);\n }\n};\n\nconst assertSchemaDataAllowed = (\n strapi: Core.Strapi,\n uid: string,\n data: Record<string, unknown>,\n path: string\n) => {\n const schema = getSchema(strapi, uid, path);\n const databaseSchema = getDatabaseSchema(strapi, uid, path);\n\n for (const [field, value] of Object.entries(data)) {\n const attribute = schema.attributes?.[field];\n if (!attribute) {\n const protectedOwnerRelation = Object.values(databaseSchema.attributes ?? {}).find(\n (candidate) =>\n candidate.type === 'relation' &&\n candidate.owner === true &&\n candidate.target &&\n isProtectedRemotePushType(candidate.target) &&\n candidate.joinColumn?.name === field\n );\n\n if (protectedOwnerRelation?.target) {\n throw protectedTypeError(protectedOwnerRelation.target, `${path}.${field}`);\n }\n continue;\n }\n\n const fieldPath = `${path}.${field}`;\n if (attribute.type === 'relation') {\n if (attribute.target && isProtectedRemotePushType(attribute.target)) {\n throw protectedTypeError(attribute.target, fieldPath);\n }\n if (attribute.relation?.startsWith('morph')) {\n assertPolymorphicValueAllowed(\n value,\n attribute.morphColumn?.typeField ?? '__type',\n fieldPath\n );\n }\n } else if (attribute.type === 'component' && attribute.component) {\n assertComponentValueAllowed(\n strapi,\n attribute.component,\n value,\n fieldPath,\n attribute.repeatable === true\n );\n } else if (attribute.type === 'dynamiczone') {\n assertDynamicZoneValueAllowed(strapi, attribute.components ?? [], value, fieldPath);\n }\n }\n};\n\nexport const assertRemoteEntityAllowed = (strapi: Core.Strapi, entity: IEntity): void => {\n if (isProtectedRemotePushType(entity.type)) {\n throw protectedTypeError(entity.type, entity.type);\n }\n\n if (!isRecord(entity.data)) {\n throw invalidPayloadError(entity.type, 'expected entity data object');\n }\n\n assertSchemaDataAllowed(strapi, entity.type, entity.data, entity.type);\n};\n\nexport const assertRemoteLinkAllowed = (link: ILink): void => {\n if (isProtectedRemotePushType(link.left.type)) {\n throw protectedTypeError(link.left.type, 'link.left');\n }\n if (isProtectedRemotePushType(link.right.type)) {\n throw protectedTypeError(link.right.type, 'link.right');\n }\n};\n"],"names":["ADMIN_UID_PREFIX","OFFICIAL_TRANSFER_IGNORED_TYPES","isRecord","value","Array","isArray","isProtectedRemotePushType","uid","startsWith","isIgnoredOfficialTransferType","includes","getIgnoredOfficialTransferTypes","getProtectedTransferUIDs","strapi","contentTypes","Object","keys","models","get","Set","map","filter","normalizeRemoteRestoreOptions","restore","protectedUIDs","entities","filters","include","exclude","protectedTypeError","path","ProviderTransferError","invalidPayloadError","reason","getSchema","schema","getModel","getDatabaseSchema","db","metadata","assertPolymorphicValueAllowed","typeField","values","entry","target","assertComponentValueAllowed","componentUID","repeatable","assertSchemaDataAllowed","assertDynamicZoneValueAllowed","componentUIDs","__component","data","databaseSchema","field","entries","attribute","attributes","protectedOwnerRelation","find","candidate","type","owner","joinColumn","name","fieldPath","relation","morphColumn","component","components","assertRemoteEntityAllowed","entity","assertRemoteLinkAllowed","link","left","right"],"mappings":"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"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { ProviderTransferError } from '../errors/providers.mjs';
|
|
2
|
+
|
|
3
|
+
const ADMIN_UID_PREFIX = 'admin::';
|
|
4
|
+
const OFFICIAL_TRANSFER_IGNORED_TYPES = [
|
|
5
|
+
'plugin::content-releases.release',
|
|
6
|
+
'plugin::content-releases.release-action'
|
|
7
|
+
];
|
|
8
|
+
const isRecord = (value)=>typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
9
|
+
const isProtectedRemotePushType = (uid)=>uid.startsWith(ADMIN_UID_PREFIX);
|
|
10
|
+
const isIgnoredOfficialTransferType = (uid)=>isProtectedRemotePushType(uid) || OFFICIAL_TRANSFER_IGNORED_TYPES.includes(uid);
|
|
11
|
+
const getIgnoredOfficialTransferTypes = ()=>[
|
|
12
|
+
...OFFICIAL_TRANSFER_IGNORED_TYPES
|
|
13
|
+
];
|
|
14
|
+
const getProtectedTransferUIDs = (strapi)=>{
|
|
15
|
+
const contentTypes = Object.keys(strapi.contentTypes);
|
|
16
|
+
const models = strapi.get('models').get();
|
|
17
|
+
return [
|
|
18
|
+
...new Set([
|
|
19
|
+
...contentTypes,
|
|
20
|
+
...models.map(({ uid })=>uid)
|
|
21
|
+
].filter(isProtectedRemotePushType))
|
|
22
|
+
];
|
|
23
|
+
};
|
|
24
|
+
const normalizeRemoteRestoreOptions = (strapi, restore = {})=>{
|
|
25
|
+
const protectedUIDs = getProtectedTransferUIDs(strapi);
|
|
26
|
+
const entities = {
|
|
27
|
+
...restore.entities
|
|
28
|
+
};
|
|
29
|
+
delete entities.filters;
|
|
30
|
+
return {
|
|
31
|
+
...restore,
|
|
32
|
+
entities: {
|
|
33
|
+
...entities,
|
|
34
|
+
...entities.include ? {
|
|
35
|
+
include: entities.include.filter((uid)=>!isProtectedRemotePushType(uid))
|
|
36
|
+
} : {},
|
|
37
|
+
exclude: [
|
|
38
|
+
...new Set([
|
|
39
|
+
...entities.exclude ?? [],
|
|
40
|
+
...protectedUIDs
|
|
41
|
+
])
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
const protectedTypeError = (uid, path)=>new ProviderTransferError(`Remote push cannot transfer protected type "${uid}" at ${path}`);
|
|
47
|
+
const invalidPayloadError = (path, reason)=>new ProviderTransferError(`Remote push received invalid relation payload at ${path}: ${reason}`);
|
|
48
|
+
const getSchema = (strapi, uid, path)=>{
|
|
49
|
+
const schema = strapi.getModel(uid);
|
|
50
|
+
if (!schema) {
|
|
51
|
+
throw invalidPayloadError(path, `unknown schema "${uid}"`);
|
|
52
|
+
}
|
|
53
|
+
return schema;
|
|
54
|
+
};
|
|
55
|
+
const getDatabaseSchema = (strapi, uid, path)=>{
|
|
56
|
+
const schema = strapi.db.metadata.get(uid);
|
|
57
|
+
if (!schema) {
|
|
58
|
+
throw invalidPayloadError(path, `unknown database schema "${uid}"`);
|
|
59
|
+
}
|
|
60
|
+
return schema;
|
|
61
|
+
};
|
|
62
|
+
const assertPolymorphicValueAllowed = (value, typeField, path)=>{
|
|
63
|
+
const values = Array.isArray(value) ? value : [
|
|
64
|
+
value
|
|
65
|
+
];
|
|
66
|
+
for (const entry of values){
|
|
67
|
+
if (!isRecord(entry) || typeof entry[typeField] !== 'string') {
|
|
68
|
+
throw invalidPayloadError(path, `missing polymorphic discriminator "${typeField}"`);
|
|
69
|
+
}
|
|
70
|
+
const target = entry[typeField];
|
|
71
|
+
if (isProtectedRemotePushType(target)) {
|
|
72
|
+
throw protectedTypeError(target, path);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const assertComponentValueAllowed = (strapi, componentUID, value, path, repeatable)=>{
|
|
77
|
+
if (!repeatable && value === null) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const values = repeatable ? value : [
|
|
81
|
+
value
|
|
82
|
+
];
|
|
83
|
+
if (repeatable && !Array.isArray(value) || !Array.isArray(values)) {
|
|
84
|
+
throw invalidPayloadError(path, 'expected component value');
|
|
85
|
+
}
|
|
86
|
+
for (const entry of values){
|
|
87
|
+
if (!isRecord(entry)) {
|
|
88
|
+
throw invalidPayloadError(path, 'expected component object');
|
|
89
|
+
}
|
|
90
|
+
assertSchemaDataAllowed(strapi, componentUID, entry, path);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const assertDynamicZoneValueAllowed = (strapi, componentUIDs, value, path)=>{
|
|
94
|
+
if (!Array.isArray(value)) {
|
|
95
|
+
throw invalidPayloadError(path, 'expected dynamic zone array');
|
|
96
|
+
}
|
|
97
|
+
for (const entry of value){
|
|
98
|
+
if (!isRecord(entry) || typeof entry.__component !== 'string') {
|
|
99
|
+
throw invalidPayloadError(path, 'missing dynamic zone component discriminator');
|
|
100
|
+
}
|
|
101
|
+
const componentUID = entry.__component;
|
|
102
|
+
if (!componentUIDs.includes(componentUID)) {
|
|
103
|
+
throw invalidPayloadError(path, `unsupported dynamic zone component "${componentUID}"`);
|
|
104
|
+
}
|
|
105
|
+
assertSchemaDataAllowed(strapi, componentUID, entry, path);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const assertSchemaDataAllowed = (strapi, uid, data, path)=>{
|
|
109
|
+
const schema = getSchema(strapi, uid, path);
|
|
110
|
+
const databaseSchema = getDatabaseSchema(strapi, uid, path);
|
|
111
|
+
for (const [field, value] of Object.entries(data)){
|
|
112
|
+
const attribute = schema.attributes?.[field];
|
|
113
|
+
if (!attribute) {
|
|
114
|
+
const protectedOwnerRelation = Object.values(databaseSchema.attributes ?? {}).find((candidate)=>candidate.type === 'relation' && candidate.owner === true && candidate.target && isProtectedRemotePushType(candidate.target) && candidate.joinColumn?.name === field);
|
|
115
|
+
if (protectedOwnerRelation?.target) {
|
|
116
|
+
throw protectedTypeError(protectedOwnerRelation.target, `${path}.${field}`);
|
|
117
|
+
}
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const fieldPath = `${path}.${field}`;
|
|
121
|
+
if (attribute.type === 'relation') {
|
|
122
|
+
if (attribute.target && isProtectedRemotePushType(attribute.target)) {
|
|
123
|
+
throw protectedTypeError(attribute.target, fieldPath);
|
|
124
|
+
}
|
|
125
|
+
if (attribute.relation?.startsWith('morph')) {
|
|
126
|
+
assertPolymorphicValueAllowed(value, attribute.morphColumn?.typeField ?? '__type', fieldPath);
|
|
127
|
+
}
|
|
128
|
+
} else if (attribute.type === 'component' && attribute.component) {
|
|
129
|
+
assertComponentValueAllowed(strapi, attribute.component, value, fieldPath, attribute.repeatable === true);
|
|
130
|
+
} else if (attribute.type === 'dynamiczone') {
|
|
131
|
+
assertDynamicZoneValueAllowed(strapi, attribute.components ?? [], value, fieldPath);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
const assertRemoteEntityAllowed = (strapi, entity)=>{
|
|
136
|
+
if (isProtectedRemotePushType(entity.type)) {
|
|
137
|
+
throw protectedTypeError(entity.type, entity.type);
|
|
138
|
+
}
|
|
139
|
+
if (!isRecord(entity.data)) {
|
|
140
|
+
throw invalidPayloadError(entity.type, 'expected entity data object');
|
|
141
|
+
}
|
|
142
|
+
assertSchemaDataAllowed(strapi, entity.type, entity.data, entity.type);
|
|
143
|
+
};
|
|
144
|
+
const assertRemoteLinkAllowed = (link)=>{
|
|
145
|
+
if (isProtectedRemotePushType(link.left.type)) {
|
|
146
|
+
throw protectedTypeError(link.left.type, 'link.left');
|
|
147
|
+
}
|
|
148
|
+
if (isProtectedRemotePushType(link.right.type)) {
|
|
149
|
+
throw protectedTypeError(link.right.type, 'link.right');
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export { OFFICIAL_TRANSFER_IGNORED_TYPES, assertRemoteEntityAllowed, assertRemoteLinkAllowed, getIgnoredOfficialTransferTypes, getProtectedTransferUIDs, isIgnoredOfficialTransferType, isProtectedRemotePushType, normalizeRemoteRestoreOptions };
|
|
154
|
+
//# sourceMappingURL=transfer-policy.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transfer-policy.mjs","sources":["../../src/strapi/transfer-policy.ts"],"sourcesContent":["import type { Core, UID } from '@strapi/types';\n\nimport { ProviderTransferError } from '../errors/providers';\nimport type { IEntity, ILink } from '../types';\nimport type { IRestoreOptions } from './providers/local-destination/strategies/restore';\n\nconst ADMIN_UID_PREFIX = 'admin::';\n\nexport const OFFICIAL_TRANSFER_IGNORED_TYPES = [\n 'plugin::content-releases.release',\n 'plugin::content-releases.release-action',\n] as const;\n\ntype SchemaAttribute = {\n type?: string;\n target?: string;\n relation?: string;\n component?: string;\n components?: string[];\n repeatable?: boolean;\n morphColumn?: { typeField?: string };\n owner?: boolean;\n joinColumn?: { name?: string };\n};\n\ntype Schema = { attributes?: Record<string, SchemaAttribute> };\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nexport const isProtectedRemotePushType = (uid: string): boolean => uid.startsWith(ADMIN_UID_PREFIX);\n\nexport const isIgnoredOfficialTransferType = (uid: string): boolean =>\n isProtectedRemotePushType(uid) ||\n OFFICIAL_TRANSFER_IGNORED_TYPES.includes(uid as (typeof OFFICIAL_TRANSFER_IGNORED_TYPES)[number]);\n\nexport const getIgnoredOfficialTransferTypes = (): string[] => [...OFFICIAL_TRANSFER_IGNORED_TYPES];\n\nexport const getProtectedTransferUIDs = (strapi: Core.Strapi): string[] => {\n const contentTypes = Object.keys(strapi.contentTypes);\n const models = strapi.get('models').get() as Array<{ uid: string }>;\n\n return [\n ...new Set(\n [...contentTypes, ...models.map(({ uid }) => uid)].filter(isProtectedRemotePushType)\n ),\n ];\n};\n\nexport const normalizeRemoteRestoreOptions = (\n strapi: Core.Strapi,\n restore: IRestoreOptions = {}\n): IRestoreOptions => {\n const protectedUIDs = getProtectedTransferUIDs(strapi);\n const entities = { ...restore.entities };\n\n delete entities.filters;\n\n return {\n ...restore,\n entities: {\n ...entities,\n ...(entities.include\n ? { include: entities.include.filter((uid) => !isProtectedRemotePushType(uid)) }\n : {}),\n exclude: [...new Set([...(entities.exclude ?? []), ...protectedUIDs])],\n },\n };\n};\n\nconst protectedTypeError = (uid: string, path: string) =>\n new ProviderTransferError(`Remote push cannot transfer protected type \"${uid}\" at ${path}`);\n\nconst invalidPayloadError = (path: string, reason: string) =>\n new ProviderTransferError(`Remote push received invalid relation payload at ${path}: ${reason}`);\n\nconst getSchema = (strapi: Core.Strapi, uid: string, path: string): Schema => {\n const schema = strapi.getModel(uid as UID.Schema) as Schema | undefined;\n\n if (!schema) {\n throw invalidPayloadError(path, `unknown schema \"${uid}\"`);\n }\n\n return schema;\n};\n\nconst getDatabaseSchema = (strapi: Core.Strapi, uid: string, path: string): Schema => {\n const schema = strapi.db.metadata.get(uid as UID.Schema) as Schema | undefined;\n\n if (!schema) {\n throw invalidPayloadError(path, `unknown database schema \"${uid}\"`);\n }\n\n return schema;\n};\n\nconst assertPolymorphicValueAllowed = (value: unknown, typeField: string, path: string) => {\n const values = Array.isArray(value) ? value : [value];\n\n for (const entry of values) {\n if (!isRecord(entry) || typeof entry[typeField] !== 'string') {\n throw invalidPayloadError(path, `missing polymorphic discriminator \"${typeField}\"`);\n }\n\n const target = entry[typeField];\n if (isProtectedRemotePushType(target)) {\n throw protectedTypeError(target, path);\n }\n }\n};\n\nconst assertComponentValueAllowed = (\n strapi: Core.Strapi,\n componentUID: string,\n value: unknown,\n path: string,\n repeatable: boolean\n) => {\n if (!repeatable && value === null) {\n return;\n }\n\n const values = repeatable ? value : [value];\n\n if ((repeatable && !Array.isArray(value)) || !Array.isArray(values)) {\n throw invalidPayloadError(path, 'expected component value');\n }\n\n for (const entry of values) {\n if (!isRecord(entry)) {\n throw invalidPayloadError(path, 'expected component object');\n }\n assertSchemaDataAllowed(strapi, componentUID, entry, path);\n }\n};\n\nconst assertDynamicZoneValueAllowed = (\n strapi: Core.Strapi,\n componentUIDs: string[],\n value: unknown,\n path: string\n) => {\n if (!Array.isArray(value)) {\n throw invalidPayloadError(path, 'expected dynamic zone array');\n }\n\n for (const entry of value) {\n if (!isRecord(entry) || typeof entry.__component !== 'string') {\n throw invalidPayloadError(path, 'missing dynamic zone component discriminator');\n }\n\n const componentUID = entry.__component;\n if (!componentUIDs.includes(componentUID)) {\n throw invalidPayloadError(path, `unsupported dynamic zone component \"${componentUID}\"`);\n }\n\n assertSchemaDataAllowed(strapi, componentUID, entry, path);\n }\n};\n\nconst assertSchemaDataAllowed = (\n strapi: Core.Strapi,\n uid: string,\n data: Record<string, unknown>,\n path: string\n) => {\n const schema = getSchema(strapi, uid, path);\n const databaseSchema = getDatabaseSchema(strapi, uid, path);\n\n for (const [field, value] of Object.entries(data)) {\n const attribute = schema.attributes?.[field];\n if (!attribute) {\n const protectedOwnerRelation = Object.values(databaseSchema.attributes ?? {}).find(\n (candidate) =>\n candidate.type === 'relation' &&\n candidate.owner === true &&\n candidate.target &&\n isProtectedRemotePushType(candidate.target) &&\n candidate.joinColumn?.name === field\n );\n\n if (protectedOwnerRelation?.target) {\n throw protectedTypeError(protectedOwnerRelation.target, `${path}.${field}`);\n }\n continue;\n }\n\n const fieldPath = `${path}.${field}`;\n if (attribute.type === 'relation') {\n if (attribute.target && isProtectedRemotePushType(attribute.target)) {\n throw protectedTypeError(attribute.target, fieldPath);\n }\n if (attribute.relation?.startsWith('morph')) {\n assertPolymorphicValueAllowed(\n value,\n attribute.morphColumn?.typeField ?? '__type',\n fieldPath\n );\n }\n } else if (attribute.type === 'component' && attribute.component) {\n assertComponentValueAllowed(\n strapi,\n attribute.component,\n value,\n fieldPath,\n attribute.repeatable === true\n );\n } else if (attribute.type === 'dynamiczone') {\n assertDynamicZoneValueAllowed(strapi, attribute.components ?? [], value, fieldPath);\n }\n }\n};\n\nexport const assertRemoteEntityAllowed = (strapi: Core.Strapi, entity: IEntity): void => {\n if (isProtectedRemotePushType(entity.type)) {\n throw protectedTypeError(entity.type, entity.type);\n }\n\n if (!isRecord(entity.data)) {\n throw invalidPayloadError(entity.type, 'expected entity data object');\n }\n\n assertSchemaDataAllowed(strapi, entity.type, entity.data, entity.type);\n};\n\nexport const assertRemoteLinkAllowed = (link: ILink): void => {\n if (isProtectedRemotePushType(link.left.type)) {\n throw protectedTypeError(link.left.type, 'link.left');\n }\n if (isProtectedRemotePushType(link.right.type)) {\n throw protectedTypeError(link.right.type, 'link.right');\n }\n};\n"],"names":["ADMIN_UID_PREFIX","OFFICIAL_TRANSFER_IGNORED_TYPES","isRecord","value","Array","isArray","isProtectedRemotePushType","uid","startsWith","isIgnoredOfficialTransferType","includes","getIgnoredOfficialTransferTypes","getProtectedTransferUIDs","strapi","contentTypes","Object","keys","models","get","Set","map","filter","normalizeRemoteRestoreOptions","restore","protectedUIDs","entities","filters","include","exclude","protectedTypeError","path","ProviderTransferError","invalidPayloadError","reason","getSchema","schema","getModel","getDatabaseSchema","db","metadata","assertPolymorphicValueAllowed","typeField","values","entry","target","assertComponentValueAllowed","componentUID","repeatable","assertSchemaDataAllowed","assertDynamicZoneValueAllowed","componentUIDs","__component","data","databaseSchema","field","entries","attribute","attributes","protectedOwnerRelation","find","candidate","type","owner","joinColumn","name","fieldPath","relation","morphColumn","component","components","assertRemoteEntityAllowed","entity","assertRemoteLinkAllowed","link","left","right"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strapi/data-transfer",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.53.0",
|
|
4
4
|
"description": "Data transfer capabilities for Strapi",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"strapi",
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
"watch": "run -T rollup -c -w"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@strapi/logger": "5.
|
|
58
|
-
"@strapi/types": "5.
|
|
59
|
-
"@strapi/utils": "5.
|
|
57
|
+
"@strapi/logger": "5.53.0",
|
|
58
|
+
"@strapi/types": "5.53.0",
|
|
59
|
+
"@strapi/utils": "5.53.0",
|
|
60
60
|
"chalk": "4.1.2",
|
|
61
61
|
"cli-table3": "0.6.5",
|
|
62
62
|
"commander": "8.3.0",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"ws": "8.21.2"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
|
-
"@strapi/database": "5.
|
|
77
|
+
"@strapi/database": "5.53.0",
|
|
78
78
|
"@types/fs-extra": "11.0.4",
|
|
79
79
|
"@types/jest": "29.5.2",
|
|
80
80
|
"@types/koa": "2.15.2",
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"rimraf": "6.1.3",
|
|
93
93
|
"typescript": "5.9.3",
|
|
94
94
|
"vitest": "catalog:",
|
|
95
|
-
"vitest-config": "5.
|
|
95
|
+
"vitest-config": "5.53.0"
|
|
96
96
|
},
|
|
97
97
|
"engines": {
|
|
98
98
|
"node": ">=20.0.0 <=26.x.x",
|