@payloadcms/plugin-multi-tenant 3.53.0-internal.2dadf5b → 3.54.0-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/components/TenantField/index.client.d.ts.map +1 -1
  2. package/dist/components/TenantField/index.client.js +139 -55
  3. package/dist/components/TenantField/index.client.js.map +1 -1
  4. package/dist/components/TenantField/index.scss +47 -13
  5. package/dist/components/TenantSelector/index.client.d.ts +10 -0
  6. package/dist/components/TenantSelector/index.client.d.ts.map +1 -0
  7. package/dist/components/TenantSelector/index.client.js +85 -0
  8. package/dist/components/TenantSelector/index.client.js.map +1 -0
  9. package/dist/components/TenantSelector/index.d.ts +8 -7
  10. package/dist/components/TenantSelector/index.d.ts.map +1 -1
  11. package/dist/components/TenantSelector/index.js +9 -128
  12. package/dist/components/TenantSelector/index.js.map +1 -1
  13. package/dist/exports/client.d.ts +0 -1
  14. package/dist/exports/client.d.ts.map +1 -1
  15. package/dist/exports/client.js +0 -1
  16. package/dist/exports/client.js.map +1 -1
  17. package/dist/exports/rsc.d.ts +1 -0
  18. package/dist/exports/rsc.d.ts.map +1 -1
  19. package/dist/exports/rsc.js +1 -0
  20. package/dist/exports/rsc.js.map +1 -1
  21. package/dist/fields/tenantField/index.d.ts +3 -1
  22. package/dist/fields/tenantField/index.d.ts.map +1 -1
  23. package/dist/fields/tenantField/index.js +61 -30
  24. package/dist/fields/tenantField/index.js.map +1 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +78 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/providers/TenantSelectionProvider/index.client.d.ts.map +1 -1
  29. package/dist/providers/TenantSelectionProvider/index.client.js +83 -38
  30. package/dist/providers/TenantSelectionProvider/index.client.js.map +1 -1
  31. package/dist/translations/languages/zhTw.js +1 -1
  32. package/dist/translations/languages/zhTw.js.map +1 -1
  33. package/dist/utilities/addCollectionAccess.d.ts.map +1 -1
  34. package/dist/utilities/addCollectionAccess.js +0 -1
  35. package/dist/utilities/addCollectionAccess.js.map +1 -1
  36. package/dist/utilities/addFilterOptionsToFields.d.ts +3 -1
  37. package/dist/utilities/addFilterOptionsToFields.d.ts.map +1 -1
  38. package/dist/utilities/addFilterOptionsToFields.js +21 -35
  39. package/dist/utilities/addFilterOptionsToFields.js.map +1 -1
  40. package/dist/utilities/generateCookie.d.ts +26 -0
  41. package/dist/utilities/generateCookie.d.ts.map +1 -0
  42. package/dist/utilities/generateCookie.js +61 -0
  43. package/dist/utilities/generateCookie.js.map +1 -0
  44. package/dist/utilities/withTenantAccess.d.ts +1 -2
  45. package/dist/utilities/withTenantAccess.d.ts.map +1 -1
  46. package/dist/utilities/withTenantAccess.js.map +1 -1
  47. package/package.json +6 -6
@@ -3,6 +3,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { toast, useAuth, useConfig } from '@payloadcms/ui';
4
4
  import { useRouter } from 'next/navigation.js';
5
5
  import React, { createContext } from 'react';
