@strapi/admin 5.52.1 → 5.52.3
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/admin/admin/src/components/Filters.js +9 -9
- package/dist/admin/admin/src/components/Filters.js.map +1 -1
- package/dist/admin/admin/src/components/Filters.mjs +10 -10
- package/dist/admin/admin/src/components/Filters.mjs.map +1 -1
- package/dist/admin/admin/src/components/Pagination.js +2 -2
- package/dist/admin/admin/src/components/Pagination.js.map +1 -1
- package/dist/admin/admin/src/components/Pagination.mjs +3 -3
- package/dist/admin/admin/src/components/Pagination.mjs.map +1 -1
- package/dist/admin/admin/src/components/SearchInput.js +7 -8
- package/dist/admin/admin/src/components/SearchInput.js.map +1 -1
- package/dist/admin/admin/src/components/SearchInput.mjs +8 -9
- package/dist/admin/admin/src/components/SearchInput.mjs.map +1 -1
- package/dist/admin/admin/src/components/Table.js +2 -2
- package/dist/admin/admin/src/components/Table.js.map +1 -1
- package/dist/admin/admin/src/components/Table.mjs +3 -3
- package/dist/admin/admin/src/components/Table.mjs.map +1 -1
- package/dist/admin/admin/src/hooks/useQueryParams.js +35 -1
- package/dist/admin/admin/src/hooks/useQueryParams.js.map +1 -1
- package/dist/admin/admin/src/hooks/useQueryParams.mjs +34 -2
- package/dist/admin/admin/src/hooks/useQueryParams.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Auth/AuthPage.js +14 -9
- package/dist/admin/admin/src/pages/Auth/AuthPage.js.map +1 -1
- package/dist/admin/admin/src/pages/Auth/AuthPage.mjs +15 -10
- package/dist/admin/admin/src/pages/Auth/AuthPage.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Auth/components/Login.js +2 -6
- package/dist/admin/admin/src/pages/Auth/components/Login.js.map +1 -1
- package/dist/admin/admin/src/pages/Auth/components/Login.mjs +2 -6
- package/dist/admin/admin/src/pages/Auth/components/Login.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Auth/constants.js +24 -8
- package/dist/admin/admin/src/pages/Auth/constants.js.map +1 -1
- package/dist/admin/admin/src/pages/Auth/constants.mjs +23 -9
- package/dist/admin/admin/src/pages/Auth/constants.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Auth/utils.js +34 -0
- package/dist/admin/admin/src/pages/Auth/utils.js.map +1 -0
- package/dist/admin/admin/src/pages/Auth/utils.mjs +32 -0
- package/dist/admin/admin/src/pages/Auth/utils.mjs.map +1 -0
- package/dist/admin/admin/src/translations/pt-BR.json.js +1 -1
- package/dist/admin/admin/src/translations/pt-BR.json.mjs +1 -1
- package/dist/admin/admin/src/utils/getFetchClient.js +4 -0
- package/dist/admin/admin/src/utils/getFetchClient.js.map +1 -1
- package/dist/admin/admin/src/utils/getFetchClient.mjs +4 -0
- package/dist/admin/admin/src/utils/getFetchClient.mjs.map +1 -1
- package/dist/admin/admin/src/utils/rulesEngine.js +27 -9
- package/dist/admin/admin/src/utils/rulesEngine.js.map +1 -1
- package/dist/admin/admin/src/utils/rulesEngine.mjs +2 -2
- package/dist/admin/admin/src/utils/rulesEngine.mjs.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/ListPage.js +9 -9
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/ListPage.js.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/ListPage.mjs +10 -10
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/ListPage.mjs.map +1 -1
- package/dist/admin/index.js +2 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +2 -2
- package/dist/admin/src/components/Filters.d.ts +1 -0
- package/dist/admin/src/hooks/useQueryParams.d.ts +13 -1
- package/dist/admin/src/index.d.ts +1 -1
- package/dist/admin/src/pages/Auth/constants.d.ts +19 -5
- package/dist/admin/src/pages/Auth/utils.d.ts +7 -0
- package/dist/admin/src/utils/rulesEngine.d.ts +9 -13
- package/dist/ee/server/src/audit-logs/services/audit-logs.d.ts.map +1 -1
- package/dist/server/ee/server/src/audit-logs/services/audit-logs.js +22 -4
- package/dist/server/ee/server/src/audit-logs/services/audit-logs.js.map +1 -1
- package/dist/server/ee/server/src/audit-logs/services/audit-logs.mjs +22 -4
- package/dist/server/ee/server/src/audit-logs/services/audit-logs.mjs.map +1 -1
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.js +1 -1
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.js.map +1 -1
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.mjs +1 -1
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.mjs.map +1 -1
- package/dist/server/server/src/controllers/validation/schema.js +36 -16
- package/dist/server/server/src/controllers/validation/schema.js.map +1 -1
- package/dist/server/server/src/controllers/validation/schema.mjs +1 -1
- package/dist/server/server/src/controllers/validation/schema.mjs.map +1 -1
- package/dist/server/server/src/services/content-type.js +8 -3
- package/dist/server/server/src/services/content-type.js.map +1 -1
- package/dist/server/server/src/services/content-type.mjs +8 -3
- package/dist/server/server/src/services/content-type.mjs.map +1 -1
- package/dist/server/server/src/services/permission/queries.js +3 -1
- package/dist/server/server/src/services/permission/queries.js.map +1 -1
- package/dist/server/server/src/services/permission/queries.mjs +3 -1
- package/dist/server/server/src/services/permission/queries.mjs.map +1 -1
- package/dist/server/src/controllers/validation/schema.d.ts +8 -48
- package/dist/server/src/controllers/validation/schema.d.ts.map +1 -1
- package/dist/server/src/services/content-type.d.ts.map +1 -1
- package/dist/server/src/services/permission/queries.d.ts.map +1 -1
- package/package.json +8 -8
|
@@ -29,7 +29,21 @@ const getSanitizedUser = (user)=>{
|
|
|
29
29
|
return this;
|
|
30
30
|
},
|
|
31
31
|
async findMany (query) {
|
|
32
|
-
|
|
32
|
+
// NOTE: We get the IDs first because sorting full rows runs MySQL/MariaDB out of sort memory
|
|
33
|
+
// See: https://github.com/strapi/strapi/issues/27399
|
|
34
|
+
const { results: logRows, pagination } = await strapi.db.query('admin::audit-log').findPage({
|
|
35
|
+
...strapi.get('query-params').transform('admin::audit-log', query),
|
|
36
|
+
select: [
|
|
37
|
+
'id'
|
|
38
|
+
]
|
|
39
|
+
});
|
|
40
|
+
const ids = logRows.map((log)=>log.id);
|
|
41
|
+
const logs = ids.length ? await strapi.db.query('admin::audit-log').findMany({
|
|
42
|
+
where: {
|
|
43
|
+
id: {
|
|
44
|
+
$in: ids
|
|
45
|
+
}
|
|
46
|
+
},
|
|
33
47
|
populate: [
|
|
34
48
|
'user'
|
|
35
49
|
],
|
|
@@ -37,9 +51,13 @@ const getSanitizedUser = (user)=>{
|
|
|
37
51
|
'action',
|
|
38
52
|
'date',
|
|
39
53
|
'payload'
|
|
40
|
-
]
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
]
|
|
55
|
+
}) : [];
|
|
56
|
+
const logsById = new Map(logs.map((log)=>[
|
|
57
|
+
log.id,
|
|
58
|
+
log
|
|
59
|
+
]));
|
|
60
|
+
const results = ids.map((id)=>logsById.get(id)).filter(Boolean);
|
|
43
61
|
const sanitizedResults = results.map((result)=>{
|
|
44
62
|
const { user, ...rest } = result;
|
|
45
63
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-logs.mjs","sources":["../../../../../../../ee/server/src/audit-logs/services/audit-logs.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\n\ninterface Event {\n action: string;\n date: Date;\n userId: string | number;\n payload: Record<string, unknown>;\n}\n\ninterface Log extends Omit<Event, 'userId'> {\n user: string | number;\n}\n\nconst getSanitizedUser = (user: any) => {\n let displayName = user.email;\n\n if (user.username) {\n displayName = user.username;\n } else if (user.firstname && user.lastname) {\n displayName = `${user.firstname} ${user.lastname}`;\n }\n\n return {\n id: user.id,\n email: user.email,\n displayName,\n };\n};\n\n/**\n * @description\n * Manages audit logs interaction with the database. Accessible via strapi.get('audit-logs')\n */\nconst createAuditLogsService = (strapi: Core.Strapi) => {\n return {\n async saveEvent(event: Event) {\n const { userId, ...rest } = event;\n\n const auditLog: Log = { ...rest, user: userId };\n\n // Save to database\n await strapi.db.query('admin::audit-log').create({ data: auditLog });\n\n return this;\n },\n\n async findMany(query: unknown) {\n const { results, pagination } = await strapi.db.query('admin::audit-log').findPage({\n populate: ['user'],\n
|
|
1
|
+
{"version":3,"file":"audit-logs.mjs","sources":["../../../../../../../ee/server/src/audit-logs/services/audit-logs.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\n\ninterface Event {\n action: string;\n date: Date;\n userId: string | number;\n payload: Record<string, unknown>;\n}\n\ninterface Log extends Omit<Event, 'userId'> {\n user: string | number;\n}\n\nconst getSanitizedUser = (user: any) => {\n let displayName = user.email;\n\n if (user.username) {\n displayName = user.username;\n } else if (user.firstname && user.lastname) {\n displayName = `${user.firstname} ${user.lastname}`;\n }\n\n return {\n id: user.id,\n email: user.email,\n displayName,\n };\n};\n\n/**\n * @description\n * Manages audit logs interaction with the database. Accessible via strapi.get('audit-logs')\n */\nconst createAuditLogsService = (strapi: Core.Strapi) => {\n return {\n async saveEvent(event: Event) {\n const { userId, ...rest } = event;\n\n const auditLog: Log = { ...rest, user: userId };\n\n // Save to database\n await strapi.db.query('admin::audit-log').create({ data: auditLog });\n\n return this;\n },\n\n async findMany(query: unknown) {\n // NOTE: We get the IDs first because sorting full rows runs MySQL/MariaDB out of sort memory\n // See: https://github.com/strapi/strapi/issues/27399\n const { results: logRows, pagination } = await strapi.db.query('admin::audit-log').findPage({\n ...strapi.get('query-params').transform('admin::audit-log', query),\n select: ['id'],\n });\n\n const ids = logRows.map((log) => log.id);\n const logs = ids.length\n ? await strapi.db.query('admin::audit-log').findMany({\n where: { id: { $in: ids } },\n populate: ['user'],\n select: ['action', 'date', 'payload'],\n })\n : [];\n const logsById = new Map(logs.map((log) => [log.id, log]));\n const results = ids.map((id) => logsById.get(id)).filter(Boolean);\n\n const sanitizedResults = results.map((result: any) => {\n const { user, ...rest } = result;\n return {\n ...rest,\n user: user ? getSanitizedUser(user) : null,\n };\n });\n\n return {\n results: sanitizedResults,\n pagination,\n };\n },\n\n async findManyUsers(query: { page?: number | string; pageSize?: number | string }) {\n const { page = 1, pageSize = 10 } = query;\n\n const userAttribute = strapi.db.metadata.get('admin::audit-log').attributes.user;\n\n if (\n userAttribute?.type !== 'relation' ||\n !('joinTable' in userAttribute) ||\n !userAttribute.joinTable ||\n !('inverseJoinColumn' in userAttribute.joinTable)\n ) {\n throw new Error('The audit log user relation is expected to use a join table');\n }\n\n const { joinTable } = userAttribute;\n\n const authorIds = await strapi.db\n .connection(joinTable.name)\n .distinct(joinTable.inverseJoinColumn.name)\n .pluck(joinTable.inverseJoinColumn.name);\n\n const { results, pagination } = await strapi.db.query('admin::user').findPage({\n select: ['id', 'email', 'username', 'firstname', 'lastname'],\n where: { id: { $in: authorIds } },\n orderBy: { id: 'asc' },\n page: Number(page),\n pageSize: Number(pageSize),\n });\n\n return {\n results: results.map(getSanitizedUser),\n pagination,\n };\n },\n\n async findOne(id: unknown) {\n const result: any = await strapi.db.query('admin::audit-log').findOne({\n where: { id },\n populate: ['user'],\n select: ['action', 'date', 'payload'],\n });\n\n if (!result) {\n return null;\n }\n\n const { user, ...rest } = result;\n return {\n ...rest,\n user: user ? getSanitizedUser(user) : null,\n };\n },\n\n deleteExpiredEvents(expirationDate: Date) {\n return strapi.db.query('admin::audit-log').deleteMany({\n where: {\n date: {\n $lt: expirationDate.toISOString(),\n },\n },\n });\n },\n };\n};\n\nexport { createAuditLogsService };\n"],"names":["getSanitizedUser","user","displayName","email","username","firstname","lastname","id","createAuditLogsService","strapi","saveEvent","event","userId","rest","auditLog","db","query","create","data","findMany","results","logRows","pagination","findPage","get","transform","select","ids","map","log","logs","length","where","$in","populate","logsById","Map","filter","Boolean","sanitizedResults","result","findManyUsers","page","pageSize","userAttribute","metadata","attributes","type","joinTable","Error","authorIds","connection","name","distinct","inverseJoinColumn","pluck","orderBy","Number","findOne","deleteExpiredEvents","expirationDate","deleteMany","date","$lt","toISOString"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycles.js","sources":["../../../../../../../ee/server/src/audit-logs/services/lifecycles.ts"],"sourcesContent":["import type { Core, Modules } from '@strapi/types';\n\nconst DEFAULT_RETENTION_DAYS = 90;\n\nconst defaultEvents = [\n 'entry.create',\n 'entry.update',\n 'entry.delete',\n 'entry.publish',\n 'entry.unpublish',\n 'media.create',\n 'media.update',\n 'media.delete',\n 'media-folder.create',\n 'media-folder.update',\n 'media-folder.delete',\n 'user.create',\n 'user.update',\n 'user.delete',\n 'admin.auth.success',\n 'admin.logout',\n 'content-type.create',\n 'content-type.update',\n 'content-type.delete',\n 'component.create',\n 'component.update',\n 'component.delete',\n 'role.create',\n 'role.update',\n 'role.delete',\n 'permission.create',\n 'permission.update',\n 'permission.delete',\n];\n\nconst getEventMap = (defaultEvents: any) => {\n const getDefaultPayload = (...args: any) => args[0];\n\n // Use the default payload for all default events\n return defaultEvents.reduce((acc: any, event: any) => {\n acc[event] = getDefaultPayload;\n return acc;\n }, {} as any);\n};\n\nconst getRetentionDays = (strapi: Core.Strapi) => {\n const featureConfig = strapi.ee.features.get('audit-logs');\n const licenseRetentionDays =\n typeof featureConfig === 'object' && featureConfig?.options?.retentionDays;\n const userRetentionDays = strapi.config.get('admin.auditLogs.retentionDays');\n\n // For enterprise plans, use 90 days by default, but allow users to override it\n if (licenseRetentionDays == null) {\n return userRetentionDays ?? DEFAULT_RETENTION_DAYS;\n }\n\n // Allow users to override the license retention days, but not to increase it\n if (userRetentionDays && userRetentionDays <= licenseRetentionDays) {\n return userRetentionDays;\n }\n\n // User didn't provide a retention days value, use the license one\n return licenseRetentionDays;\n};\n\n/**\n * @description\n * Manages the lifecycle of audit logs. Accessible via strapi.get('audit-logs-lifecycles')\n */\nconst createAuditLogsLifecycleService = (strapi: Core.Strapi) => {\n // Manage internal service state privately\n const state = {} as any;\n const auditLogsService = strapi.get('audit-logs');\n\n // NOTE: providers should be able to replace getEventMap to add or remove events\n const eventMap = getEventMap(defaultEvents);\n\n const processEvent = (name: string, ...args: any) => {\n const requestState = strapi.requestContext.get()?.state;\n\n // Only audit admin-authenticated actions, plus MCP actions flagged via auditSource.\n const isUsingAdminAuth = requestState?.route.info.type === 'admin';\n const auditSource = requestState?.auditSource;\n const isMcpAdminAction = auditSource === 'mcp';\n const user = requestState?.user;\n if ((!isUsingAdminAuth && !isMcpAdminAction) || !user) {\n return null;\n }\n\n const origin: Modules.AuditLogs.AuditSource = auditSource ?? 'admin';\n\n const getPayload = eventMap[name];\n\n // Ignore the event if it's not in the map\n if (!getPayload) {\n return null;\n }\n\n // Ignore some events based on payload\n // TODO: What does this ignore in upload? Why would we want to ignore anything?\n const ignoredUids = ['plugin::upload.file', 'plugin::upload.folder'];\n if (ignoredUids.includes(args[0]?.uid)) {\n return null;\n }\n\n return {\n action: name,\n date: new Date().toISOString(),\n payload: { ...(getPayload(...args) || {}), origin },\n userId: user.id,\n };\n };\n\n const handleEvent = async (name: string, ...args: any) => {\n const processedEvent = processEvent(name, ...args);\n\n if (processedEvent) {\n await auditLogsService.saveEvent(processedEvent);\n }\n };\n\n return {\n async register() {\n // Handle license being enabled\n if (!state.eeEnableUnsubscribe) {\n // @ts-expect-error- update event hub to receive callback argument\n state.eeEnableUnsubscribe = strapi.eventHub.on('ee.enable', () => {\n // Recreate the service to use the new license info\n this.destroy();\n this.register();\n });\n }\n\n // Handle license being updated\n if (!state.eeUpdateUnsubscribe) {\n // @ts-expect-error- update event hub to receive callback argument\n state.eeUpdateUnsubscribe = strapi.eventHub.on('ee.update', () => {\n // Recreate the service to use the new license info\n this.destroy();\n this.register();\n });\n }\n\n // Handle license being disabled\n // @ts-expect-error- update event hub to receive callback argument\n state.eeDisableUnsubscribe = strapi.eventHub.on('ee.disable', () => {\n // Turn off service when the license gets disabled\n // Only ee.enable and ee.update listeners remain active to recreate the service\n this.destroy();\n });\n\n // Check current state of license\n if (!strapi.ee.features.isEnabled('audit-logs')) {\n return this;\n }\n\n // Start saving events\n state.eventHubUnsubscribe = strapi.eventHub.subscribe(handleEvent);\n\n // Manage audit logs auto deletion\n const retentionDays = getRetentionDays(strapi);\n\n strapi.cron.add({\n deleteExpiredAuditLogs: {\n async task() {\n const expirationDate = new Date(Date.now() - retentionDays * 24 * 60 * 60 * 1000);\n await auditLogsService.deleteExpiredEvents(expirationDate);\n },\n options: '0 0 * * *',\n },\n });\n\n return this;\n },\n\n unsubscribe() {\n if (state.eeDisableUnsubscribe) {\n state.eeDisableUnsubscribe();\n }\n\n if (state.eventHubUnsubscribe) {\n state.eventHubUnsubscribe();\n }\n\n strapi.cron.remove('deleteExpiredAuditLogs');\n\n return this;\n },\n\n destroy() {\n return this.unsubscribe();\n },\n };\n};\n\nexport { createAuditLogsLifecycleService };\n"],"names":["DEFAULT_RETENTION_DAYS","defaultEvents","getEventMap","getDefaultPayload","args","reduce","acc","event","getRetentionDays","strapi","featureConfig","ee","features","get","licenseRetentionDays","options","retentionDays","userRetentionDays","config","createAuditLogsLifecycleService","state","auditLogsService","eventMap","processEvent","name","requestState","requestContext","isUsingAdminAuth","route","info","type","auditSource","isMcpAdminAction","user","origin","getPayload","ignoredUids","includes","uid","action","date","Date","toISOString","payload","userId","id","handleEvent","processedEvent","saveEvent","register","eeEnableUnsubscribe","eventHub","on","destroy","eeUpdateUnsubscribe","eeDisableUnsubscribe","isEnabled","eventHubUnsubscribe","subscribe","cron","add","deleteExpiredAuditLogs","task","expirationDate","now","deleteExpiredEvents","unsubscribe","remove"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecycles.js","sources":["../../../../../../../ee/server/src/audit-logs/services/lifecycles.ts"],"sourcesContent":["import type { Core, Modules } from '@strapi/types';\n\nconst DEFAULT_RETENTION_DAYS = 90;\n\nconst defaultEvents = [\n 'entry.create',\n 'entry.update',\n 'entry.delete',\n 'entry.publish',\n 'entry.unpublish',\n 'media.create',\n 'media.update',\n 'media.delete',\n 'media-folder.create',\n 'media-folder.update',\n 'media-folder.delete',\n 'user.create',\n 'user.update',\n 'user.delete',\n 'admin.auth.success',\n 'admin.logout',\n 'content-type.create',\n 'content-type.update',\n 'content-type.delete',\n 'component.create',\n 'component.update',\n 'component.delete',\n 'role.create',\n 'role.update',\n 'role.delete',\n 'permission.create',\n 'permission.update',\n 'permission.delete',\n];\n\nconst getEventMap = (defaultEvents: any) => {\n const getDefaultPayload = (...args: any) => args[0];\n\n // Use the default payload for all default events\n return defaultEvents.reduce((acc: any, event: any) => {\n acc[event] = getDefaultPayload;\n return acc;\n }, {} as any);\n};\n\nconst getRetentionDays = (strapi: Core.Strapi) => {\n const featureConfig = strapi.ee.features.get('audit-logs');\n const licenseRetentionDays =\n typeof featureConfig === 'object' && featureConfig?.options?.retentionDays;\n const userRetentionDays = strapi.config.get('admin.auditLogs.retentionDays');\n\n // For enterprise plans, use 90 days by default, but allow users to override it\n if (licenseRetentionDays == null) {\n return userRetentionDays ?? DEFAULT_RETENTION_DAYS;\n }\n\n // Allow users to override the license retention days, but not to increase it\n if (userRetentionDays && userRetentionDays <= licenseRetentionDays) {\n return userRetentionDays;\n }\n\n // User didn't provide a retention days value, use the license one\n return licenseRetentionDays;\n};\n\n/**\n * @description\n * Manages the lifecycle of audit logs. Accessible via strapi.get('audit-logs-lifecycles')\n */\nconst createAuditLogsLifecycleService = (strapi: Core.Strapi) => {\n // Manage internal service state privately\n const state = {} as any;\n const auditLogsService = strapi.get('audit-logs');\n\n // NOTE: providers should be able to replace getEventMap to add or remove events\n const eventMap = getEventMap(defaultEvents);\n\n const processEvent = (name: string, ...args: any) => {\n const requestState = strapi.requestContext.get()?.state;\n\n // Only audit admin-authenticated actions, plus MCP actions flagged via auditSource.\n const isUsingAdminAuth = requestState?.route.info.type === 'admin';\n const auditSource = requestState?.auditSource;\n const isMcpAdminAction = auditSource === 'mcp';\n const user = requestState?.user;\n if ((!isUsingAdminAuth && !isMcpAdminAction) || !user) {\n return null;\n }\n\n const origin: Modules.AuditLogs.AuditSource = auditSource ?? 'admin';\n\n const getPayload = eventMap[name];\n\n // Ignore the event if it's not in the map\n if (!getPayload) {\n return null;\n }\n\n // Ignore some events based on payload\n // TODO: What does this ignore in upload? Why would we want to ignore anything?\n const ignoredUids = ['plugin::upload.file', 'plugin::upload.folder'];\n if (ignoredUids.includes(args[0]?.uid)) {\n return null;\n }\n\n return {\n action: name,\n date: new Date().toISOString(),\n payload: { ...getPayload(...args), origin },\n userId: user.id,\n };\n };\n\n const handleEvent = async (name: string, ...args: any) => {\n const processedEvent = processEvent(name, ...args);\n\n if (processedEvent) {\n await auditLogsService.saveEvent(processedEvent);\n }\n };\n\n return {\n async register() {\n // Handle license being enabled\n if (!state.eeEnableUnsubscribe) {\n // @ts-expect-error- update event hub to receive callback argument\n state.eeEnableUnsubscribe = strapi.eventHub.on('ee.enable', () => {\n // Recreate the service to use the new license info\n this.destroy();\n this.register();\n });\n }\n\n // Handle license being updated\n if (!state.eeUpdateUnsubscribe) {\n // @ts-expect-error- update event hub to receive callback argument\n state.eeUpdateUnsubscribe = strapi.eventHub.on('ee.update', () => {\n // Recreate the service to use the new license info\n this.destroy();\n this.register();\n });\n }\n\n // Handle license being disabled\n // @ts-expect-error- update event hub to receive callback argument\n state.eeDisableUnsubscribe = strapi.eventHub.on('ee.disable', () => {\n // Turn off service when the license gets disabled\n // Only ee.enable and ee.update listeners remain active to recreate the service\n this.destroy();\n });\n\n // Check current state of license\n if (!strapi.ee.features.isEnabled('audit-logs')) {\n return this;\n }\n\n // Start saving events\n state.eventHubUnsubscribe = strapi.eventHub.subscribe(handleEvent);\n\n // Manage audit logs auto deletion\n const retentionDays = getRetentionDays(strapi);\n\n strapi.cron.add({\n deleteExpiredAuditLogs: {\n async task() {\n const expirationDate = new Date(Date.now() - retentionDays * 24 * 60 * 60 * 1000);\n await auditLogsService.deleteExpiredEvents(expirationDate);\n },\n options: '0 0 * * *',\n },\n });\n\n return this;\n },\n\n unsubscribe() {\n if (state.eeDisableUnsubscribe) {\n state.eeDisableUnsubscribe();\n }\n\n if (state.eventHubUnsubscribe) {\n state.eventHubUnsubscribe();\n }\n\n strapi.cron.remove('deleteExpiredAuditLogs');\n\n return this;\n },\n\n destroy() {\n return this.unsubscribe();\n },\n };\n};\n\nexport { createAuditLogsLifecycleService };\n"],"names":["DEFAULT_RETENTION_DAYS","defaultEvents","getEventMap","getDefaultPayload","args","reduce","acc","event","getRetentionDays","strapi","featureConfig","ee","features","get","licenseRetentionDays","options","retentionDays","userRetentionDays","config","createAuditLogsLifecycleService","state","auditLogsService","eventMap","processEvent","name","requestState","requestContext","isUsingAdminAuth","route","info","type","auditSource","isMcpAdminAction","user","origin","getPayload","ignoredUids","includes","uid","action","date","Date","toISOString","payload","userId","id","handleEvent","processedEvent","saveEvent","register","eeEnableUnsubscribe","eventHub","on","destroy","eeUpdateUnsubscribe","eeDisableUnsubscribe","isEnabled","eventHubUnsubscribe","subscribe","cron","add","deleteExpiredAuditLogs","task","expirationDate","now","deleteExpiredEvents","unsubscribe","remove"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycles.mjs","sources":["../../../../../../../ee/server/src/audit-logs/services/lifecycles.ts"],"sourcesContent":["import type { Core, Modules } from '@strapi/types';\n\nconst DEFAULT_RETENTION_DAYS = 90;\n\nconst defaultEvents = [\n 'entry.create',\n 'entry.update',\n 'entry.delete',\n 'entry.publish',\n 'entry.unpublish',\n 'media.create',\n 'media.update',\n 'media.delete',\n 'media-folder.create',\n 'media-folder.update',\n 'media-folder.delete',\n 'user.create',\n 'user.update',\n 'user.delete',\n 'admin.auth.success',\n 'admin.logout',\n 'content-type.create',\n 'content-type.update',\n 'content-type.delete',\n 'component.create',\n 'component.update',\n 'component.delete',\n 'role.create',\n 'role.update',\n 'role.delete',\n 'permission.create',\n 'permission.update',\n 'permission.delete',\n];\n\nconst getEventMap = (defaultEvents: any) => {\n const getDefaultPayload = (...args: any) => args[0];\n\n // Use the default payload for all default events\n return defaultEvents.reduce((acc: any, event: any) => {\n acc[event] = getDefaultPayload;\n return acc;\n }, {} as any);\n};\n\nconst getRetentionDays = (strapi: Core.Strapi) => {\n const featureConfig = strapi.ee.features.get('audit-logs');\n const licenseRetentionDays =\n typeof featureConfig === 'object' && featureConfig?.options?.retentionDays;\n const userRetentionDays = strapi.config.get('admin.auditLogs.retentionDays');\n\n // For enterprise plans, use 90 days by default, but allow users to override it\n if (licenseRetentionDays == null) {\n return userRetentionDays ?? DEFAULT_RETENTION_DAYS;\n }\n\n // Allow users to override the license retention days, but not to increase it\n if (userRetentionDays && userRetentionDays <= licenseRetentionDays) {\n return userRetentionDays;\n }\n\n // User didn't provide a retention days value, use the license one\n return licenseRetentionDays;\n};\n\n/**\n * @description\n * Manages the lifecycle of audit logs. Accessible via strapi.get('audit-logs-lifecycles')\n */\nconst createAuditLogsLifecycleService = (strapi: Core.Strapi) => {\n // Manage internal service state privately\n const state = {} as any;\n const auditLogsService = strapi.get('audit-logs');\n\n // NOTE: providers should be able to replace getEventMap to add or remove events\n const eventMap = getEventMap(defaultEvents);\n\n const processEvent = (name: string, ...args: any) => {\n const requestState = strapi.requestContext.get()?.state;\n\n // Only audit admin-authenticated actions, plus MCP actions flagged via auditSource.\n const isUsingAdminAuth = requestState?.route.info.type === 'admin';\n const auditSource = requestState?.auditSource;\n const isMcpAdminAction = auditSource === 'mcp';\n const user = requestState?.user;\n if ((!isUsingAdminAuth && !isMcpAdminAction) || !user) {\n return null;\n }\n\n const origin: Modules.AuditLogs.AuditSource = auditSource ?? 'admin';\n\n const getPayload = eventMap[name];\n\n // Ignore the event if it's not in the map\n if (!getPayload) {\n return null;\n }\n\n // Ignore some events based on payload\n // TODO: What does this ignore in upload? Why would we want to ignore anything?\n const ignoredUids = ['plugin::upload.file', 'plugin::upload.folder'];\n if (ignoredUids.includes(args[0]?.uid)) {\n return null;\n }\n\n return {\n action: name,\n date: new Date().toISOString(),\n payload: { ...(getPayload(...args) || {}), origin },\n userId: user.id,\n };\n };\n\n const handleEvent = async (name: string, ...args: any) => {\n const processedEvent = processEvent(name, ...args);\n\n if (processedEvent) {\n await auditLogsService.saveEvent(processedEvent);\n }\n };\n\n return {\n async register() {\n // Handle license being enabled\n if (!state.eeEnableUnsubscribe) {\n // @ts-expect-error- update event hub to receive callback argument\n state.eeEnableUnsubscribe = strapi.eventHub.on('ee.enable', () => {\n // Recreate the service to use the new license info\n this.destroy();\n this.register();\n });\n }\n\n // Handle license being updated\n if (!state.eeUpdateUnsubscribe) {\n // @ts-expect-error- update event hub to receive callback argument\n state.eeUpdateUnsubscribe = strapi.eventHub.on('ee.update', () => {\n // Recreate the service to use the new license info\n this.destroy();\n this.register();\n });\n }\n\n // Handle license being disabled\n // @ts-expect-error- update event hub to receive callback argument\n state.eeDisableUnsubscribe = strapi.eventHub.on('ee.disable', () => {\n // Turn off service when the license gets disabled\n // Only ee.enable and ee.update listeners remain active to recreate the service\n this.destroy();\n });\n\n // Check current state of license\n if (!strapi.ee.features.isEnabled('audit-logs')) {\n return this;\n }\n\n // Start saving events\n state.eventHubUnsubscribe = strapi.eventHub.subscribe(handleEvent);\n\n // Manage audit logs auto deletion\n const retentionDays = getRetentionDays(strapi);\n\n strapi.cron.add({\n deleteExpiredAuditLogs: {\n async task() {\n const expirationDate = new Date(Date.now() - retentionDays * 24 * 60 * 60 * 1000);\n await auditLogsService.deleteExpiredEvents(expirationDate);\n },\n options: '0 0 * * *',\n },\n });\n\n return this;\n },\n\n unsubscribe() {\n if (state.eeDisableUnsubscribe) {\n state.eeDisableUnsubscribe();\n }\n\n if (state.eventHubUnsubscribe) {\n state.eventHubUnsubscribe();\n }\n\n strapi.cron.remove('deleteExpiredAuditLogs');\n\n return this;\n },\n\n destroy() {\n return this.unsubscribe();\n },\n };\n};\n\nexport { createAuditLogsLifecycleService };\n"],"names":["DEFAULT_RETENTION_DAYS","defaultEvents","getEventMap","getDefaultPayload","args","reduce","acc","event","getRetentionDays","strapi","featureConfig","ee","features","get","licenseRetentionDays","options","retentionDays","userRetentionDays","config","createAuditLogsLifecycleService","state","auditLogsService","eventMap","processEvent","name","requestState","requestContext","isUsingAdminAuth","route","info","type","auditSource","isMcpAdminAction","user","origin","getPayload","ignoredUids","includes","uid","action","date","Date","toISOString","payload","userId","id","handleEvent","processedEvent","saveEvent","register","eeEnableUnsubscribe","eventHub","on","destroy","eeUpdateUnsubscribe","eeDisableUnsubscribe","isEnabled","eventHubUnsubscribe","subscribe","cron","add","deleteExpiredAuditLogs","task","expirationDate","now","deleteExpiredEvents","unsubscribe","remove"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecycles.mjs","sources":["../../../../../../../ee/server/src/audit-logs/services/lifecycles.ts"],"sourcesContent":["import type { Core, Modules } from '@strapi/types';\n\nconst DEFAULT_RETENTION_DAYS = 90;\n\nconst defaultEvents = [\n 'entry.create',\n 'entry.update',\n 'entry.delete',\n 'entry.publish',\n 'entry.unpublish',\n 'media.create',\n 'media.update',\n 'media.delete',\n 'media-folder.create',\n 'media-folder.update',\n 'media-folder.delete',\n 'user.create',\n 'user.update',\n 'user.delete',\n 'admin.auth.success',\n 'admin.logout',\n 'content-type.create',\n 'content-type.update',\n 'content-type.delete',\n 'component.create',\n 'component.update',\n 'component.delete',\n 'role.create',\n 'role.update',\n 'role.delete',\n 'permission.create',\n 'permission.update',\n 'permission.delete',\n];\n\nconst getEventMap = (defaultEvents: any) => {\n const getDefaultPayload = (...args: any) => args[0];\n\n // Use the default payload for all default events\n return defaultEvents.reduce((acc: any, event: any) => {\n acc[event] = getDefaultPayload;\n return acc;\n }, {} as any);\n};\n\nconst getRetentionDays = (strapi: Core.Strapi) => {\n const featureConfig = strapi.ee.features.get('audit-logs');\n const licenseRetentionDays =\n typeof featureConfig === 'object' && featureConfig?.options?.retentionDays;\n const userRetentionDays = strapi.config.get('admin.auditLogs.retentionDays');\n\n // For enterprise plans, use 90 days by default, but allow users to override it\n if (licenseRetentionDays == null) {\n return userRetentionDays ?? DEFAULT_RETENTION_DAYS;\n }\n\n // Allow users to override the license retention days, but not to increase it\n if (userRetentionDays && userRetentionDays <= licenseRetentionDays) {\n return userRetentionDays;\n }\n\n // User didn't provide a retention days value, use the license one\n return licenseRetentionDays;\n};\n\n/**\n * @description\n * Manages the lifecycle of audit logs. Accessible via strapi.get('audit-logs-lifecycles')\n */\nconst createAuditLogsLifecycleService = (strapi: Core.Strapi) => {\n // Manage internal service state privately\n const state = {} as any;\n const auditLogsService = strapi.get('audit-logs');\n\n // NOTE: providers should be able to replace getEventMap to add or remove events\n const eventMap = getEventMap(defaultEvents);\n\n const processEvent = (name: string, ...args: any) => {\n const requestState = strapi.requestContext.get()?.state;\n\n // Only audit admin-authenticated actions, plus MCP actions flagged via auditSource.\n const isUsingAdminAuth = requestState?.route.info.type === 'admin';\n const auditSource = requestState?.auditSource;\n const isMcpAdminAction = auditSource === 'mcp';\n const user = requestState?.user;\n if ((!isUsingAdminAuth && !isMcpAdminAction) || !user) {\n return null;\n }\n\n const origin: Modules.AuditLogs.AuditSource = auditSource ?? 'admin';\n\n const getPayload = eventMap[name];\n\n // Ignore the event if it's not in the map\n if (!getPayload) {\n return null;\n }\n\n // Ignore some events based on payload\n // TODO: What does this ignore in upload? Why would we want to ignore anything?\n const ignoredUids = ['plugin::upload.file', 'plugin::upload.folder'];\n if (ignoredUids.includes(args[0]?.uid)) {\n return null;\n }\n\n return {\n action: name,\n date: new Date().toISOString(),\n payload: { ...getPayload(...args), origin },\n userId: user.id,\n };\n };\n\n const handleEvent = async (name: string, ...args: any) => {\n const processedEvent = processEvent(name, ...args);\n\n if (processedEvent) {\n await auditLogsService.saveEvent(processedEvent);\n }\n };\n\n return {\n async register() {\n // Handle license being enabled\n if (!state.eeEnableUnsubscribe) {\n // @ts-expect-error- update event hub to receive callback argument\n state.eeEnableUnsubscribe = strapi.eventHub.on('ee.enable', () => {\n // Recreate the service to use the new license info\n this.destroy();\n this.register();\n });\n }\n\n // Handle license being updated\n if (!state.eeUpdateUnsubscribe) {\n // @ts-expect-error- update event hub to receive callback argument\n state.eeUpdateUnsubscribe = strapi.eventHub.on('ee.update', () => {\n // Recreate the service to use the new license info\n this.destroy();\n this.register();\n });\n }\n\n // Handle license being disabled\n // @ts-expect-error- update event hub to receive callback argument\n state.eeDisableUnsubscribe = strapi.eventHub.on('ee.disable', () => {\n // Turn off service when the license gets disabled\n // Only ee.enable and ee.update listeners remain active to recreate the service\n this.destroy();\n });\n\n // Check current state of license\n if (!strapi.ee.features.isEnabled('audit-logs')) {\n return this;\n }\n\n // Start saving events\n state.eventHubUnsubscribe = strapi.eventHub.subscribe(handleEvent);\n\n // Manage audit logs auto deletion\n const retentionDays = getRetentionDays(strapi);\n\n strapi.cron.add({\n deleteExpiredAuditLogs: {\n async task() {\n const expirationDate = new Date(Date.now() - retentionDays * 24 * 60 * 60 * 1000);\n await auditLogsService.deleteExpiredEvents(expirationDate);\n },\n options: '0 0 * * *',\n },\n });\n\n return this;\n },\n\n unsubscribe() {\n if (state.eeDisableUnsubscribe) {\n state.eeDisableUnsubscribe();\n }\n\n if (state.eventHubUnsubscribe) {\n state.eventHubUnsubscribe();\n }\n\n strapi.cron.remove('deleteExpiredAuditLogs');\n\n return this;\n },\n\n destroy() {\n return this.unsubscribe();\n },\n };\n};\n\nexport { createAuditLogsLifecycleService };\n"],"names":["DEFAULT_RETENTION_DAYS","defaultEvents","getEventMap","getDefaultPayload","args","reduce","acc","event","getRetentionDays","strapi","featureConfig","ee","features","get","licenseRetentionDays","options","retentionDays","userRetentionDays","config","createAuditLogsLifecycleService","state","auditLogsService","eventMap","processEvent","name","requestState","requestContext","isUsingAdminAuth","route","info","type","auditSource","isMcpAdminAction","user","origin","getPayload","ignoredUids","includes","uid","action","date","Date","toISOString","payload","userId","id","handleEvent","processedEvent","saveEvent","register","eeEnableUnsubscribe","eventHub","on","destroy","eeUpdateUnsubscribe","eeDisableUnsubscribe","isEnabled","eventHubUnsubscribe","subscribe","cron","add","deleteExpiredAuditLogs","task","expirationDate","now","deleteExpiredEvents","unsubscribe","remove"],"mappings":"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"}
|
|
@@ -1,27 +1,47 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var z = require('zod/v4');
|
|
4
|
+
|
|
5
|
+
function _interopNamespace(e) {
|
|
6
|
+
if (e && e.__esModule) return e;
|
|
7
|
+
var n = Object.create(null);
|
|
8
|
+
if (e) {
|
|
9
|
+
Object.keys(e).forEach(function (k) {
|
|
10
|
+
if (k !== 'default') {
|
|
11
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
12
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () { return e[k]; }
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
n.default = e;
|
|
20
|
+
return Object.freeze(n);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
var z__namespace = /*#__PURE__*/_interopNamespace(z);
|
|
4
24
|
|
|
5
25
|
// widths must be one of 4, 6, 8, 12
|
|
6
|
-
const WidthSchema =
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
26
|
+
const WidthSchema = z__namespace.union([
|
|
27
|
+
z__namespace.literal(4),
|
|
28
|
+
z__namespace.literal(6),
|
|
29
|
+
z__namespace.literal(8),
|
|
30
|
+
z__namespace.literal(12)
|
|
11
31
|
]);
|
|
12
|
-
const WidgetEntrySchema =
|
|
13
|
-
uid:
|
|
32
|
+
const WidgetEntrySchema = z__namespace.object({
|
|
33
|
+
uid: z__namespace.string().nonempty(),
|
|
14
34
|
width: WidthSchema
|
|
15
35
|
}).strict();
|
|
16
|
-
const HomepageLayoutSchema =
|
|
17
|
-
version:
|
|
18
|
-
widgets:
|
|
19
|
-
updatedAt:
|
|
36
|
+
const HomepageLayoutSchema = z__namespace.object({
|
|
37
|
+
version: z__namespace.number().int().min(1),
|
|
38
|
+
widgets: z__namespace.array(WidgetEntrySchema).max(100),
|
|
39
|
+
updatedAt: z__namespace.string().datetime()
|
|
20
40
|
}).strict();
|
|
21
|
-
const HomepageLayoutWriteSchema =
|
|
22
|
-
version:
|
|
23
|
-
widgets:
|
|
24
|
-
updatedAt:
|
|
41
|
+
const HomepageLayoutWriteSchema = z__namespace.object({
|
|
42
|
+
version: z__namespace.number().int().min(1).optional(),
|
|
43
|
+
widgets: z__namespace.array(WidgetEntrySchema).max(100),
|
|
44
|
+
updatedAt: z__namespace.string().datetime().optional()
|
|
25
45
|
}).strict();
|
|
26
46
|
|
|
27
47
|
exports.HomepageLayoutSchema = HomepageLayoutSchema;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sources":["../../../../../../server/src/controllers/validation/schema.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"schema.js","sources":["../../../../../../server/src/controllers/validation/schema.ts"],"sourcesContent":["import * as z from 'zod/v4';\n\n// widths must be one of 4, 6, 8, 12\nexport const WidthSchema = z.union([z.literal(4), z.literal(6), z.literal(8), z.literal(12)]);\n\nconst WidgetEntrySchema = z\n .object({\n uid: z.string().nonempty(),\n width: WidthSchema,\n })\n .strict();\n\nexport const HomepageLayoutSchema = z\n .object({\n version: z.number().int().min(1),\n widgets: z.array(WidgetEntrySchema).max(100),\n updatedAt: z.string().datetime(),\n })\n .strict();\n\nexport type HomepageLayout = z.infer<typeof HomepageLayoutSchema>;\n\nexport const HomepageLayoutWriteSchema = z\n .object({\n version: z.number().int().min(1).optional(),\n widgets: z.array(WidgetEntrySchema).max(100),\n updatedAt: z.string().datetime().optional(),\n })\n .strict();\n\nexport type HomepageLayoutWrite = z.infer<typeof HomepageLayoutWriteSchema>;\n"],"names":["WidthSchema","z","union","literal","WidgetEntrySchema","object","uid","string","nonempty","width","strict","HomepageLayoutSchema","version","number","int","min","widgets","array","max","updatedAt","datetime","HomepageLayoutWriteSchema","optional"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAEA;AACO,MAAMA,WAAAA,GAAcC,YAAAA,CAAEC,KAAK,CAAC;AAACD,IAAAA,YAAAA,CAAEE,OAAO,CAAC,CAAA,CAAA;AAAIF,IAAAA,YAAAA,CAAEE,OAAO,CAAC,CAAA,CAAA;AAAIF,IAAAA,YAAAA,CAAEE,OAAO,CAAC,CAAA,CAAA;AAAIF,IAAAA,YAAAA,CAAEE,OAAO,CAAC,EAAA;CAAI;AAE5F,MAAMC,iBAAAA,GAAoBH,YAAAA,CACvBI,MAAM,CAAC;IACNC,GAAAA,EAAKL,YAAAA,CAAEM,MAAM,EAAA,CAAGC,QAAQ,EAAA;IACxBC,KAAAA,EAAOT;AACT,CAAA,CAAA,CACCU,MAAM,EAAA;AAEF,MAAMC,oBAAAA,GAAuBV,YAAAA,CACjCI,MAAM,CAAC;AACNO,IAAAA,OAAAA,EAASX,aAAEY,MAAM,EAAA,CAAGC,GAAG,EAAA,CAAGC,GAAG,CAAC,CAAA,CAAA;AAC9BC,IAAAA,OAAAA,EAASf,YAAAA,CAAEgB,KAAK,CAACb,iBAAAA,CAAAA,CAAmBc,GAAG,CAAC,GAAA,CAAA;IACxCC,SAAAA,EAAWlB,YAAAA,CAAEM,MAAM,EAAA,CAAGa,QAAQ;AAChC,CAAA,CAAA,CACCV,MAAM;AAIF,MAAMW,yBAAAA,GAA4BpB,YAAAA,CACtCI,MAAM,CAAC;IACNO,OAAAA,EAASX,YAAAA,CAAEY,MAAM,EAAA,CAAGC,GAAG,GAAGC,GAAG,CAAC,GAAGO,QAAQ,EAAA;AACzCN,IAAAA,OAAAA,EAASf,YAAAA,CAAEgB,KAAK,CAACb,iBAAAA,CAAAA,CAAmBc,GAAG,CAAC,GAAA,CAAA;AACxCC,IAAAA,SAAAA,EAAWlB,YAAAA,CAAEM,MAAM,EAAA,CAAGa,QAAQ,GAAGE,QAAQ;AAC3C,CAAA,CAAA,CACCZ,MAAM;;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.mjs","sources":["../../../../../../server/src/controllers/validation/schema.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"schema.mjs","sources":["../../../../../../server/src/controllers/validation/schema.ts"],"sourcesContent":["import * as z from 'zod/v4';\n\n// widths must be one of 4, 6, 8, 12\nexport const WidthSchema = z.union([z.literal(4), z.literal(6), z.literal(8), z.literal(12)]);\n\nconst WidgetEntrySchema = z\n .object({\n uid: z.string().nonempty(),\n width: WidthSchema,\n })\n .strict();\n\nexport const HomepageLayoutSchema = z\n .object({\n version: z.number().int().min(1),\n widgets: z.array(WidgetEntrySchema).max(100),\n updatedAt: z.string().datetime(),\n })\n .strict();\n\nexport type HomepageLayout = z.infer<typeof HomepageLayoutSchema>;\n\nexport const HomepageLayoutWriteSchema = z\n .object({\n version: z.number().int().min(1).optional(),\n widgets: z.array(WidgetEntrySchema).max(100),\n updatedAt: z.string().datetime().optional(),\n })\n .strict();\n\nexport type HomepageLayoutWrite = z.infer<typeof HomepageLayoutWriteSchema>;\n"],"names":["WidthSchema","z","union","literal","WidgetEntrySchema","object","uid","string","nonempty","width","strict","HomepageLayoutSchema","version","number","int","min","widgets","array","max","updatedAt","datetime","HomepageLayoutWriteSchema","optional"],"mappings":";;AAEA;AACO,MAAMA,WAAAA,GAAcC,CAAAA,CAAEC,KAAK,CAAC;AAACD,IAAAA,CAAAA,CAAEE,OAAO,CAAC,CAAA,CAAA;AAAIF,IAAAA,CAAAA,CAAEE,OAAO,CAAC,CAAA,CAAA;AAAIF,IAAAA,CAAAA,CAAEE,OAAO,CAAC,CAAA,CAAA;AAAIF,IAAAA,CAAAA,CAAEE,OAAO,CAAC,EAAA;CAAI;AAE5F,MAAMC,iBAAAA,GAAoBH,CAAAA,CACvBI,MAAM,CAAC;IACNC,GAAAA,EAAKL,CAAAA,CAAEM,MAAM,EAAA,CAAGC,QAAQ,EAAA;IACxBC,KAAAA,EAAOT;AACT,CAAA,CAAA,CACCU,MAAM,EAAA;AAEF,MAAMC,oBAAAA,GAAuBV,CAAAA,CACjCI,MAAM,CAAC;AACNO,IAAAA,OAAAA,EAASX,EAAEY,MAAM,EAAA,CAAGC,GAAG,EAAA,CAAGC,GAAG,CAAC,CAAA,CAAA;AAC9BC,IAAAA,OAAAA,EAASf,CAAAA,CAAEgB,KAAK,CAACb,iBAAAA,CAAAA,CAAmBc,GAAG,CAAC,GAAA,CAAA;IACxCC,SAAAA,EAAWlB,CAAAA,CAAEM,MAAM,EAAA,CAAGa,QAAQ;AAChC,CAAA,CAAA,CACCV,MAAM;AAIF,MAAMW,yBAAAA,GAA4BpB,CAAAA,CACtCI,MAAM,CAAC;IACNO,OAAAA,EAASX,CAAAA,CAAEY,MAAM,EAAA,CAAGC,GAAG,GAAGC,GAAG,CAAC,GAAGO,QAAQ,EAAA;AACzCN,IAAAA,OAAAA,EAASf,CAAAA,CAAEgB,KAAK,CAACb,iBAAAA,CAAAA,CAAmBc,GAAG,CAAC,GAAA,CAAA;AACxCC,IAAAA,SAAAA,EAAWlB,CAAAA,CAAEM,MAAM,EAAA,CAAGa,QAAQ,GAAGE,QAAQ;AAC3C,CAAA,CAAA,CACCZ,MAAM;;;;"}
|
|
@@ -96,6 +96,7 @@ var ___default = /*#__PURE__*/_interopDefault(_);
|
|
|
96
96
|
* Cleans permissions' fields (add required ones, remove the non-existing ones)
|
|
97
97
|
*/ const cleanPermissionFields = (permissions)=>{
|
|
98
98
|
const { actionProvider } = index.getService('permission');
|
|
99
|
+
const nestedFieldsCache = new Map();
|
|
99
100
|
return permissions.map((permission)=>{
|
|
100
101
|
const { action: actionId, subject, properties: { fields } } = permission;
|
|
101
102
|
const action = actionProvider.get(actionId);
|
|
@@ -106,9 +107,13 @@ var ___default = /*#__PURE__*/_interopDefault(_);
|
|
|
106
107
|
if (!subject || !strapi.contentTypes[subject]) {
|
|
107
108
|
return permission;
|
|
108
109
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
let possibleFields = nestedFieldsCache.get(subject);
|
|
111
|
+
if (!possibleFields) {
|
|
112
|
+
possibleFields = getNestedFieldsWithIntermediate(strapi.contentTypes[subject], {
|
|
113
|
+
components: strapi.components
|
|
114
|
+
});
|
|
115
|
+
nestedFieldsCache.set(subject, possibleFields);
|
|
116
|
+
}
|
|
112
117
|
const currentFields = fields || [];
|
|
113
118
|
const validUserFields = fp.uniq(possibleFields.filter((pf)=>currentFields.some((cf)=>pf === cf || fp.startsWith(`${cf}.`, pf))));
|
|
114
119
|
// A field is considered "not nested" if no other valid user field starts with this field's path followed by a dot.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-type.js","sources":["../../../../../server/src/services/content-type.ts"],"sourcesContent":["import _ from 'lodash';\nimport { uniq, startsWith } from 'lodash/fp';\nimport { contentTypes as contentTypesUtils } from '@strapi/utils';\nimport type { Modules, Struct } from '@strapi/types';\nimport { getService } from '../utils';\nimport actionDomain from '../domain/action';\nimport permissionDomain from '../domain/permission';\n\ninterface FieldOptions {\n prefix?: string; // prefix to add to the path\n nestingLevel?: number; // level of nesting to achieve\n requiredOnly?: boolean; // only returns required nestedFields\n existingFields?: string[]; // fields that are already selected, meaning that some sub-fields may be required\n restrictedSubjects?: string[]; // subjectsId to ignore\n components?: {\n // components where components attributes can be found\n [key: string]: any;\n };\n}\n\n/**\n * Creates an array of paths to the fields and nested fields, without path nodes\n */\nconst getNestedFields = (\n model: Struct.ContentTypeSchema,\n {\n prefix = '',\n nestingLevel = 15,\n components = {},\n requiredOnly = false,\n existingFields = [],\n }: FieldOptions\n): string[] => {\n if (nestingLevel === 0) {\n return prefix ? [prefix] : [];\n }\n\n const nonAuthorizableFields = contentTypesUtils.getNonVisibleAttributes(model);\n\n return _.reduce(\n model.attributes,\n (fields: any, attr: any, key: any) => {\n if (nonAuthorizableFields.includes(key)) return fields;\n\n const fieldPath = prefix ? `${prefix}.${key}` : key;\n const shouldBeIncluded = !requiredOnly || attr.required === true;\n const insideExistingFields = existingFields && existingFields.some(startsWith(fieldPath));\n\n if (attr.type === 'component') {\n if (shouldBeIncluded || insideExistingFields) {\n const compoFields = getNestedFields(components[attr.component], {\n nestingLevel: nestingLevel - 1,\n prefix: fieldPath,\n components,\n requiredOnly,\n existingFields,\n });\n\n if (compoFields.length === 0 && shouldBeIncluded) {\n return fields.concat(fieldPath);\n }\n\n return fields.concat(compoFields);\n }\n return fields;\n }\n\n if (shouldBeIncluded) {\n return fields.concat(fieldPath);\n }\n\n return fields;\n },\n []\n );\n};\n\n/**\n * Creates an array of paths to the fields and nested fields, with path nodes\n */\nconst getNestedFieldsWithIntermediate = (\n model: Struct.ContentTypeSchema,\n { prefix = '', nestingLevel = 15, components = {} }: FieldOptions\n): string[] => {\n if (nestingLevel === 0) {\n return [];\n }\n\n const nonAuthorizableFields = contentTypesUtils.getNonVisibleAttributes(model);\n\n return _.reduce(\n model.attributes,\n (fields: any, attr: any, key: any) => {\n if (nonAuthorizableFields.includes(key)) return fields;\n\n const fieldPath = prefix ? `${prefix}.${key}` : key;\n fields.push(fieldPath);\n\n if (attr.type === 'component') {\n const compoFields = getNestedFieldsWithIntermediate(components[attr.component], {\n nestingLevel: nestingLevel - 1,\n prefix: fieldPath,\n components,\n });\n\n fields.push(...compoFields);\n }\n\n return fields;\n },\n []\n );\n};\n\n/**\n * Creates an array of permissions with the \"properties.fields\" attribute filled\n */\nconst getPermissionsWithNestedFields = (\n actions: any[],\n { nestingLevel, restrictedSubjects = [] }: FieldOptions = {}\n): Modules.Permissions.PermissionRule[] => {\n return actions.reduce((permissions, action) => {\n const validSubjects = action.subjects.filter(\n (subject: any) => !restrictedSubjects.includes(subject)\n );\n\n // Create a Permission for each subject (content-type uid) within the action\n for (const subject of validSubjects) {\n const fields = actionDomain.appliesToProperty('fields', action)\n ? getNestedFields(strapi.contentTypes[subject], {\n components: strapi.components,\n nestingLevel,\n })\n : undefined;\n\n const permission = permissionDomain.create({\n action: action.actionId,\n subject,\n properties: { fields },\n });\n\n permissions.push(permission);\n }\n\n return permissions;\n }, []);\n};\n\n/**\n * Cleans permissions' fields (add required ones, remove the non-existing ones)\n */\nconst cleanPermissionFields = (\n permissions: Modules.Permissions.PermissionRule[]\n): Modules.Permissions.PermissionRule[] => {\n const { actionProvider } = getService('permission');\n\n return permissions.map((permission: any) => {\n const {\n action: actionId,\n subject,\n properties: { fields },\n } = permission;\n\n const action = actionProvider.get(actionId) as any;\n\n // todo see if it's possible to check property on action + subject (async)\n if (!actionDomain.appliesToProperty('fields', action)) {\n return permissionDomain.deleteProperty('fields', permission);\n }\n\n if (!subject || !strapi.contentTypes[subject]) {\n return permission;\n }\n\n const possibleFields = getNestedFieldsWithIntermediate(strapi.contentTypes[subject], {\n components: strapi.components,\n });\n\n const currentFields: string[] = fields || [];\n\n const validUserFields: string[] = uniq(\n possibleFields.filter((pf) =>\n currentFields.some((cf) => pf === cf || startsWith(`${cf}.`, pf))\n )\n );\n\n // A field is considered \"not nested\" if no other valid user field starts with this field's path followed by a dot.\n // This helps to remove redundant parent paths when a more specific child path is already included.\n // For example, if 'component.title' is present, 'component' would be filtered out by this condition.\n const isNotNestedField = (field: string) =>\n !validUserFields.some(\n (validUserField: string) =>\n validUserField !== field && startsWith(`${field}.`, validUserField)\n );\n\n // Filter out fields that are parent paths of other included fields.\n const newFields = validUserFields.filter(isNotNestedField);\n\n return permissionDomain.setProperty('fields', newFields, permission);\n }, []);\n};\n\nexport {\n getNestedFields,\n getPermissionsWithNestedFields,\n cleanPermissionFields,\n getNestedFieldsWithIntermediate,\n};\n"],"names":["getNestedFields","model","prefix","nestingLevel","components","requiredOnly","existingFields","nonAuthorizableFields","contentTypesUtils","getNonVisibleAttributes","_","reduce","attributes","fields","attr","key","includes","fieldPath","shouldBeIncluded","required","insideExistingFields","some","startsWith","type","compoFields","component","length","concat","getNestedFieldsWithIntermediate","push","getPermissionsWithNestedFields","actions","restrictedSubjects","permissions","action","validSubjects","subjects","filter","subject","actionDomain","appliesToProperty","strapi","contentTypes","undefined","permission","permissionDomain","create","actionId","properties","cleanPermissionFields","actionProvider","getService","map","get","deleteProperty","possibleFields","currentFields","validUserFields","uniq","pf","cf","isNotNestedField","field","validUserField","newFields","setProperty"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"content-type.js","sources":["../../../../../server/src/services/content-type.ts"],"sourcesContent":["import _ from 'lodash';\nimport { uniq, startsWith } from 'lodash/fp';\nimport { contentTypes as contentTypesUtils } from '@strapi/utils';\nimport type { Modules, Struct } from '@strapi/types';\nimport { getService } from '../utils';\nimport actionDomain from '../domain/action';\nimport permissionDomain from '../domain/permission';\n\ninterface FieldOptions {\n prefix?: string; // prefix to add to the path\n nestingLevel?: number; // level of nesting to achieve\n requiredOnly?: boolean; // only returns required nestedFields\n existingFields?: string[]; // fields that are already selected, meaning that some sub-fields may be required\n restrictedSubjects?: string[]; // subjectsId to ignore\n components?: {\n // components where components attributes can be found\n [key: string]: any;\n };\n}\n\n/**\n * Creates an array of paths to the fields and nested fields, without path nodes\n */\nconst getNestedFields = (\n model: Struct.ContentTypeSchema,\n {\n prefix = '',\n nestingLevel = 15,\n components = {},\n requiredOnly = false,\n existingFields = [],\n }: FieldOptions\n): string[] => {\n if (nestingLevel === 0) {\n return prefix ? [prefix] : [];\n }\n\n const nonAuthorizableFields = contentTypesUtils.getNonVisibleAttributes(model);\n\n return _.reduce(\n model.attributes,\n (fields: any, attr: any, key: any) => {\n if (nonAuthorizableFields.includes(key)) return fields;\n\n const fieldPath = prefix ? `${prefix}.${key}` : key;\n const shouldBeIncluded = !requiredOnly || attr.required === true;\n const insideExistingFields = existingFields && existingFields.some(startsWith(fieldPath));\n\n if (attr.type === 'component') {\n if (shouldBeIncluded || insideExistingFields) {\n const compoFields = getNestedFields(components[attr.component], {\n nestingLevel: nestingLevel - 1,\n prefix: fieldPath,\n components,\n requiredOnly,\n existingFields,\n });\n\n if (compoFields.length === 0 && shouldBeIncluded) {\n return fields.concat(fieldPath);\n }\n\n return fields.concat(compoFields);\n }\n return fields;\n }\n\n if (shouldBeIncluded) {\n return fields.concat(fieldPath);\n }\n\n return fields;\n },\n []\n );\n};\n\n/**\n * Creates an array of paths to the fields and nested fields, with path nodes\n */\nconst getNestedFieldsWithIntermediate = (\n model: Struct.ContentTypeSchema,\n { prefix = '', nestingLevel = 15, components = {} }: FieldOptions\n): string[] => {\n if (nestingLevel === 0) {\n return [];\n }\n\n const nonAuthorizableFields = contentTypesUtils.getNonVisibleAttributes(model);\n\n return _.reduce(\n model.attributes,\n (fields: any, attr: any, key: any) => {\n if (nonAuthorizableFields.includes(key)) return fields;\n\n const fieldPath = prefix ? `${prefix}.${key}` : key;\n fields.push(fieldPath);\n\n if (attr.type === 'component') {\n const compoFields = getNestedFieldsWithIntermediate(components[attr.component], {\n nestingLevel: nestingLevel - 1,\n prefix: fieldPath,\n components,\n });\n\n fields.push(...compoFields);\n }\n\n return fields;\n },\n []\n );\n};\n\n/**\n * Creates an array of permissions with the \"properties.fields\" attribute filled\n */\nconst getPermissionsWithNestedFields = (\n actions: any[],\n { nestingLevel, restrictedSubjects = [] }: FieldOptions = {}\n): Modules.Permissions.PermissionRule[] => {\n return actions.reduce((permissions, action) => {\n const validSubjects = action.subjects.filter(\n (subject: any) => !restrictedSubjects.includes(subject)\n );\n\n // Create a Permission for each subject (content-type uid) within the action\n for (const subject of validSubjects) {\n const fields = actionDomain.appliesToProperty('fields', action)\n ? getNestedFields(strapi.contentTypes[subject], {\n components: strapi.components,\n nestingLevel,\n })\n : undefined;\n\n const permission = permissionDomain.create({\n action: action.actionId,\n subject,\n properties: { fields },\n });\n\n permissions.push(permission);\n }\n\n return permissions;\n }, []);\n};\n\n/**\n * Cleans permissions' fields (add required ones, remove the non-existing ones)\n */\nconst cleanPermissionFields = (\n permissions: Modules.Permissions.PermissionRule[]\n): Modules.Permissions.PermissionRule[] => {\n const { actionProvider } = getService('permission');\n const nestedFieldsCache = new Map<string, string[]>();\n\n return permissions.map((permission: any) => {\n const {\n action: actionId,\n subject,\n properties: { fields },\n } = permission;\n\n const action = actionProvider.get(actionId) as any;\n\n // todo see if it's possible to check property on action + subject (async)\n if (!actionDomain.appliesToProperty('fields', action)) {\n return permissionDomain.deleteProperty('fields', permission);\n }\n\n if (!subject || !strapi.contentTypes[subject]) {\n return permission;\n }\n\n let possibleFields = nestedFieldsCache.get(subject);\n if (!possibleFields) {\n possibleFields = getNestedFieldsWithIntermediate(strapi.contentTypes[subject], {\n components: strapi.components,\n });\n nestedFieldsCache.set(subject, possibleFields);\n }\n\n const currentFields: string[] = fields || [];\n\n const validUserFields: string[] = uniq(\n possibleFields.filter((pf) =>\n currentFields.some((cf) => pf === cf || startsWith(`${cf}.`, pf))\n )\n );\n\n // A field is considered \"not nested\" if no other valid user field starts with this field's path followed by a dot.\n // This helps to remove redundant parent paths when a more specific child path is already included.\n // For example, if 'component.title' is present, 'component' would be filtered out by this condition.\n const isNotNestedField = (field: string) =>\n !validUserFields.some(\n (validUserField: string) =>\n validUserField !== field && startsWith(`${field}.`, validUserField)\n );\n\n // Filter out fields that are parent paths of other included fields.\n const newFields = validUserFields.filter(isNotNestedField);\n\n return permissionDomain.setProperty('fields', newFields, permission);\n }, []);\n};\n\nexport {\n getNestedFields,\n getPermissionsWithNestedFields,\n cleanPermissionFields,\n getNestedFieldsWithIntermediate,\n};\n"],"names":["getNestedFields","model","prefix","nestingLevel","components","requiredOnly","existingFields","nonAuthorizableFields","contentTypesUtils","getNonVisibleAttributes","_","reduce","attributes","fields","attr","key","includes","fieldPath","shouldBeIncluded","required","insideExistingFields","some","startsWith","type","compoFields","component","length","concat","getNestedFieldsWithIntermediate","push","getPermissionsWithNestedFields","actions","restrictedSubjects","permissions","action","validSubjects","subjects","filter","subject","actionDomain","appliesToProperty","strapi","contentTypes","undefined","permission","permissionDomain","create","actionId","properties","cleanPermissionFields","actionProvider","getService","nestedFieldsCache","Map","map","get","deleteProperty","possibleFields","set","currentFields","validUserFields","uniq","pf","cf","isNotNestedField","field","validUserField","newFields","setProperty"],"mappings":"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"}
|
|
@@ -90,6 +90,7 @@ import permissionDomain from '../domain/permission/index.mjs';
|
|
|
90
90
|
* Cleans permissions' fields (add required ones, remove the non-existing ones)
|
|
91
91
|
*/ const cleanPermissionFields = (permissions)=>{
|
|
92
92
|
const { actionProvider } = getService('permission');
|
|
93
|
+
const nestedFieldsCache = new Map();
|
|
93
94
|
return permissions.map((permission)=>{
|
|
94
95
|
const { action: actionId, subject, properties: { fields } } = permission;
|
|
95
96
|
const action = actionProvider.get(actionId);
|
|
@@ -100,9 +101,13 @@ import permissionDomain from '../domain/permission/index.mjs';
|
|
|
100
101
|
if (!subject || !strapi.contentTypes[subject]) {
|
|
101
102
|
return permission;
|
|
102
103
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
let possibleFields = nestedFieldsCache.get(subject);
|
|
105
|
+
if (!possibleFields) {
|
|
106
|
+
possibleFields = getNestedFieldsWithIntermediate(strapi.contentTypes[subject], {
|
|
107
|
+
components: strapi.components
|
|
108
|
+
});
|
|
109
|
+
nestedFieldsCache.set(subject, possibleFields);
|
|
110
|
+
}
|
|
106
111
|
const currentFields = fields || [];
|
|
107
112
|
const validUserFields = uniq(possibleFields.filter((pf)=>currentFields.some((cf)=>pf === cf || startsWith(`${cf}.`, pf))));
|
|
108
113
|
// A field is considered "not nested" if no other valid user field starts with this field's path followed by a dot.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-type.mjs","sources":["../../../../../server/src/services/content-type.ts"],"sourcesContent":["import _ from 'lodash';\nimport { uniq, startsWith } from 'lodash/fp';\nimport { contentTypes as contentTypesUtils } from '@strapi/utils';\nimport type { Modules, Struct } from '@strapi/types';\nimport { getService } from '../utils';\nimport actionDomain from '../domain/action';\nimport permissionDomain from '../domain/permission';\n\ninterface FieldOptions {\n prefix?: string; // prefix to add to the path\n nestingLevel?: number; // level of nesting to achieve\n requiredOnly?: boolean; // only returns required nestedFields\n existingFields?: string[]; // fields that are already selected, meaning that some sub-fields may be required\n restrictedSubjects?: string[]; // subjectsId to ignore\n components?: {\n // components where components attributes can be found\n [key: string]: any;\n };\n}\n\n/**\n * Creates an array of paths to the fields and nested fields, without path nodes\n */\nconst getNestedFields = (\n model: Struct.ContentTypeSchema,\n {\n prefix = '',\n nestingLevel = 15,\n components = {},\n requiredOnly = false,\n existingFields = [],\n }: FieldOptions\n): string[] => {\n if (nestingLevel === 0) {\n return prefix ? [prefix] : [];\n }\n\n const nonAuthorizableFields = contentTypesUtils.getNonVisibleAttributes(model);\n\n return _.reduce(\n model.attributes,\n (fields: any, attr: any, key: any) => {\n if (nonAuthorizableFields.includes(key)) return fields;\n\n const fieldPath = prefix ? `${prefix}.${key}` : key;\n const shouldBeIncluded = !requiredOnly || attr.required === true;\n const insideExistingFields = existingFields && existingFields.some(startsWith(fieldPath));\n\n if (attr.type === 'component') {\n if (shouldBeIncluded || insideExistingFields) {\n const compoFields = getNestedFields(components[attr.component], {\n nestingLevel: nestingLevel - 1,\n prefix: fieldPath,\n components,\n requiredOnly,\n existingFields,\n });\n\n if (compoFields.length === 0 && shouldBeIncluded) {\n return fields.concat(fieldPath);\n }\n\n return fields.concat(compoFields);\n }\n return fields;\n }\n\n if (shouldBeIncluded) {\n return fields.concat(fieldPath);\n }\n\n return fields;\n },\n []\n );\n};\n\n/**\n * Creates an array of paths to the fields and nested fields, with path nodes\n */\nconst getNestedFieldsWithIntermediate = (\n model: Struct.ContentTypeSchema,\n { prefix = '', nestingLevel = 15, components = {} }: FieldOptions\n): string[] => {\n if (nestingLevel === 0) {\n return [];\n }\n\n const nonAuthorizableFields = contentTypesUtils.getNonVisibleAttributes(model);\n\n return _.reduce(\n model.attributes,\n (fields: any, attr: any, key: any) => {\n if (nonAuthorizableFields.includes(key)) return fields;\n\n const fieldPath = prefix ? `${prefix}.${key}` : key;\n fields.push(fieldPath);\n\n if (attr.type === 'component') {\n const compoFields = getNestedFieldsWithIntermediate(components[attr.component], {\n nestingLevel: nestingLevel - 1,\n prefix: fieldPath,\n components,\n });\n\n fields.push(...compoFields);\n }\n\n return fields;\n },\n []\n );\n};\n\n/**\n * Creates an array of permissions with the \"properties.fields\" attribute filled\n */\nconst getPermissionsWithNestedFields = (\n actions: any[],\n { nestingLevel, restrictedSubjects = [] }: FieldOptions = {}\n): Modules.Permissions.PermissionRule[] => {\n return actions.reduce((permissions, action) => {\n const validSubjects = action.subjects.filter(\n (subject: any) => !restrictedSubjects.includes(subject)\n );\n\n // Create a Permission for each subject (content-type uid) within the action\n for (const subject of validSubjects) {\n const fields = actionDomain.appliesToProperty('fields', action)\n ? getNestedFields(strapi.contentTypes[subject], {\n components: strapi.components,\n nestingLevel,\n })\n : undefined;\n\n const permission = permissionDomain.create({\n action: action.actionId,\n subject,\n properties: { fields },\n });\n\n permissions.push(permission);\n }\n\n return permissions;\n }, []);\n};\n\n/**\n * Cleans permissions' fields (add required ones, remove the non-existing ones)\n */\nconst cleanPermissionFields = (\n permissions: Modules.Permissions.PermissionRule[]\n): Modules.Permissions.PermissionRule[] => {\n const { actionProvider } = getService('permission');\n\n return permissions.map((permission: any) => {\n const {\n action: actionId,\n subject,\n properties: { fields },\n } = permission;\n\n const action = actionProvider.get(actionId) as any;\n\n // todo see if it's possible to check property on action + subject (async)\n if (!actionDomain.appliesToProperty('fields', action)) {\n return permissionDomain.deleteProperty('fields', permission);\n }\n\n if (!subject || !strapi.contentTypes[subject]) {\n return permission;\n }\n\n const possibleFields = getNestedFieldsWithIntermediate(strapi.contentTypes[subject], {\n components: strapi.components,\n });\n\n const currentFields: string[] = fields || [];\n\n const validUserFields: string[] = uniq(\n possibleFields.filter((pf) =>\n currentFields.some((cf) => pf === cf || startsWith(`${cf}.`, pf))\n )\n );\n\n // A field is considered \"not nested\" if no other valid user field starts with this field's path followed by a dot.\n // This helps to remove redundant parent paths when a more specific child path is already included.\n // For example, if 'component.title' is present, 'component' would be filtered out by this condition.\n const isNotNestedField = (field: string) =>\n !validUserFields.some(\n (validUserField: string) =>\n validUserField !== field && startsWith(`${field}.`, validUserField)\n );\n\n // Filter out fields that are parent paths of other included fields.\n const newFields = validUserFields.filter(isNotNestedField);\n\n return permissionDomain.setProperty('fields', newFields, permission);\n }, []);\n};\n\nexport {\n getNestedFields,\n getPermissionsWithNestedFields,\n cleanPermissionFields,\n getNestedFieldsWithIntermediate,\n};\n"],"names":["getNestedFields","model","prefix","nestingLevel","components","requiredOnly","existingFields","nonAuthorizableFields","contentTypesUtils","getNonVisibleAttributes","_","reduce","attributes","fields","attr","key","includes","fieldPath","shouldBeIncluded","required","insideExistingFields","some","startsWith","type","compoFields","component","length","concat","getNestedFieldsWithIntermediate","push","getPermissionsWithNestedFields","actions","restrictedSubjects","permissions","action","validSubjects","subjects","filter","subject","actionDomain","appliesToProperty","strapi","contentTypes","undefined","permission","permissionDomain","create","actionId","properties","cleanPermissionFields","actionProvider","getService","map","get","deleteProperty","possibleFields","currentFields","validUserFields","uniq","pf","cf","isNotNestedField","field","validUserField","newFields","setProperty"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"content-type.mjs","sources":["../../../../../server/src/services/content-type.ts"],"sourcesContent":["import _ from 'lodash';\nimport { uniq, startsWith } from 'lodash/fp';\nimport { contentTypes as contentTypesUtils } from '@strapi/utils';\nimport type { Modules, Struct } from '@strapi/types';\nimport { getService } from '../utils';\nimport actionDomain from '../domain/action';\nimport permissionDomain from '../domain/permission';\n\ninterface FieldOptions {\n prefix?: string; // prefix to add to the path\n nestingLevel?: number; // level of nesting to achieve\n requiredOnly?: boolean; // only returns required nestedFields\n existingFields?: string[]; // fields that are already selected, meaning that some sub-fields may be required\n restrictedSubjects?: string[]; // subjectsId to ignore\n components?: {\n // components where components attributes can be found\n [key: string]: any;\n };\n}\n\n/**\n * Creates an array of paths to the fields and nested fields, without path nodes\n */\nconst getNestedFields = (\n model: Struct.ContentTypeSchema,\n {\n prefix = '',\n nestingLevel = 15,\n components = {},\n requiredOnly = false,\n existingFields = [],\n }: FieldOptions\n): string[] => {\n if (nestingLevel === 0) {\n return prefix ? [prefix] : [];\n }\n\n const nonAuthorizableFields = contentTypesUtils.getNonVisibleAttributes(model);\n\n return _.reduce(\n model.attributes,\n (fields: any, attr: any, key: any) => {\n if (nonAuthorizableFields.includes(key)) return fields;\n\n const fieldPath = prefix ? `${prefix}.${key}` : key;\n const shouldBeIncluded = !requiredOnly || attr.required === true;\n const insideExistingFields = existingFields && existingFields.some(startsWith(fieldPath));\n\n if (attr.type === 'component') {\n if (shouldBeIncluded || insideExistingFields) {\n const compoFields = getNestedFields(components[attr.component], {\n nestingLevel: nestingLevel - 1,\n prefix: fieldPath,\n components,\n requiredOnly,\n existingFields,\n });\n\n if (compoFields.length === 0 && shouldBeIncluded) {\n return fields.concat(fieldPath);\n }\n\n return fields.concat(compoFields);\n }\n return fields;\n }\n\n if (shouldBeIncluded) {\n return fields.concat(fieldPath);\n }\n\n return fields;\n },\n []\n );\n};\n\n/**\n * Creates an array of paths to the fields and nested fields, with path nodes\n */\nconst getNestedFieldsWithIntermediate = (\n model: Struct.ContentTypeSchema,\n { prefix = '', nestingLevel = 15, components = {} }: FieldOptions\n): string[] => {\n if (nestingLevel === 0) {\n return [];\n }\n\n const nonAuthorizableFields = contentTypesUtils.getNonVisibleAttributes(model);\n\n return _.reduce(\n model.attributes,\n (fields: any, attr: any, key: any) => {\n if (nonAuthorizableFields.includes(key)) return fields;\n\n const fieldPath = prefix ? `${prefix}.${key}` : key;\n fields.push(fieldPath);\n\n if (attr.type === 'component') {\n const compoFields = getNestedFieldsWithIntermediate(components[attr.component], {\n nestingLevel: nestingLevel - 1,\n prefix: fieldPath,\n components,\n });\n\n fields.push(...compoFields);\n }\n\n return fields;\n },\n []\n );\n};\n\n/**\n * Creates an array of permissions with the \"properties.fields\" attribute filled\n */\nconst getPermissionsWithNestedFields = (\n actions: any[],\n { nestingLevel, restrictedSubjects = [] }: FieldOptions = {}\n): Modules.Permissions.PermissionRule[] => {\n return actions.reduce((permissions, action) => {\n const validSubjects = action.subjects.filter(\n (subject: any) => !restrictedSubjects.includes(subject)\n );\n\n // Create a Permission for each subject (content-type uid) within the action\n for (const subject of validSubjects) {\n const fields = actionDomain.appliesToProperty('fields', action)\n ? getNestedFields(strapi.contentTypes[subject], {\n components: strapi.components,\n nestingLevel,\n })\n : undefined;\n\n const permission = permissionDomain.create({\n action: action.actionId,\n subject,\n properties: { fields },\n });\n\n permissions.push(permission);\n }\n\n return permissions;\n }, []);\n};\n\n/**\n * Cleans permissions' fields (add required ones, remove the non-existing ones)\n */\nconst cleanPermissionFields = (\n permissions: Modules.Permissions.PermissionRule[]\n): Modules.Permissions.PermissionRule[] => {\n const { actionProvider } = getService('permission');\n const nestedFieldsCache = new Map<string, string[]>();\n\n return permissions.map((permission: any) => {\n const {\n action: actionId,\n subject,\n properties: { fields },\n } = permission;\n\n const action = actionProvider.get(actionId) as any;\n\n // todo see if it's possible to check property on action + subject (async)\n if (!actionDomain.appliesToProperty('fields', action)) {\n return permissionDomain.deleteProperty('fields', permission);\n }\n\n if (!subject || !strapi.contentTypes[subject]) {\n return permission;\n }\n\n let possibleFields = nestedFieldsCache.get(subject);\n if (!possibleFields) {\n possibleFields = getNestedFieldsWithIntermediate(strapi.contentTypes[subject], {\n components: strapi.components,\n });\n nestedFieldsCache.set(subject, possibleFields);\n }\n\n const currentFields: string[] = fields || [];\n\n const validUserFields: string[] = uniq(\n possibleFields.filter((pf) =>\n currentFields.some((cf) => pf === cf || startsWith(`${cf}.`, pf))\n )\n );\n\n // A field is considered \"not nested\" if no other valid user field starts with this field's path followed by a dot.\n // This helps to remove redundant parent paths when a more specific child path is already included.\n // For example, if 'component.title' is present, 'component' would be filtered out by this condition.\n const isNotNestedField = (field: string) =>\n !validUserFields.some(\n (validUserField: string) =>\n validUserField !== field && startsWith(`${field}.`, validUserField)\n );\n\n // Filter out fields that are parent paths of other included fields.\n const newFields = validUserFields.filter(isNotNestedField);\n\n return permissionDomain.setProperty('fields', newFields, permission);\n }, []);\n};\n\nexport {\n getNestedFields,\n getPermissionsWithNestedFields,\n cleanPermissionFields,\n getNestedFieldsWithIntermediate,\n};\n"],"names":["getNestedFields","model","prefix","nestingLevel","components","requiredOnly","existingFields","nonAuthorizableFields","contentTypesUtils","getNonVisibleAttributes","_","reduce","attributes","fields","attr","key","includes","fieldPath","shouldBeIncluded","required","insideExistingFields","some","startsWith","type","compoFields","component","length","concat","getNestedFieldsWithIntermediate","push","getPermissionsWithNestedFields","actions","restrictedSubjects","permissions","action","validSubjects","subjects","filter","subject","actionDomain","appliesToProperty","strapi","contentTypes","undefined","permission","permissionDomain","create","actionId","properties","cleanPermissionFields","actionProvider","getService","nestedFieldsCache","Map","map","get","deleteProperty","possibleFields","set","currentFields","validUserFields","uniq","pf","cf","isNotNestedField","field","validUserField","newFields","setProperty"],"mappings":"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"}
|
|
@@ -110,8 +110,10 @@ const filterPermissionsToRemove = async (permissions)=>{
|
|
|
110
110
|
const isRegisteredAction = actionProvider.has(permission.action);
|
|
111
111
|
const hasInvalidProperties = fp.isArray(applyToProperties) && invalidProperties.every(fp.eq(true));
|
|
112
112
|
const isInvalidSubject = fp.isArray(subjects) && !subjects.includes(permission.subject);
|
|
113
|
+
// On an api token permission, nil properties mean "everything", not "invalid"
|
|
114
|
+
const hasApiToken = !fp.isNil(fp.prop('apiToken', permission));
|
|
113
115
|
// If the permission has an invalid action, an invalid subject or invalid properties, then add it to the toBeRemoved collection
|
|
114
|
-
if (!isRegisteredAction || isInvalidSubject || hasInvalidProperties) {
|
|
116
|
+
if (!isRegisteredAction || isInvalidSubject || hasInvalidProperties && !hasApiToken) {
|
|
115
117
|
permissionsToRemove.push(permission);
|
|
116
118
|
}
|
|
117
119
|
}
|