@payloadcms/plugin-multi-tenant 4.0.0-internal.c2b57ce → 4.0.0-internal.c6494b5

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 (101) hide show
  1. package/LICENSE.md +1 -1
  2. package/dist/components/AssignTenantFieldModal/index.client.d.ts +2 -3
  3. package/dist/components/AssignTenantFieldModal/index.client.d.ts.map +1 -1
  4. package/dist/components/AssignTenantFieldModal/index.client.js +26 -81
  5. package/dist/components/AssignTenantFieldModal/index.client.js.map +1 -1
  6. package/dist/components/GlobalViewRedirect/index.d.ts +1 -1
  7. package/dist/components/GlobalViewRedirect/index.d.ts.map +1 -1
  8. package/dist/components/GlobalViewRedirect/index.js.map +1 -1
  9. package/dist/components/TenantField/index.client.d.ts +1 -1
  10. package/dist/components/TenantField/index.client.d.ts.map +1 -1
  11. package/dist/components/TenantField/index.client.js +85 -75
  12. package/dist/components/TenantField/index.client.js.map +1 -1
  13. package/dist/components/TenantField/index.css +44 -0
  14. package/dist/components/TenantSelector/index.client.d.ts +2 -2
  15. package/dist/components/TenantSelector/index.client.d.ts.map +1 -1
  16. package/dist/components/TenantSelector/index.client.js +4 -2
  17. package/dist/components/TenantSelector/index.client.js.map +1 -1
  18. package/dist/components/TenantSelector/index.css +13 -0
  19. package/dist/components/TenantSelector/index.d.ts.map +1 -1
  20. package/dist/defaults.d.ts.map +1 -1
  21. package/dist/endpoints/getTenantOptionsEndpoint.d.ts +2 -2
  22. package/dist/endpoints/getTenantOptionsEndpoint.d.ts.map +1 -1
  23. package/dist/endpoints/getTenantOptionsEndpoint.js.map +1 -1
  24. package/dist/fields/tenantField/index.d.ts +4 -2
  25. package/dist/fields/tenantField/index.d.ts.map +1 -1
  26. package/dist/fields/tenantField/index.js +36 -9
  27. package/dist/fields/tenantField/index.js.map +1 -1
  28. package/dist/fields/tenantsArrayField/index.d.ts.map +1 -1
  29. package/dist/filters/filterDocumentsByTenants.d.ts +3 -3
  30. package/dist/filters/filterDocumentsByTenants.d.ts.map +1 -1
  31. package/dist/filters/filterDocumentsByTenants.js.map +1 -1
  32. package/dist/hooks/afterTenantDelete.d.ts +1 -1
  33. package/dist/hooks/afterTenantDelete.d.ts.map +1 -1
  34. package/dist/hooks/afterTenantDelete.js +7 -1
  35. package/dist/hooks/afterTenantDelete.js.map +1 -1
  36. package/dist/hooks/enforceTenantMembership.d.ts +15 -0
  37. package/dist/hooks/enforceTenantMembership.d.ts.map +1 -0
  38. package/dist/hooks/enforceTenantMembership.js +39 -0
  39. package/dist/hooks/enforceTenantMembership.js.map +1 -0
  40. package/dist/index.d.ts +1 -2
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +32 -6
  43. package/dist/index.js.map +1 -1
  44. package/dist/providers/TenantSelectionProvider/index.client.d.ts.map +1 -1
  45. package/dist/providers/TenantSelectionProvider/index.client.js +43 -15
  46. package/dist/providers/TenantSelectionProvider/index.client.js.map +1 -1
  47. package/dist/providers/TenantSelectionProvider/index.d.ts +5 -5
  48. package/dist/providers/TenantSelectionProvider/index.d.ts.map +1 -1
  49. package/dist/providers/TenantSelectionProvider/index.js.map +1 -1
  50. package/dist/translations/languages/en.d.ts.map +1 -1
  51. package/dist/types.d.ts +9 -9
  52. package/dist/types.d.ts.map +1 -1
  53. package/dist/types.js.map +1 -1
  54. package/dist/utilities/addCollectionAccess.d.ts +8 -10
  55. package/dist/utilities/addCollectionAccess.d.ts.map +1 -1
  56. package/dist/utilities/addCollectionAccess.js +99 -21
  57. package/dist/utilities/addCollectionAccess.js.map +1 -1
  58. package/dist/utilities/addFilterOptionsToFields.d.ts +3 -3
  59. package/dist/utilities/addFilterOptionsToFields.d.ts.map +1 -1
  60. package/dist/utilities/addFilterOptionsToFields.js +6 -9
  61. package/dist/utilities/addFilterOptionsToFields.js.map +1 -1
  62. package/dist/utilities/combineFilters.d.ts.map +1 -1
  63. package/dist/utilities/extractID.d.ts.map +1 -1
  64. package/dist/utilities/generateCookie.d.ts.map +1 -1
  65. package/dist/utilities/getCollectionIDType.d.ts +1 -1
  66. package/dist/utilities/getCollectionIDType.d.ts.map +1 -1
  67. package/dist/utilities/getGlobalViewRedirect.d.ts +3 -3
  68. package/dist/utilities/getGlobalViewRedirect.d.ts.map +1 -1
  69. package/dist/utilities/getGlobalViewRedirect.js +2 -0
  70. package/dist/utilities/getGlobalViewRedirect.js.map +1 -1
  71. package/dist/utilities/getTenantIDsFromValue.d.ts +2 -0
  72. package/dist/utilities/getTenantIDsFromValue.d.ts.map +1 -0
  73. package/dist/utilities/getTenantIDsFromValue.js +14 -0
  74. package/dist/utilities/getTenantIDsFromValue.js.map +1 -0
  75. package/dist/utilities/getTenantOptions.d.ts +3 -3
  76. package/dist/utilities/getTenantOptions.d.ts.map +1 -1
  77. package/dist/utilities/getTenantOptions.js.map +1 -1
  78. package/dist/utilities/getUserTenantIDs.d.ts.map +1 -1
  79. package/dist/utilities/getUserTenantIDs.js +5 -3
  80. package/dist/utilities/getUserTenantIDs.js.map +1 -1
  81. package/dist/utilities/isValidTenantAssignment.d.ts +13 -0
  82. package/dist/utilities/isValidTenantAssignment.d.ts.map +1 -0
  83. package/dist/utilities/isValidTenantAssignment.js +28 -0
  84. package/dist/utilities/isValidTenantAssignment.js.map +1 -0
  85. package/dist/utilities/miniChalk.d.ts.map +1 -1
  86. package/dist/utilities/shouldRefreshTenantSelection.d.ts +5 -0
  87. package/dist/utilities/shouldRefreshTenantSelection.d.ts.map +1 -0
  88. package/dist/utilities/shouldRefreshTenantSelection.js +3 -0
  89. package/dist/utilities/shouldRefreshTenantSelection.js.map +1 -0
  90. package/package.json +7 -8
  91. package/dist/components/AssignTenantFieldModal/index.scss +0 -78
  92. package/dist/components/TenantField/index.scss +0 -52
  93. package/dist/components/TenantSelector/index.scss +0 -4
  94. package/dist/utilities/combineWhereConstraints.d.ts +0 -3
  95. package/dist/utilities/combineWhereConstraints.d.ts.map +0 -1
  96. package/dist/utilities/combineWhereConstraints.js +0 -19
  97. package/dist/utilities/combineWhereConstraints.js.map +0 -1
  98. package/dist/utilities/withTenantAccess.d.ts +0 -16
  99. package/dist/utilities/withTenantAccess.d.ts.map +0 -1
  100. package/dist/utilities/withTenantAccess.js +0 -76
  101. package/dist/utilities/withTenantAccess.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/TenantSelector/index.client.tsx"],"sourcesContent":["'use client'\nimport type { ReactSelectOption } from '@payloadcms/ui'\nimport type { ViewTypes } from 'payload'\n\nimport { getTranslation } from '@payloadcms/translations'\nimport { ConfirmationModal, SelectInput, useModal, useTranslation } from '@payloadcms/ui'\nimport React from 'react'\n\nimport type {\n PluginMultiTenantTranslationKeys,\n PluginMultiTenantTranslations,\n} from '../../translations/index.js'\nimport type { MultiTenantPluginConfig } from '../../types.js'\n\nimport { useTenantSelection } from '../../providers/TenantSelectionProvider/index.client.js'\nimport './index.scss'\n\nconst confirmLeaveWithoutSavingSlug = 'confirm-leave-without-saving'\n\nexport const TenantSelectorClient = ({\n disabled: disabledFromProps,\n label,\n viewType,\n}: {\n disabled?: boolean\n label?: MultiTenantPluginConfig['tenantSelectorLabel']\n viewType?: ViewTypes\n}) => {\n const { entityType, modified, options, selectedTenantID, setTenant } = useTenantSelection()\n const { closeModal, openModal } = useModal()\n const { i18n, t } = useTranslation<\n PluginMultiTenantTranslations,\n PluginMultiTenantTranslationKeys\n >()\n const [tenantSelection, setTenantSelection] = React.useState<\n ReactSelectOption | ReactSelectOption[]\n >()\n\n const switchTenant = React.useCallback(\n (option: ReactSelectOption | ReactSelectOption[] | undefined) => {\n if (option && 'value' in option) {\n setTenant({ id: option.value as string, refresh: true })\n } else {\n setTenant({ id: undefined, refresh: true })\n }\n },\n [setTenant],\n )\n\n const onChange = React.useCallback(\n (option: ReactSelectOption | ReactSelectOption[]) => {\n if (option && 'value' in option && option.value === selectedTenantID) {\n // If the selected option is the same as the current tenant, do nothing\n return\n }\n\n if (entityType === 'global' && modified) {\n // If the entityType is 'global' and there are unsaved changes, prompt for confirmation\n setTenantSelection(option)\n openModal(confirmLeaveWithoutSavingSlug)\n } else {\n // If the entityType is not 'document', switch tenant without confirmation\n switchTenant(option)\n }\n },\n [selectedTenantID, entityType, modified, switchTenant, openModal],\n )\n\n if (options.length <= 1) {\n return null\n }\n\n return (\n <div className=\"tenant-selector\">\n <SelectInput\n isClearable={['dashboard', 'list'].includes(viewType ?? '')}\n label={\n label ? getTranslation(label, i18n) : t('plugin-multi-tenant:nav-tenantSelector-label')\n }\n name=\"setTenant\"\n onChange={onChange}\n options={options}\n path=\"setTenant\"\n readOnly={\n disabledFromProps ||\n (entityType !== 'global' &&\n viewType &&\n (['document', 'version'] satisfies ViewTypes[] as ViewTypes[]).includes(viewType))\n }\n value={selectedTenantID as string | undefined}\n />\n\n <ConfirmationModal\n body={t('general:changesNotSaved')}\n cancelLabel={t('general:stayOnThisPage')}\n confirmLabel={t('general:leaveAnyway')}\n heading={t('general:leaveWithoutSaving')}\n modalSlug={confirmLeaveWithoutSavingSlug}\n onCancel={() => {\n closeModal(confirmLeaveWithoutSavingSlug)\n }}\n onConfirm={() => {\n switchTenant(tenantSelection)\n }}\n />\n </div>\n )\n}\n"],"names":["getTranslation","ConfirmationModal","SelectInput","useModal","useTranslation","React","useTenantSelection","confirmLeaveWithoutSavingSlug","TenantSelectorClient","disabled","disabledFromProps","label","viewType","entityType","modified","options","selectedTenantID","setTenant","closeModal","openModal","i18n","t","tenantSelection","setTenantSelection","useState","switchTenant","useCallback","option","id","value","refresh","undefined","onChange","length","div","className","isClearable","includes","name","path","readOnly","body","cancelLabel","confirmLabel","heading","modalSlug","onCancel","onConfirm"],"mappings":"AAAA;;AAIA,SAASA,cAAc,QAAQ,2BAA0B;AACzD,SAASC,iBAAiB,EAAEC,WAAW,EAAEC,QAAQ,EAAEC,cAAc,QAAQ,iBAAgB;AACzF,OAAOC,WAAW,QAAO;AAQzB,SAASC,kBAAkB,QAAQ,0DAAyD;AAC5F,OAAO,eAAc;AAErB,MAAMC,gCAAgC;AAEtC,OAAO,MAAMC,uBAAuB,CAAC,EACnCC,UAAUC,iBAAiB,EAC3BC,KAAK,EACLC,QAAQ,EAKT;IACC,MAAM,EAAEC,UAAU,EAAEC,QAAQ,EAAEC,OAAO,EAAEC,gBAAgB,EAAEC,SAAS,EAAE,GAAGX;IACvE,MAAM,EAAEY,UAAU,EAAEC,SAAS,EAAE,GAAGhB;IAClC,MAAM,EAAEiB,IAAI,EAAEC,CAAC,EAAE,GAAGjB;IAIpB,MAAM,CAACkB,iBAAiBC,mBAAmB,GAAGlB,MAAMmB,QAAQ;IAI5D,MAAMC,eAAepB,MAAMqB,WAAW,CACpC,CAACC;QACC,IAAIA,UAAU,WAAWA,QAAQ;YAC/BV,UAAU;gBAAEW,IAAID,OAAOE,KAAK;gBAAYC,SAAS;YAAK;QACxD,OAAO;YACLb,UAAU;gBAAEW,IAAIG;gBAAWD,SAAS;YAAK;QAC3C;IACF,GACA;QAACb;KAAU;IAGb,MAAMe,WAAW3B,MAAMqB,WAAW,CAChC,CAACC;QACC,IAAIA,UAAU,WAAWA,UAAUA,OAAOE,KAAK,KAAKb,kBAAkB;YACpE,uEAAuE;YACvE;QACF;QAEA,IAAIH,eAAe,YAAYC,UAAU;YACvC,uFAAuF;YACvFS,mBAAmBI;YACnBR,UAAUZ;QACZ,OAAO;YACL,0EAA0E;YAC1EkB,aAAaE;QACf;IACF,GACA;QAACX;QAAkBH;QAAYC;QAAUW;QAAcN;KAAU;IAGnE,IAAIJ,QAAQkB,MAAM,IAAI,GAAG;QACvB,OAAO;IACT;IAEA,qBACE,MAACC;QAAIC,WAAU;;0BACb,KAACjC;gBACCkC,aAAa;oBAAC;oBAAa;iBAAO,CAACC,QAAQ,CAACzB,YAAY;gBACxDD,OACEA,QAAQX,eAAeW,OAAOS,QAAQC,EAAE;gBAE1CiB,MAAK;gBACLN,UAAUA;gBACVjB,SAASA;gBACTwB,MAAK;gBACLC,UACE9B,qBACCG,eAAe,YACdD,YACA,AAAC;oBAAC;oBAAY;iBAAU,CAAuCyB,QAAQ,CAACzB;gBAE5EiB,OAAOb;;0BAGT,KAACf;gBACCwC,MAAMpB,EAAE;gBACRqB,aAAarB,EAAE;gBACfsB,cAActB,EAAE;gBAChBuB,SAASvB,EAAE;gBACXwB,WAAWtC;gBACXuC,UAAU;oBACR5B,WAAWX;gBACb;gBACAwC,WAAW;oBACTtB,aAAaH;gBACf;;;;AAIR,EAAC"}
1
+ {"version":3,"sources":["../../../src/components/TenantSelector/index.client.tsx"],"sourcesContent":["'use client'\nimport type { ReactSelectOption } from '@payloadcms/ui'\nimport type { ViewTypes } from 'payload'\n\nimport { getTranslation } from '@payloadcms/translations'\nimport { ConfirmationModal, SelectInput, useModal, useTranslation } from '@payloadcms/ui'\nimport React from 'react'\n\nimport type {\n PluginMultiTenantTranslationKeys,\n PluginMultiTenantTranslations,\n} from '../../translations/index.js'\nimport type { MultiTenantPluginConfig } from '../../types.js'\n\nimport { useTenantSelection } from '../../providers/TenantSelectionProvider/index.client.js'\nimport './index.css'\n\nconst confirmLeaveWithoutSavingSlug = 'confirm-leave-without-saving'\n\nconst baseClass = 'tenant-selector'\n\nexport const TenantSelectorClient = ({\n disabled: disabledFromProps,\n label,\n viewType,\n}: {\n disabled?: boolean\n label?: MultiTenantPluginConfig['tenantSelectorLabel']\n viewType?: ViewTypes\n}) => {\n const { entityType, modified, options, selectedTenantID, setTenant } = useTenantSelection()\n const { closeModal, openModal } = useModal()\n const { i18n, t } = useTranslation<\n PluginMultiTenantTranslations,\n PluginMultiTenantTranslationKeys\n >()\n const [tenantSelection, setTenantSelection] = React.useState<\n ReactSelectOption | ReactSelectOption[]\n >()\n\n const switchTenant = React.useCallback(\n (option: ReactSelectOption | ReactSelectOption[] | undefined) => {\n if (option && 'value' in option) {\n setTenant({ id: option.value as string, refresh: true })\n } else {\n setTenant({ id: undefined, refresh: true })\n }\n },\n [setTenant],\n )\n\n const onChange = React.useCallback(\n (option: ReactSelectOption | ReactSelectOption[]) => {\n if (option && 'value' in option && option.value === selectedTenantID) {\n // If the selected option is the same as the current tenant, do nothing\n return\n }\n\n if (entityType === 'global' && modified) {\n // If the entityType is 'global' and there are unsaved changes, prompt for confirmation\n setTenantSelection(option)\n openModal(confirmLeaveWithoutSavingSlug)\n } else {\n // If the entityType is not 'document', switch tenant without confirmation\n switchTenant(option)\n }\n },\n [selectedTenantID, entityType, modified, switchTenant, openModal],\n )\n\n if (options.length <= 1) {\n return null\n }\n\n return (\n <div className={baseClass}>\n <SelectInput\n className={`${baseClass}__select`}\n isClearable={['dashboard', 'list'].includes(viewType ?? '')}\n label={\n label ? getTranslation(label, i18n) : t('plugin-multi-tenant:nav-tenantSelector-label')\n }\n name=\"setTenant\"\n onChange={onChange}\n options={options}\n path=\"setTenant\"\n readOnly={\n disabledFromProps ||\n (entityType !== 'global' &&\n viewType &&\n (['document', 'version'] satisfies ViewTypes[] as ViewTypes[]).includes(viewType))\n }\n value={selectedTenantID as string | undefined}\n />\n\n <ConfirmationModal\n body={t('general:changesNotSaved')}\n cancelLabel={t('general:stayOnThisPage')}\n confirmLabel={t('general:leaveAnyway')}\n heading={t('general:leaveWithoutSaving')}\n modalSlug={confirmLeaveWithoutSavingSlug}\n onCancel={() => {\n closeModal(confirmLeaveWithoutSavingSlug)\n }}\n onConfirm={() => {\n switchTenant(tenantSelection)\n }}\n />\n </div>\n )\n}\n"],"names":["getTranslation","ConfirmationModal","SelectInput","useModal","useTranslation","React","useTenantSelection","confirmLeaveWithoutSavingSlug","baseClass","TenantSelectorClient","disabled","disabledFromProps","label","viewType","entityType","modified","options","selectedTenantID","setTenant","closeModal","openModal","i18n","t","tenantSelection","setTenantSelection","useState","switchTenant","useCallback","option","id","value","refresh","undefined","onChange","length","div","className","isClearable","includes","name","path","readOnly","body","cancelLabel","confirmLabel","heading","modalSlug","onCancel","onConfirm"],"mappings":"AAAA;;AAIA,SAASA,cAAc,QAAQ,2BAA0B;AACzD,SAASC,iBAAiB,EAAEC,WAAW,EAAEC,QAAQ,EAAEC,cAAc,QAAQ,iBAAgB;AACzF,OAAOC,WAAW,QAAO;AAQzB,SAASC,kBAAkB,QAAQ,0DAAyD;AAC5F,OAAO,cAAa;AAEpB,MAAMC,gCAAgC;AAEtC,MAAMC,YAAY;AAElB,OAAO,MAAMC,uBAAuB,CAAC,EACnCC,UAAUC,iBAAiB,EAC3BC,KAAK,EACLC,QAAQ,EAKT;IACC,MAAM,EAAEC,UAAU,EAAEC,QAAQ,EAAEC,OAAO,EAAEC,gBAAgB,EAAEC,SAAS,EAAE,GAAGZ;IACvE,MAAM,EAAEa,UAAU,EAAEC,SAAS,EAAE,GAAGjB;IAClC,MAAM,EAAEkB,IAAI,EAAEC,CAAC,EAAE,GAAGlB;IAIpB,MAAM,CAACmB,iBAAiBC,mBAAmB,GAAGnB,MAAMoB,QAAQ;IAI5D,MAAMC,eAAerB,MAAMsB,WAAW,CACpC,CAACC;QACC,IAAIA,UAAU,WAAWA,QAAQ;YAC/BV,UAAU;gBAAEW,IAAID,OAAOE,KAAK;gBAAYC,SAAS;YAAK;QACxD,OAAO;YACLb,UAAU;gBAAEW,IAAIG;gBAAWD,SAAS;YAAK;QAC3C;IACF,GACA;QAACb;KAAU;IAGb,MAAMe,WAAW5B,MAAMsB,WAAW,CAChC,CAACC;QACC,IAAIA,UAAU,WAAWA,UAAUA,OAAOE,KAAK,KAAKb,kBAAkB;YACpE,uEAAuE;YACvE;QACF;QAEA,IAAIH,eAAe,YAAYC,UAAU;YACvC,uFAAuF;YACvFS,mBAAmBI;YACnBR,UAAUb;QACZ,OAAO;YACL,0EAA0E;YAC1EmB,aAAaE;QACf;IACF,GACA;QAACX;QAAkBH;QAAYC;QAAUW;QAAcN;KAAU;IAGnE,IAAIJ,QAAQkB,MAAM,IAAI,GAAG;QACvB,OAAO;IACT;IAEA,qBACE,MAACC;QAAIC,WAAW5B;;0BACd,KAACN;gBACCkC,WAAW,GAAG5B,UAAU,QAAQ,CAAC;gBACjC6B,aAAa;oBAAC;oBAAa;iBAAO,CAACC,QAAQ,CAACzB,YAAY;gBACxDD,OACEA,QAAQZ,eAAeY,OAAOS,QAAQC,EAAE;gBAE1CiB,MAAK;gBACLN,UAAUA;gBACVjB,SAASA;gBACTwB,MAAK;gBACLC,UACE9B,qBACCG,eAAe,YACdD,YACA,AAAC;oBAAC;oBAAY;iBAAU,CAAuCyB,QAAQ,CAACzB;gBAE5EiB,OAAOb;;0BAGT,KAAChB;gBACCyC,MAAMpB,EAAE;gBACRqB,aAAarB,EAAE;gBACfsB,cAActB,EAAE;gBAChBuB,SAASvB,EAAE;gBACXwB,WAAWvC;gBACXwC,UAAU;oBACR5B,WAAWZ;gBACb;gBACAyC,WAAW;oBACTtB,aAAaH;gBACf;;;;AAIR,EAAC"}
@@ -0,0 +1,13 @@
1
+ @layer payload-default {
2
+ .tenant-selector {
3
+ border-bottom: var(--stroke-width-small) solid var(--color-border);
4
+ width: 100%;
5
+ margin-block-end: var(--spacer-2);
6
+ padding-block-start: var(--nav-padding-block-start);
7
+ padding-block-end: var(--spacer-3);
8
+
9
+ .tenant-selector__select {
10
+ margin-inline: var(--nav-padding-inline-start);
11
+ }
12
+ }
13
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/TenantSelector/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE1C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAI7D,KAAK,KAAK,GAAG;IACX,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,KAAK,EAAE,uBAAuB,CAAC,qBAAqB,CAAC,CAAA;CACtD,GAAG,WAAW,CAAA;AACf,eAAO,MAAM,cAAc,GAAI,OAAO,KAAK,gCAI1C,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/TenantSelector/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE1C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAI7D,KAAK,KAAK,GAAG;IACX,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,KAAK,EAAE,uBAAuB,CAAC,qBAAqB,CAAC,CAAA;CACtD,GAAG,WAAW,CAAA;AACf,eAAO,MAAM,cAAc,UAAW,KAAK,gCAI1C,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ;;;;;;CAMpB,CAAA"}
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ;IACnB,oBAAoB;IACpB,eAAe;IACf,qBAAqB;IACrB,2BAA2B;IAC3B,mBAAmB;CACpB,CAAA"}
@@ -1,10 +1,10 @@
1
1
  import type { Endpoint } from 'payload';
2
2
  import type { MultiTenantPluginConfig } from '../types.js';
3
- export declare const getTenantOptionsEndpoint: <ConfigType>({ tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, userHasAccessToAllTenants, }: {
3
+ export declare const getTenantOptionsEndpoint: ({ tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, userHasAccessToAllTenants, }: {
4
4
  tenantsArrayFieldName: string;
5
5
  tenantsArrayTenantFieldName: string;
6
6
  tenantsCollectionSlug: string;
7
7
  useAsTitle: string;
8
- userHasAccessToAllTenants: Required<MultiTenantPluginConfig<ConfigType>>["userHasAccessToAllTenants"];
8
+ userHasAccessToAllTenants: Required<MultiTenantPluginConfig>['userHasAccessToAllTenants'];
9
9
  }) => Endpoint;
10
10
  //# sourceMappingURL=getTenantOptionsEndpoint.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"getTenantOptionsEndpoint.d.ts","sourceRoot":"","sources":["../../src/endpoints/getTenantOptionsEndpoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAIvC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAI1D,eAAO,MAAM,wBAAwB,GAAI,UAAU,EAAE,uHAMlD;IACD,qBAAqB,EAAE,MAAM,CAAA;IAC7B,2BAA2B,EAAE,MAAM,CAAA;IACnC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,yBAAyB,EAAE,QAAQ,CACjC,uBAAuB,CAAC,UAAU,CAAC,CACpC,CAAC,2BAA2B,CAAC,CAAA;CAC/B,KAAG,QAsBF,CAAA"}
1
+ {"version":3,"file":"getTenantOptionsEndpoint.d.ts","sourceRoot":"","sources":["../../src/endpoints/getTenantOptionsEndpoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAIvC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAI1D,eAAO,MAAM,wBAAwB,0HAMlC;IACD,qBAAqB,EAAE,MAAM,CAAA;IAC7B,2BAA2B,EAAE,MAAM,CAAA;IACnC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,yBAAyB,EAAE,QAAQ,CAAC,uBAAuB,CAAC,CAAC,2BAA2B,CAAC,CAAA;CAC1F,KAAG,QAsBF,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/endpoints/getTenantOptionsEndpoint.ts"],"sourcesContent":["import type { Endpoint } from 'payload'\n\nimport { APIError } from 'payload'\n\nimport type { MultiTenantPluginConfig } from '../types.js'\n\nimport { getTenantOptions } from '../utilities/getTenantOptions.js'\n\nexport const getTenantOptionsEndpoint = <ConfigType>({\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n userHasAccessToAllTenants,\n}: {\n tenantsArrayFieldName: string\n tenantsArrayTenantFieldName: string\n tenantsCollectionSlug: string\n useAsTitle: string\n userHasAccessToAllTenants: Required<\n MultiTenantPluginConfig<ConfigType>\n >['userHasAccessToAllTenants']\n}): Endpoint => ({\n handler: async (req) => {\n const { payload, user } = req\n\n if (!user) {\n throw new APIError('Unauthorized', 401)\n }\n\n const tenantOptions = await getTenantOptions({\n payload,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n userHasAccessToAllTenants,\n })\n\n return new Response(JSON.stringify({ tenantOptions }))\n },\n method: 'get',\n path: '/populate-tenant-options',\n})\n"],"names":["APIError","getTenantOptions","getTenantOptionsEndpoint","tenantsArrayFieldName","tenantsArrayTenantFieldName","tenantsCollectionSlug","useAsTitle","userHasAccessToAllTenants","handler","req","payload","user","tenantOptions","Response","JSON","stringify","method","path"],"mappings":"AAEA,SAASA,QAAQ,QAAQ,UAAS;AAIlC,SAASC,gBAAgB,QAAQ,mCAAkC;AAEnE,OAAO,MAAMC,2BAA2B,CAAa,EACnDC,qBAAqB,EACrBC,2BAA2B,EAC3BC,qBAAqB,EACrBC,UAAU,EACVC,yBAAyB,EAS1B,GAAgB,CAAA;QACfC,SAAS,OAAOC;YACd,MAAM,EAAEC,OAAO,EAAEC,IAAI,EAAE,GAAGF;YAE1B,IAAI,CAACE,MAAM;gBACT,MAAM,IAAIX,SAAS,gBAAgB;YACrC;YAEA,MAAMY,gBAAgB,MAAMX,iBAAiB;gBAC3CS;gBACAP;gBACAC;gBACAC;gBACAC;gBACAK;gBACAJ;YACF;YAEA,OAAO,IAAIM,SAASC,KAAKC,SAAS,CAAC;gBAAEH;YAAc;QACrD;QACAI,QAAQ;QACRC,MAAM;IACR,CAAA,EAAE"}
1
+ {"version":3,"sources":["../../src/endpoints/getTenantOptionsEndpoint.ts"],"sourcesContent":["import type { Endpoint } from 'payload'\n\nimport { APIError } from 'payload'\n\nimport type { MultiTenantPluginConfig } from '../types.js'\n\nimport { getTenantOptions } from '../utilities/getTenantOptions.js'\n\nexport const getTenantOptionsEndpoint = ({\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n userHasAccessToAllTenants,\n}: {\n tenantsArrayFieldName: string\n tenantsArrayTenantFieldName: string\n tenantsCollectionSlug: string\n useAsTitle: string\n userHasAccessToAllTenants: Required<MultiTenantPluginConfig>['userHasAccessToAllTenants']\n}): Endpoint => ({\n handler: async (req) => {\n const { payload, user } = req\n\n if (!user) {\n throw new APIError('Unauthorized', 401)\n }\n\n const tenantOptions = await getTenantOptions({\n payload,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n userHasAccessToAllTenants,\n })\n\n return new Response(JSON.stringify({ tenantOptions }))\n },\n method: 'get',\n path: '/populate-tenant-options',\n})\n"],"names":["APIError","getTenantOptions","getTenantOptionsEndpoint","tenantsArrayFieldName","tenantsArrayTenantFieldName","tenantsCollectionSlug","useAsTitle","userHasAccessToAllTenants","handler","req","payload","user","tenantOptions","Response","JSON","stringify","method","path"],"mappings":"AAEA,SAASA,QAAQ,QAAQ,UAAS;AAIlC,SAASC,gBAAgB,QAAQ,mCAAkC;AAEnE,OAAO,MAAMC,2BAA2B,CAAC,EACvCC,qBAAqB,EACrBC,2BAA2B,EAC3BC,qBAAqB,EACrBC,UAAU,EACVC,yBAAyB,EAO1B,GAAgB,CAAA;QACfC,SAAS,OAAOC;YACd,MAAM,EAAEC,OAAO,EAAEC,IAAI,EAAE,GAAGF;YAE1B,IAAI,CAACE,MAAM;gBACT,MAAM,IAAIX,SAAS,gBAAgB;YACrC;YAEA,MAAMY,gBAAgB,MAAMX,iBAAiB;gBAC3CS;gBACAP;gBACAC;gBACAC;gBACAC;gBACAK;gBACAJ;YACF;YAEA,OAAO,IAAIM,SAASC,KAAKC,SAAS,CAAC;gBAAEH;YAAc;QACrD;QACAI,QAAQ;QACRC,MAAM;IACR,CAAA,EAAE"}
@@ -1,6 +1,7 @@
1
1
  import type { SingleRelationshipField } from 'payload';
2
- import type { RootTenantFieldConfigOverrides } from '../../types.js';
2
+ import type { MultiTenantPluginConfig, RootTenantFieldConfigOverrides } from '../../types.js';
3
3
  type Args = {
4
+ adminUsersSlug?: string;
4
5
  debug?: boolean;
5
6
  isAutosaveEnabled?: boolean;
6
7
  name: string;
@@ -9,7 +10,8 @@ type Args = {
9
10
  tenantsArrayTenantFieldName: string;
10
11
  tenantsCollectionSlug: string;
11
12
  unique: boolean;
13
+ userHasAccessToAllTenants?: MultiTenantPluginConfig['userHasAccessToAllTenants'];
12
14
  };
13
- export declare const tenantField: ({ name, debug, isAutosaveEnabled, overrides: _overrides, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, unique, }: Args) => SingleRelationshipField;
15
+ export declare const tenantField: ({ name, adminUsersSlug, debug, isAutosaveEnabled, overrides: _overrides, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, unique, userHasAccessToAllTenants, }: Args) => SingleRelationshipField;
14
16
  export {};
15
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fields/tenantField/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA+B,uBAAuB,EAAE,MAAM,SAAS,CAAA;AAEnF,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,gBAAgB,CAAA;AA8BpE,KAAK,IAAI,GAAG;IACV,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,8BAA8B,CAAA;IAC1C,qBAAqB,EAAE,MAAM,CAAA;IAC7B,2BAA2B,EAAE,MAAM,CAAA;IACnC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,MAAM,EAAE,OAAO,CAAA;CAChB,CAAA;AACD,eAAO,MAAM,WAAW,GAAI,+IASzB,IAAI,KAAG,uBAiGT,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fields/tenantField/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA+B,uBAAuB,EAAE,MAAM,SAAS,CAAA;AAEnF,OAAO,KAAK,EAAE,uBAAuB,EAAE,8BAA8B,EAAE,MAAM,gBAAgB,CAAA;AAsD7F,KAAK,IAAI,GAAG;IACV,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,8BAA8B,CAAA;IAC1C,qBAAqB,EAAE,MAAM,CAAA;IAC7B,2BAA2B,EAAE,MAAM,CAAA;IACnC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,MAAM,EAAE,OAAO,CAAA;IACf,yBAAyB,CAAC,EAAE,uBAAuB,CAAC,2BAA2B,CAAC,CAAA;CACjF,CAAA;AACD,eAAO,MAAM,WAAW,6LAWrB,IAAI,KAAG,uBAmHT,CAAA"}
@@ -2,9 +2,10 @@ import { defaults } from '../../defaults.js';
2
2
  import { getCollectionIDType } from '../../utilities/getCollectionIDType.js';
3
3
  import { getTenantFromCookie } from '../../utilities/getTenantFromCookie.js';
4
4
  import { getUserTenantIDs } from '../../utilities/getUserTenantIDs.js';
5
- const fieldValidation = (validateFunction)=>(value, options)=>{
5
+ import { isValidTenantAssignment } from '../../utilities/isValidTenantAssignment.js';
6
+ const fieldValidation = ({ tenantsArrayFieldName, tenantsArrayTenantFieldName, userHasAccessToAllTenants, validateFunction })=>async (value, options)=>{
6
7
  if (validateFunction) {
7
- const result = validateFunction(value, options);
8
+ const result = await validateFunction(value, options);
8
9
  if (result !== true) {
9
10
  return result;
10
11
  }
@@ -18,15 +19,31 @@ const fieldValidation = (validateFunction)=>(value, options)=>{
18
19
  return options.req.t('validation:required');
19
20
  }
20
21
  }
21
- return true;
22
+ if (isValidTenantAssignment({
23
+ previousValue: options.previousValue,
24
+ req: options.req,
25
+ tenantsArrayFieldName,
26
+ tenantsArrayTenantFieldName,
27
+ userHasAccessToAllTenants,
28
+ value
29
+ })) {
30
+ return true;
31
+ }
32
+ return options.req.t('validation:invalidSelection');
22
33
  };
23
- export const tenantField = ({ name = defaults.tenantFieldName, debug, isAutosaveEnabled, overrides: _overrides = {}, tenantsArrayFieldName = defaults.tenantsArrayFieldName, tenantsArrayTenantFieldName = defaults.tenantsArrayTenantFieldName, tenantsCollectionSlug = defaults.tenantCollectionSlug, unique })=>{
34
+ export const tenantField = ({ name = defaults.tenantFieldName, adminUsersSlug, debug, isAutosaveEnabled, overrides: _overrides = {}, tenantsArrayFieldName = defaults.tenantsArrayFieldName, tenantsArrayTenantFieldName = defaults.tenantsArrayTenantFieldName, tenantsCollectionSlug = defaults.tenantCollectionSlug, unique, userHasAccessToAllTenants })=>{
24
35
  const { hasMany = false, validate, ...overrides } = _overrides || {};
25
36
  return {
26
37
  ...overrides || {},
27
38
  name,
28
39
  type: 'relationship',
29
- access: overrides.access || {},
40
+ access: {
41
+ ...adminUsersSlug ? {
42
+ create: ({ req })=>Boolean(req.user && req.user.collection === adminUsersSlug),
43
+ update: ({ req })=>Boolean(req.user && req.user.collection === adminUsersSlug)
44
+ } : {},
45
+ ...overrides.access || {}
46
+ },
30
47
  admin: {
31
48
  allowCreate: false,
32
49
  allowEdit: false,
@@ -57,7 +74,7 @@ export const tenantField = ({ name = defaults.tenantFieldName, debug, isAutosave
57
74
  });
58
75
  const tenantFromCookie = getTenantFromCookie(req.headers, idType);
59
76
  if (tenantFromCookie) {
60
- const isValidTenant = await req.payload.count({
77
+ const { totalDocs } = await req.payload.count({
61
78
  collection: tenantsCollectionSlug,
62
79
  overrideAccess: false,
63
80
  req,
@@ -70,7 +87,7 @@ export const tenantField = ({ name = defaults.tenantFieldName, debug, isAutosave
70
87
  }
71
88
  }
72
89
  });
73
- return isValidTenant ? tenantFromCookie : null;
90
+ return totalDocs > 0 ? tenantFromCookie : null;
74
91
  }
75
92
  if (req.user && isAutosaveEnabled) {
76
93
  const userTenants = getUserTenantIDs(req.user, {
@@ -103,11 +120,21 @@ export const tenantField = ({ name = defaults.tenantFieldName, debug, isAutosave
103
120
  ...hasMany ? {
104
121
  hasMany: true,
105
122
  // TODO: V4 - replace validation with required: true
106
- validate: fieldValidation(validate)
123
+ validate: fieldValidation({
124
+ tenantsArrayFieldName,
125
+ tenantsArrayTenantFieldName,
126
+ userHasAccessToAllTenants,
127
+ validateFunction: validate
128
+ })
107
129
  } : {
108
130
  hasMany: false,
109
131
  // TODO: V4 - replace validation with required: true
110
- validate: fieldValidation(validate)
132
+ validate: fieldValidation({
133
+ tenantsArrayFieldName,
134
+ tenantsArrayTenantFieldName,
135
+ userHasAccessToAllTenants,
136
+ validateFunction: validate
137
+ })
111
138
  },
112
139
  // @ts-expect-error translations are not typed for this plugin
113
140
  label: overrides.label || (({ t })=>t('plugin-multi-tenant:field-assignedTenant-label'))
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/fields/tenantField/index.ts"],"sourcesContent":["import type { RelationshipFieldValidation, SingleRelationshipField } from 'payload'\n\nimport type { RootTenantFieldConfigOverrides } from '../../types.js'\n\nimport { defaults } from '../../defaults.js'\nimport { getCollectionIDType } from '../../utilities/getCollectionIDType.js'\nimport { getTenantFromCookie } from '../../utilities/getTenantFromCookie.js'\nimport { getUserTenantIDs } from '../../utilities/getUserTenantIDs.js'\n\nconst fieldValidation =\n (validateFunction?: RelationshipFieldValidation): RelationshipFieldValidation =>\n (value, options) => {\n if (validateFunction) {\n const result = validateFunction(value, options)\n if (result !== true) {\n return result\n }\n }\n\n if (options.hasMany) {\n if (!value || (Array.isArray(value) && value.length === 0)) {\n return options.req.t('validation:required')\n }\n } else {\n if (!value) {\n return options.req.t('validation:required')\n }\n }\n\n return true\n }\n\ntype Args = {\n debug?: boolean\n isAutosaveEnabled?: boolean\n name: string\n overrides?: RootTenantFieldConfigOverrides\n tenantsArrayFieldName: string\n tenantsArrayTenantFieldName: string\n tenantsCollectionSlug: string\n unique: boolean\n}\nexport const tenantField = ({\n name = defaults.tenantFieldName,\n debug,\n isAutosaveEnabled,\n overrides: _overrides = {},\n tenantsArrayFieldName = defaults.tenantsArrayFieldName,\n tenantsArrayTenantFieldName = defaults.tenantsArrayTenantFieldName,\n tenantsCollectionSlug = defaults.tenantCollectionSlug,\n unique,\n}: Args): SingleRelationshipField => {\n const { hasMany = false, validate, ...overrides } = _overrides || {}\n return {\n ...(overrides || {}),\n name,\n type: 'relationship',\n access: overrides.access || {},\n admin: {\n allowCreate: false,\n allowEdit: false,\n disabled: { column: true, filter: true, groupBy: true },\n position: 'sidebar',\n ...(overrides.admin || {}),\n components: {\n ...(overrides.admin?.components || {}),\n Field: {\n path: '@payloadcms/plugin-multi-tenant/client#TenantField',\n ...(typeof overrides.admin?.components?.Field !== 'string'\n ? overrides.admin?.components?.Field || {}\n : {}),\n clientProps: {\n ...(typeof overrides.admin?.components?.Field !== 'string'\n ? (overrides.admin?.components?.Field || {})?.clientProps\n : {}),\n debug,\n unique,\n },\n },\n },\n },\n defaultValue:\n overrides.defaultValue ||\n (async ({ req }) => {\n const idType = getCollectionIDType({\n collectionSlug: tenantsCollectionSlug,\n payload: req.payload,\n })\n const tenantFromCookie = getTenantFromCookie(req.headers, idType)\n if (tenantFromCookie) {\n const isValidTenant = await req.payload.count({\n collection: tenantsCollectionSlug,\n overrideAccess: false,\n req,\n user: req.user,\n where: {\n id: {\n in: [tenantFromCookie],\n },\n },\n })\n return isValidTenant ? tenantFromCookie : null\n }\n if (req.user && isAutosaveEnabled) {\n const userTenants = getUserTenantIDs(req.user, {\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n })\n if (userTenants.length > 0) {\n return userTenants[0]\n }\n }\n return null\n }),\n filterOptions:\n overrides.filterOptions ||\n (({ req }) => {\n const userAssignedTenants = getUserTenantIDs(req.user, {\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n })\n if (userAssignedTenants.length > 0) {\n return {\n id: {\n in: userAssignedTenants,\n },\n }\n }\n\n return true\n }),\n index: true,\n relationTo: tenantsCollectionSlug,\n unique,\n ...(hasMany\n ? {\n hasMany: true,\n // TODO: V4 - replace validation with required: true\n validate: fieldValidation(validate as RelationshipFieldValidation),\n }\n : {\n hasMany: false,\n // TODO: V4 - replace validation with required: true\n validate: fieldValidation(validate as RelationshipFieldValidation),\n }),\n // @ts-expect-error translations are not typed for this plugin\n label: overrides.label || (({ t }) => t('plugin-multi-tenant:field-assignedTenant-label')),\n }\n}\n"],"names":["defaults","getCollectionIDType","getTenantFromCookie","getUserTenantIDs","fieldValidation","validateFunction","value","options","result","hasMany","Array","isArray","length","req","t","tenantField","name","tenantFieldName","debug","isAutosaveEnabled","overrides","_overrides","tenantsArrayFieldName","tenantsArrayTenantFieldName","tenantsCollectionSlug","tenantCollectionSlug","unique","validate","type","access","admin","allowCreate","allowEdit","disabled","column","filter","groupBy","position","components","Field","path","clientProps","defaultValue","idType","collectionSlug","payload","tenantFromCookie","headers","isValidTenant","count","collection","overrideAccess","user","where","id","in","userTenants","filterOptions","userAssignedTenants","index","relationTo","label"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/fields/tenantField/index.ts"],"sourcesContent":["import type { RelationshipFieldValidation, SingleRelationshipField } from 'payload'\n\nimport type { MultiTenantPluginConfig, RootTenantFieldConfigOverrides } from '../../types.js'\n\nimport { defaults } from '../../defaults.js'\nimport { getCollectionIDType } from '../../utilities/getCollectionIDType.js'\nimport { getTenantFromCookie } from '../../utilities/getTenantFromCookie.js'\nimport { getUserTenantIDs } from '../../utilities/getUserTenantIDs.js'\nimport { isValidTenantAssignment } from '../../utilities/isValidTenantAssignment.js'\n\nconst fieldValidation =\n ({\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n validateFunction,\n }: {\n tenantsArrayFieldName: string\n tenantsArrayTenantFieldName: string\n userHasAccessToAllTenants?: MultiTenantPluginConfig['userHasAccessToAllTenants']\n validateFunction?: RelationshipFieldValidation\n }): RelationshipFieldValidation =>\n async (value, options) => {\n if (validateFunction) {\n const result = await validateFunction(value, options)\n if (result !== true) {\n return result\n }\n }\n\n if (options.hasMany) {\n if (!value || (Array.isArray(value) && value.length === 0)) {\n return options.req.t('validation:required')\n }\n } else {\n if (!value) {\n return options.req.t('validation:required')\n }\n }\n\n if (\n isValidTenantAssignment({\n previousValue: options.previousValue,\n req: options.req,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n value,\n })\n ) {\n return true\n }\n\n return options.req.t('validation:invalidSelection')\n }\n\ntype Args = {\n adminUsersSlug?: string\n debug?: boolean\n isAutosaveEnabled?: boolean\n name: string\n overrides?: RootTenantFieldConfigOverrides\n tenantsArrayFieldName: string\n tenantsArrayTenantFieldName: string\n tenantsCollectionSlug: string\n unique: boolean\n userHasAccessToAllTenants?: MultiTenantPluginConfig['userHasAccessToAllTenants']\n}\nexport const tenantField = ({\n name = defaults.tenantFieldName,\n adminUsersSlug,\n debug,\n isAutosaveEnabled,\n overrides: _overrides = {},\n tenantsArrayFieldName = defaults.tenantsArrayFieldName,\n tenantsArrayTenantFieldName = defaults.tenantsArrayTenantFieldName,\n tenantsCollectionSlug = defaults.tenantCollectionSlug,\n unique,\n userHasAccessToAllTenants,\n}: Args): SingleRelationshipField => {\n const { hasMany = false, validate, ...overrides } = _overrides || {}\n return {\n ...(overrides || {}),\n name,\n type: 'relationship',\n access: {\n ...(adminUsersSlug\n ? {\n create: ({ req }) => Boolean(req.user && req.user.collection === adminUsersSlug),\n update: ({ req }) => Boolean(req.user && req.user.collection === adminUsersSlug),\n }\n : {}),\n ...(overrides.access || {}),\n },\n admin: {\n allowCreate: false,\n allowEdit: false,\n disabled: { column: true, filter: true, groupBy: true },\n position: 'sidebar',\n ...(overrides.admin || {}),\n components: {\n ...(overrides.admin?.components || {}),\n Field: {\n path: '@payloadcms/plugin-multi-tenant/client#TenantField',\n ...(typeof overrides.admin?.components?.Field !== 'string'\n ? overrides.admin?.components?.Field || {}\n : {}),\n clientProps: {\n ...(typeof overrides.admin?.components?.Field !== 'string'\n ? (overrides.admin?.components?.Field || {})?.clientProps\n : {}),\n debug,\n unique,\n },\n },\n },\n },\n defaultValue:\n overrides.defaultValue ||\n (async ({ req }) => {\n const idType = getCollectionIDType({\n collectionSlug: tenantsCollectionSlug,\n payload: req.payload,\n })\n const tenantFromCookie = getTenantFromCookie(req.headers, idType)\n if (tenantFromCookie) {\n const { totalDocs } = await req.payload.count({\n collection: tenantsCollectionSlug,\n overrideAccess: false,\n req,\n user: req.user,\n where: {\n id: {\n in: [tenantFromCookie],\n },\n },\n })\n return totalDocs > 0 ? tenantFromCookie : null\n }\n if (req.user && isAutosaveEnabled) {\n const userTenants = getUserTenantIDs(req.user, {\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n })\n if (userTenants.length > 0) {\n return userTenants[0]\n }\n }\n return null\n }),\n filterOptions:\n overrides.filterOptions ||\n (({ req }) => {\n const userAssignedTenants = getUserTenantIDs(req.user, {\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n })\n if (userAssignedTenants.length > 0) {\n return {\n id: {\n in: userAssignedTenants,\n },\n }\n }\n\n return true\n }),\n index: true,\n relationTo: tenantsCollectionSlug,\n unique,\n ...(hasMany\n ? {\n hasMany: true,\n // TODO: V4 - replace validation with required: true\n validate: fieldValidation({\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n validateFunction: validate as RelationshipFieldValidation,\n }),\n }\n : {\n hasMany: false,\n // TODO: V4 - replace validation with required: true\n validate: fieldValidation({\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n validateFunction: validate as RelationshipFieldValidation,\n }),\n }),\n // @ts-expect-error translations are not typed for this plugin\n label: overrides.label || (({ t }) => t('plugin-multi-tenant:field-assignedTenant-label')),\n }\n}\n"],"names":["defaults","getCollectionIDType","getTenantFromCookie","getUserTenantIDs","isValidTenantAssignment","fieldValidation","tenantsArrayFieldName","tenantsArrayTenantFieldName","userHasAccessToAllTenants","validateFunction","value","options","result","hasMany","Array","isArray","length","req","t","previousValue","tenantField","name","tenantFieldName","adminUsersSlug","debug","isAutosaveEnabled","overrides","_overrides","tenantsCollectionSlug","tenantCollectionSlug","unique","validate","type","access","create","Boolean","user","collection","update","admin","allowCreate","allowEdit","disabled","column","filter","groupBy","position","components","Field","path","clientProps","defaultValue","idType","collectionSlug","payload","tenantFromCookie","headers","totalDocs","count","overrideAccess","where","id","in","userTenants","filterOptions","userAssignedTenants","index","relationTo","label"],"mappings":"AAIA,SAASA,QAAQ,QAAQ,oBAAmB;AAC5C,SAASC,mBAAmB,QAAQ,yCAAwC;AAC5E,SAASC,mBAAmB,QAAQ,yCAAwC;AAC5E,SAASC,gBAAgB,QAAQ,sCAAqC;AACtE,SAASC,uBAAuB,QAAQ,6CAA4C;AAEpF,MAAMC,kBACJ,CAAC,EACCC,qBAAqB,EACrBC,2BAA2B,EAC3BC,yBAAyB,EACzBC,gBAAgB,EAMjB,GACD,OAAOC,OAAOC;QACZ,IAAIF,kBAAkB;YACpB,MAAMG,SAAS,MAAMH,iBAAiBC,OAAOC;YAC7C,IAAIC,WAAW,MAAM;gBACnB,OAAOA;YACT;QACF;QAEA,IAAID,QAAQE,OAAO,EAAE;YACnB,IAAI,CAACH,SAAUI,MAAMC,OAAO,CAACL,UAAUA,MAAMM,MAAM,KAAK,GAAI;gBAC1D,OAAOL,QAAQM,GAAG,CAACC,CAAC,CAAC;YACvB;QACF,OAAO;YACL,IAAI,CAACR,OAAO;gBACV,OAAOC,QAAQM,GAAG,CAACC,CAAC,CAAC;YACvB;QACF;QAEA,IACEd,wBAAwB;YACtBe,eAAeR,QAAQQ,aAAa;YACpCF,KAAKN,QAAQM,GAAG;YAChBX;YACAC;YACAC;YACAE;QACF,IACA;YACA,OAAO;QACT;QAEA,OAAOC,QAAQM,GAAG,CAACC,CAAC,CAAC;IACvB;AAcF,OAAO,MAAME,cAAc,CAAC,EAC1BC,OAAOrB,SAASsB,eAAe,EAC/BC,cAAc,EACdC,KAAK,EACLC,iBAAiB,EACjBC,WAAWC,aAAa,CAAC,CAAC,EAC1BrB,wBAAwBN,SAASM,qBAAqB,EACtDC,8BAA8BP,SAASO,2BAA2B,EAClEqB,wBAAwB5B,SAAS6B,oBAAoB,EACrDC,MAAM,EACNtB,yBAAyB,EACpB;IACL,MAAM,EAAEK,UAAU,KAAK,EAAEkB,QAAQ,EAAE,GAAGL,WAAW,GAAGC,cAAc,CAAC;IACnE,OAAO;QACL,GAAID,aAAa,CAAC,CAAC;QACnBL;QACAW,MAAM;QACNC,QAAQ;YACN,GAAIV,iBACA;gBACEW,QAAQ,CAAC,EAAEjB,GAAG,EAAE,GAAKkB,QAAQlB,IAAImB,IAAI,IAAInB,IAAImB,IAAI,CAACC,UAAU,KAAKd;gBACjEe,QAAQ,CAAC,EAAErB,GAAG,EAAE,GAAKkB,QAAQlB,IAAImB,IAAI,IAAInB,IAAImB,IAAI,CAACC,UAAU,KAAKd;YACnE,IACA,CAAC,CAAC;YACN,GAAIG,UAAUO,MAAM,IAAI,CAAC,CAAC;QAC5B;QACAM,OAAO;YACLC,aAAa;YACbC,WAAW;YACXC,UAAU;gBAAEC,QAAQ;gBAAMC,QAAQ;gBAAMC,SAAS;YAAK;YACtDC,UAAU;YACV,GAAIpB,UAAUa,KAAK,IAAI,CAAC,CAAC;YACzBQ,YAAY;gBACV,GAAIrB,UAAUa,KAAK,EAAEQ,cAAc,CAAC,CAAC;gBACrCC,OAAO;oBACLC,MAAM;oBACN,GAAI,OAAOvB,UAAUa,KAAK,EAAEQ,YAAYC,UAAU,WAC9CtB,UAAUa,KAAK,EAAEQ,YAAYC,SAAS,CAAC,IACvC,CAAC,CAAC;oBACNE,aAAa;wBACX,GAAI,OAAOxB,UAAUa,KAAK,EAAEQ,YAAYC,UAAU,WAC7CtB,CAAAA,UAAUa,KAAK,EAAEQ,YAAYC,SAAS,CAAC,CAAA,GAAIE,cAC5C,CAAC,CAAC;wBACN1B;wBACAM;oBACF;gBACF;YACF;QACF;QACAqB,cACEzB,UAAUyB,YAAY,IACrB,CAAA,OAAO,EAAElC,GAAG,EAAE;YACb,MAAMmC,SAASnD,oBAAoB;gBACjCoD,gBAAgBzB;gBAChB0B,SAASrC,IAAIqC,OAAO;YACtB;YACA,MAAMC,mBAAmBrD,oBAAoBe,IAAIuC,OAAO,EAAEJ;YAC1D,IAAIG,kBAAkB;gBACpB,MAAM,EAAEE,SAAS,EAAE,GAAG,MAAMxC,IAAIqC,OAAO,CAACI,KAAK,CAAC;oBAC5CrB,YAAYT;oBACZ+B,gBAAgB;oBAChB1C;oBACAmB,MAAMnB,IAAImB,IAAI;oBACdwB,OAAO;wBACLC,IAAI;4BACFC,IAAI;gCAACP;6BAAiB;wBACxB;oBACF;gBACF;gBACA,OAAOE,YAAY,IAAIF,mBAAmB;YAC5C;YACA,IAAItC,IAAImB,IAAI,IAAIX,mBAAmB;gBACjC,MAAMsC,cAAc5D,iBAAiBc,IAAImB,IAAI,EAAE;oBAC7C9B;oBACAC;gBACF;gBACA,IAAIwD,YAAY/C,MAAM,GAAG,GAAG;oBAC1B,OAAO+C,WAAW,CAAC,EAAE;gBACvB;YACF;YACA,OAAO;QACT,CAAA;QACFC,eACEtC,UAAUsC,aAAa,IACtB,CAAA,CAAC,EAAE/C,GAAG,EAAE;YACP,MAAMgD,sBAAsB9D,iBAAiBc,IAAImB,IAAI,EAAE;gBACrD9B;gBACAC;YACF;YACA,IAAI0D,oBAAoBjD,MAAM,GAAG,GAAG;gBAClC,OAAO;oBACL6C,IAAI;wBACFC,IAAIG;oBACN;gBACF;YACF;YAEA,OAAO;QACT,CAAA;QACFC,OAAO;QACPC,YAAYvC;QACZE;QACA,GAAIjB,UACA;YACEA,SAAS;YACT,oDAAoD;YACpDkB,UAAU1B,gBAAgB;gBACxBC;gBACAC;gBACAC;gBACAC,kBAAkBsB;YACpB;QACF,IACA;YACElB,SAAS;YACT,oDAAoD;YACpDkB,UAAU1B,gBAAgB;gBACxBC;gBACAC;gBACAC;gBACAC,kBAAkBsB;YACpB;QACF,CAAC;QACL,8DAA8D;QAC9DqC,OAAO1C,UAAU0C,KAAK,IAAK,CAAA,CAAC,EAAElD,CAAC,EAAE,GAAKA,EAAE,iDAAgD;IAC1F;AACF,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fields/tenantsArrayField/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAI5D,KAAK,IAAI,GAAG;IACV;;OAEG;IACH,gBAAgB,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;IACvC;;OAEG;IACH,SAAS,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;IAChC;;OAEG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IAC/C;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAA;IAC1C;;;;OAIG;IACH,2BAA2B,CAAC,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAA;IACvD;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAA;CAC/B,CAAA;AACD,eAAO,MAAM,iBAAiB,GAAI,gIAO/B,IAAI,KAAG,UAiBR,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fields/tenantsArrayField/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAI5D,KAAK,IAAI,GAAG;IACV;;OAEG;IACH,gBAAgB,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;IACvC;;OAEG;IACH,SAAS,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;IAChC;;OAEG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IAC/C;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAA;IAC1C;;;;OAIG;IACH,2BAA2B,CAAC,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAA;IACvD;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAA;CAC/B,CAAA;AACD,eAAO,MAAM,iBAAiB,mIAO3B,IAAI,KAAG,UAiBR,CAAA"}
@@ -1,6 +1,6 @@
1
1
  import type { PayloadRequest, Where } from 'payload';
2
2
  import type { MultiTenantPluginConfig } from '../types.js';
3
- type Args<ConfigType = unknown> = {
3
+ type Args = {
4
4
  /**
5
5
  * If the document this filter is run belongs to a tenant, the tenant ID should be passed here.
6
6
  * If set, this will be used instead of the tenant cookie
@@ -12,8 +12,8 @@ type Args<ConfigType = unknown> = {
12
12
  tenantsArrayFieldName?: string;
13
13
  tenantsArrayTenantFieldName?: string;
14
14
  tenantsCollectionSlug: string;
15
- userHasAccessToAllTenants: Required<MultiTenantPluginConfig<ConfigType>>['userHasAccessToAllTenants'];
15
+ userHasAccessToAllTenants: Required<MultiTenantPluginConfig>['userHasAccessToAllTenants'];
16
16
  };
17
- export declare const filterDocumentsByTenants: <ConfigType = unknown>({ docTenantID, filterFieldName, req, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, userHasAccessToAllTenants, }: Args<ConfigType>) => null | Where;
17
+ export declare const filterDocumentsByTenants: ({ docTenantID, filterFieldName, req, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, userHasAccessToAllTenants, }: Args) => null | Where;
18
18
  export {};
19
19
  //# sourceMappingURL=filterDocumentsByTenants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"filterDocumentsByTenants.d.ts","sourceRoot":"","sources":["../../src/filters/filterDocumentsByTenants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAa,KAAK,EAAE,MAAM,SAAS,CAAA;AAE/D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAO1D,KAAK,IAAI,CAAC,UAAU,GAAG,OAAO,IAAI;IAChC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;IACnD,eAAe,EAAE,MAAM,CAAA;IACvB,GAAG,EAAE,cAAc,CAAA;IACnB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,2BAA2B,CAAC,EAAE,MAAM,CAAA;IACpC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,yBAAyB,EAAE,QAAQ,CACjC,uBAAuB,CAAC,UAAU,CAAC,CACpC,CAAC,2BAA2B,CAAC,CAAA;CAC/B,CAAA;AACD,eAAO,MAAM,wBAAwB,GAAI,UAAU,GAAG,OAAO,EAAE,8IAQ5D,IAAI,CAAC,UAAU,CAAC,KAAG,IAAI,GAAG,KAwC5B,CAAA"}
1
+ {"version":3,"file":"filterDocumentsByTenants.d.ts","sourceRoot":"","sources":["../../src/filters/filterDocumentsByTenants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAQ,KAAK,EAAE,MAAM,SAAS,CAAA;AAE1D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAO1D,KAAK,IAAI,GAAG;IACV;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;IACnD,eAAe,EAAE,MAAM,CAAA;IACvB,GAAG,EAAE,cAAc,CAAA;IACnB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,2BAA2B,CAAC,EAAE,MAAM,CAAA;IACpC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,yBAAyB,EAAE,QAAQ,CAAC,uBAAuB,CAAC,CAAC,2BAA2B,CAAC,CAAA;CAC1F,CAAA;AACD,eAAO,MAAM,wBAAwB,iJAQlC,IAAI,KAAG,IAAI,GAAG,KAmChB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/filters/filterDocumentsByTenants.ts"],"sourcesContent":["import type { PayloadRequest, TypedUser, Where } from 'payload'\n\nimport type { MultiTenantPluginConfig } from '../types.js'\n\nimport { defaults } from '../defaults.js'\nimport { getCollectionIDType } from '../utilities/getCollectionIDType.js'\nimport { getTenantFromCookie } from '../utilities/getTenantFromCookie.js'\nimport { getUserTenantIDs } from '../utilities/getUserTenantIDs.js'\n\ntype Args<ConfigType = unknown> = {\n /**\n * If the document this filter is run belongs to a tenant, the tenant ID should be passed here.\n * If set, this will be used instead of the tenant cookie\n * Can be an array when hasMany is true\n */\n docTenantID?: number | number[] | string | string[]\n filterFieldName: string\n req: PayloadRequest\n tenantsArrayFieldName?: string\n tenantsArrayTenantFieldName?: string\n tenantsCollectionSlug: string\n userHasAccessToAllTenants: Required<\n MultiTenantPluginConfig<ConfigType>\n >['userHasAccessToAllTenants']\n}\nexport const filterDocumentsByTenants = <ConfigType = unknown>({\n docTenantID,\n filterFieldName,\n req,\n tenantsArrayFieldName = defaults.tenantsArrayFieldName,\n tenantsArrayTenantFieldName = defaults.tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n userHasAccessToAllTenants,\n}: Args<ConfigType>): null | Where => {\n const idType = getCollectionIDType({\n collectionSlug: tenantsCollectionSlug,\n payload: req.payload,\n })\n\n // scope results to selected tenant\n const selectedTenant = docTenantID ?? getTenantFromCookie(req.headers, idType)\n if (selectedTenant) {\n return {\n [filterFieldName]: {\n in: Array.isArray(selectedTenant) ? selectedTenant : [selectedTenant],\n },\n }\n }\n\n if (\n req.user &&\n userHasAccessToAllTenants(\n req?.user as ConfigType extends { user: unknown } ? ConfigType['user'] : TypedUser,\n )\n ) {\n return null\n }\n\n // scope to user assigned tenants\n const userAssignedTenants = getUserTenantIDs(req.user, {\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n })\n if (userAssignedTenants.length > 0) {\n return {\n [filterFieldName]: {\n in: userAssignedTenants,\n },\n }\n }\n\n // no tenant selected and no user tenants, return null to allow access control to handle it\n return null\n}\n"],"names":["defaults","getCollectionIDType","getTenantFromCookie","getUserTenantIDs","filterDocumentsByTenants","docTenantID","filterFieldName","req","tenantsArrayFieldName","tenantsArrayTenantFieldName","tenantsCollectionSlug","userHasAccessToAllTenants","idType","collectionSlug","payload","selectedTenant","headers","in","Array","isArray","user","userAssignedTenants","length"],"mappings":"AAIA,SAASA,QAAQ,QAAQ,iBAAgB;AACzC,SAASC,mBAAmB,QAAQ,sCAAqC;AACzE,SAASC,mBAAmB,QAAQ,sCAAqC;AACzE,SAASC,gBAAgB,QAAQ,mCAAkC;AAkBnE,OAAO,MAAMC,2BAA2B,CAAuB,EAC7DC,WAAW,EACXC,eAAe,EACfC,GAAG,EACHC,wBAAwBR,SAASQ,qBAAqB,EACtDC,8BAA8BT,SAASS,2BAA2B,EAClEC,qBAAqB,EACrBC,yBAAyB,EACR;IACjB,MAAMC,SAASX,oBAAoB;QACjCY,gBAAgBH;QAChBI,SAASP,IAAIO,OAAO;IACtB;IAEA,mCAAmC;IACnC,MAAMC,iBAAiBV,eAAeH,oBAAoBK,IAAIS,OAAO,EAAEJ;IACvE,IAAIG,gBAAgB;QAClB,OAAO;YACL,CAACT,gBAAgB,EAAE;gBACjBW,IAAIC,MAAMC,OAAO,CAACJ,kBAAkBA,iBAAiB;oBAACA;iBAAe;YACvE;QACF;IACF;IAEA,IACER,IAAIa,IAAI,IACRT,0BACEJ,KAAKa,OAEP;QACA,OAAO;IACT;IAEA,iCAAiC;IACjC,MAAMC,sBAAsBlB,iBAAiBI,IAAIa,IAAI,EAAE;QACrDZ;QACAC;IACF;IACA,IAAIY,oBAAoBC,MAAM,GAAG,GAAG;QAClC,OAAO;YACL,CAAChB,gBAAgB,EAAE;gBACjBW,IAAII;YACN;QACF;IACF;IAEA,2FAA2F;IAC3F,OAAO;AACT,EAAC"}
1
+ {"version":3,"sources":["../../src/filters/filterDocumentsByTenants.ts"],"sourcesContent":["import type { PayloadRequest, User, Where } from 'payload'\n\nimport type { MultiTenantPluginConfig } from '../types.js'\n\nimport { defaults } from '../defaults.js'\nimport { getCollectionIDType } from '../utilities/getCollectionIDType.js'\nimport { getTenantFromCookie } from '../utilities/getTenantFromCookie.js'\nimport { getUserTenantIDs } from '../utilities/getUserTenantIDs.js'\n\ntype Args = {\n /**\n * If the document this filter is run belongs to a tenant, the tenant ID should be passed here.\n * If set, this will be used instead of the tenant cookie\n * Can be an array when hasMany is true\n */\n docTenantID?: number | number[] | string | string[]\n filterFieldName: string\n req: PayloadRequest\n tenantsArrayFieldName?: string\n tenantsArrayTenantFieldName?: string\n tenantsCollectionSlug: string\n userHasAccessToAllTenants: Required<MultiTenantPluginConfig>['userHasAccessToAllTenants']\n}\nexport const filterDocumentsByTenants = ({\n docTenantID,\n filterFieldName,\n req,\n tenantsArrayFieldName = defaults.tenantsArrayFieldName,\n tenantsArrayTenantFieldName = defaults.tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n userHasAccessToAllTenants,\n}: Args): null | Where => {\n const idType = getCollectionIDType({\n collectionSlug: tenantsCollectionSlug,\n payload: req.payload,\n })\n\n // scope results to selected tenant\n const selectedTenant = docTenantID ?? getTenantFromCookie(req.headers, idType)\n if (selectedTenant) {\n return {\n [filterFieldName]: {\n in: Array.isArray(selectedTenant) ? selectedTenant : [selectedTenant],\n },\n }\n }\n\n if (req.user && userHasAccessToAllTenants(req?.user as User)) {\n return null\n }\n\n // scope to user assigned tenants\n const userAssignedTenants = getUserTenantIDs(req.user, {\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n })\n if (userAssignedTenants.length > 0) {\n return {\n [filterFieldName]: {\n in: userAssignedTenants,\n },\n }\n }\n\n // no tenant selected and no user tenants, return null to allow access control to handle it\n return null\n}\n"],"names":["defaults","getCollectionIDType","getTenantFromCookie","getUserTenantIDs","filterDocumentsByTenants","docTenantID","filterFieldName","req","tenantsArrayFieldName","tenantsArrayTenantFieldName","tenantsCollectionSlug","userHasAccessToAllTenants","idType","collectionSlug","payload","selectedTenant","headers","in","Array","isArray","user","userAssignedTenants","length"],"mappings":"AAIA,SAASA,QAAQ,QAAQ,iBAAgB;AACzC,SAASC,mBAAmB,QAAQ,sCAAqC;AACzE,SAASC,mBAAmB,QAAQ,sCAAqC;AACzE,SAASC,gBAAgB,QAAQ,mCAAkC;AAgBnE,OAAO,MAAMC,2BAA2B,CAAC,EACvCC,WAAW,EACXC,eAAe,EACfC,GAAG,EACHC,wBAAwBR,SAASQ,qBAAqB,EACtDC,8BAA8BT,SAASS,2BAA2B,EAClEC,qBAAqB,EACrBC,yBAAyB,EACpB;IACL,MAAMC,SAASX,oBAAoB;QACjCY,gBAAgBH;QAChBI,SAASP,IAAIO,OAAO;IACtB;IAEA,mCAAmC;IACnC,MAAMC,iBAAiBV,eAAeH,oBAAoBK,IAAIS,OAAO,EAAEJ;IACvE,IAAIG,gBAAgB;QAClB,OAAO;YACL,CAACT,gBAAgB,EAAE;gBACjBW,IAAIC,MAAMC,OAAO,CAACJ,kBAAkBA,iBAAiB;oBAACA;iBAAe;YACvE;QACF;IACF;IAEA,IAAIR,IAAIa,IAAI,IAAIT,0BAA0BJ,KAAKa,OAAe;QAC5D,OAAO;IACT;IAEA,iCAAiC;IACjC,MAAMC,sBAAsBlB,iBAAiBI,IAAIa,IAAI,EAAE;QACrDZ;QACAC;IACF;IACA,IAAIY,oBAAoBC,MAAM,GAAG,GAAG;QAClC,OAAO;YACL,CAAChB,gBAAgB,EAAE;gBACjBW,IAAII;YACN;QACF;IACF;IAEA,2FAA2F;IAC3F,OAAO;AACT,EAAC"}
@@ -14,6 +14,6 @@ type Args = {
14
14
  * - remove tenant from users
15
15
  */
16
16
  export declare const addTenantCleanup: ({ collection, enabledSlugs, tenantFieldName, tenantsCollectionSlug, usersSlug, usersTenantsArrayFieldName, usersTenantsArrayTenantFieldName, }: Args) => void;
17
- export declare const afterTenantDelete: ({ enabledSlugs, tenantFieldName, tenantsCollectionSlug, usersSlug, usersTenantsArrayFieldName, usersTenantsArrayTenantFieldName, }: Omit<Args, "collection">) => CollectionAfterDeleteHook;
17
+ export declare const afterTenantDelete: ({ enabledSlugs, tenantFieldName, tenantsCollectionSlug, usersSlug, usersTenantsArrayFieldName, usersTenantsArrayTenantFieldName, }: Omit<Args, 'collection'>) => CollectionAfterDeleteHook;
18
18
  export {};
19
19
  //# sourceMappingURL=afterTenantDelete.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"afterTenantDelete.d.ts","sourceRoot":"","sources":["../../src/hooks/afterTenantDelete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,gBAAgB,EAGjB,MAAM,SAAS,CAAA;AAShB,KAAK,IAAI,GAAG;IACV,UAAU,EAAE,gBAAgB,CAAA;IAC5B,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,eAAe,EAAE,MAAM,CAAA;IACvB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,0BAA0B,EAAE,MAAM,CAAA;IAClC,gCAAgC,EAAE,MAAM,CAAA;CACzC,CAAA;AACD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,gJAQ9B,IAAI,SAiBN,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC3B,oIAOE,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,KAAG,yBAsE7B,CAAA"}
1
+ {"version":3,"file":"afterTenantDelete.d.ts","sourceRoot":"","sources":["../../src/hooks/afterTenantDelete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,gBAAgB,EAGjB,MAAM,SAAS,CAAA;AAShB,KAAK,IAAI,GAAG;IACV,UAAU,EAAE,gBAAgB,CAAA;IAC5B,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,eAAe,EAAE,MAAM,CAAA;IACvB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,0BAA0B,EAAE,MAAM,CAAA;IAClC,gCAAgC,EAAE,MAAM,CAAA;CACzC,CAAA;AACD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,mJAQ1B,IAAI,SAiBN,CAAA;AAED,eAAO,MAAM,iBAAiB,uIAQzB,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,KAAG,yBA+E7B,CAAA"}
@@ -43,6 +43,8 @@ export const afterTenantDelete = ({ enabledSlugs, tenantFieldName, tenantsCollec
43
43
  enabledSlugs.forEach((slug)=>{
44
44
  cleanupPromises.push(req.payload.delete({
45
45
  collection: slug,
46
+ overrideAccess: true,
47
+ req,
46
48
  where: {
47
49
  [tenantFieldName]: {
48
50
  in: [
@@ -57,6 +59,8 @@ export const afterTenantDelete = ({ enabledSlugs, tenantFieldName, tenantsCollec
57
59
  collection: usersSlug,
58
60
  depth: 0,
59
61
  limit: 0,
62
+ overrideAccess: true,
63
+ req,
60
64
  where: {
61
65
  [`${usersTenantsArrayFieldName}.${usersTenantsArrayTenantFieldName}`]: {
62
66
  in: [
@@ -75,7 +79,9 @@ export const afterTenantDelete = ({ enabledSlugs, tenantFieldName, tenantsCollec
75
79
  return row[usersTenantsArrayTenantFieldName] !== id;
76
80
  }
77
81
  })
78
- }
82
+ },
83
+ overrideAccess: true,
84
+ req
79
85
  }));
80
86
  });
81
87
  } catch (e) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/afterTenantDelete.ts"],"sourcesContent":["import type {\n CollectionAfterDeleteHook,\n CollectionConfig,\n JsonObject,\n PaginatedDocs,\n} from 'payload'\n\nimport { generateCookie, mergeHeaders } from 'payload'\n\nimport type { UserWithTenantsField } from '../types.js'\n\nimport { getCollectionIDType } from '../utilities/getCollectionIDType.js'\nimport { getTenantFromCookie } from '../utilities/getTenantFromCookie.js'\n\ntype Args = {\n collection: CollectionConfig\n enabledSlugs: string[]\n tenantFieldName: string\n tenantsCollectionSlug: string\n usersSlug: string\n usersTenantsArrayFieldName: string\n usersTenantsArrayTenantFieldName: string\n}\n/**\n * Add cleanup logic when tenant is deleted\n * - delete documents related to tenant\n * - remove tenant from users\n */\nexport const addTenantCleanup = ({\n collection,\n enabledSlugs,\n tenantFieldName,\n tenantsCollectionSlug,\n usersSlug,\n usersTenantsArrayFieldName,\n usersTenantsArrayTenantFieldName,\n}: Args) => {\n if (!collection.hooks) {\n collection.hooks = {}\n }\n if (!collection.hooks?.afterDelete) {\n collection.hooks.afterDelete = []\n }\n collection.hooks.afterDelete.push(\n afterTenantDelete({\n enabledSlugs,\n tenantFieldName,\n tenantsCollectionSlug,\n usersSlug,\n usersTenantsArrayFieldName,\n usersTenantsArrayTenantFieldName,\n }),\n )\n}\n\nexport const afterTenantDelete =\n ({\n enabledSlugs,\n tenantFieldName,\n tenantsCollectionSlug,\n usersSlug,\n usersTenantsArrayFieldName,\n usersTenantsArrayTenantFieldName,\n }: Omit<Args, 'collection'>): CollectionAfterDeleteHook =>\n async ({ id, req }) => {\n const idType = getCollectionIDType({\n collectionSlug: tenantsCollectionSlug,\n payload: req.payload,\n })\n const currentTenantCookieID = getTenantFromCookie(req.headers, idType)\n if (currentTenantCookieID === id) {\n const newHeaders = new Headers({\n 'Set-Cookie': generateCookie<string>({\n name: 'payload-tenant',\n expires: new Date(Date.now() - 1000),\n path: '/',\n returnCookieAsObject: false,\n value: '',\n }),\n })\n\n req.responseHeaders = req.responseHeaders\n ? mergeHeaders(req.responseHeaders, newHeaders)\n : newHeaders\n }\n const cleanupPromises: Promise<JsonObject>[] = []\n enabledSlugs.forEach((slug) => {\n cleanupPromises.push(\n req.payload.delete({\n collection: slug,\n where: {\n [tenantFieldName]: {\n in: [id],\n },\n },\n }),\n )\n })\n\n try {\n const usersWithTenant = (await req.payload.find({\n collection: usersSlug,\n depth: 0,\n limit: 0,\n where: {\n [`${usersTenantsArrayFieldName}.${usersTenantsArrayTenantFieldName}`]: {\n in: [id],\n },\n },\n })) as PaginatedDocs<UserWithTenantsField>\n\n usersWithTenant?.docs?.forEach((user) => {\n cleanupPromises.push(\n req.payload.update({\n id: user.id,\n collection: usersSlug,\n data: {\n [usersTenantsArrayFieldName]: (user[usersTenantsArrayFieldName] || []).filter(\n (row: Record<string, string>) => {\n if (row[usersTenantsArrayTenantFieldName]) {\n return row[usersTenantsArrayTenantFieldName] !== id\n }\n },\n ),\n },\n }),\n )\n })\n } catch (e) {\n console.error('Error deleting tenants from users:', e)\n }\n\n await Promise.all(cleanupPromises)\n }\n"],"names":["generateCookie","mergeHeaders","getCollectionIDType","getTenantFromCookie","addTenantCleanup","collection","enabledSlugs","tenantFieldName","tenantsCollectionSlug","usersSlug","usersTenantsArrayFieldName","usersTenantsArrayTenantFieldName","hooks","afterDelete","push","afterTenantDelete","id","req","idType","collectionSlug","payload","currentTenantCookieID","headers","newHeaders","Headers","name","expires","Date","now","path","returnCookieAsObject","value","responseHeaders","cleanupPromises","forEach","slug","delete","where","in","usersWithTenant","find","depth","limit","docs","user","update","data","filter","row","e","console","error","Promise","all"],"mappings":"AAOA,SAASA,cAAc,EAAEC,YAAY,QAAQ,UAAS;AAItD,SAASC,mBAAmB,QAAQ,sCAAqC;AACzE,SAASC,mBAAmB,QAAQ,sCAAqC;AAWzE;;;;CAIC,GACD,OAAO,MAAMC,mBAAmB,CAAC,EAC/BC,UAAU,EACVC,YAAY,EACZC,eAAe,EACfC,qBAAqB,EACrBC,SAAS,EACTC,0BAA0B,EAC1BC,gCAAgC,EAC3B;IACL,IAAI,CAACN,WAAWO,KAAK,EAAE;QACrBP,WAAWO,KAAK,GAAG,CAAC;IACtB;IACA,IAAI,CAACP,WAAWO,KAAK,EAAEC,aAAa;QAClCR,WAAWO,KAAK,CAACC,WAAW,GAAG,EAAE;IACnC;IACAR,WAAWO,KAAK,CAACC,WAAW,CAACC,IAAI,CAC/BC,kBAAkB;QAChBT;QACAC;QACAC;QACAC;QACAC;QACAC;IACF;AAEJ,EAAC;AAED,OAAO,MAAMI,oBACX,CAAC,EACCT,YAAY,EACZC,eAAe,EACfC,qBAAqB,EACrBC,SAAS,EACTC,0BAA0B,EAC1BC,gCAAgC,EACP,GAC3B,OAAO,EAAEK,EAAE,EAAEC,GAAG,EAAE;QAChB,MAAMC,SAAShB,oBAAoB;YACjCiB,gBAAgBX;YAChBY,SAASH,IAAIG,OAAO;QACtB;QACA,MAAMC,wBAAwBlB,oBAAoBc,IAAIK,OAAO,EAAEJ;QAC/D,IAAIG,0BAA0BL,IAAI;YAChC,MAAMO,aAAa,IAAIC,QAAQ;gBAC7B,cAAcxB,eAAuB;oBACnCyB,MAAM;oBACNC,SAAS,IAAIC,KAAKA,KAAKC,GAAG,KAAK;oBAC/BC,MAAM;oBACNC,sBAAsB;oBACtBC,OAAO;gBACT;YACF;YAEAd,IAAIe,eAAe,GAAGf,IAAIe,eAAe,GACrC/B,aAAagB,IAAIe,eAAe,EAAET,cAClCA;QACN;QACA,MAAMU,kBAAyC,EAAE;QACjD3B,aAAa4B,OAAO,CAAC,CAACC;YACpBF,gBAAgBnB,IAAI,CAClBG,IAAIG,OAAO,CAACgB,MAAM,CAAC;gBACjB/B,YAAY8B;gBACZE,OAAO;oBACL,CAAC9B,gBAAgB,EAAE;wBACjB+B,IAAI;4BAACtB;yBAAG;oBACV;gBACF;YACF;QAEJ;QAEA,IAAI;YACF,MAAMuB,kBAAmB,MAAMtB,IAAIG,OAAO,CAACoB,IAAI,CAAC;gBAC9CnC,YAAYI;gBACZgC,OAAO;gBACPC,OAAO;gBACPL,OAAO;oBACL,CAAC,GAAG3B,2BAA2B,CAAC,EAAEC,kCAAkC,CAAC,EAAE;wBACrE2B,IAAI;4BAACtB;yBAAG;oBACV;gBACF;YACF;YAEAuB,iBAAiBI,MAAMT,QAAQ,CAACU;gBAC9BX,gBAAgBnB,IAAI,CAClBG,IAAIG,OAAO,CAACyB,MAAM,CAAC;oBACjB7B,IAAI4B,KAAK5B,EAAE;oBACXX,YAAYI;oBACZqC,MAAM;wBACJ,CAACpC,2BAA2B,EAAE,AAACkC,CAAAA,IAAI,CAAClC,2BAA2B,IAAI,EAAE,AAAD,EAAGqC,MAAM,CAC3E,CAACC;4BACC,IAAIA,GAAG,CAACrC,iCAAiC,EAAE;gCACzC,OAAOqC,GAAG,CAACrC,iCAAiC,KAAKK;4BACnD;wBACF;oBAEJ;gBACF;YAEJ;QACF,EAAE,OAAOiC,GAAG;YACVC,QAAQC,KAAK,CAAC,sCAAsCF;QACtD;QAEA,MAAMG,QAAQC,GAAG,CAACpB;IACpB,EAAC"}
1
+ {"version":3,"sources":["../../src/hooks/afterTenantDelete.ts"],"sourcesContent":["import type {\n CollectionAfterDeleteHook,\n CollectionConfig,\n JsonObject,\n PaginatedDocs,\n} from 'payload'\n\nimport { generateCookie, mergeHeaders } from 'payload'\n\nimport type { UserWithTenantsField } from '../types.js'\n\nimport { getCollectionIDType } from '../utilities/getCollectionIDType.js'\nimport { getTenantFromCookie } from '../utilities/getTenantFromCookie.js'\n\ntype Args = {\n collection: CollectionConfig\n enabledSlugs: string[]\n tenantFieldName: string\n tenantsCollectionSlug: string\n usersSlug: string\n usersTenantsArrayFieldName: string\n usersTenantsArrayTenantFieldName: string\n}\n/**\n * Add cleanup logic when tenant is deleted\n * - delete documents related to tenant\n * - remove tenant from users\n */\nexport const addTenantCleanup = ({\n collection,\n enabledSlugs,\n tenantFieldName,\n tenantsCollectionSlug,\n usersSlug,\n usersTenantsArrayFieldName,\n usersTenantsArrayTenantFieldName,\n}: Args) => {\n if (!collection.hooks) {\n collection.hooks = {}\n }\n if (!collection.hooks?.afterDelete) {\n collection.hooks.afterDelete = []\n }\n collection.hooks.afterDelete.push(\n afterTenantDelete({\n enabledSlugs,\n tenantFieldName,\n tenantsCollectionSlug,\n usersSlug,\n usersTenantsArrayFieldName,\n usersTenantsArrayTenantFieldName,\n }),\n )\n}\n\nexport const afterTenantDelete =\n ({\n enabledSlugs,\n tenantFieldName,\n tenantsCollectionSlug,\n usersSlug,\n usersTenantsArrayFieldName,\n usersTenantsArrayTenantFieldName,\n }: Omit<Args, 'collection'>): CollectionAfterDeleteHook =>\n async ({ id, req }) => {\n const idType = getCollectionIDType({\n collectionSlug: tenantsCollectionSlug,\n payload: req.payload,\n })\n const currentTenantCookieID = getTenantFromCookie(req.headers, idType)\n if (currentTenantCookieID === id) {\n const newHeaders = new Headers({\n 'Set-Cookie': generateCookie<string>({\n name: 'payload-tenant',\n expires: new Date(Date.now() - 1000),\n path: '/',\n returnCookieAsObject: false,\n value: '',\n }),\n })\n\n req.responseHeaders = req.responseHeaders\n ? mergeHeaders(req.responseHeaders, newHeaders)\n : newHeaders\n }\n const cleanupPromises: Promise<JsonObject>[] = []\n enabledSlugs.forEach((slug) => {\n cleanupPromises.push(\n req.payload.delete({\n collection: slug,\n overrideAccess: true,\n req,\n where: {\n [tenantFieldName]: {\n in: [id],\n },\n },\n }),\n )\n })\n\n try {\n const usersWithTenant = (await req.payload.find({\n collection: usersSlug,\n depth: 0,\n limit: 0,\n overrideAccess: true,\n req,\n where: {\n [`${usersTenantsArrayFieldName}.${usersTenantsArrayTenantFieldName}`]: {\n in: [id],\n },\n },\n })) as PaginatedDocs<UserWithTenantsField>\n\n usersWithTenant?.docs?.forEach((user) => {\n cleanupPromises.push(\n req.payload.update({\n id: user.id,\n collection: usersSlug,\n data: {\n [usersTenantsArrayFieldName]: (\n ((user as Record<string, unknown>)[usersTenantsArrayFieldName] as Record<\n string,\n string\n >[]) || []\n ).filter((row: Record<string, string>) => {\n if (row[usersTenantsArrayTenantFieldName]) {\n return row[usersTenantsArrayTenantFieldName] !== id\n }\n }),\n },\n overrideAccess: true,\n req,\n }),\n )\n })\n } catch (e) {\n console.error('Error deleting tenants from users:', e)\n }\n\n await Promise.all(cleanupPromises)\n }\n"],"names":["generateCookie","mergeHeaders","getCollectionIDType","getTenantFromCookie","addTenantCleanup","collection","enabledSlugs","tenantFieldName","tenantsCollectionSlug","usersSlug","usersTenantsArrayFieldName","usersTenantsArrayTenantFieldName","hooks","afterDelete","push","afterTenantDelete","id","req","idType","collectionSlug","payload","currentTenantCookieID","headers","newHeaders","Headers","name","expires","Date","now","path","returnCookieAsObject","value","responseHeaders","cleanupPromises","forEach","slug","delete","overrideAccess","where","in","usersWithTenant","find","depth","limit","docs","user","update","data","filter","row","e","console","error","Promise","all"],"mappings":"AAOA,SAASA,cAAc,EAAEC,YAAY,QAAQ,UAAS;AAItD,SAASC,mBAAmB,QAAQ,sCAAqC;AACzE,SAASC,mBAAmB,QAAQ,sCAAqC;AAWzE;;;;CAIC,GACD,OAAO,MAAMC,mBAAmB,CAAC,EAC/BC,UAAU,EACVC,YAAY,EACZC,eAAe,EACfC,qBAAqB,EACrBC,SAAS,EACTC,0BAA0B,EAC1BC,gCAAgC,EAC3B;IACL,IAAI,CAACN,WAAWO,KAAK,EAAE;QACrBP,WAAWO,KAAK,GAAG,CAAC;IACtB;IACA,IAAI,CAACP,WAAWO,KAAK,EAAEC,aAAa;QAClCR,WAAWO,KAAK,CAACC,WAAW,GAAG,EAAE;IACnC;IACAR,WAAWO,KAAK,CAACC,WAAW,CAACC,IAAI,CAC/BC,kBAAkB;QAChBT;QACAC;QACAC;QACAC;QACAC;QACAC;IACF;AAEJ,EAAC;AAED,OAAO,MAAMI,oBACX,CAAC,EACCT,YAAY,EACZC,eAAe,EACfC,qBAAqB,EACrBC,SAAS,EACTC,0BAA0B,EAC1BC,gCAAgC,EACP,GAC3B,OAAO,EAAEK,EAAE,EAAEC,GAAG,EAAE;QAChB,MAAMC,SAAShB,oBAAoB;YACjCiB,gBAAgBX;YAChBY,SAASH,IAAIG,OAAO;QACtB;QACA,MAAMC,wBAAwBlB,oBAAoBc,IAAIK,OAAO,EAAEJ;QAC/D,IAAIG,0BAA0BL,IAAI;YAChC,MAAMO,aAAa,IAAIC,QAAQ;gBAC7B,cAAcxB,eAAuB;oBACnCyB,MAAM;oBACNC,SAAS,IAAIC,KAAKA,KAAKC,GAAG,KAAK;oBAC/BC,MAAM;oBACNC,sBAAsB;oBACtBC,OAAO;gBACT;YACF;YAEAd,IAAIe,eAAe,GAAGf,IAAIe,eAAe,GACrC/B,aAAagB,IAAIe,eAAe,EAAET,cAClCA;QACN;QACA,MAAMU,kBAAyC,EAAE;QACjD3B,aAAa4B,OAAO,CAAC,CAACC;YACpBF,gBAAgBnB,IAAI,CAClBG,IAAIG,OAAO,CAACgB,MAAM,CAAC;gBACjB/B,YAAY8B;gBACZE,gBAAgB;gBAChBpB;gBACAqB,OAAO;oBACL,CAAC/B,gBAAgB,EAAE;wBACjBgC,IAAI;4BAACvB;yBAAG;oBACV;gBACF;YACF;QAEJ;QAEA,IAAI;YACF,MAAMwB,kBAAmB,MAAMvB,IAAIG,OAAO,CAACqB,IAAI,CAAC;gBAC9CpC,YAAYI;gBACZiC,OAAO;gBACPC,OAAO;gBACPN,gBAAgB;gBAChBpB;gBACAqB,OAAO;oBACL,CAAC,GAAG5B,2BAA2B,CAAC,EAAEC,kCAAkC,CAAC,EAAE;wBACrE4B,IAAI;4BAACvB;yBAAG;oBACV;gBACF;YACF;YAEAwB,iBAAiBI,MAAMV,QAAQ,CAACW;gBAC9BZ,gBAAgBnB,IAAI,CAClBG,IAAIG,OAAO,CAAC0B,MAAM,CAAC;oBACjB9B,IAAI6B,KAAK7B,EAAE;oBACXX,YAAYI;oBACZsC,MAAM;wBACJ,CAACrC,2BAA2B,EAAE,AAC5B,CAAA,AAAC,AAACmC,IAAgC,CAACnC,2BAA2B,IAGtD,EAAE,AAAD,EACTsC,MAAM,CAAC,CAACC;4BACR,IAAIA,GAAG,CAACtC,iCAAiC,EAAE;gCACzC,OAAOsC,GAAG,CAACtC,iCAAiC,KAAKK;4BACnD;wBACF;oBACF;oBACAqB,gBAAgB;oBAChBpB;gBACF;YAEJ;QACF,EAAE,OAAOiC,GAAG;YACVC,QAAQC,KAAK,CAAC,sCAAsCF;QACtD;QAEA,MAAMG,QAAQC,GAAG,CAACrB;IACpB,EAAC"}
@@ -0,0 +1,15 @@
1
+ import type { CollectionBeforeValidateHook, CollectionConfig } from 'payload';
2
+ import type { MultiTenantPluginConfig } from '../types.js';
3
+ type Args = {
4
+ collection: CollectionConfig;
5
+ tenantFieldName: string;
6
+ tenantsArrayFieldName: string;
7
+ tenantsArrayTenantFieldName: string;
8
+ userHasAccessToAllTenants: Required<MultiTenantPluginConfig>['userHasAccessToAllTenants'];
9
+ };
10
+ export declare const addCollectionBeforeValidateHook: ({ collection, tenantFieldName, tenantsArrayFieldName, tenantsArrayTenantFieldName, userHasAccessToAllTenants, }: Args) => void;
11
+ export declare const enforceTenantMembership: ({ collectionSlug, tenantFieldName, tenantsArrayFieldName, tenantsArrayTenantFieldName, userHasAccessToAllTenants, }: {
12
+ collectionSlug: string;
13
+ } & Omit<Args, 'collection'>) => CollectionBeforeValidateHook;
14
+ export {};
15
+ //# sourceMappingURL=enforceTenantMembership.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enforceTenantMembership.d.ts","sourceRoot":"","sources":["../../src/hooks/enforceTenantMembership.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,4BAA4B,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAI7E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAI1D,KAAK,IAAI,GAAG;IACV,UAAU,EAAE,gBAAgB,CAAA;IAC5B,eAAe,EAAE,MAAM,CAAA;IACvB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,2BAA2B,EAAE,MAAM,CAAA;IACnC,yBAAyB,EAAE,QAAQ,CAAC,uBAAuB,CAAC,CAAC,2BAA2B,CAAC,CAAA;CAC1F,CAAA;AAED,eAAO,MAAM,+BAA+B,oHAMzC,IAAI,SAYN,CAAA;AAED,eAAO,MAAM,uBAAuB,wHAO/B;IAAE,cAAc,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,KAAG,4BA0B1D,CAAA"}
@@ -0,0 +1,39 @@
1
+ import { ValidationError } from 'payload';
2
+ import { isValidTenantAssignment } from '../utilities/isValidTenantAssignment.js';
3
+ export const addCollectionBeforeValidateHook = ({ collection, tenantFieldName, tenantsArrayFieldName, tenantsArrayTenantFieldName, userHasAccessToAllTenants })=>{
4
+ collection.hooks ??= {};
5
+ collection.hooks.beforeValidate ??= [];
6
+ collection.hooks.beforeValidate.push(enforceTenantMembership({
7
+ collectionSlug: collection.slug,
8
+ tenantFieldName,
9
+ tenantsArrayFieldName,
10
+ tenantsArrayTenantFieldName,
11
+ userHasAccessToAllTenants
12
+ }));
13
+ };
14
+ export const enforceTenantMembership = ({ collectionSlug, tenantFieldName, tenantsArrayFieldName, tenantsArrayTenantFieldName, userHasAccessToAllTenants })=>({ data, originalDoc, req })=>{
15
+ if (!data || !(tenantFieldName in data)) {
16
+ return data;
17
+ }
18
+ if (!isValidTenantAssignment({
19
+ previousValue: originalDoc?.[tenantFieldName],
20
+ req,
21
+ tenantsArrayFieldName,
22
+ tenantsArrayTenantFieldName,
23
+ userHasAccessToAllTenants,
24
+ value: data[tenantFieldName]
25
+ })) {
26
+ throw new ValidationError({
27
+ collection: collectionSlug,
28
+ errors: [
29
+ {
30
+ message: req.t('validation:invalidSelection'),
31
+ path: tenantFieldName
32
+ }
33
+ ]
34
+ }, req.t);
35
+ }
36
+ return data;
37
+ };
38
+
39
+ //# sourceMappingURL=enforceTenantMembership.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/enforceTenantMembership.ts"],"sourcesContent":["import type { CollectionBeforeValidateHook, CollectionConfig } from 'payload'\n\nimport { ValidationError } from 'payload'\n\nimport type { MultiTenantPluginConfig } from '../types.js'\n\nimport { isValidTenantAssignment } from '../utilities/isValidTenantAssignment.js'\n\ntype Args = {\n collection: CollectionConfig\n tenantFieldName: string\n tenantsArrayFieldName: string\n tenantsArrayTenantFieldName: string\n userHasAccessToAllTenants: Required<MultiTenantPluginConfig>['userHasAccessToAllTenants']\n}\n\nexport const addCollectionBeforeValidateHook = ({\n collection,\n tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n}: Args) => {\n collection.hooks ??= {}\n collection.hooks.beforeValidate ??= []\n collection.hooks.beforeValidate.push(\n enforceTenantMembership({\n collectionSlug: collection.slug,\n tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n }),\n )\n}\n\nexport const enforceTenantMembership =\n ({\n collectionSlug,\n tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n }: { collectionSlug: string } & Omit<Args, 'collection'>): CollectionBeforeValidateHook =>\n ({ data, originalDoc, req }) => {\n if (!data || !(tenantFieldName in data)) {\n return data\n }\n\n if (\n !isValidTenantAssignment({\n previousValue: originalDoc?.[tenantFieldName],\n req,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n value: (data as Record<string, unknown>)[tenantFieldName],\n })\n ) {\n throw new ValidationError(\n {\n collection: collectionSlug,\n errors: [{ message: req.t('validation:invalidSelection'), path: tenantFieldName }],\n },\n req.t,\n )\n }\n\n return data\n }\n"],"names":["ValidationError","isValidTenantAssignment","addCollectionBeforeValidateHook","collection","tenantFieldName","tenantsArrayFieldName","tenantsArrayTenantFieldName","userHasAccessToAllTenants","hooks","beforeValidate","push","enforceTenantMembership","collectionSlug","slug","data","originalDoc","req","previousValue","value","errors","message","t","path"],"mappings":"AAEA,SAASA,eAAe,QAAQ,UAAS;AAIzC,SAASC,uBAAuB,QAAQ,0CAAyC;AAUjF,OAAO,MAAMC,kCAAkC,CAAC,EAC9CC,UAAU,EACVC,eAAe,EACfC,qBAAqB,EACrBC,2BAA2B,EAC3BC,yBAAyB,EACpB;IACLJ,WAAWK,KAAK,KAAK,CAAC;IACtBL,WAAWK,KAAK,CAACC,cAAc,KAAK,EAAE;IACtCN,WAAWK,KAAK,CAACC,cAAc,CAACC,IAAI,CAClCC,wBAAwB;QACtBC,gBAAgBT,WAAWU,IAAI;QAC/BT;QACAC;QACAC;QACAC;IACF;AAEJ,EAAC;AAED,OAAO,MAAMI,0BACX,CAAC,EACCC,cAAc,EACdR,eAAe,EACfC,qBAAqB,EACrBC,2BAA2B,EAC3BC,yBAAyB,EAC6B,GACxD,CAAC,EAAEO,IAAI,EAAEC,WAAW,EAAEC,GAAG,EAAE;QACzB,IAAI,CAACF,QAAQ,CAAEV,CAAAA,mBAAmBU,IAAG,GAAI;YACvC,OAAOA;QACT;QAEA,IACE,CAACb,wBAAwB;YACvBgB,eAAeF,aAAa,CAACX,gBAAgB;YAC7CY;YACAX;YACAC;YACAC;YACAW,OAAO,AAACJ,IAAgC,CAACV,gBAAgB;QAC3D,IACA;YACA,MAAM,IAAIJ,gBACR;gBACEG,YAAYS;gBACZO,QAAQ;oBAAC;wBAAEC,SAASJ,IAAIK,CAAC,CAAC;wBAAgCC,MAAMlB;oBAAgB;iBAAE;YACpF,GACAY,IAAIK,CAAC;QAET;QAEA,OAAOP;IACT,EAAC"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import type { Config } from 'payload';
2
1
  import type { MultiTenantPluginConfig } from './types.js';
3
- export declare const multiTenantPlugin: <ConfigType>(pluginConfig: MultiTenantPluginConfig<ConfigType>) => (incomingConfig: Config) => Config;
2
+ export declare const multiTenantPlugin: (options: MultiTenantPluginConfig) => import("payload").Plugin;
4
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAoB,MAAM,EAAE,MAAM,SAAS,CAAA;AAMvD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAA;AAczD,eAAO,MAAM,iBAAiB,GAC3B,UAAU,EAAE,cAAc,uBAAuB,CAAC,UAAU,CAAC,MAC7D,gBAAgB,MAAM,KAAG,MAsazB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAA;AAezD,eAAO,MAAM,iBAAiB,gEA6b5B,CAAA"}
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { definePlugin } from 'payload';
1
2
  import { hasAutosaveEnabled } from 'payload/shared';
2
3
  import { defaults } from './defaults.js';
3
4
  import { getTenantOptionsEndpoint } from './endpoints/getTenantOptionsEndpoint.js';
@@ -5,12 +6,15 @@ import { tenantField } from './fields/tenantField/index.js';
5
6
  import { tenantsArrayField } from './fields/tenantsArrayField/index.js';
6
7
  import { filterDocumentsByTenants } from './filters/filterDocumentsByTenants.js';
7
8
  import { addTenantCleanup } from './hooks/afterTenantDelete.js';
9
+ import { enforceTenantMembership } from './hooks/enforceTenantMembership.js';
8
10
  import { translations } from './translations/index.js';
9
11
  import { addCollectionAccess } from './utilities/addCollectionAccess.js';
10
12
  import { addFilterOptionsToFields } from './utilities/addFilterOptionsToFields.js';
11
13
  import { combineFilters } from './utilities/combineFilters.js';
12
14
  import { miniChalk } from './utilities/miniChalk.js';
13
- export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
15
+ export const multiTenantPlugin = definePlugin({
16
+ slug: '@payloadcms/plugin-multi-tenant',
17
+ plugin: ({ config: incomingConfig, options: pluginConfig })=>{
14
18
  if (pluginConfig.enabled === false) {
15
19
  return incomingConfig;
16
20
  }
@@ -21,6 +25,7 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
21
25
  const tenantFieldName = pluginConfig?.tenantField?.name || defaults.tenantFieldName;
22
26
  const tenantsArrayFieldName = pluginConfig?.tenantsArrayField?.arrayFieldName || defaults.tenantsArrayFieldName;
23
27
  const tenantsArrayTenantFieldName = pluginConfig?.tenantsArrayField?.arrayTenantFieldName || defaults.tenantsArrayTenantFieldName;
28
+ const tenantAccessScopes = [];
24
29
  /**
25
30
  * Add defaults for admin properties
26
31
  */ if (!incomingConfig.admin) {
@@ -62,12 +67,17 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
62
67
  */ if (pluginConfig?.tenantsArrayField?.includeDefaultField !== false) {
63
68
  adminUsersCollection.fields.push(tenantsArrayField({
64
69
  ...pluginConfig?.tenantsArrayField || {},
70
+ arrayFieldAccess: {
71
+ create: ({ req })=>Boolean(req.user && userHasAccessToAllTenants(req.user)),
72
+ update: ({ req })=>Boolean(req.user && userHasAccessToAllTenants(req.user)),
73
+ ...pluginConfig?.tenantsArrayField?.arrayFieldAccess || {}
74
+ },
65
75
  tenantsArrayFieldName,
66
76
  tenantsArrayTenantFieldName,
67
77
  tenantsCollectionSlug
68
78
  }));
69
79
  }
70
- addCollectionAccess({
80
+ tenantAccessScopes.push({
71
81
  accessResultCallback: pluginConfig.usersAccessResultOverride,
72
82
  adminUsersSlug: adminUsersCollection.slug,
73
83
  collection: adminUsersCollection,
@@ -123,7 +133,7 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
123
133
  /**
124
134
  * Add access control constraint to tenants collection
125
135
  * - constrains access a users assigned tenants
126
- */ addCollectionAccess({
136
+ */ tenantAccessScopes.push({
127
137
  adminUsersSlug: adminUsersCollection.slug,
128
138
  collection,
129
139
  fieldName: 'id',
@@ -236,15 +246,26 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
236
246
  * Add tenant field to enabled collections
237
247
  */ collection.fields.unshift(tenantField({
238
248
  name: tenantFieldName,
249
+ adminUsersSlug: adminUsersCollection.slug,
239
250
  debug: pluginConfig.debug,
240
251
  isAutosaveEnabled: hasAutosaveEnabled(collection),
241
252
  overrides: pluginConfig.collections[collection.slug]?.tenantFieldOverrides ? pluginConfig.collections[collection.slug]?.tenantFieldOverrides : pluginConfig.tenantField || {},
242
253
  tenantsArrayFieldName,
243
254
  tenantsArrayTenantFieldName,
244
255
  tenantsCollectionSlug,
245
- unique: isGlobal
256
+ unique: isGlobal,
257
+ userHasAccessToAllTenants
246
258
  }));
247
259
  }
260
+ collection.hooks ??= {};
261
+ collection.hooks.beforeValidate ??= [];
262
+ collection.hooks.beforeValidate.push(enforceTenantMembership({
263
+ collectionSlug: collection.slug,
264
+ tenantFieldName,
265
+ tenantsArrayFieldName,
266
+ tenantsArrayTenantFieldName,
267
+ userHasAccessToAllTenants
268
+ }));
248
269
  const { useBaseFilter, useBaseListFilter } = pluginConfig.collections[collection.slug] || {};
249
270
  if (useBaseFilter ?? useBaseListFilter ?? true) {
250
271
  /**
@@ -266,7 +287,7 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
266
287
  if (pluginConfig.collections[collection.slug]?.useTenantAccess !== false) {
267
288
  /**
268
289
  * Add access control constraint to tenant enabled collection
269
- */ addCollectionAccess({
290
+ */ tenantAccessScopes.push({
270
291
  accessResultCallback: pluginConfig.collections[collection.slug]?.accessResultOverride,
271
292
  adminUsersSlug: adminUsersCollection.slug,
272
293
  collection,
@@ -289,6 +310,10 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
289
310
  // eslint-disable-next-line no-console
290
311
  console.error(miniChalk.yellowBold('WARNING (plugin-multi-tenant)'), 'missing collections', missingSlugs, 'try placing the multi-tenant plugin after other plugins.');
291
312
  }
313
+ addCollectionAccess({
314
+ config: incomingConfig,
315
+ scopes: tenantAccessScopes
316
+ });
292
317
  /**
293
318
  * Add TenantSelectionProvider to admin providers
294
319
  */ incomingConfig.admin.components.providers.push({
@@ -355,6 +380,7 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
355
380
  };
356
381
  });
357
382
  return incomingConfig;
358
- };
383
+ }
384
+ });
359
385
 
360
386
  //# sourceMappingURL=index.js.map