6
+ import { generateCookie } from '../../utilities/generateCookie.js';
6
7
  const Context = /*#__PURE__*/ createContext({
7
8
  entityType: undefined,
8
9
  options: [],
@@ -13,12 +14,31 @@ const Context = /*#__PURE__*/ createContext({
13
14
  syncTenants: ()=>Promise.resolve(),
14
15
  updateTenants: ()=>null
15
16
  });
17
+ const setCookie = (value)=>{
18
+ document.cookie = generateCookie({
19
+ name: 'payload-tenant',
20
+ maxAge: 60 * 60 * 24 * 365,
21
+ path: '/',
22
+ returnCookieAsObject: false,
23
+ value: value || ''
24
+ });
25
+ };
26
+ const deleteCookie = ()=>{
27
+ document.cookie = generateCookie({
28
+ name: 'payload-tenant',
29
+ maxAge: -1,
30
+ path: '/',
31
+ returnCookieAsObject: false,
32
+ value: ''
33
+ });
34
+ };
16
35
  export const TenantSelectionProviderClient = ({ children, initialTenantOptions, initialValue, tenantsCollectionSlug })=>{
17
36
  const [selectedTenantID, setSelectedTenantID] = React.useState(initialValue);
18
37
  const [modified, setModified] = React.useState(false);
19
38
  const [entityType, setEntityType] = React.useState(undefined);
20
39
  const { user } = useAuth();
21
40
  const { config } = useConfig();
41
+ const router = useRouter();
22
42
  const userID = React.useMemo(()=>user?.id, [
23
43
  user?.id
24
44
  ]);
@@ -29,53 +49,50 @@ export const TenantSelectionProviderClient = ({ children, initialTenantOptions,
29
49
  selectedTenantID,
30
50
  tenantOptions
31
51
  ]);
32
- const router = useRouter();
33
- const setCookie = React.useCallback((value)=>{
34
- const expires = '; expires=Fri, 31 Dec 9999 23:59:59 GMT';
35
- document.cookie = 'payload-tenant=' + (value || '') + expires + '; path=/';
36
- }, []);
37
- const deleteCookie = React.useCallback(()=>{
38
- // eslint-disable-next-line react-compiler/react-compiler -- TODO: fix
39
- document.cookie = 'payload-tenant=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/';
40
- }, []);
52
+ const setTenantAndCookie = React.useCallback(({ id, refresh })=>{
53
+ setSelectedTenantID(id);
54
+ if (id !== undefined) {
55
+ setCookie(String(id));
56
+ } else {
57
+ deleteCookie();
58
+ }
59
+ if (refresh) {
60
+ router.refresh();
61
+ }
62
+ }, [
63
+ router
64
+ ]);
41
65
  const setTenant = React.useCallback(({ id, refresh })=>{
42
66
  if (id === undefined) {
43
- if (tenantOptions.length > 1) {
67
+ if (tenantOptions.length > 1 || tenantOptions.length === 0) {
44
68
  // users with multiple tenants can clear the tenant selection
45
- setSelectedTenantID(undefined);
46
- deleteCookie();
47
- } else if (tenantOptions[0]) {
48
- // if there is only one tenant, force the selection of that tenant
49
- setSelectedTenantID(tenantOptions[0].value);
50
- setCookie(String(tenantOptions[0].value));
51
- }
52
- } else if (!tenantOptions.find((option)=>option.value === id)) {
53
- // if the tenant is not valid, set the first tenant as selected
54
- if (tenantOptions[0]?.value) {
55
- setTenant({
56
- id: tenantOptions[0]?.value,
57
- refresh: true
58
- });
59
- } else {
60
- setTenant({
69
+ setTenantAndCookie({
61
70
  id: undefined,
71
+ refresh
72
+ });
73
+ } else if (tenantOptions[0]) {
74
+ // if there is only one tenant, auto-select that tenant
75
+ setTenantAndCookie({
76
+ id: tenantOptions[0].value,
62
77
  refresh: true
63
78
  });
64
79
  }
80
+ } else if (!tenantOptions.find((option)=>option.value === id)) {
81
+ // if the tenant is invalid, set the first tenant as selected
82
+ setTenantAndCookie({
83
+ id: tenantOptions[0]?.value,
84
+ refresh
85
+ });
65
86
  } else {
66
87
  // if the tenant is in the options, set it as selected
67
- setSelectedTenantID(id);
68
- setCookie(String(id));
69
- }
70
- if (entityType !== 'document' && refresh) {
71
- router.refresh();
88
+ setTenantAndCookie({
89
+ id,
90
+ refresh
91
+ });
72
92
  }
73
93
  }, [
74
- deleteCookie,
75
- entityType,
76
- router,
77
- setCookie,
78
- tenantOptions
94
+ tenantOptions,
95
+ setTenantAndCookie
79
96
  ]);
80
97
  const syncTenants = React.useCallback(async ()=>{
81
98
  try {
@@ -98,7 +115,6 @@ export const TenantSelectionProviderClient = ({ children, initialTenantOptions,
98
115
  config.serverURL,
99
116
  config.routes.api,
100
117
  tenantsCollectionSlug,
101
- setCookie,
102
118
  userID
103
119
  ]);
104
120
  const updateTenants = React.useCallback(({ id, label })=>{
@@ -136,9 +152,38 @@ export const TenantSelectionProviderClient = ({ children, initialTenantOptions,
136
152
  userID,
137
153
  userChanged,
138
154
  syncTenants,
139
- deleteCookie,
140
155
  tenantOptions
141
156
  ]);
157
+ /**
158
+ * If there is no initial value, clear the tenant and refresh the router.
159
+ * Needed for stale tenantIDs set as a cookie.
160
+ */ React.useEffect(()=>{
161
+ if (!initialValue) {
162
+ setTenant({
163
+ id: undefined,
164
+ refresh: true
165
+ });
166
+ }
167
+ }, [
168
+ initialValue,
169
+ setTenant
170
+ ]);
171
+ /**
172
+ * If there is no selected tenant ID and the entity type is 'global', set the first tenant as selected.
173
+ * This ensures that the global tenant is always set when the component mounts.
174
+ */ React.useEffect(()=>{
175
+ if (!selectedTenantID && tenantOptions.length > 0 && entityType === 'global') {
176
+ setTenant({
177
+ id: tenantOptions[0]?.value,
178
+ refresh: true
179
+ });
180
+ }
181
+ }, [
182
+ selectedTenantID,
183
+ tenantOptions,
184
+ entityType,
185
+ setTenant
186
+ ]);
142
187
  return /*#__PURE__*/ _jsx("span", {
143
188
  "data-selected-tenant-id": selectedTenantID,
144
189
  "data-selected-tenant-title": selectedTenantLabel,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/providers/TenantSelectionProvider/index.client.tsx"],"sourcesContent":["'use client'\n\nimport type { OptionObject } from 'payload'\n\nimport { toast, useAuth, useConfig } from '@payloadcms/ui'\nimport { useRouter } from 'next/navigation.js'\nimport React, { createContext } from 'react'\n\ntype ContextType = {\n /**\n * What is the context of the selector? It is either 'document' | 'global' | undefined.\n *\n * - 'document' means you are viewing a document in the context of a tenant\n * - 'global' means you are viewing a \"global\" (globals are collection documents but prevent you from viewing the list view) document in the context of a tenant\n * - undefined means you are not viewing a document at all\n */\n entityType?: 'document' | 'global'\n /**\n * Hoists the forms modified state\n */\n modified?: boolean\n /**\n * Array of options to select from\n */\n options: OptionObject[]\n /**\n * The currently selected tenant ID\n */\n selectedTenantID: number | string | undefined\n /**\n * Sets the entityType when a document is loaded and sets it to undefined when the document unmounts.\n */\n setEntityType: React.Dispatch<React.SetStateAction<'document' | 'global' | undefined>>\n /**\n * Sets the modified state\n */\n setModified: React.Dispatch<React.SetStateAction<boolean>>\n /**\n * Sets the selected tenant ID\n *\n * @param args.id - The ID of the tenant to select\n * @param args.refresh - Whether to refresh the page after changing the tenant\n */\n setTenant: (args: { id: number | string | undefined; refresh?: boolean }) => void\n /**\n * Used to sync tenants displayed in the tenant selector when updates are made to the tenants collection.\n */\n syncTenants: () => Promise<void>\n /**\n *\n */\n updateTenants: (args: { id: number | string; label: string }) => void\n}\n\nconst Context = createContext<ContextType>({\n entityType: undefined,\n options: [],\n selectedTenantID: undefined,\n setEntityType: () => undefined,\n setModified: () => undefined,\n setTenant: () => null,\n syncTenants: () => Promise.resolve(),\n updateTenants: () => null,\n})\n\nexport const TenantSelectionProviderClient = ({\n children,\n initialTenantOptions,\n initialValue,\n tenantsCollectionSlug,\n}: {\n children: React.ReactNode\n initialTenantOptions: OptionObject[]\n initialValue?: number | string\n tenantsCollectionSlug: string\n}) => {\n const [selectedTenantID, setSelectedTenantID] = React.useState<number | string | undefined>(\n initialValue,\n )\n const [modified, setModified] = React.useState<boolean>(false)\n const [entityType, setEntityType] = React.useState<'document' | 'global' | undefined>(undefined)\n const { user } = useAuth()\n const { config } = useConfig()\n const userID = React.useMemo(() => user?.id, [user?.id])\n const prevUserID = React.useRef(userID)\n const userChanged = userID !== prevUserID.current\n const [tenantOptions, setTenantOptions] = React.useState<OptionObject[]>(\n () => initialTenantOptions,\n )\n const selectedTenantLabel = React.useMemo(\n () => tenantOptions.find((option) => option.value === selectedTenantID)?.label,\n [selectedTenantID, tenantOptions],\n )\n\n const router = useRouter()\n\n const setCookie = React.useCallback((value?: string) => {\n const expires = '; expires=Fri, 31 Dec 9999 23:59:59 GMT'\n document.cookie = 'payload-tenant=' + (value || '') + expires + '; path=/'\n }, [])\n\n const deleteCookie = React.useCallback(() => {\n // eslint-disable-next-line react-compiler/react-compiler -- TODO: fix\n document.cookie = 'payload-tenant=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/'\n }, [])\n\n const setTenant = React.useCallback<ContextType['setTenant']>(\n ({ id, refresh }) => {\n if (id === undefined) {\n if (tenantOptions.length > 1) {\n // users with multiple tenants can clear the tenant selection\n setSelectedTenantID(undefined)\n deleteCookie()\n } else if (tenantOptions[0]) {\n // if there is only one tenant, force the selection of that tenant\n setSelectedTenantID(tenantOptions[0].value)\n setCookie(String(tenantOptions[0].value))\n }\n } else if (!tenantOptions.find((option) => option.value === id)) {\n // if the tenant is not valid, set the first tenant as selected\n if (tenantOptions[0]?.value) {\n setTenant({ id: tenantOptions[0]?.value, refresh: true })\n } else {\n setTenant({ id: undefined, refresh: true })\n }\n } else {\n // if the tenant is in the options, set it as selected\n setSelectedTenantID(id)\n setCookie(String(id))\n }\n if (entityType !== 'document' && refresh) {\n router.refresh()\n }\n },\n [deleteCookie, entityType, router, setCookie, tenantOptions],\n )\n\n const syncTenants = React.useCallback(async () => {\n try {\n const req = await fetch(\n `${config.serverURL}${config.routes.api}/${tenantsCollectionSlug}/populate-tenant-options`,\n {\n credentials: 'include',\n method: 'GET',\n },\n )\n\n const result = await req.json()\n\n if (result.tenantOptions && userID) {\n setTenantOptions(result.tenantOptions)\n\n if (result.tenantOptions.length === 1) {\n setSelectedTenantID(result.tenantOptions[0].value)\n setCookie(String(result.tenantOptions[0].value))\n }\n }\n } catch (e) {\n toast.error(`Error fetching tenants`)\n }\n }, [config.serverURL, config.routes.api, tenantsCollectionSlug, setCookie, userID])\n\n const updateTenants = React.useCallback<ContextType['updateTenants']>(\n ({ id, label }) => {\n setTenantOptions((prev) => {\n return prev.map((currentTenant) => {\n if (id === currentTenant.value) {\n return {\n label,\n value: id,\n }\n }\n return currentTenant\n })\n })\n\n void syncTenants()\n },\n [syncTenants],\n )\n\n React.useEffect(() => {\n if (userChanged) {\n if (userID) {\n // user logging in\n void syncTenants()\n } else {\n // user logging out\n setSelectedTenantID(undefined)\n deleteCookie()\n if (tenantOptions.length > 0) {\n setTenantOptions([])\n }\n }\n prevUserID.current = userID\n }\n }, [userID, userChanged, syncTenants, deleteCookie, tenantOptions])\n\n return (\n <span\n data-selected-tenant-id={selectedTenantID}\n data-selected-tenant-title={selectedTenantLabel}\n >\n <Context\n value={{\n entityType,\n modified,\n options: tenantOptions,\n selectedTenantID,\n setEntityType,\n setModified,\n setTenant,\n syncTenants,\n updateTenants,\n }}\n >\n {children}\n </Context>\n </span>\n )\n}\n\nexport const useTenantSelection = () => React.use(Context)\n"],"names":["toast","useAuth","useConfig","useRouter","React","createContext","Context","entityType","undefined","options","selectedTenantID","setEntityType","setModified","setTenant","syncTenants","Promise","resolve","updateTenants","TenantSelectionProviderClient","children","initialTenantOptions","initialValue","tenantsCollectionSlug","setSelectedTenantID","useState","modified","user","config","userID","useMemo","id","prevUserID","useRef","userChanged","current","tenantOptions","setTenantOptions","selectedTenantLabel","find","option","value","label","router","setCookie","useCallback","expires","document","cookie","deleteCookie","refresh","length","String","req","fetch","serverURL","routes","api","credentials","method","result","json","e","error","prev","map","currentTenant","useEffect","span","data-selected-tenant-id","data-selected-tenant-title","useTenantSelection","use"],"mappings":"AAAA;;AAIA,SAASA,KAAK,EAAEC,OAAO,EAAEC,SAAS,QAAQ,iBAAgB;AAC1D,SAASC,SAAS,QAAQ,qBAAoB;AAC9C,OAAOC,SAASC,aAAa,QAAQ,QAAO;AAgD5C,MAAMC,wBAAUD,cAA2B;IACzCE,YAAYC;IACZC,SAAS,EAAE;IACXC,kBAAkBF;IAClBG,eAAe,IAAMH;IACrBI,aAAa,IAAMJ;IACnBK,WAAW,IAAM;IACjBC,aAAa,IAAMC,QAAQC,OAAO;IAClCC,eAAe,IAAM;AACvB;AAEA,OAAO,MAAMC,gCAAgC,CAAC,EAC5CC,QAAQ,EACRC,oBAAoB,EACpBC,YAAY,EACZC,qBAAqB,EAMtB;IACC,MAAM,CAACZ,kBAAkBa,oBAAoB,GAAGnB,MAAMoB,QAAQ,CAC5DH;IAEF,MAAM,CAACI,UAAUb,YAAY,GAAGR,MAAMoB,QAAQ,CAAU;IACxD,MAAM,CAACjB,YAAYI,cAAc,GAAGP,MAAMoB,QAAQ,CAAoChB;IACtF,MAAM,EAAEkB,IAAI,EAAE,GAAGzB;IACjB,MAAM,EAAE0B,MAAM,EAAE,GAAGzB;IACnB,MAAM0B,SAASxB,MAAMyB,OAAO,CAAC,IAAMH,MAAMI,IAAI;QAACJ,MAAMI;KAAG;IACvD,MAAMC,aAAa3B,MAAM4B,MAAM,CAACJ;IAChC,MAAMK,cAAcL,WAAWG,WAAWG,OAAO;IACjD,MAAM,CAACC,eAAeC,iBAAiB,GAAGhC,MAAMoB,QAAQ,CACtD,IAAMJ;IAER,MAAMiB,sBAAsBjC,MAAMyB,OAAO,CACvC,IAAMM,cAAcG,IAAI,CAAC,CAACC,SAAWA,OAAOC,KAAK,KAAK9B,mBAAmB+B,OACzE;QAAC/B;QAAkByB;KAAc;IAGnC,MAAMO,SAASvC;IAEf,MAAMwC,YAAYvC,MAAMwC,WAAW,CAAC,CAACJ;QACnC,MAAMK,UAAU;QAChBC,SAASC,MAAM,GAAG,oBAAqBP,CAAAA,SAAS,EAAC,IAAKK,UAAU;IAClE,GAAG,EAAE;IAEL,MAAMG,eAAe5C,MAAMwC,WAAW,CAAC;QACrC,sEAAsE;QACtEE,SAASC,MAAM,GAAG;IACpB,GAAG,EAAE;IAEL,MAAMlC,YAAYT,MAAMwC,WAAW,CACjC,CAAC,EAAEd,EAAE,EAAEmB,OAAO,EAAE;QACd,IAAInB,OAAOtB,WAAW;YACpB,IAAI2B,cAAce,MAAM,GAAG,GAAG;gBAC5B,6DAA6D;gBAC7D3B,oBAAoBf;gBACpBwC;YACF,OAAO,IAAIb,aAAa,CAAC,EAAE,EAAE;gBAC3B,kEAAkE;gBAClEZ,oBAAoBY,aAAa,CAAC,EAAE,CAACK,KAAK;gBAC1CG,UAAUQ,OAAOhB,aAAa,CAAC,EAAE,CAACK,KAAK;YACzC;QACF,OAAO,IAAI,CAACL,cAAcG,IAAI,CAAC,CAACC,SAAWA,OAAOC,KAAK,KAAKV,KAAK;YAC/D,+DAA+D;YAC/D,IAAIK,aAAa,CAAC,EAAE,EAAEK,OAAO;gBAC3B3B,UAAU;oBAAEiB,IAAIK,aAAa,CAAC,EAAE,EAAEK;oBAAOS,SAAS;gBAAK;YACzD,OAAO;gBACLpC,UAAU;oBAAEiB,IAAItB;oBAAWyC,SAAS;gBAAK;YAC3C;QACF,OAAO;YACL,sDAAsD;YACtD1B,oBAAoBO;YACpBa,UAAUQ,OAAOrB;QACnB;QACA,IAAIvB,eAAe,cAAc0C,SAAS;YACxCP,OAAOO,OAAO;QAChB;IACF,GACA;QAACD;QAAczC;QAAYmC;QAAQC;QAAWR;KAAc;IAG9D,MAAMrB,cAAcV,MAAMwC,WAAW,CAAC;QACpC,IAAI;YACF,MAAMQ,MAAM,MAAMC,MAChB,GAAG1B,OAAO2B,SAAS,GAAG3B,OAAO4B,MAAM,CAACC,GAAG,CAAC,CAAC,EAAElC,sBAAsB,wBAAwB,CAAC,EAC1F;gBACEmC,aAAa;gBACbC,QAAQ;YACV;YAGF,MAAMC,SAAS,MAAMP,IAAIQ,IAAI;YAE7B,IAAID,OAAOxB,aAAa,IAAIP,QAAQ;gBAClCQ,iBAAiBuB,OAAOxB,aAAa;gBAErC,IAAIwB,OAAOxB,aAAa,CAACe,MAAM,KAAK,GAAG;oBACrC3B,oBAAoBoC,OAAOxB,aAAa,CAAC,EAAE,CAACK,KAAK;oBACjDG,UAAUQ,OAAOQ,OAAOxB,aAAa,CAAC,EAAE,CAACK,KAAK;gBAChD;YACF;QACF,EAAE,OAAOqB,GAAG;YACV7D,MAAM8D,KAAK,CAAC,CAAC,sBAAsB,CAAC;QACtC;IACF,GAAG;QAACnC,OAAO2B,SAAS;QAAE3B,OAAO4B,MAAM,CAACC,GAAG;QAAElC;QAAuBqB;QAAWf;KAAO;IAElF,MAAMX,gBAAgBb,MAAMwC,WAAW,CACrC,CAAC,EAAEd,EAAE,EAAEW,KAAK,EAAE;QACZL,iBAAiB,CAAC2B;YAChB,OAAOA,KAAKC,GAAG,CAAC,CAACC;gBACf,IAAInC,OAAOmC,cAAczB,KAAK,EAAE;oBAC9B,OAAO;wBACLC;wBACAD,OAAOV;oBACT;gBACF;gBACA,OAAOmC;YACT;QACF;QAEA,KAAKnD;IACP,GACA;QAACA;KAAY;IAGfV,MAAM8D,SAAS,CAAC;QACd,IAAIjC,aAAa;YACf,IAAIL,QAAQ;gBACV,kBAAkB;gBAClB,KAAKd;YACP,OAAO;gBACL,mBAAmB;gBACnBS,oBAAoBf;gBACpBwC;gBACA,IAAIb,cAAce,MAAM,GAAG,GAAG;oBAC5Bd,iBAAiB,EAAE;gBACrB;YACF;YACAL,WAAWG,OAAO,GAAGN;QACvB;IACF,GAAG;QAACA;QAAQK;QAAanB;QAAakC;QAAcb;KAAc;IAElE,qBACE,KAACgC;QACCC,2BAAyB1D;QACzB2D,8BAA4BhC;kBAE5B,cAAA,KAAC/B;YACCkC,OAAO;gBACLjC;gBACAkB;gBACAhB,SAAS0B;gBACTzB;gBACAC;gBACAC;gBACAC;gBACAC;gBACAG;YACF;sBAECE;;;AAIT,EAAC;AAED,OAAO,MAAMmD,qBAAqB,IAAMlE,MAAMmE,GAAG,CAACjE,SAAQ"}
1
+ {"version":3,"sources":["../../../src/providers/TenantSelectionProvider/index.client.tsx"],"sourcesContent":["'use client'\n\nimport type { OptionObject } from 'payload'\n\nimport { toast, useAuth, useConfig } from '@payloadcms/ui'\nimport { useRouter } from 'next/navigation.js'\nimport React, { createContext } from 'react'\n\nimport { generateCookie } from '../../utilities/generateCookie.js'\n\ntype ContextType = {\n /**\n * What is the context of the selector? It is either 'document' | 'global' | undefined.\n *\n * - 'document' means you are viewing a document in the context of a tenant\n * - 'global' means you are viewing a \"global\" (globals are collection documents but prevent you from viewing the list view) document in the context of a tenant\n * - undefined means you are not viewing a document at all\n */\n entityType?: 'document' | 'global'\n /**\n * Hoists the forms modified state\n */\n modified?: boolean\n /**\n * Array of options to select from\n */\n options: OptionObject[]\n /**\n * The currently selected tenant ID\n */\n selectedTenantID: number | string | undefined\n /**\n * Sets the entityType when a document is loaded and sets it to undefined when the document unmounts.\n */\n setEntityType: React.Dispatch<React.SetStateAction<'document' | 'global' | undefined>>\n /**\n * Sets the modified state\n */\n setModified: React.Dispatch<React.SetStateAction<boolean>>\n /**\n * Sets the selected tenant ID\n *\n * @param args.id - The ID of the tenant to select\n * @param args.refresh - Whether to refresh the page after changing the tenant\n */\n setTenant: (args: { id: number | string | undefined; refresh?: boolean }) => void\n /**\n * Used to sync tenants displayed in the tenant selector when updates are made to the tenants collection.\n */\n syncTenants: () => Promise<void>\n /**\n *\n */\n updateTenants: (args: { id: number | string; label: string }) => void\n}\n\nconst Context = createContext<ContextType>({\n entityType: undefined,\n options: [],\n selectedTenantID: undefined,\n setEntityType: () => undefined,\n setModified: () => undefined,\n setTenant: () => null,\n syncTenants: () => Promise.resolve(),\n updateTenants: () => null,\n})\n\nconst setCookie = (value?: string) => {\n document.cookie = generateCookie<string>({\n name: 'payload-tenant',\n maxAge: 60 * 60 * 24 * 365, // 1 year in seconds\n path: '/',\n returnCookieAsObject: false,\n value: value || '',\n })\n}\n\nconst deleteCookie = () => {\n document.cookie = generateCookie<string>({\n name: 'payload-tenant',\n maxAge: -1,\n path: '/',\n returnCookieAsObject: false,\n value: '',\n })\n}\n\nexport const TenantSelectionProviderClient = ({\n children,\n initialTenantOptions,\n initialValue,\n tenantsCollectionSlug,\n}: {\n children: React.ReactNode\n initialTenantOptions: OptionObject[]\n initialValue?: number | string\n tenantsCollectionSlug: string\n}) => {\n const [selectedTenantID, setSelectedTenantID] = React.useState<number | string | undefined>(\n initialValue,\n )\n const [modified, setModified] = React.useState<boolean>(false)\n const [entityType, setEntityType] = React.useState<'document' | 'global' | undefined>(undefined)\n const { user } = useAuth()\n const { config } = useConfig()\n const router = useRouter()\n const userID = React.useMemo(() => user?.id, [user?.id])\n const prevUserID = React.useRef(userID)\n const userChanged = userID !== prevUserID.current\n const [tenantOptions, setTenantOptions] = React.useState<OptionObject[]>(\n () => initialTenantOptions,\n )\n const selectedTenantLabel = React.useMemo(\n () => tenantOptions.find((option) => option.value === selectedTenantID)?.label,\n [selectedTenantID, tenantOptions],\n )\n\n const setTenantAndCookie = React.useCallback(\n ({ id, refresh }: { id: number | string | undefined; refresh?: boolean }) => {\n setSelectedTenantID(id)\n if (id !== undefined) {\n setCookie(String(id))\n } else {\n deleteCookie()\n }\n if (refresh) {\n router.refresh()\n }\n },\n [router],\n )\n\n const setTenant = React.useCallback<ContextType['setTenant']>(\n ({ id, refresh }) => {\n if (id === undefined) {\n if (tenantOptions.length > 1 || tenantOptions.length === 0) {\n // users with multiple tenants can clear the tenant selection\n setTenantAndCookie({ id: undefined, refresh })\n } else if (tenantOptions[0]) {\n // if there is only one tenant, auto-select that tenant\n setTenantAndCookie({ id: tenantOptions[0].value, refresh: true })\n }\n } else if (!tenantOptions.find((option) => option.value === id)) {\n // if the tenant is invalid, set the first tenant as selected\n setTenantAndCookie({\n id: tenantOptions[0]?.value,\n refresh,\n })\n } else {\n // if the tenant is in the options, set it as selected\n setTenantAndCookie({ id, refresh })\n }\n },\n [tenantOptions, setTenantAndCookie],\n )\n\n const syncTenants = React.useCallback(async () => {\n try {\n const req = await fetch(\n `${config.serverURL}${config.routes.api}/${tenantsCollectionSlug}/populate-tenant-options`,\n {\n credentials: 'include',\n method: 'GET',\n },\n )\n\n const result = await req.json()\n\n if (result.tenantOptions && userID) {\n setTenantOptions(result.tenantOptions)\n\n if (result.tenantOptions.length === 1) {\n setSelectedTenantID(result.tenantOptions[0].value)\n setCookie(String(result.tenantOptions[0].value))\n }\n }\n } catch (e) {\n toast.error(`Error fetching tenants`)\n }\n }, [config.serverURL, config.routes.api, tenantsCollectionSlug, userID])\n\n const updateTenants = React.useCallback<ContextType['updateTenants']>(\n ({ id, label }) => {\n setTenantOptions((prev) => {\n return prev.map((currentTenant) => {\n if (id === currentTenant.value) {\n return {\n label,\n value: id,\n }\n }\n return currentTenant\n })\n })\n\n void syncTenants()\n },\n [syncTenants],\n )\n\n React.useEffect(() => {\n if (userChanged) {\n if (userID) {\n // user logging in\n void syncTenants()\n } else {\n // user logging out\n setSelectedTenantID(undefined)\n deleteCookie()\n if (tenantOptions.length > 0) {\n setTenantOptions([])\n }\n }\n prevUserID.current = userID\n }\n }, [userID, userChanged, syncTenants, tenantOptions])\n\n /**\n * If there is no initial value, clear the tenant and refresh the router.\n * Needed for stale tenantIDs set as a cookie.\n */\n React.useEffect(() => {\n if (!initialValue) {\n setTenant({ id: undefined, refresh: true })\n }\n }, [initialValue, setTenant])\n\n /**\n * If there is no selected tenant ID and the entity type is 'global', set the first tenant as selected.\n * This ensures that the global tenant is always set when the component mounts.\n */\n React.useEffect(() => {\n if (!selectedTenantID && tenantOptions.length > 0 && entityType === 'global') {\n setTenant({\n id: tenantOptions[0]?.value,\n refresh: true,\n })\n }\n }, [selectedTenantID, tenantOptions, entityType, setTenant])\n\n return (\n <span\n data-selected-tenant-id={selectedTenantID}\n data-selected-tenant-title={selectedTenantLabel}\n >\n <Context\n value={{\n entityType,\n modified,\n options: tenantOptions,\n selectedTenantID,\n setEntityType,\n setModified,\n setTenant,\n syncTenants,\n updateTenants,\n }}\n >\n {children}\n </Context>\n </span>\n )\n}\n\nexport const useTenantSelection = () => React.use(Context)\n"],"names":["toast","useAuth","useConfig","useRouter","React","createContext","generateCookie","Context","entityType","undefined","options","selectedTenantID","setEntityType","setModified","setTenant","syncTenants","Promise","resolve","updateTenants","setCookie","value","document","cookie","name","maxAge","path","returnCookieAsObject","deleteCookie","TenantSelectionProviderClient","children","initialTenantOptions","initialValue","tenantsCollectionSlug","setSelectedTenantID","useState","modified","user","config","router","userID","useMemo","id","prevUserID","useRef","userChanged","current","tenantOptions","setTenantOptions","selectedTenantLabel","find","option","label","setTenantAndCookie","useCallback","refresh","String","length","req","fetch","serverURL","routes","api","credentials","method","result","json","e","error","prev","map","currentTenant","useEffect","span","data-selected-tenant-id","data-selected-tenant-title","useTenantSelection","use"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  export const zhTwTranslations = {
2
2
  'plugin-multi-tenant': {
3
- 'confirm-modal-tenant-switch--body': '您即將從<0>{{fromTenant}}</0>變更所有權至<0>{{toTenant}}</0>',
3
+ 'confirm-modal-tenant-switch--body': '您即將變更擁有者,從 <0>{{fromTenant}}</0> 切換為 <0>{{toTenant}}</0>',
4
4
  'confirm-modal-tenant-switch--heading': '確認變更 {{tenantLabel}}',
5
5
  'field-assignedTenant-label': '指派的租用戶',
6
6
  'nav-tenantSelector-label': '租戶'
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/translations/languages/zhTw.ts"],"sourcesContent":["import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.js'\n\nexport const zhTwTranslations: PluginDefaultTranslationsObject = {\n 'plugin-multi-tenant': {\n 'confirm-modal-tenant-switch--body':\n '您即將從<0>{{fromTenant}}</0>變更所有權至<0>{{toTenant}}</0>',\n 'confirm-modal-tenant-switch--heading': '確認變更 {{tenantLabel}}',\n 'field-assignedTenant-label': '指派的租用戶',\n 'nav-tenantSelector-label': '租戶',\n },\n}\n\nexport const zhTw: PluginLanguage = {\n dateFNSKey: 'zh-TW',\n translations: zhTwTranslations,\n}\n"],"names":["zhTwTranslations","zhTw","dateFNSKey","translations"],"mappings":"AAEA,OAAO,MAAMA,mBAAoD;IAC/D,uBAAuB;QACrB,qCACE;QACF,wCAAwC;QACxC,8BAA8B;QAC9B,4BAA4B;IAC9B;AACF,EAAC;AAED,OAAO,MAAMC,OAAuB;IAClCC,YAAY;IACZC,cAAcH;AAChB,EAAC"}
1
+ {"version":3,"sources":["../../../src/translations/languages/zhTw.ts"],"sourcesContent":["import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.js'\n\nexport const zhTwTranslations: PluginDefaultTranslationsObject = {\n 'plugin-multi-tenant': {\n 'confirm-modal-tenant-switch--body':\n '您即將變更擁有者,從 <0>{{fromTenant}}</0> 切換為 <0>{{toTenant}}</0>',\n 'confirm-modal-tenant-switch--heading': '確認變更 {{tenantLabel}}',\n 'field-assignedTenant-label': '指派的租用戶',\n 'nav-tenantSelector-label': '租戶',\n },\n}\n\nexport const zhTw: PluginLanguage = {\n dateFNSKey: 'zh-TW',\n translations: zhTwTranslations,\n}\n"],"names":["zhTwTranslations","zhTw","dateFNSKey","translations"],"mappings":"AAEA,OAAO,MAAMA,mBAAoD;IAC/D,uBAAuB;QACrB,qCACE;QACF,wCAAwC;QACxC,8BAA8B;QAC9B,4BAA4B;IAC9B;AACF,EAAC;AAED,OAAO,MAAMC,OAAuB;IAClCC,YAAY;IACZC,cAAcH;AAChB,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"addCollectionAccess.d.ts","sourceRoot":"","sources":["../../src/utilities/addCollectionAccess.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAE/C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAiB1D,KAAK,IAAI,CAAC,UAAU,IAAI;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,2BAA2B,CAAC,EAAE,MAAM,CAAA;IACpC,yBAAyB,EAAE,QAAQ,CACjC,uBAAuB,CAAC,UAAU,CAAC,CACpC,CAAC,2BAA2B,CAAC,CAAA;CAC/B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,UAAU,6HAO3C,IAAI,CAAC,UAAU,CAAC,KAAG,IAgBrB,CAAA"}
1
+ {"version":3,"file":"addCollectionAccess.d.ts","sourceRoot":"","sources":["../../src/utilities/addCollectionAccess.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAE/C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAiB1D,KAAK,IAAI,CAAC,UAAU,IAAI;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,2BAA2B,CAAC,EAAE,MAAM,CAAA;IACpC,yBAAyB,EAAE,QAAQ,CACjC,uBAAuB,CAAC,UAAU,CAAC,CACpC,CAAC,2BAA2B,CAAC,CAAA;CAC/B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,UAAU,6HAO3C,IAAI,CAAC,UAAU,CAAC,KAAG,IAerB,CAAA"}
@@ -20,7 +20,6 @@ const collectionAccessKeys = [
20
20
  adminUsersSlug,
21
21
  collection,
22
22
  fieldName: key === 'readVersions' ? `version.${fieldName}` : fieldName,
23
- operation: key,
24
23
  tenantsArrayFieldName,
25
24
  tenantsArrayTenantFieldName,
26
25
  userHasAccessToAllTenants
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/addCollectionAccess.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\n\nimport type { MultiTenantPluginConfig } from '../types.js'\n\nimport { withTenantAccess } from './withTenantAccess.js'\n\ntype AllAccessKeys<T extends readonly string[]> = T[number] extends keyof Omit<\n Required<CollectionConfig>['access'],\n 'admin'\n>\n ? keyof Omit<Required<CollectionConfig>['access'], 'admin'> extends T[number]\n ? T\n : never\n : never\n\nconst collectionAccessKeys: AllAccessKeys<\n ['create', 'read', 'update', 'delete', 'readVersions', 'unlock']\n> = ['create', 'read', 'update', 'delete', 'readVersions', 'unlock'] as const\n\ntype Args<ConfigType> = {\n adminUsersSlug: string\n collection: CollectionConfig\n fieldName: string\n tenantsArrayFieldName?: string\n tenantsArrayTenantFieldName?: string\n userHasAccessToAllTenants: Required<\n MultiTenantPluginConfig<ConfigType>\n >['userHasAccessToAllTenants']\n}\n\n/**\n * Adds tenant access constraint to collection\n * - constrains access a users assigned tenants\n */\nexport const addCollectionAccess = <ConfigType>({\n adminUsersSlug,\n collection,\n fieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n}: Args<ConfigType>): void => {\n collectionAccessKeys.forEach((key) => {\n if (!collection.access) {\n collection.access = {}\n }\n collection.access[key] = withTenantAccess<ConfigType>({\n accessFunction: collection.access?.[key],\n adminUsersSlug,\n collection,\n fieldName: key === 'readVersions' ? `version.${fieldName}` : fieldName,\n operation: key,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n })\n}\n"],"names":["withTenantAccess","collectionAccessKeys","addCollectionAccess","adminUsersSlug","collection","fieldName","tenantsArrayFieldName","tenantsArrayTenantFieldName","userHasAccessToAllTenants","forEach","key","access","accessFunction","operation"],"mappings":"AAIA,SAASA,gBAAgB,QAAQ,wBAAuB;AAWxD,MAAMC,uBAEF;IAAC;IAAU;IAAQ;IAAU;IAAU;IAAgB;CAAS;AAapE;;;CAGC,GACD,OAAO,MAAMC,sBAAsB,CAAa,EAC9CC,cAAc,EACdC,UAAU,EACVC,SAAS,EACTC,qBAAqB,EACrBC,2BAA2B,EAC3BC,yBAAyB,EACR;IACjBP,qBAAqBQ,OAAO,CAAC,CAACC;QAC5B,IAAI,CAACN,WAAWO,MAAM,EAAE;YACtBP,WAAWO,MAAM,GAAG,CAAC;QACvB;QACAP,WAAWO,MAAM,CAACD,IAAI,GAAGV,iBAA6B;YACpDY,gBAAgBR,WAAWO,MAAM,EAAE,CAACD,IAAI;YACxCP;YACAC;YACAC,WAAWK,QAAQ,iBAAiB,CAAC,QAAQ,EAAEL,WAAW,GAAGA;YAC7DQ,WAAWH;YACXJ;YACAC;YACAC;QACF;IACF;AACF,EAAC"}
1
+ {"version":3,"sources":["../../src/utilities/addCollectionAccess.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\n\nimport type { MultiTenantPluginConfig } from '../types.js'\n\nimport { withTenantAccess } from './withTenantAccess.js'\n\ntype AllAccessKeys<T extends readonly string[]> = T[number] extends keyof Omit<\n Required<CollectionConfig>['access'],\n 'admin'\n>\n ? keyof Omit<Required<CollectionConfig>['access'], 'admin'> extends T[number]\n ? T\n : never\n : never\n\nconst collectionAccessKeys: AllAccessKeys<\n ['create', 'read', 'update', 'delete', 'readVersions', 'unlock']\n> = ['create', 'read', 'update', 'delete', 'readVersions', 'unlock'] as const\n\ntype Args<ConfigType> = {\n adminUsersSlug: string\n collection: CollectionConfig\n fieldName: string\n tenantsArrayFieldName?: string\n tenantsArrayTenantFieldName?: string\n userHasAccessToAllTenants: Required<\n MultiTenantPluginConfig<ConfigType>\n >['userHasAccessToAllTenants']\n}\n\n/**\n * Adds tenant access constraint to collection\n * - constrains access a users assigned tenants\n */\nexport const addCollectionAccess = <ConfigType>({\n adminUsersSlug,\n collection,\n fieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n}: Args<ConfigType>): void => {\n collectionAccessKeys.forEach((key) => {\n if (!collection.access) {\n collection.access = {}\n }\n collection.access[key] = withTenantAccess<ConfigType>({\n accessFunction: collection.access?.[key],\n adminUsersSlug,\n collection,\n fieldName: key === 'readVersions' ? `version.${fieldName}` : fieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n })\n}\n"],"names":["withTenantAccess","collectionAccessKeys","addCollectionAccess","adminUsersSlug","collection","fieldName","tenantsArrayFieldName","tenantsArrayTenantFieldName","userHasAccessToAllTenants","forEach","key","access","accessFunction"],"mappings":"AAIA,SAASA,gBAAgB,QAAQ,wBAAuB;AAWxD,MAAMC,uBAEF;IAAC;IAAU;IAAQ;IAAU;IAAU;IAAgB;CAAS;AAapE;;;CAGC,GACD,OAAO,MAAMC,sBAAsB,CAAa,EAC9CC,cAAc,EACdC,UAAU,EACVC,SAAS,EACTC,qBAAqB,EACrBC,2BAA2B,EAC3BC,yBAAyB,EACR;IACjBP,qBAAqBQ,OAAO,CAAC,CAACC;QAC5B,IAAI,CAACN,WAAWO,MAAM,EAAE;YACtBP,WAAWO,MAAM,GAAG,CAAC;QACvB;QACAP,WAAWO,MAAM,CAACD,IAAI,GAAGV,iBAA6B;YACpDY,gBAAgBR,WAAWO,MAAM,EAAE,CAACD,IAAI;YACxCP;YACAC;YACAC,WAAWK,QAAQ,iBAAiB,CAAC,QAAQ,EAAEL,WAAW,GAAGA;YAC7DC;YACAC;YACAC;QACF;IACF;AACF,EAAC"}
@@ -5,8 +5,10 @@ type AddFilterOptionsToFieldsArgs = {
5
5
  tenantEnabledCollectionSlugs: string[];
6
6
  tenantEnabledGlobalSlugs: string[];
7
7
  tenantFieldName: string;
8
+ tenantsArrayFieldName: string;
9
+ tenantsArrayTenantFieldName: string;
8
10
  tenantsCollectionSlug: string;
9
11
  };
10
- export declare function addFilterOptionsToFields({ config, fields, tenantEnabledCollectionSlugs, tenantEnabledGlobalSlugs, tenantFieldName, tenantsCollectionSlug, }: AddFilterOptionsToFieldsArgs): void;
12
+ export declare function addFilterOptionsToFields({ config, fields, tenantEnabledCollectionSlugs, tenantEnabledGlobalSlugs, tenantFieldName, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, }: AddFilterOptionsToFieldsArgs): void;
11
13
  export {};
12
14
  //# sourceMappingURL=addFilterOptionsToFields.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"addFilterOptionsToFields.d.ts","sourceRoot":"","sources":["../../src/utilities/addFilterOptionsToFields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAyC,eAAe,EAAE,MAAM,SAAS,CAAA;AAKpG,KAAK,4BAA4B,GAAG;IAClC,MAAM,EAAE,MAAM,GAAG,eAAe,CAAA;IAChC,MAAM,EAAE,KAAK,EAAE,CAAA;IACf,4BAA4B,EAAE,MAAM,EAAE,CAAA;IACtC,wBAAwB,EAAE,MAAM,EAAE,CAAA;IAClC,eAAe,EAAE,MAAM,CAAA;IACvB,qBAAqB,EAAE,MAAM,CAAA;CAC9B,CAAA;AAED,wBAAgB,wBAAwB,CAAC,EACvC,MAAM,EACN,MAAM,EACN,4BAA4B,EAC5B,wBAAwB,EACxB,eAAe,EACf,qBAAqB,GACtB,EAAE,4BAA4B,QAqF9B"}
1
+ {"version":3,"file":"addFilterOptionsToFields.d.ts","sourceRoot":"","sources":["../../src/utilities/addFilterOptionsToFields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAqB,eAAe,EAAE,MAAM,SAAS,CAAA;AAKhF,KAAK,4BAA4B,GAAG;IAClC,MAAM,EAAE,MAAM,GAAG,eAAe,CAAA;IAChC,MAAM,EAAE,KAAK,EAAE,CAAA;IACf,4BAA4B,EAAE,MAAM,EAAE,CAAA;IACtC,wBAAwB,EAAE,MAAM,EAAE,CAAA;IAClC,eAAe,EAAE,MAAM,CAAA;IACvB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,2BAA2B,EAAE,MAAM,CAAA;IACnC,qBAAqB,EAAE,MAAM,CAAA;CAC9B,CAAA;AAED,wBAAgB,wBAAwB,CAAC,EACvC,MAAM,EACN,MAAM,EACN,4BAA4B,EAC5B,wBAAwB,EACxB,eAAe,EACf,qBAAsD,EACtD,2BAAkE,EAClE,qBAAqB,GACtB,EAAE,4BAA4B,QAoG9B"}
@@ -1,6 +1,6 @@
1
- import { getCollectionIDType } from './getCollectionIDType.js';
2
- import { getTenantFromCookie } from './getTenantFromCookie.js';
3
- export function addFilterOptionsToFields({ config, fields, tenantEnabledCollectionSlugs, tenantEnabledGlobalSlugs, tenantFieldName, tenantsCollectionSlug }) {
1
+ import { defaults } from '../defaults.js';
2
+ import { filterDocumentsByTenants } from '../filters/filterDocumentsByTenants.js';
3
+ export function addFilterOptionsToFields({ config, fields, tenantEnabledCollectionSlugs, tenantEnabledGlobalSlugs, tenantFieldName, tenantsArrayFieldName = defaults.tenantsArrayFieldName, tenantsArrayTenantFieldName = defaults.tenantsArrayTenantFieldName, tenantsCollectionSlug }) {
4
4
  fields.forEach((field)=>{
5
5
  if (field.type === 'relationship') {
6
6
  /**
@@ -15,6 +15,8 @@ export function addFilterOptionsToFields({ config, fields, tenantEnabledCollecti
15
15
  field,
16
16
  tenantEnabledCollectionSlugs,
17
17
  tenantFieldName,
18
+ tenantsArrayFieldName,
19
+ tenantsArrayTenantFieldName,
18
20
  tenantsCollectionSlug
19
21
  });
20
22
  }
@@ -28,6 +30,8 @@ export function addFilterOptionsToFields({ config, fields, tenantEnabledCollecti
28
30
  field,
29
31
  tenantEnabledCollectionSlugs,
30
32
  tenantFieldName,
33
+ tenantsArrayFieldName,
34
+ tenantsArrayTenantFieldName,
31
35
  tenantsCollectionSlug
32
36
  });
33
37
  }
@@ -41,6 +45,8 @@ export function addFilterOptionsToFields({ config, fields, tenantEnabledCollecti
41
45
  tenantEnabledCollectionSlugs,
42
46
  tenantEnabledGlobalSlugs,
43
47
  tenantFieldName,
48
+ tenantsArrayFieldName,
49
+ tenantsArrayTenantFieldName,
44
50
  tenantsCollectionSlug
45
51
  });
46
52
  }
@@ -55,6 +61,8 @@ export function addFilterOptionsToFields({ config, fields, tenantEnabledCollecti
55
61
  tenantEnabledCollectionSlugs,
56
62
  tenantEnabledGlobalSlugs,
57
63
  tenantFieldName,
64
+ tenantsArrayFieldName,
65
+ tenantsArrayTenantFieldName,
58
66
  tenantsCollectionSlug
59
67
  });
60
68
  }
@@ -68,13 +76,15 @@ export function addFilterOptionsToFields({ config, fields, tenantEnabledCollecti
68
76
  tenantEnabledCollectionSlugs,
69
77
  tenantEnabledGlobalSlugs,
70
78
  tenantFieldName,
79
+ tenantsArrayFieldName,
80
+ tenantsArrayTenantFieldName,
71
81
  tenantsCollectionSlug
72
82
  });
73
83
  });
74
84
  }
75
85
  });
76
86
  }
77
- function addFilter({ field, tenantEnabledCollectionSlugs, tenantFieldName, tenantsCollectionSlug }) {
87
+ function addFilter({ field, tenantEnabledCollectionSlugs, tenantFieldName, tenantsArrayFieldName = defaults.tenantsArrayFieldName, tenantsArrayTenantFieldName = defaults.tenantsArrayTenantFieldName, tenantsCollectionSlug }) {
78
88
  // User specified filter
79
89
  const originalFilter = field.filterOptions;
80
90
  field.filterOptions = async (args)=>{
@@ -88,13 +98,15 @@ function addFilter({ field, tenantEnabledCollectionSlugs, tenantFieldName, tenan
88
98
  return false;
89
99
  }
90
100
  // Custom tenant filter
91
- const tenantFilterResults = filterOptionsByTenant({
92
- ...args,
93
- tenantFieldName,
101
+ const tenantFilterResults = filterDocumentsByTenants({
102
+ filterFieldName: tenantFieldName,
103
+ req: args.req,
104
+ tenantsArrayFieldName,
105
+ tenantsArrayTenantFieldName,
94
106
  tenantsCollectionSlug
95
107
  });
96
- // If the tenant filter returns true, just use the original filter
97
- if (tenantFilterResults === true) {
108
+ // If the tenant filter returns null, meaning no tenant filter, just use the original filter
109
+ if (tenantFilterResults === null) {
98
110
  return originalFilterResult;
99
111
  }
100
112
  // If the original filter returns true, just use the tenant filter
@@ -109,31 +121,5 @@ function addFilter({ field, tenantEnabledCollectionSlugs, tenantFieldName, tenan
109
121
  };
110
122
  };
111
123
  }
112
- const filterOptionsByTenant = ({ req, tenantFieldName = 'tenant', tenantsCollectionSlug })=>{
113
- const idType = getCollectionIDType({
114
- collectionSlug: tenantsCollectionSlug,
115
- payload: req.payload
116
- });
117
- const selectedTenant = getTenantFromCookie(req.headers, idType);
118
- if (!selectedTenant) {
119
- return true;
120
- }
121
- return {
122
- or: [
123
- // ie a related collection that doesn't have a tenant field
124
- {
125
- [tenantFieldName]: {
126
- exists: false
127
- }
128
- },
129
- // related collections that have a tenant field
130
- {
131
- [tenantFieldName]: {
132
- equals: selectedTenant
133
- }
134
- }
135
- ]
136
- };
137
- };
138
124
 
139
125
  //# sourceMappingURL=addFilterOptionsToFields.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/addFilterOptionsToFields.ts"],"sourcesContent":["import type { Config, Field, FilterOptionsProps, RelationshipField, SanitizedConfig } from 'payload'\n\nimport { getCollectionIDType } from './getCollectionIDType.js'\nimport { getTenantFromCookie } from './getTenantFromCookie.js'\n\ntype AddFilterOptionsToFieldsArgs = {\n config: Config | SanitizedConfig\n fields: Field[]\n tenantEnabledCollectionSlugs: string[]\n tenantEnabledGlobalSlugs: string[]\n tenantFieldName: string\n tenantsCollectionSlug: string\n}\n\nexport function addFilterOptionsToFields({\n config,\n fields,\n tenantEnabledCollectionSlugs,\n tenantEnabledGlobalSlugs,\n tenantFieldName,\n tenantsCollectionSlug,\n}: AddFilterOptionsToFieldsArgs) {\n fields.forEach((field) => {\n if (field.type === 'relationship') {\n /**\n * Adjusts relationship fields to filter by tenant\n * and ensures relationTo cannot be a tenant global collection\n */\n if (typeof field.relationTo === 'string') {\n if (tenantEnabledGlobalSlugs.includes(field.relationTo)) {\n throw new Error(\n `The collection ${field.relationTo} is a global collection and cannot be related to a tenant enabled collection.`,\n )\n }\n if (tenantEnabledCollectionSlugs.includes(field.relationTo)) {\n addFilter({ field, tenantEnabledCollectionSlugs, tenantFieldName, tenantsCollectionSlug })\n }\n } else {\n field.relationTo.map((relationTo) => {\n if (tenantEnabledGlobalSlugs.includes(relationTo)) {\n throw new Error(\n `The collection ${relationTo} is a global collection and cannot be related to a tenant enabled collection.`,\n )\n }\n if (tenantEnabledCollectionSlugs.includes(relationTo)) {\n addFilter({\n field,\n tenantEnabledCollectionSlugs,\n tenantFieldName,\n tenantsCollectionSlug,\n })\n }\n })\n }\n }\n\n if (\n field.type === 'row' ||\n field.type === 'array' ||\n field.type === 'collapsible' ||\n field.type === 'group'\n ) {\n addFilterOptionsToFields({\n config,\n fields: field.fields,\n tenantEnabledCollectionSlugs,\n tenantEnabledGlobalSlugs,\n tenantFieldName,\n tenantsCollectionSlug,\n })\n }\n\n if (field.type === 'blocks') {\n ;(field.blockReferences ?? field.blocks).forEach((_block) => {\n const block =\n typeof _block === 'string'\n ? // TODO: iterate over blocks mapped to block slug in v4, or pass through payload.blocks\n config?.blocks?.find((b) => b.slug === _block)\n : _block\n\n if (block?.fields) {\n addFilterOptionsToFields({\n config,\n fields: block.fields,\n tenantEnabledCollectionSlugs,\n tenantEnabledGlobalSlugs,\n tenantFieldName,\n tenantsCollectionSlug,\n })\n }\n })\n }\n\n if (field.type === 'tabs') {\n field.tabs.forEach((tab) => {\n addFilterOptionsToFields({\n config,\n fields: tab.fields,\n tenantEnabledCollectionSlugs,\n tenantEnabledGlobalSlugs,\n tenantFieldName,\n tenantsCollectionSlug,\n })\n })\n }\n })\n}\n\ntype AddFilterArgs = {\n field: RelationshipField\n tenantEnabledCollectionSlugs: string[]\n tenantFieldName: string\n tenantsCollectionSlug: string\n}\nfunction addFilter({\n field,\n tenantEnabledCollectionSlugs,\n tenantFieldName,\n tenantsCollectionSlug,\n}: AddFilterArgs) {\n // User specified filter\n const originalFilter = field.filterOptions\n field.filterOptions = async (args) => {\n const originalFilterResult =\n typeof originalFilter === 'function' ? await originalFilter(args) : (originalFilter ?? true)\n\n // If the relationTo is not a tenant enabled collection, return early\n if (args.relationTo && !tenantEnabledCollectionSlugs.includes(args.relationTo)) {\n return originalFilterResult\n }\n\n // If the original filtr returns false, return early\n if (originalFilterResult === false) {\n return false\n }\n\n // Custom tenant filter\n const tenantFilterResults = filterOptionsByTenant({\n ...args,\n tenantFieldName,\n tenantsCollectionSlug,\n })\n\n // If the tenant filter returns true, just use the original filter\n if (tenantFilterResults === true) {\n return originalFilterResult\n }\n\n // If the original filter returns true, just use the tenant filter\n if (originalFilterResult === true) {\n return tenantFilterResults\n }\n\n return {\n and: [originalFilterResult, tenantFilterResults],\n }\n }\n}\n\ntype Args = {\n tenantFieldName?: string\n tenantsCollectionSlug: string\n} & FilterOptionsProps\nconst filterOptionsByTenant = ({\n req,\n tenantFieldName = 'tenant',\n tenantsCollectionSlug,\n}: Args) => {\n const idType = getCollectionIDType({\n collectionSlug: tenantsCollectionSlug,\n payload: req.payload,\n })\n const selectedTenant = getTenantFromCookie(req.headers, idType)\n if (!selectedTenant) {\n return true\n }\n\n return {\n or: [\n // ie a related collection that doesn't have a tenant field\n {\n [tenantFieldName]: {\n exists: false,\n },\n },\n // related collections that have a tenant field\n {\n [tenantFieldName]: {\n equals: selectedTenant,\n },\n },\n ],\n }\n}\n"],"names":["getCollectionIDType","getTenantFromCookie","addFilterOptionsToFields","config","fields","tenantEnabledCollectionSlugs","tenantEnabledGlobalSlugs","tenantFieldName","tenantsCollectionSlug","forEach","field","type","relationTo","includes","Error","addFilter","map","blockReferences","blocks","_block","block","find","b","slug","tabs","tab","originalFilter","filterOptions","args","originalFilterResult","tenantFilterResults","filterOptionsByTenant","and","req","idType","collectionSlug","payload","selectedTenant","headers","or","exists","equals"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/utilities/addFilterOptionsToFields.ts"],"sourcesContent":["import type { Config, Field, RelationshipField, SanitizedConfig } from 'payload'\n\nimport { defaults } from '../defaults.js'\nimport { filterDocumentsByTenants } from '../filters/filterDocumentsByTenants.js'\n\ntype AddFilterOptionsToFieldsArgs = {\n config: Config | SanitizedConfig\n fields: Field[]\n tenantEnabledCollectionSlugs: string[]\n tenantEnabledGlobalSlugs: string[]\n tenantFieldName: string\n tenantsArrayFieldName: string\n tenantsArrayTenantFieldName: string\n tenantsCollectionSlug: string\n}\n\nexport function addFilterOptionsToFields({\n config,\n fields,\n tenantEnabledCollectionSlugs,\n tenantEnabledGlobalSlugs,\n tenantFieldName,\n tenantsArrayFieldName = defaults.tenantsArrayFieldName,\n tenantsArrayTenantFieldName = defaults.tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n}: AddFilterOptionsToFieldsArgs) {\n fields.forEach((field) => {\n if (field.type === 'relationship') {\n /**\n * Adjusts relationship fields to filter by tenant\n * and ensures relationTo cannot be a tenant global collection\n */\n if (typeof field.relationTo === 'string') {\n if (tenantEnabledGlobalSlugs.includes(field.relationTo)) {\n throw new Error(\n `The collection ${field.relationTo} is a global collection and cannot be related to a tenant enabled collection.`,\n )\n }\n if (tenantEnabledCollectionSlugs.includes(field.relationTo)) {\n addFilter({\n field,\n tenantEnabledCollectionSlugs,\n tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n })\n }\n } else {\n field.relationTo.map((relationTo) => {\n if (tenantEnabledGlobalSlugs.includes(relationTo)) {\n throw new Error(\n `The collection ${relationTo} is a global collection and cannot be related to a tenant enabled collection.`,\n )\n }\n if (tenantEnabledCollectionSlugs.includes(relationTo)) {\n addFilter({\n field,\n tenantEnabledCollectionSlugs,\n tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n })\n }\n })\n }\n }\n\n if (\n field.type === 'row' ||\n field.type === 'array' ||\n field.type === 'collapsible' ||\n field.type === 'group'\n ) {\n addFilterOptionsToFields({\n config,\n fields: field.fields,\n tenantEnabledCollectionSlugs,\n tenantEnabledGlobalSlugs,\n tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n })\n }\n\n if (field.type === 'blocks') {\n ;(field.blockReferences ?? field.blocks).forEach((_block) => {\n const block =\n typeof _block === 'string'\n ? // TODO: iterate over blocks mapped to block slug in v4, or pass through payload.blocks\n config?.blocks?.find((b) => b.slug === _block)\n : _block\n\n if (block?.fields) {\n addFilterOptionsToFields({\n config,\n fields: block.fields,\n tenantEnabledCollectionSlugs,\n tenantEnabledGlobalSlugs,\n tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n })\n }\n })\n }\n\n if (field.type === 'tabs') {\n field.tabs.forEach((tab) => {\n addFilterOptionsToFields({\n config,\n fields: tab.fields,\n tenantEnabledCollectionSlugs,\n tenantEnabledGlobalSlugs,\n tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n })\n })\n }\n })\n}\n\ntype AddFilterArgs = {\n field: RelationshipField\n tenantEnabledCollectionSlugs: string[]\n tenantFieldName: string\n tenantsArrayFieldName: string\n tenantsArrayTenantFieldName: string\n tenantsCollectionSlug: string\n}\nfunction addFilter({\n field,\n tenantEnabledCollectionSlugs,\n tenantFieldName,\n tenantsArrayFieldName = defaults.tenantsArrayFieldName,\n tenantsArrayTenantFieldName = defaults.tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n}: AddFilterArgs) {\n // User specified filter\n const originalFilter = field.filterOptions\n field.filterOptions = async (args) => {\n const originalFilterResult =\n typeof originalFilter === 'function' ? await originalFilter(args) : (originalFilter ?? true)\n\n // If the relationTo is not a tenant enabled collection, return early\n if (args.relationTo && !tenantEnabledCollectionSlugs.includes(args.relationTo)) {\n return originalFilterResult\n }\n\n // If the original filtr returns false, return early\n if (originalFilterResult === false) {\n return false\n }\n\n // Custom tenant filter\n const tenantFilterResults = filterDocumentsByTenants({\n filterFieldName: tenantFieldName,\n req: args.req,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n })\n\n // If the tenant filter returns null, meaning no tenant filter, just use the original filter\n if (tenantFilterResults === null) {\n return originalFilterResult\n }\n\n // If the original filter returns true, just use the tenant filter\n if (originalFilterResult === true) {\n return tenantFilterResults\n }\n\n return {\n and: [originalFilterResult, tenantFilterResults],\n }\n }\n}\n"],"names":["defaults","filterDocumentsByTenants","addFilterOptionsToFields","config","fields","tenantEnabledCollectionSlugs","tenantEnabledGlobalSlugs","tenantFieldName","tenantsArrayFieldName","tenantsArrayTenantFieldName","tenantsCollectionSlug","forEach","field","type","relationTo","includes","Error","addFilter","map","blockReferences","blocks","_block","block","find","b","slug","tabs","tab","originalFilter","filterOptions","args","originalFilterResult","tenantFilterResults","filterFieldName","req","and"],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ type CookieOptions = {
2
+ domain?: string;
3
+ expires?: Date;
4
+ httpOnly?: boolean;
5
+ maxAge?: number;
6
+ name: string;
7
+ path?: string;
8
+ returnCookieAsObject: boolean;
9
+ sameSite?: 'Lax' | 'None' | 'Strict';
10
+ secure?: boolean;
11
+ value?: string;
12
+ };
13
+ type CookieObject = {
14
+ domain?: string;
15
+ expires?: string;
16
+ httpOnly?: boolean;
17
+ maxAge?: number;
18
+ name: string;
19
+ path?: string;
20
+ sameSite?: 'Lax' | 'None' | 'Strict';
21
+ secure?: boolean;
22
+ value: string | undefined;
23
+ };
24
+ export declare const generateCookie: <ReturnCookieAsObject = boolean>(args: CookieOptions) => ReturnCookieAsObject extends true ? CookieObject : string;
25
+ export {};
26
+ //# sourceMappingURL=generateCookie.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generateCookie.d.ts","sourceRoot":"","sources":["../../src/utilities/generateCookie.ts"],"names":[],"mappings":"AAAA,KAAK,aAAa,GAAG;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,IAAI,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,oBAAoB,EAAE,OAAO,CAAA;IAC7B,QAAQ,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAA;IACpC,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,KAAK,YAAY,GAAG;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAA;IACpC,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;CAC1B,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,oBAAoB,kBAC3C,aAAa,KAClB,oBAAoB,SAAS,IAAI,GAAG,YAAY,GAAG,MA6ErD,CAAA"}
@@ -0,0 +1,61 @@
1
+ export const generateCookie = (args)=>{
2
+ const { name, domain, expires, httpOnly, maxAge, path, returnCookieAsObject, sameSite, secure: secureArg, value } = args;
3
+ let cookieString = `${name}=${value || ''}`;
4
+ const cookieObject = {
5
+ name,
6
+ value
7
+ };
8
+ const secure = secureArg || sameSite === 'None';
9
+ if (expires) {
10
+ if (returnCookieAsObject) {
11
+ cookieObject.expires = expires.toUTCString();
12
+ } else {
13
+ cookieString += `; Expires=${expires.toUTCString()}`;
14
+ }
15
+ }
16
+ if (maxAge) {
17
+ if (returnCookieAsObject) {
18
+ cookieObject.maxAge = maxAge;
19
+ } else {
20
+ cookieString += `; Max-Age=${maxAge.toString()}`;
21
+ }
22
+ }
23
+ if (domain) {
24
+ if (returnCookieAsObject) {
25
+ cookieObject.domain = domain;
26
+ } else {
27
+ cookieString += `; Domain=${domain}`;
28
+ }
29
+ }
30
+ if (path) {
31
+ if (returnCookieAsObject) {
32
+ cookieObject.path = path;
33
+ } else {
34
+ cookieString += `; Path=${path}`;
35
+ }
36
+ }
37
+ if (secure) {
38
+ if (returnCookieAsObject) {
39
+ cookieObject.secure = secure;
40
+ } else {
41
+ cookieString += `; Secure`;
42
+ }
43
+ }
44
+ if (httpOnly) {
45
+ if (returnCookieAsObject) {
46
+ cookieObject.httpOnly = httpOnly;
47
+ } else {
48
+ cookieString += `; HttpOnly`;
49
+ }
50
+ }
51
+ if (sameSite) {
52
+ if (returnCookieAsObject) {
53
+ cookieObject.sameSite = sameSite;
54
+ } else {
55
+ cookieString += `; SameSite=${sameSite}`;
56
+ }
57
+ }
58
+ return returnCookieAsObject ? cookieObject : cookieString;
59
+ };
60
+
61
+ //# sourceMappingURL=generateCookie.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utilities/generateCookie.ts"],"sourcesContent":["type CookieOptions = {\n domain?: string\n expires?: Date\n httpOnly?: boolean\n maxAge?: number\n name: string\n path?: string\n returnCookieAsObject: boolean\n sameSite?: 'Lax' | 'None' | 'Strict'\n secure?: boolean\n value?: string\n}\n\ntype CookieObject = {\n domain?: string\n expires?: string\n httpOnly?: boolean\n maxAge?: number\n name: string\n path?: string\n sameSite?: 'Lax' | 'None' | 'Strict'\n secure?: boolean\n value: string | undefined\n}\n\nexport const generateCookie = <ReturnCookieAsObject = boolean>(\n args: CookieOptions,\n): ReturnCookieAsObject extends true ? CookieObject : string => {\n const {\n name,\n domain,\n expires,\n httpOnly,\n maxAge,\n path,\n returnCookieAsObject,\n sameSite,\n secure: secureArg,\n value,\n } = args\n let cookieString = `${name}=${value || ''}`\n const cookieObject: CookieObject = {\n name,\n value,\n }\n const secure = secureArg || sameSite === 'None'\n\n if (expires) {\n if (returnCookieAsObject) {\n cookieObject.expires = expires.toUTCString()\n } else {\n cookieString += `; Expires=${expires.toUTCString()}`\n }\n }\n\n if (maxAge) {\n if (returnCookieAsObject) {\n cookieObject.maxAge = maxAge\n } else {\n cookieString += `; Max-Age=${maxAge.toString()}`\n }\n }\n\n if (domain) {\n if (returnCookieAsObject) {\n cookieObject.domain = domain\n } else {\n cookieString += `; Domain=${domain}`\n }\n }\n\n if (path) {\n if (returnCookieAsObject) {\n cookieObject.path = path\n } else {\n cookieString += `; Path=${path}`\n }\n }\n\n if (secure) {\n if (returnCookieAsObject) {\n cookieObject.secure = secure\n } else {\n cookieString += `; Secure`\n }\n }\n\n if (httpOnly) {\n if (returnCookieAsObject) {\n cookieObject.httpOnly = httpOnly\n } else {\n cookieString += `; HttpOnly`\n }\n }\n\n if (sameSite) {\n if (returnCookieAsObject) {\n cookieObject.sameSite = sameSite\n } else {\n cookieString += `; SameSite=${sameSite}`\n }\n }\n\n return returnCookieAsObject ? (cookieObject as any) : (cookieString as any)\n}\n"],"names":["generateCookie","args","name","domain","expires","httpOnly","maxAge","path","returnCookieAsObject","sameSite","secure","secureArg","value","cookieString","cookieObject","toUTCString","toString"],"mappings":"AAyBA,OAAO,MAAMA,iBAAiB,CAC5BC;IAEA,MAAM,EACJC,IAAI,EACJC,MAAM,EACNC,OAAO,EACPC,QAAQ,EACRC,MAAM,EACNC,IAAI,EACJC,oBAAoB,EACpBC,QAAQ,EACRC,QAAQC,SAAS,EACjBC,KAAK,EACN,GAAGX;IACJ,IAAIY,eAAe,GAAGX,KAAK,CAAC,EAAEU,SAAS,IAAI;IAC3C,MAAME,eAA6B;QACjCZ;QACAU;IACF;IACA,MAAMF,SAASC,aAAaF,aAAa;IAEzC,IAAIL,SAAS;QACX,IAAII,sBAAsB;YACxBM,aAAaV,OAAO,GAAGA,QAAQW,WAAW;QAC5C,OAAO;YACLF,gBAAgB,CAAC,UAAU,EAAET,QAAQW,WAAW,IAAI;QACtD;IACF;IAEA,IAAIT,QAAQ;QACV,IAAIE,sBAAsB;YACxBM,aAAaR,MAAM,GAAGA;QACxB,OAAO;YACLO,gBAAgB,CAAC,UAAU,EAAEP,OAAOU,QAAQ,IAAI;QAClD;IACF;IAEA,IAAIb,QAAQ;QACV,IAAIK,sBAAsB;YACxBM,aAAaX,MAAM,GAAGA;QACxB,OAAO;YACLU,gBAAgB,CAAC,SAAS,EAAEV,QAAQ;QACtC;IACF;IAEA,IAAII,MAAM;QACR,IAAIC,sBAAsB;YACxBM,aAAaP,IAAI,GAAGA;QACtB,OAAO;YACLM,gBAAgB,CAAC,OAAO,EAAEN,MAAM;QAClC;IACF;IAEA,IAAIG,QAAQ;QACV,IAAIF,sBAAsB;YACxBM,aAAaJ,MAAM,GAAGA;QACxB,OAAO;YACLG,gBAAgB,CAAC,QAAQ,CAAC;QAC5B;IACF;IAEA,IAAIR,UAAU;QACZ,IAAIG,sBAAsB;YACxBM,aAAaT,QAAQ,GAAGA;QAC1B,OAAO;YACLQ,gBAAgB,CAAC,UAAU,CAAC;QAC9B;IACF;IAEA,IAAIJ,UAAU;QACZ,IAAID,sBAAsB;YACxBM,aAAaL,QAAQ,GAAGA;QAC1B,OAAO;YACLI,gBAAgB,CAAC,WAAW,EAAEJ,UAAU;QAC1C;IACF;IAEA,OAAOD,uBAAwBM,eAAwBD;AACzD,EAAC"}
@@ -1,11 +1,10 @@
1
- import type { Access, AccessArgs, AccessResult, AllOperations, CollectionConfig } from 'payload';
1
+ import type { Access, AccessArgs, AccessResult, CollectionConfig } from 'payload';
2
2
  import type { MultiTenantPluginConfig } from '../types.js';
3
3
  type Args<ConfigType> = {
4
4
  accessFunction?: Access;
5
5
  adminUsersSlug: string;
6
6
  collection: CollectionConfig;
7
7
  fieldName: string;
8
- operation: AllOperations;
9
8
  tenantsArrayFieldName?: string;
10
9
  tenantsArrayTenantFieldName?: string;
11
10
  userHasAccessToAllTenants: Required<MultiTenantPluginConfig<ConfigType>>['userHasAccessToAllTenants'];
@@ -1 +1 @@
1
- {"version":3,"file":"withTenantAccess.d.ts","sourceRoot":"","sources":["../../src/utilities/withTenantAccess.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,EACN,UAAU,EACV,YAAY,EACZ,aAAa,EACb,gBAAgB,EAGjB,MAAM,SAAS,CAAA;AAEhB,OAAO,KAAK,EAAE,uBAAuB,EAAwB,MAAM,aAAa,CAAA;AAKhF,KAAK,IAAI,CAAC,UAAU,IAAI;IACtB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,aAAa,CAAA;IACxB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,2BAA2B,CAAC,EAAE,MAAM,CAAA;IACpC,yBAAyB,EAAE,QAAQ,CACjC,uBAAuB,CAAC,UAAU,CAAC,CACpC,CAAC,2BAA2B,CAAC,CAAA;CAC/B,CAAA;AACD,eAAO,MAAM,gBAAgB,GAC1B,UAAU,6IAQR,IAAI,CAAC,UAAU,CAAC,YACN,UAAU,KAAG,OAAO,CAAC,YAAY,CA6C7C,CAAA"}
1
+ {"version":3,"file":"withTenantAccess.d.ts","sourceRoot":"","sources":["../../src/utilities/withTenantAccess.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAoB,MAAM,SAAS,CAAA;AAEnG,OAAO,KAAK,EAAE,uBAAuB,EAAwB,MAAM,aAAa,CAAA;AAKhF,KAAK,IAAI,CAAC,UAAU,IAAI;IACtB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,2BAA2B,CAAC,EAAE,MAAM,CAAA;IACpC,yBAAyB,EAAE,QAAQ,CACjC,uBAAuB,CAAC,UAAU,CAAC,CACpC,CAAC,2BAA2B,CAAC,CAAA;CAC/B,CAAA;AACD,eAAO,MAAM,gBAAgB,GAC1B,UAAU,6IAQR,IAAI,CAAC,UAAU,CAAC,YACN,UAAU,KAAG,OAAO,CAAC,YAAY,CA6C7C,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/withTenantAccess.ts"],"sourcesContent":["import type {\n Access,\n AccessArgs,\n AccessResult,\n AllOperations,\n CollectionConfig,\n TypedUser,\n Where,\n} from 'payload'\n\nimport type { MultiTenantPluginConfig, UserWithTenantsField } from '../types.js'\n\nimport { combineWhereConstraints } from './combineWhereConstraints.js'\nimport { getTenantAccess } from './getTenantAccess.js'\n\ntype Args<ConfigType> = {\n accessFunction?: Access\n adminUsersSlug: string\n collection: CollectionConfig\n fieldName: string\n operation: AllOperations\n tenantsArrayFieldName?: string\n tenantsArrayTenantFieldName?: string\n userHasAccessToAllTenants: Required<\n MultiTenantPluginConfig<ConfigType>\n >['userHasAccessToAllTenants']\n}\nexport const withTenantAccess =\n <ConfigType>({\n accessFunction,\n adminUsersSlug,\n collection,\n fieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n }: Args<ConfigType>) =>\n async (args: AccessArgs): Promise<AccessResult> => {\n const constraints: Where[] = []\n const accessFn =\n typeof accessFunction === 'function'\n ? accessFunction\n : ({ req }: AccessArgs): AccessResult => Boolean(req.user)\n const accessResult: AccessResult = await accessFn(args)\n\n if (accessResult === false) {\n return false\n } else if (accessResult && typeof accessResult === 'object') {\n constraints.push(accessResult)\n }\n\n if (\n args.req.user &&\n args.req.user.collection === adminUsersSlug &&\n !userHasAccessToAllTenants(\n args.req.user as ConfigType extends { user: unknown } ? ConfigType['user'] : TypedUser,\n )\n ) {\n const tenantConstraint = getTenantAccess({\n fieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n user: args.req.user as UserWithTenantsField,\n })\n if (collection.slug === args.req.user.collection) {\n constraints.push({\n or: [\n {\n id: {\n equals: args.req.user.id,\n },\n },\n tenantConstraint,\n ],\n })\n } else {\n constraints.push(tenantConstraint)\n }\n return combineWhereConstraints(constraints)\n }\n\n return accessResult\n }\n"],"names":["combineWhereConstraints","getTenantAccess","withTenantAccess","accessFunction","adminUsersSlug","collection","fieldName","tenantsArrayFieldName","tenantsArrayTenantFieldName","userHasAccessToAllTenants","args","constraints","accessFn","req","Boolean","user","accessResult","push","tenantConstraint","slug","or","id","equals"],"mappings":"AAYA,SAASA,uBAAuB,QAAQ,+BAA8B;AACtE,SAASC,eAAe,QAAQ,uBAAsB;AActD,OAAO,MAAMC,mBACX,CAAa,EACXC,cAAc,EACdC,cAAc,EACdC,UAAU,EACVC,SAAS,EACTC,qBAAqB,EACrBC,2BAA2B,EAC3BC,yBAAyB,EACR,GACnB,OAAOC;QACL,MAAMC,cAAuB,EAAE;QAC/B,MAAMC,WACJ,OAAOT,mBAAmB,aACtBA,iBACA,CAAC,EAAEU,GAAG,EAAc,GAAmBC,QAAQD,IAAIE,IAAI;QAC7D,MAAMC,eAA6B,MAAMJ,SAASF;QAElD,IAAIM,iBAAiB,OAAO;YAC1B,OAAO;QACT,OAAO,IAAIA,gBAAgB,OAAOA,iBAAiB,UAAU;YAC3DL,YAAYM,IAAI,CAACD;QACnB;QAEA,IACEN,KAAKG,GAAG,CAACE,IAAI,IACbL,KAAKG,GAAG,CAACE,IAAI,CAACV,UAAU,KAAKD,kBAC7B,CAACK,0BACCC,KAAKG,GAAG,CAACE,IAAI,GAEf;YACA,MAAMG,mBAAmBjB,gBAAgB;gBACvCK;gBACAC;gBACAC;gBACAO,MAAML,KAAKG,GAAG,CAACE,IAAI;YACrB;YACA,IAAIV,WAAWc,IAAI,KAAKT,KAAKG,GAAG,CAACE,IAAI,CAACV,UAAU,EAAE;gBAChDM,YAAYM,IAAI,CAAC;oBACfG,IAAI;wBACF;4BACEC,IAAI;gCACFC,QAAQZ,KAAKG,GAAG,CAACE,IAAI,CAACM,EAAE;4BAC1B;wBACF;wBACAH;qBACD;gBACH;YACF,OAAO;gBACLP,YAAYM,IAAI,CAACC;YACnB;YACA,OAAOlB,wBAAwBW;QACjC;QAEA,OAAOK;IACT,EAAC"}
1
+ {"version":3,"sources":["../../src/utilities/withTenantAccess.ts"],"sourcesContent":["import type { Access, AccessArgs, AccessResult, CollectionConfig, TypedUser, Where } from 'payload'\n\nimport type { MultiTenantPluginConfig, UserWithTenantsField } from '../types.js'\n\nimport { combineWhereConstraints } from './combineWhereConstraints.js'\nimport { getTenantAccess } from './getTenantAccess.js'\n\ntype Args<ConfigType> = {\n accessFunction?: Access\n adminUsersSlug: string\n collection: CollectionConfig\n fieldName: string\n tenantsArrayFieldName?: string\n tenantsArrayTenantFieldName?: string\n userHasAccessToAllTenants: Required<\n MultiTenantPluginConfig<ConfigType>\n >['userHasAccessToAllTenants']\n}\nexport const withTenantAccess =\n <ConfigType>({\n accessFunction,\n adminUsersSlug,\n collection,\n fieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n }: Args<ConfigType>) =>\n async (args: AccessArgs): Promise<AccessResult> => {\n const constraints: Where[] = []\n const accessFn =\n typeof accessFunction === 'function'\n ? accessFunction\n : ({ req }: AccessArgs): AccessResult => Boolean(req.user)\n const accessResult: AccessResult = await accessFn(args)\n\n if (accessResult === false) {\n return false\n } else if (accessResult && typeof accessResult === 'object') {\n constraints.push(accessResult)\n }\n\n if (\n args.req.user &&\n args.req.user.collection === adminUsersSlug &&\n !userHasAccessToAllTenants(\n args.req.user as ConfigType extends { user: unknown } ? ConfigType['user'] : TypedUser,\n )\n ) {\n const tenantConstraint = getTenantAccess({\n fieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n user: args.req.user as UserWithTenantsField,\n })\n if (collection.slug === args.req.user.collection) {\n constraints.push({\n or: [\n {\n id: {\n equals: args.req.user.id,\n },\n },\n tenantConstraint,\n ],\n })\n } else {\n constraints.push(tenantConstraint)\n }\n return combineWhereConstraints(constraints)\n }\n\n return accessResult\n }\n"],"names":["combineWhereConstraints","getTenantAccess","withTenantAccess","accessFunction","adminUsersSlug","collection","fieldName","tenantsArrayFieldName","tenantsArrayTenantFieldName","userHasAccessToAllTenants","args","constraints","accessFn","req","Boolean","user","accessResult","push","tenantConstraint","slug","or","id","equals"],"mappings":"AAIA,SAASA,uBAAuB,QAAQ,+BAA8B;AACtE,SAASC,eAAe,QAAQ,uBAAsB;AAatD,OAAO,MAAMC,mBACX,CAAa,EACXC,cAAc,EACdC,cAAc,EACdC,UAAU,EACVC,SAAS,EACTC,qBAAqB,EACrBC,2BAA2B,EAC3BC,yBAAyB,EACR,GACnB,OAAOC;QACL,MAAMC,cAAuB,EAAE;QAC/B,MAAMC,WACJ,OAAOT,mBAAmB,aACtBA,iBACA,CAAC,EAAEU,GAAG,EAAc,GAAmBC,QAAQD,IAAIE,IAAI;QAC7D,MAAMC,eAA6B,MAAMJ,SAASF;QAElD,IAAIM,iBAAiB,OAAO;YAC1B,OAAO;QACT,OAAO,IAAIA,gBAAgB,OAAOA,iBAAiB,UAAU;YAC3DL,YAAYM,IAAI,CAACD;QACnB;QAEA,IACEN,KAAKG,GAAG,CAACE,IAAI,IACbL,KAAKG,GAAG,CAACE,IAAI,CAACV,UAAU,KAAKD,kBAC7B,CAACK,0BACCC,KAAKG,GAAG,CAACE,IAAI,GAEf;YACA,MAAMG,mBAAmBjB,gBAAgB;gBACvCK;gBACAC;gBACAC;gBACAO,MAAML,KAAKG,GAAG,CAACE,IAAI;YACrB;YACA,IAAIV,WAAWc,IAAI,KAAKT,KAAKG,GAAG,CAACE,IAAI,CAACV,UAAU,EAAE;gBAChDM,YAAYM,IAAI,CAAC;oBACfG,IAAI;wBACF;4BACEC,IAAI;gCACFC,QAAQZ,KAAKG,GAAG,CAACE,IAAI,CAACM,EAAE;4BAC1B;wBACF;wBACAH;qBACD;gBACH;YACF,OAAO;gBACLP,YAAYM,IAAI,CAACC;YACnB;YACA,OAAOlB,wBAAwBW;QACjC;QAEA,OAAOK;IACT,EAAC"}