payload 3.0.0-beta.130 → 3.0.0-beta.131

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.
Files changed (92) hide show
  1. package/dist/admin/elements/Cell.d.ts +16 -3
  2. package/dist/admin/elements/Cell.d.ts.map +1 -1
  3. package/dist/admin/elements/Cell.js.map +1 -1
  4. package/dist/admin/elements/Tab.d.ts +3 -3
  5. package/dist/admin/elements/Tab.d.ts.map +1 -1
  6. package/dist/admin/elements/Tab.js.map +1 -1
  7. package/dist/admin/fields/Hidden.d.ts +2 -5
  8. package/dist/admin/fields/Hidden.d.ts.map +1 -1
  9. package/dist/admin/fields/Hidden.js.map +1 -1
  10. package/dist/admin/forms/Field.d.ts +2 -2
  11. package/dist/admin/forms/Field.d.ts.map +1 -1
  12. package/dist/admin/forms/Field.js.map +1 -1
  13. package/dist/admin/forms/Form.d.ts +2 -2
  14. package/dist/admin/forms/Form.d.ts.map +1 -1
  15. package/dist/admin/forms/Form.js.map +1 -1
  16. package/dist/admin/types.d.ts +1 -1
  17. package/dist/admin/types.d.ts.map +1 -1
  18. package/dist/admin/types.js.map +1 -1
  19. package/dist/admin/views/types.d.ts +2 -2
  20. package/dist/admin/views/types.d.ts.map +1 -1
  21. package/dist/admin/views/types.js.map +1 -1
  22. package/dist/auth/getAccessResults.d.ts +2 -2
  23. package/dist/auth/getAccessResults.d.ts.map +1 -1
  24. package/dist/auth/getAccessResults.js +2 -1
  25. package/dist/auth/getAccessResults.js.map +1 -1
  26. package/dist/auth/operations/access.d.ts +2 -2
  27. package/dist/auth/operations/access.d.ts.map +1 -1
  28. package/dist/auth/operations/access.js.map +1 -1
  29. package/dist/auth/operations/auth.d.ts +2 -3
  30. package/dist/auth/operations/auth.d.ts.map +1 -1
  31. package/dist/auth/operations/auth.js.map +1 -1
  32. package/dist/auth/types.d.ts +66 -4
  33. package/dist/auth/types.d.ts.map +1 -1
  34. package/dist/auth/types.js.map +1 -1
  35. package/dist/collections/config/client.d.ts +1 -2
  36. package/dist/collections/config/client.d.ts.map +1 -1
  37. package/dist/collections/config/client.js +6 -4
  38. package/dist/collections/config/client.js.map +1 -1
  39. package/dist/collections/config/types.d.ts +2 -1
  40. package/dist/collections/config/types.d.ts.map +1 -1
  41. package/dist/collections/config/types.js.map +1 -1
  42. package/dist/config/client.d.ts +2 -1
  43. package/dist/config/client.d.ts.map +1 -1
  44. package/dist/config/client.js +4 -1
  45. package/dist/config/client.js.map +1 -1
  46. package/dist/config/types.d.ts +2 -2
  47. package/dist/config/types.d.ts.map +1 -1
  48. package/dist/config/types.js.map +1 -1
  49. package/dist/database/types.d.ts +29 -16
  50. package/dist/database/types.d.ts.map +1 -1
  51. package/dist/database/types.js.map +1 -1
  52. package/dist/fields/config/client.d.ts.map +1 -1
  53. package/dist/fields/config/client.js +14 -10
  54. package/dist/fields/config/client.js.map +1 -1
  55. package/dist/globals/config/client.js +1 -1
  56. package/dist/globals/config/client.js.map +1 -1
  57. package/dist/globals/config/types.d.ts +2 -1
  58. package/dist/globals/config/types.d.ts.map +1 -1
  59. package/dist/globals/config/types.js.map +1 -1
  60. package/dist/index.d.ts +8 -2
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +1 -0
  63. package/dist/index.js.map +1 -1
  64. package/dist/preferences/preferencesCollection.d.ts.map +1 -1
  65. package/dist/preferences/preferencesCollection.js +5 -2
  66. package/dist/preferences/preferencesCollection.js.map +1 -1
  67. package/dist/utilities/deepCopyObject.d.ts +1 -1
  68. package/dist/utilities/deepCopyObject.d.ts.map +1 -1
  69. package/dist/utilities/deepCopyObject.js +6 -3
  70. package/dist/utilities/deepCopyObject.js.map +1 -1
  71. package/dist/utilities/deepMerge.d.ts +1 -1
  72. package/dist/utilities/deepMerge.d.ts.map +1 -1
  73. package/dist/utilities/deepMerge.js +3 -2
  74. package/dist/utilities/deepMerge.js.map +1 -1
  75. package/dist/utilities/getEntityPolicies.d.ts.map +1 -1
  76. package/dist/utilities/getEntityPolicies.js +5 -1
  77. package/dist/utilities/getEntityPolicies.js.map +1 -1
  78. package/dist/utilities/removeUndefined.d.ts +2 -0
  79. package/dist/utilities/removeUndefined.d.ts.map +1 -0
  80. package/dist/utilities/removeUndefined.js +5 -0
  81. package/dist/utilities/removeUndefined.js.map +1 -0
  82. package/dist/utilities/sanitizePermissions.d.ts +14 -0
  83. package/dist/utilities/sanitizePermissions.d.ts.map +1 -0
  84. package/dist/utilities/sanitizePermissions.js +153 -0
  85. package/dist/utilities/sanitizePermissions.js.map +1 -0
  86. package/dist/utilities/sanitizePermissions.spec.js +428 -0
  87. package/dist/utilities/sanitizePermissions.spec.js.map +1 -0
  88. package/dist/utilities/traverseFields.d.ts +3 -1
  89. package/dist/utilities/traverseFields.d.ts.map +1 -1
  90. package/dist/utilities/traverseFields.js +67 -27
  91. package/dist/utilities/traverseFields.js.map +1 -1
  92. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/getEntityPolicies.ts"],"sourcesContent":["import type { CollectionPermission, GlobalPermission } from '../auth/types.js'\nimport type { SanitizedCollectionConfig, TypeWithID } from '../collections/config/types.js'\nimport type { Access } from '../config/types.js'\nimport type { Field, FieldAccess } from '../fields/config/types.js'\nimport type { SanitizedGlobalConfig } from '../globals/config/types.js'\nimport type { AllOperations, Document, PayloadRequest, Where } from '../types/index.js'\n\nimport { combineQueries } from '../database/combineQueries.js'\nimport { tabHasName } from '../fields/config/types.js'\n\ntype Args = {\n entity: SanitizedCollectionConfig | SanitizedGlobalConfig\n id?: number | string\n operations: AllOperations[]\n req: PayloadRequest\n type: 'collection' | 'global'\n}\n\ntype ReturnType<T extends Args> = T['type'] extends 'global'\n ? GlobalPermission\n : CollectionPermission\n\ntype CreateAccessPromise = (args: {\n access: Access | FieldAccess\n accessLevel: 'entity' | 'field'\n disableWhere?: boolean\n operation: AllOperations\n policiesObj: {\n [key: string]: any\n }\n}) => Promise<void>\n\nexport async function getEntityPolicies<T extends Args>(args: T): Promise<ReturnType<T>> {\n const { id, type, entity, operations, req } = args\n const { data, locale, payload, user } = req\n const isLoggedIn = !!user\n\n const policies = {\n fields: {},\n } as ReturnType<T>\n\n let docBeingAccessed\n\n async function getEntityDoc({ where }: { where?: Where } = {}): Promise<Document & TypeWithID> {\n if (entity.slug) {\n if (type === 'global') {\n return payload.findGlobal({\n slug: entity.slug,\n fallbackLocale: null,\n locale,\n overrideAccess: true,\n req,\n })\n }\n\n if (type === 'collection' && id) {\n if (typeof where === 'object') {\n const paginatedRes = await payload.find({\n collection: entity.slug,\n depth: 0,\n fallbackLocale: null,\n limit: 1,\n locale,\n overrideAccess: true,\n pagination: false,\n req,\n where: combineQueries(where, { id: { equals: id } }),\n })\n\n return paginatedRes?.docs?.[0] || undefined\n }\n\n return payload.findByID({\n id,\n collection: entity.slug,\n depth: 0,\n fallbackLocale: null,\n locale,\n overrideAccess: true,\n req,\n })\n }\n }\n\n return undefined\n }\n\n const createAccessPromise: CreateAccessPromise = async ({\n access,\n accessLevel,\n disableWhere = false,\n operation,\n policiesObj,\n }) => {\n const mutablePolicies = policiesObj\n\n if (accessLevel === 'field' && docBeingAccessed === undefined) {\n // assign docBeingAccessed first as the promise to avoid multiple calls to getEntityDoc\n docBeingAccessed = getEntityDoc().then((doc) => {\n docBeingAccessed = doc\n })\n }\n // awaiting the promise to ensure docBeingAccessed is assigned before it is used\n await docBeingAccessed\n\n // https://payloadcms.slack.com/archives/C048Z9C2BEX/p1702054928343769\n const accessResult = await access({ id, data, doc: docBeingAccessed, req })\n\n if (typeof accessResult === 'object' && !disableWhere) {\n mutablePolicies[operation] = {\n permission:\n id || type === 'global' ? !!(await getEntityDoc({ where: accessResult })) : true,\n where: accessResult,\n }\n } else if (mutablePolicies[operation]?.permission !== false) {\n mutablePolicies[operation] = {\n permission: !!accessResult,\n }\n }\n }\n\n const executeFieldPolicies = async ({\n entityPermission,\n fields,\n operation,\n policiesObj,\n }: {\n entityPermission\n fields: Field[]\n operation: AllOperations\n policiesObj\n }) => {\n const mutablePolicies = policiesObj.fields\n\n await Promise.all(\n fields.map(async (field) => {\n if ('name' in field && field.name) {\n if (!mutablePolicies[field.name]) {\n mutablePolicies[field.name] = {}\n }\n\n if ('access' in field && field.access && typeof field.access[operation] === 'function') {\n await createAccessPromise({\n access: field.access[operation],\n accessLevel: 'field',\n disableWhere: true,\n operation,\n policiesObj: mutablePolicies[field.name],\n })\n } else {\n mutablePolicies[field.name][operation] = {\n permission: policiesObj[operation]?.permission,\n }\n }\n\n if ('fields' in field && field.fields) {\n if (!mutablePolicies[field.name].fields) {\n mutablePolicies[field.name].fields = {}\n }\n\n await executeFieldPolicies({\n entityPermission,\n fields: field.fields,\n operation,\n policiesObj: mutablePolicies[field.name],\n })\n }\n\n if ('blocks' in field && field?.blocks) {\n if (!mutablePolicies[field.name]?.blocks) {\n mutablePolicies[field.name].blocks = {}\n }\n\n await Promise.all(\n field.blocks.map(async (block) => {\n if (!mutablePolicies[field.name].blocks?.[block.slug]) {\n mutablePolicies[field.name].blocks[block.slug] = {\n fields: {},\n [operation]: { permission: entityPermission },\n }\n } else if (!mutablePolicies[field.name].blocks[block.slug][operation]) {\n mutablePolicies[field.name].blocks[block.slug][operation] = {\n permission: entityPermission,\n }\n }\n\n await executeFieldPolicies({\n entityPermission,\n fields: block.fields,\n operation,\n policiesObj: mutablePolicies[field.name].blocks[block.slug],\n })\n }),\n )\n }\n } else if ('fields' in field && field.fields) {\n await executeFieldPolicies({\n entityPermission,\n fields: field.fields,\n operation,\n policiesObj,\n })\n } else if (field.type === 'tabs') {\n await Promise.all(\n field.tabs.map(async (tab) => {\n if (tabHasName(tab)) {\n if (!mutablePolicies[tab.name]) {\n mutablePolicies[tab.name] = {\n fields: {},\n [operation]: { permission: entityPermission },\n }\n } else if (!mutablePolicies[tab.name][operation]) {\n mutablePolicies[tab.name][operation] = { permission: entityPermission }\n }\n await executeFieldPolicies({\n entityPermission,\n fields: tab.fields,\n operation,\n policiesObj: mutablePolicies[tab.name],\n })\n } else {\n await executeFieldPolicies({\n entityPermission,\n fields: tab.fields,\n operation,\n policiesObj,\n })\n }\n }),\n )\n }\n }),\n )\n }\n\n await operations.reduce(async (priorOperation, operation) => {\n await priorOperation\n\n let entityAccessPromise: Promise<void>\n\n if (typeof entity.access[operation] === 'function') {\n entityAccessPromise = createAccessPromise({\n access: entity.access[operation],\n accessLevel: 'entity',\n operation,\n policiesObj: policies,\n })\n } else {\n policies[operation] = {\n permission: isLoggedIn,\n }\n }\n\n await entityAccessPromise\n\n await executeFieldPolicies({\n entityPermission: policies[operation].permission,\n fields: entity.fields,\n operation,\n policiesObj: policies,\n })\n }, Promise.resolve())\n\n return policies\n}\n"],"names":["combineQueries","tabHasName","getEntityPolicies","args","id","type","entity","operations","req","data","locale","payload","user","isLoggedIn","policies","fields","docBeingAccessed","getEntityDoc","where","slug","findGlobal","fallbackLocale","overrideAccess","paginatedRes","find","collection","depth","limit","pagination","equals","docs","undefined","findByID","createAccessPromise","access","accessLevel","disableWhere","operation","policiesObj","mutablePolicies","then","doc","accessResult","permission","executeFieldPolicies","entityPermission","Promise","all","map","field","name","blocks","block","tabs","tab","reduce","priorOperation","entityAccessPromise","resolve"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/utilities/getEntityPolicies.ts"],"sourcesContent":["import type { CollectionPermission, GlobalPermission } from '../auth/types.js'\nimport type { SanitizedCollectionConfig, TypeWithID } from '../collections/config/types.js'\nimport type { Access } from '../config/types.js'\nimport type { Field, FieldAccess } from '../fields/config/types.js'\nimport type { SanitizedGlobalConfig } from '../globals/config/types.js'\nimport type { AllOperations, Document, PayloadRequest, Where } from '../types/index.js'\n\nimport { combineQueries } from '../database/combineQueries.js'\nimport { fieldAffectsData, tabHasName } from '../fields/config/types.js'\n\ntype Args = {\n entity: SanitizedCollectionConfig | SanitizedGlobalConfig\n id?: number | string\n operations: AllOperations[]\n req: PayloadRequest\n type: 'collection' | 'global'\n}\n\ntype ReturnType<T extends Args> = T['type'] extends 'global'\n ? GlobalPermission\n : CollectionPermission\n\ntype CreateAccessPromise = (args: {\n access: Access | FieldAccess\n accessLevel: 'entity' | 'field'\n disableWhere?: boolean\n operation: AllOperations\n policiesObj: {\n [key: string]: any\n }\n}) => Promise<void>\n\nexport async function getEntityPolicies<T extends Args>(args: T): Promise<ReturnType<T>> {\n const { id, type, entity, operations, req } = args\n const { data, locale, payload, user } = req\n const isLoggedIn = !!user\n\n const policies = {\n fields: {},\n } as ReturnType<T>\n\n let docBeingAccessed\n\n async function getEntityDoc({ where }: { where?: Where } = {}): Promise<Document & TypeWithID> {\n if (entity.slug) {\n if (type === 'global') {\n return payload.findGlobal({\n slug: entity.slug,\n fallbackLocale: null,\n locale,\n overrideAccess: true,\n req,\n })\n }\n\n if (type === 'collection' && id) {\n if (typeof where === 'object') {\n const paginatedRes = await payload.find({\n collection: entity.slug,\n depth: 0,\n fallbackLocale: null,\n limit: 1,\n locale,\n overrideAccess: true,\n pagination: false,\n req,\n where: combineQueries(where, { id: { equals: id } }),\n })\n\n return paginatedRes?.docs?.[0] || undefined\n }\n\n return payload.findByID({\n id,\n collection: entity.slug,\n depth: 0,\n fallbackLocale: null,\n locale,\n overrideAccess: true,\n req,\n })\n }\n }\n\n return undefined\n }\n\n const createAccessPromise: CreateAccessPromise = async ({\n access,\n accessLevel,\n disableWhere = false,\n operation,\n policiesObj,\n }) => {\n const mutablePolicies = policiesObj\n\n if (accessLevel === 'field' && docBeingAccessed === undefined) {\n // assign docBeingAccessed first as the promise to avoid multiple calls to getEntityDoc\n docBeingAccessed = getEntityDoc().then((doc) => {\n docBeingAccessed = doc\n })\n }\n // awaiting the promise to ensure docBeingAccessed is assigned before it is used\n await docBeingAccessed\n\n // https://payloadcms.slack.com/archives/C048Z9C2BEX/p1702054928343769\n const accessResult = await access({ id, data, doc: docBeingAccessed, req })\n\n if (typeof accessResult === 'object' && !disableWhere) {\n mutablePolicies[operation] = {\n permission:\n id || type === 'global' ? !!(await getEntityDoc({ where: accessResult })) : true,\n where: accessResult,\n }\n } else if (mutablePolicies[operation]?.permission !== false) {\n mutablePolicies[operation] = {\n permission: !!accessResult,\n }\n }\n }\n\n const executeFieldPolicies = async ({\n entityPermission,\n fields,\n operation,\n policiesObj,\n }: {\n entityPermission\n fields: Field[]\n operation: AllOperations\n policiesObj\n }) => {\n const mutablePolicies = policiesObj.fields\n\n // Fields don't have all operations of a collection\n if (operation === 'delete' || operation === 'readVersions' || operation === 'unlock') {\n return\n }\n\n await Promise.all(\n fields.map(async (field) => {\n if ('name' in field && field.name) {\n if (!mutablePolicies[field.name]) {\n mutablePolicies[field.name] = {}\n }\n\n if ('access' in field && field.access && typeof field.access[operation] === 'function') {\n await createAccessPromise({\n access: field.access[operation],\n accessLevel: 'field',\n disableWhere: true,\n operation,\n policiesObj: mutablePolicies[field.name],\n })\n } else {\n mutablePolicies[field.name][operation] = {\n permission: policiesObj[operation]?.permission,\n }\n }\n\n if ('fields' in field && field.fields) {\n if (!mutablePolicies[field.name].fields) {\n mutablePolicies[field.name].fields = {}\n }\n\n await executeFieldPolicies({\n entityPermission,\n fields: field.fields,\n operation,\n policiesObj: mutablePolicies[field.name],\n })\n }\n\n if ('blocks' in field && field.blocks) {\n if (!mutablePolicies[field.name]?.blocks) {\n mutablePolicies[field.name].blocks = {}\n }\n\n await Promise.all(\n field.blocks.map(async (block) => {\n if (!mutablePolicies[field.name].blocks?.[block.slug]) {\n mutablePolicies[field.name].blocks[block.slug] = {\n fields: {},\n [operation]: { permission: entityPermission },\n }\n } else if (!mutablePolicies[field.name].blocks[block.slug][operation]) {\n mutablePolicies[field.name].blocks[block.slug][operation] = {\n permission: entityPermission,\n }\n }\n\n await executeFieldPolicies({\n entityPermission,\n fields: block.fields,\n operation,\n policiesObj: mutablePolicies[field.name].blocks[block.slug],\n })\n }),\n )\n }\n } else if ('fields' in field && field.fields) {\n await executeFieldPolicies({\n entityPermission,\n fields: field.fields,\n operation,\n policiesObj,\n })\n } else if (field.type === 'tabs') {\n await Promise.all(\n field.tabs.map(async (tab) => {\n if (tabHasName(tab)) {\n if (!mutablePolicies[tab.name]) {\n mutablePolicies[tab.name] = {\n fields: {},\n [operation]: { permission: entityPermission },\n }\n } else if (!mutablePolicies[tab.name][operation]) {\n mutablePolicies[tab.name][operation] = { permission: entityPermission }\n }\n await executeFieldPolicies({\n entityPermission,\n fields: tab.fields,\n operation,\n policiesObj: mutablePolicies[tab.name],\n })\n } else {\n await executeFieldPolicies({\n entityPermission,\n fields: tab.fields,\n operation,\n policiesObj,\n })\n }\n }),\n )\n }\n }),\n )\n }\n\n await operations.reduce(async (priorOperation, operation) => {\n await priorOperation\n\n let entityAccessPromise: Promise<void>\n\n if (typeof entity.access[operation] === 'function') {\n entityAccessPromise = createAccessPromise({\n access: entity.access[operation],\n accessLevel: 'entity',\n operation,\n policiesObj: policies,\n })\n } else {\n policies[operation] = {\n permission: isLoggedIn,\n }\n }\n\n await entityAccessPromise\n\n await executeFieldPolicies({\n entityPermission: policies[operation].permission,\n fields: entity.fields,\n operation,\n policiesObj: policies,\n })\n }, Promise.resolve())\n\n return policies\n}\n"],"names":["combineQueries","tabHasName","getEntityPolicies","args","id","type","entity","operations","req","data","locale","payload","user","isLoggedIn","policies","fields","docBeingAccessed","getEntityDoc","where","slug","findGlobal","fallbackLocale","overrideAccess","paginatedRes","find","collection","depth","limit","pagination","equals","docs","undefined","findByID","createAccessPromise","access","accessLevel","disableWhere","operation","policiesObj","mutablePolicies","then","doc","accessResult","permission","executeFieldPolicies","entityPermission","Promise","all","map","field","name","blocks","block","tabs","tab","reduce","priorOperation","entityAccessPromise","resolve"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function removeUndefined<T extends object>(obj: T): T;
2
+ //# sourceMappingURL=removeUndefined.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"removeUndefined.d.ts","sourceRoot":"","sources":["../../src/utilities/removeUndefined.ts"],"names":[],"mappings":"AAAA,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAE3D"}
@@ -0,0 +1,5 @@
1
+ export function removeUndefined(obj) {
2
+ return Object.fromEntries(Object.entries(obj).filter(([, value])=>value !== undefined));
3
+ }
4
+
5
+ //# sourceMappingURL=removeUndefined.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utilities/removeUndefined.ts"],"sourcesContent":["export function removeUndefined<T extends object>(obj: T): T {\n return Object.fromEntries(Object.entries(obj).filter(([, value]) => value !== undefined)) as T\n}\n"],"names":["removeUndefined","obj","Object","fromEntries","entries","filter","value","undefined"],"mappings":"AAAA,OAAO,SAASA,gBAAkCC,GAAM;IACtD,OAAOC,OAAOC,WAAW,CAACD,OAAOE,OAAO,CAACH,KAAKI,MAAM,CAAC,CAAC,GAAGC,MAAM,GAAKA,UAAUC;AAChF"}
@@ -0,0 +1,14 @@
1
+ import type { Permissions, SanitizedPermissions } from '../auth/types.js';
2
+ type PermissionObject = {
3
+ [key: string]: any;
4
+ };
5
+ /**
6
+ * Recursively resolve permissions in an object.
7
+ */
8
+ export declare function recursivelySanitizePermissions(obj: PermissionObject): void;
9
+ /**
10
+ * Recursively remove empty objects and false values from an object.
11
+ */
12
+ export declare function sanitizePermissions(data: Permissions): SanitizedPermissions;
13
+ export {};
14
+ //# sourceMappingURL=sanitizePermissions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizePermissions.d.ts","sourceRoot":"","sources":["../../src/utilities/sanitizePermissions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAEzE,KAAK,gBAAgB,GAAG;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CACnB,CAAA;AAiFD;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,CA4E1E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,WAAW,GAAG,oBAAoB,CAiB3E"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Check if all permissions in a FieldPermissions object are true on the condition that no nested blocks or fields are present.
3
+ */ function areAllPermissionsTrue(data) {
4
+ if (data.blocks) {
5
+ for(const key in data.blocks){
6
+ if (typeof data.blocks[key] === 'object') {
7
+ // If any recursive call returns false, the whole function returns false
8
+ if (key === 'fields' && !areAllPermissionsTrue(data.blocks[key].fields)) {
9
+ return false;
10
+ }
11
+ if (data.blocks[key].fields && !areAllPermissionsTrue(data.blocks[key].fields)) {
12
+ return false;
13
+ }
14
+ } else if (data.blocks[key] !== true) {
15
+ // If any value is not true, return false
16
+ return false;
17
+ }
18
+ }
19
+ // If all values are true or it's an empty object, return true
20
+ return true;
21
+ }
22
+ if (data.fields) {
23
+ for(const key in data.fields){
24
+ if (typeof data.fields[key] === 'object') {
25
+ // If any recursive call returns false, the whole function returns false
26
+ if (!areAllPermissionsTrue(data.fields[key])) {
27
+ return false;
28
+ }
29
+ } else if (data.fields[key] !== true) {
30
+ // If any value is not true, return false
31
+ return false;
32
+ }
33
+ }
34
+ // If all values are true or it's an empty object, return true
35
+ return true;
36
+ }
37
+ for(const key in data){
38
+ if (typeof data[key] === 'object') {
39
+ // If any recursive call returns false, the whole function returns false
40
+ if (!areAllPermissionsTrue(data[key])) {
41
+ return false;
42
+ }
43
+ } else if (data[key] !== true) {
44
+ // If any value is not true, return false
45
+ return false;
46
+ }
47
+ }
48
+ // If all values are true or it's an empty object, return true
49
+ return true;
50
+ }
51
+ /**
52
+ * Check if an object is a permission object.
53
+ */ function isPermissionObject(data) {
54
+ return typeof data === 'object' && 'permission' in data && typeof data['permission'] === 'boolean';
55
+ }
56
+ /**
57
+ * Recursively remove empty objects from an object.
58
+ */ function cleanEmptyObjects(obj) {
59
+ Object.keys(obj).forEach((key)=>{
60
+ if (typeof obj[key] === 'object' && obj[key] !== null) {
61
+ // Recursive call
62
+ cleanEmptyObjects(obj[key]);
63
+ if (Object.keys(obj[key]).length === 0) {
64
+ // Delete the key if the object is empty
65
+ delete obj[key];
66
+ }
67
+ } else if (obj[key] === null || obj[key] === undefined) {
68
+ delete obj[key];
69
+ }
70
+ });
71
+ }
72
+ /**
73
+ * Recursively resolve permissions in an object.
74
+ */ export function recursivelySanitizePermissions(obj) {
75
+ if (typeof obj !== 'object') {
76
+ return;
77
+ }
78
+ const entries = Object.entries(obj);
79
+ for(let i = 0; i < entries.length; i++){
80
+ const [key, value] = entries[i];
81
+ // Check if it's a 'fields' key
82
+ if (key === 'fields') {
83
+ // Check if fields is empty
84
+ if (Object.keys(obj[key]).length === 0) {
85
+ delete obj[key];
86
+ continue;
87
+ } else if (areAllPermissionsTrue(value)) {
88
+ obj[key] = true;
89
+ continue;
90
+ }
91
+ } else if (key === 'blocks') {
92
+ // Check if fields is empty
93
+ if (Object.keys(obj[key]).length === 0) {
94
+ delete obj[key];
95
+ continue;
96
+ } else if (areAllPermissionsTrue(value)) {
97
+ obj[key] = true;
98
+ continue;
99
+ }
100
+ }
101
+ // Check if the whole object is a permission object
102
+ const isFullPermissionObject = Object.keys(value).every((subKey)=>subKey !== 'blocks' && typeof value?.[subKey] === 'object' && 'permission' in value[subKey] && !('where' in value[subKey]) && typeof value[subKey]['permission'] === 'boolean');
103
+ if (isFullPermissionObject) {
104
+ if (areAllPermissionsTrue(value)) {
105
+ obj[key] = true;
106
+ continue;
107
+ } else {
108
+ for(const subKey in value){
109
+ if (value[subKey]['permission'] === true && !('where' in value[subKey])) {
110
+ value[subKey] = true;
111
+ continue;
112
+ } else if (value[subKey]['permission'] === true && 'where' in value[subKey]) {
113
+ // do nothing
114
+ } else {
115
+ delete value[subKey];
116
+ continue;
117
+ }
118
+ }
119
+ }
120
+ } else if (isPermissionObject(value)) {
121
+ if (value['permission'] === true && !('where' in value)) {
122
+ // If the permission is true and there is no where clause, set the key to true
123
+ obj[key] = true;
124
+ continue;
125
+ } else if (value['permission'] === true && 'where' in value) {
126
+ // otherwise do nothing so we can keep the where clause
127
+ } else {
128
+ delete obj[key];
129
+ continue;
130
+ }
131
+ } else {
132
+ recursivelySanitizePermissions(value);
133
+ }
134
+ }
135
+ }
136
+ /**
137
+ * Recursively remove empty objects and false values from an object.
138
+ */ export function sanitizePermissions(data) {
139
+ if (data.canAccessAdmin === false) {
140
+ delete data.canAccessAdmin;
141
+ }
142
+ if (data.collections) {
143
+ recursivelySanitizePermissions(data.collections);
144
+ }
145
+ if (data.globals) {
146
+ recursivelySanitizePermissions(data.globals);
147
+ }
148
+ // Run clean up of empty objects at the end
149
+ cleanEmptyObjects(data);
150
+ return data;
151
+ }
152
+
153
+ //# sourceMappingURL=sanitizePermissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utilities/sanitizePermissions.ts"],"sourcesContent":["import type { Permissions, SanitizedPermissions } from '../auth/types.js'\n\ntype PermissionObject = {\n [key: string]: any\n}\n\n/**\n * Check if all permissions in a FieldPermissions object are true on the condition that no nested blocks or fields are present.\n */\nfunction areAllPermissionsTrue(data: PermissionObject): boolean {\n if (data.blocks) {\n for (const key in data.blocks) {\n if (typeof data.blocks[key] === 'object') {\n // If any recursive call returns false, the whole function returns false\n if (key === 'fields' && !areAllPermissionsTrue(data.blocks[key].fields)) {\n return false\n }\n if (data.blocks[key].fields && !areAllPermissionsTrue(data.blocks[key].fields)) {\n return false\n }\n } else if (data.blocks[key] !== true) {\n // If any value is not true, return false\n return false\n }\n }\n // If all values are true or it's an empty object, return true\n return true\n }\n\n if (data.fields) {\n for (const key in data.fields) {\n if (typeof data.fields[key] === 'object') {\n // If any recursive call returns false, the whole function returns false\n if (!areAllPermissionsTrue(data.fields[key])) {\n return false\n }\n } else if (data.fields[key] !== true) {\n // If any value is not true, return false\n return false\n }\n }\n // If all values are true or it's an empty object, return true\n return true\n }\n\n for (const key in data) {\n if (typeof data[key] === 'object') {\n // If any recursive call returns false, the whole function returns false\n if (!areAllPermissionsTrue(data[key])) {\n return false\n }\n } else if (data[key] !== true) {\n // If any value is not true, return false\n return false\n }\n }\n // If all values are true or it's an empty object, return true\n return true\n}\n\n/**\n * Check if an object is a permission object.\n */\nfunction isPermissionObject(data: unknown): boolean {\n return typeof data === 'object' && 'permission' in data && typeof data['permission'] === 'boolean'\n}\n\n/**\n * Recursively remove empty objects from an object.\n */\nfunction cleanEmptyObjects(obj: any): void {\n Object.keys(obj).forEach((key) => {\n if (typeof obj[key] === 'object' && obj[key] !== null) {\n // Recursive call\n cleanEmptyObjects(obj[key])\n if (Object.keys(obj[key]).length === 0) {\n // Delete the key if the object is empty\n delete obj[key]\n }\n } else if (obj[key] === null || obj[key] === undefined) {\n delete obj[key]\n }\n })\n}\n\n/**\n * Recursively resolve permissions in an object.\n */\nexport function recursivelySanitizePermissions(obj: PermissionObject): void {\n if (typeof obj !== 'object') {\n return\n }\n\n const entries = Object.entries(obj)\n\n for (let i = 0; i < entries.length; i++) {\n const [key, value] = entries[i]\n // Check if it's a 'fields' key\n if (key === 'fields') {\n // Check if fields is empty\n if (Object.keys(obj[key]).length === 0) {\n delete obj[key]\n continue\n }\n // Otherwise set fields to true if all permissions are true\n else if (areAllPermissionsTrue(value)) {\n obj[key] = true\n continue\n }\n } else if (key === 'blocks') {\n // Check if fields is empty\n if (Object.keys(obj[key]).length === 0) {\n delete obj[key]\n continue\n }\n // Otherwise set fields to true if all permissions are true\n else if (areAllPermissionsTrue(value)) {\n obj[key] = true\n continue\n }\n }\n\n // Check if the whole object is a permission object\n const isFullPermissionObject = Object.keys(value).every(\n (subKey) =>\n subKey !== 'blocks' &&\n typeof value?.[subKey] === 'object' &&\n 'permission' in value[subKey] &&\n !('where' in value[subKey]) &&\n typeof value[subKey]['permission'] === 'boolean',\n )\n\n if (isFullPermissionObject) {\n if (areAllPermissionsTrue(value)) {\n obj[key] = true\n continue\n } else {\n for (const subKey in value) {\n if (value[subKey]['permission'] === true && !('where' in value[subKey])) {\n value[subKey] = true\n continue\n } else if (value[subKey]['permission'] === true && 'where' in value[subKey]) {\n // do nothing\n } else {\n delete value[subKey]\n continue\n }\n }\n }\n } else if (isPermissionObject(value)) {\n if (value['permission'] === true && !('where' in value)) {\n // If the permission is true and there is no where clause, set the key to true\n obj[key] = true\n continue\n } else if (value['permission'] === true && 'where' in value) {\n // otherwise do nothing so we can keep the where clause\n } else {\n delete obj[key]\n continue\n }\n } else {\n recursivelySanitizePermissions(value)\n }\n }\n}\n\n/**\n * Recursively remove empty objects and false values from an object.\n */\nexport function sanitizePermissions(data: Permissions): SanitizedPermissions {\n if (data.canAccessAdmin === false) {\n delete data.canAccessAdmin\n }\n\n if (data.collections) {\n recursivelySanitizePermissions(data.collections)\n }\n\n if (data.globals) {\n recursivelySanitizePermissions(data.globals)\n }\n\n // Run clean up of empty objects at the end\n cleanEmptyObjects(data)\n\n return data as unknown as SanitizedPermissions\n}\n"],"names":["areAllPermissionsTrue","data","blocks","key","fields","isPermissionObject","cleanEmptyObjects","obj","Object","keys","forEach","length","undefined","recursivelySanitizePermissions","entries","i","value","isFullPermissionObject","every","subKey","sanitizePermissions","canAccessAdmin","collections","globals"],"mappings":"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"}