@payloadcms/plugin-multi-tenant 3.49.0 → 3.50.0-canary.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/GlobalViewRedirect/index.d.ts +4 -0
- package/dist/components/GlobalViewRedirect/index.d.ts.map +1 -1
- package/dist/components/GlobalViewRedirect/index.js +3 -0
- package/dist/components/GlobalViewRedirect/index.js.map +1 -1
- package/dist/endpoints/getTenantOptionsEndpoint.d.ts +10 -0
- package/dist/endpoints/getTenantOptionsEndpoint.d.ts.map +1 -0
- package/dist/endpoints/getTenantOptionsEndpoint.js +26 -0
- package/dist/endpoints/getTenantOptionsEndpoint.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -2
- package/dist/index.js.map +1 -1
- package/dist/providers/TenantSelectionProvider/index.client.d.ts +2 -4
- package/dist/providers/TenantSelectionProvider/index.client.d.ts.map +1 -1
- package/dist/providers/TenantSelectionProvider/index.client.js +8 -12
- package/dist/providers/TenantSelectionProvider/index.client.js.map +1 -1
- package/dist/providers/TenantSelectionProvider/index.d.ts +6 -2
- package/dist/providers/TenantSelectionProvider/index.d.ts.map +1 -1
- package/dist/providers/TenantSelectionProvider/index.js +13 -23
- package/dist/providers/TenantSelectionProvider/index.js.map +1 -1
- package/dist/utilities/getGlobalViewRedirect.d.ts +5 -1
- package/dist/utilities/getGlobalViewRedirect.d.ts.map +1 -1
- package/dist/utilities/getGlobalViewRedirect.js +12 -6
- package/dist/utilities/getGlobalViewRedirect.js.map +1 -1
- package/dist/utilities/getTenantOptions.d.ts +12 -0
- package/dist/utilities/getTenantOptions.d.ts.map +1 -0
- package/dist/utilities/getTenantOptions.js +63 -0
- package/dist/utilities/getTenantOptions.js.map +1 -0
- package/package.json +6 -6
- package/dist/queries/findTenantOptions.d.ts +0 -11
- package/dist/queries/findTenantOptions.d.ts.map +0 -1
- package/dist/queries/findTenantOptions.js +0 -19
- package/dist/queries/findTenantOptions.js.map +0 -1
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import type { CollectionSlug, ServerProps, ViewTypes } from 'payload';
|
|
2
|
+
import type { MultiTenantPluginConfig } from '../../types.js';
|
|
2
3
|
type Args = {
|
|
3
4
|
basePath?: string;
|
|
4
5
|
collectionSlug: CollectionSlug;
|
|
5
6
|
docID?: number | string;
|
|
6
7
|
globalSlugs: string[];
|
|
8
|
+
tenantArrayFieldName: string;
|
|
9
|
+
tenantArrayTenantFieldName: string;
|
|
7
10
|
tenantFieldName: string;
|
|
8
11
|
tenantsCollectionSlug: string;
|
|
9
12
|
useAsTitle: string;
|
|
13
|
+
userHasAccessToAllTenants: Required<MultiTenantPluginConfig<any>>['userHasAccessToAllTenants'];
|
|
10
14
|
viewType: ViewTypes;
|
|
11
15
|
} & ServerProps;
|
|
12
16
|
export declare const GlobalViewRedirect: (args: Args) => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/GlobalViewRedirect/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/GlobalViewRedirect/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAKrE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAI7D,KAAK,IAAI,GAAG;IACV,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,cAAc,CAAA;IAC9B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,oBAAoB,EAAE,MAAM,CAAA;IAC5B,0BAA0B,EAAE,MAAM,CAAA;IAClC,eAAe,EAAE,MAAM,CAAA;IACvB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,yBAAyB,EAAE,QAAQ,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAA;IAC9F,QAAQ,EAAE,SAAS,CAAA;CACpB,GAAG,WAAW,CAAA;AAEf,eAAO,MAAM,kBAAkB,SAAgB,IAAI,kBAwBlD,CAAA"}
|
|
@@ -12,9 +12,12 @@ export const GlobalViewRedirect = async (args)=>{
|
|
|
12
12
|
headers,
|
|
13
13
|
payload: args.payload,
|
|
14
14
|
tenantFieldName: args.tenantFieldName,
|
|
15
|
+
tenantsArrayFieldName: args.tenantArrayFieldName,
|
|
16
|
+
tenantsArrayTenantFieldName: args.tenantArrayTenantFieldName,
|
|
15
17
|
tenantsCollectionSlug: args.tenantsCollectionSlug,
|
|
16
18
|
useAsTitle: args.useAsTitle,
|
|
17
19
|
user: args.user,
|
|
20
|
+
userHasAccessToAllTenants: args.userHasAccessToAllTenants,
|
|
18
21
|
view: args.viewType
|
|
19
22
|
});
|
|
20
23
|
if (redirectRoute) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/GlobalViewRedirect/index.ts"],"sourcesContent":["import type { CollectionSlug, ServerProps, ViewTypes } from 'payload'\n\nimport { headers as getHeaders } from 'next/headers.js'\nimport { redirect } from 'next/navigation.js'\n\nimport { getGlobalViewRedirect } from '../../utilities/getGlobalViewRedirect.js'\n\ntype Args = {\n basePath?: string\n collectionSlug: CollectionSlug\n docID?: number | string\n globalSlugs: string[]\n tenantFieldName: string\n tenantsCollectionSlug: string\n useAsTitle: string\n viewType: ViewTypes\n} & ServerProps\n\nexport const GlobalViewRedirect = async (args: Args) => {\n const collectionSlug = args?.collectionSlug\n if (collectionSlug && args.globalSlugs?.includes(collectionSlug)) {\n const headers = await getHeaders()\n const redirectRoute = await getGlobalViewRedirect({\n slug: collectionSlug,\n basePath: args.basePath,\n docID: args.docID,\n headers,\n payload: args.payload,\n tenantFieldName: args.tenantFieldName,\n tenantsCollectionSlug: args.tenantsCollectionSlug,\n useAsTitle: args.useAsTitle,\n user: args.user,\n view: args.viewType,\n })\n\n if (redirectRoute) {\n redirect(redirectRoute)\n }\n }\n}\n"],"names":["headers","getHeaders","redirect","getGlobalViewRedirect","GlobalViewRedirect","args","collectionSlug","globalSlugs","includes","redirectRoute","slug","basePath","docID","payload","tenantFieldName","tenantsCollectionSlug","useAsTitle","user","view","viewType"],"mappings":"AAEA,SAASA,WAAWC,UAAU,QAAQ,kBAAiB;AACvD,SAASC,QAAQ,QAAQ,qBAAoB;
|
|
1
|
+
{"version":3,"sources":["../../../src/components/GlobalViewRedirect/index.ts"],"sourcesContent":["import type { CollectionSlug, ServerProps, ViewTypes } from 'payload'\n\nimport { headers as getHeaders } from 'next/headers.js'\nimport { redirect } from 'next/navigation.js'\n\nimport type { MultiTenantPluginConfig } from '../../types.js'\n\nimport { getGlobalViewRedirect } from '../../utilities/getGlobalViewRedirect.js'\n\ntype Args = {\n basePath?: string\n collectionSlug: CollectionSlug\n docID?: number | string\n globalSlugs: string[]\n tenantArrayFieldName: string\n tenantArrayTenantFieldName: string\n tenantFieldName: string\n tenantsCollectionSlug: string\n useAsTitle: string\n userHasAccessToAllTenants: Required<MultiTenantPluginConfig<any>>['userHasAccessToAllTenants']\n viewType: ViewTypes\n} & ServerProps\n\nexport const GlobalViewRedirect = async (args: Args) => {\n const collectionSlug = args?.collectionSlug\n if (collectionSlug && args.globalSlugs?.includes(collectionSlug)) {\n const headers = await getHeaders()\n const redirectRoute = await getGlobalViewRedirect({\n slug: collectionSlug,\n basePath: args.basePath,\n docID: args.docID,\n headers,\n payload: args.payload,\n tenantFieldName: args.tenantFieldName,\n tenantsArrayFieldName: args.tenantArrayFieldName,\n tenantsArrayTenantFieldName: args.tenantArrayTenantFieldName,\n tenantsCollectionSlug: args.tenantsCollectionSlug,\n useAsTitle: args.useAsTitle,\n user: args.user,\n userHasAccessToAllTenants: args.userHasAccessToAllTenants,\n view: args.viewType,\n })\n\n if (redirectRoute) {\n redirect(redirectRoute)\n }\n }\n}\n"],"names":["headers","getHeaders","redirect","getGlobalViewRedirect","GlobalViewRedirect","args","collectionSlug","globalSlugs","includes","redirectRoute","slug","basePath","docID","payload","tenantFieldName","tenantsArrayFieldName","tenantArrayFieldName","tenantsArrayTenantFieldName","tenantArrayTenantFieldName","tenantsCollectionSlug","useAsTitle","user","userHasAccessToAllTenants","view","viewType"],"mappings":"AAEA,SAASA,WAAWC,UAAU,QAAQ,kBAAiB;AACvD,SAASC,QAAQ,QAAQ,qBAAoB;AAI7C,SAASC,qBAAqB,QAAQ,2CAA0C;AAgBhF,OAAO,MAAMC,qBAAqB,OAAOC;IACvC,MAAMC,iBAAiBD,MAAMC;IAC7B,IAAIA,kBAAkBD,KAAKE,WAAW,EAAEC,SAASF,iBAAiB;QAChE,MAAMN,UAAU,MAAMC;QACtB,MAAMQ,gBAAgB,MAAMN,sBAAsB;YAChDO,MAAMJ;YACNK,UAAUN,KAAKM,QAAQ;YACvBC,OAAOP,KAAKO,KAAK;YACjBZ;YACAa,SAASR,KAAKQ,OAAO;YACrBC,iBAAiBT,KAAKS,eAAe;YACrCC,uBAAuBV,KAAKW,oBAAoB;YAChDC,6BAA6BZ,KAAKa,0BAA0B;YAC5DC,uBAAuBd,KAAKc,qBAAqB;YACjDC,YAAYf,KAAKe,UAAU;YAC3BC,MAAMhB,KAAKgB,IAAI;YACfC,2BAA2BjB,KAAKiB,yBAAyB;YACzDC,MAAMlB,KAAKmB,QAAQ;QACrB;QAEA,IAAIf,eAAe;YACjBP,SAASO;QACX;IACF;AACF,EAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Endpoint } from 'payload';
|
|
2
|
+
import type { MultiTenantPluginConfig } from '../types.js';
|
|
3
|
+
export declare const getTenantOptionsEndpoint: <ConfigType>({ tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, userHasAccessToAllTenants, }: {
|
|
4
|
+
tenantsArrayFieldName: string;
|
|
5
|
+
tenantsArrayTenantFieldName: string;
|
|
6
|
+
tenantsCollectionSlug: string;
|
|
7
|
+
useAsTitle: string;
|
|
8
|
+
userHasAccessToAllTenants: Required<MultiTenantPluginConfig<ConfigType>>["userHasAccessToAllTenants"];
|
|
9
|
+
}) => Endpoint;
|
|
10
|
+
//# sourceMappingURL=getTenantOptionsEndpoint.d.ts.map
|
|
@@ -0,0 +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,yHAMhD;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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { APIError } from 'payload';
|
|
2
|
+
import { getTenantOptions } from '../utilities/getTenantOptions.js';
|
|
3
|
+
export const getTenantOptionsEndpoint = ({ tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, userHasAccessToAllTenants })=>({
|
|
4
|
+
handler: async (req)=>{
|
|
5
|
+
const { payload, user } = req;
|
|
6
|
+
if (!user) {
|
|
7
|
+
throw new APIError('Unauthorized', 401);
|
|
8
|
+
}
|
|
9
|
+
const tenantOptions = await getTenantOptions({
|
|
10
|
+
payload,
|
|
11
|
+
tenantsArrayFieldName,
|
|
12
|
+
tenantsArrayTenantFieldName,
|
|
13
|
+
tenantsCollectionSlug,
|
|
14
|
+
useAsTitle,
|
|
15
|
+
user,
|
|
16
|
+
userHasAccessToAllTenants
|
|
17
|
+
});
|
|
18
|
+
return new Response(JSON.stringify({
|
|
19
|
+
tenantOptions
|
|
20
|
+
}));
|
|
21
|
+
},
|
|
22
|
+
method: 'get',
|
|
23
|
+
path: '/populate-tenant-options'
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=getTenantOptionsEndpoint.js.map
|
|
@@ -0,0 +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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;AAKvD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAoB,MAAM,EAAE,MAAM,SAAS,CAAA;AAKvD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAA;AAezD,eAAO,MAAM,iBAAiB,GAC3B,UAAU,gBAAgB,uBAAuB,CAAC,UAAU,CAAC,sBAC7C,MAAM,KAAG,MAyXzB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { deepMergeSimple } from 'payload';
|
|
2
2
|
import { defaults } from './defaults.js';
|
|
3
|
+
import { getTenantOptionsEndpoint } from './endpoints/getTenantOptionsEndpoint.js';
|
|
3
4
|
import { tenantField } from './fields/tenantField/index.js';
|
|
4
5
|
import { tenantsArrayField } from './fields/tenantsArrayField/index.js';
|
|
5
6
|
import { addTenantCleanup } from './hooks/afterTenantDelete.js';
|
|
@@ -198,6 +199,16 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
|
|
|
198
199
|
}
|
|
199
200
|
}
|
|
200
201
|
});
|
|
202
|
+
collection.endpoints = [
|
|
203
|
+
...collection.endpoints || [],
|
|
204
|
+
getTenantOptionsEndpoint({
|
|
205
|
+
tenantsArrayFieldName,
|
|
206
|
+
tenantsArrayTenantFieldName,
|
|
207
|
+
tenantsCollectionSlug,
|
|
208
|
+
useAsTitle: tenantCollection.admin?.useAsTitle || 'id',
|
|
209
|
+
userHasAccessToAllTenants
|
|
210
|
+
})
|
|
211
|
+
];
|
|
201
212
|
} else if (pluginConfig.collections?.[collection.slug]) {
|
|
202
213
|
const isGlobal = Boolean(pluginConfig.collections[collection.slug]?.isGlobal);
|
|
203
214
|
if (isGlobal) {
|
|
@@ -259,8 +270,11 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
|
|
|
259
270
|
* Add TenantSelectionProvider to admin providers
|
|
260
271
|
*/ incomingConfig.admin.components.providers.push({
|
|
261
272
|
clientProps: {
|
|
273
|
+
tenantsArrayFieldName,
|
|
274
|
+
tenantsArrayTenantFieldName,
|
|
262
275
|
tenantsCollectionSlug: tenantCollection.slug,
|
|
263
|
-
useAsTitle: tenantCollection.admin?.useAsTitle || 'id'
|
|
276
|
+
useAsTitle: tenantCollection.admin?.useAsTitle || 'id',
|
|
277
|
+
userHasAccessToAllTenants
|
|
264
278
|
},
|
|
265
279
|
path: '@payloadcms/plugin-multi-tenant/rsc#TenantSelectionProvider'
|
|
266
280
|
});
|
|
@@ -273,8 +287,11 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
|
|
|
273
287
|
basePath,
|
|
274
288
|
globalSlugs: globalCollectionSlugs,
|
|
275
289
|
tenantFieldName,
|
|
290
|
+
tenantsArrayFieldName,
|
|
291
|
+
tenantsArrayTenantFieldName,
|
|
276
292
|
tenantsCollectionSlug,
|
|
277
|
-
useAsTitle: tenantCollection.admin?.useAsTitle || 'id'
|
|
293
|
+
useAsTitle: tenantCollection.admin?.useAsTitle || 'id',
|
|
294
|
+
userHasAccessToAllTenants
|
|
278
295
|
}
|
|
279
296
|
});
|
|
280
297
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { AcceptedLanguages } from '@payloadcms/translations'\nimport type { CollectionConfig, Config } from 'payload'\n\nimport { deepMergeSimple } from 'payload'\n\nimport type { PluginDefaultTranslationsObject } from './translations/types.js'\nimport type { MultiTenantPluginConfig } from './types.js'\n\nimport { defaults } from './defaults.js'\nimport { tenantField } from './fields/tenantField/index.js'\nimport { tenantsArrayField } from './fields/tenantsArrayField/index.js'\nimport { addTenantCleanup } from './hooks/afterTenantDelete.js'\nimport { filterDocumentsBySelectedTenant } from './list-filters/filterDocumentsBySelectedTenant.js'\nimport { filterTenantsBySelectedTenant } from './list-filters/filterTenantsBySelectedTenant.js'\nimport { filterUsersBySelectedTenant } from './list-filters/filterUsersBySelectedTenant.js'\nimport { translations } from './translations/index.js'\nimport { addCollectionAccess } from './utilities/addCollectionAccess.js'\nimport { addFilterOptionsToFields } from './utilities/addFilterOptionsToFields.js'\nimport { combineListFilters } from './utilities/combineListFilters.js'\n\nexport const multiTenantPlugin =\n <ConfigType>(pluginConfig: MultiTenantPluginConfig<ConfigType>) =>\n (incomingConfig: Config): Config => {\n if (pluginConfig.enabled === false) {\n return incomingConfig\n }\n\n /**\n * Set defaults\n */\n const userHasAccessToAllTenants: Required<\n MultiTenantPluginConfig<ConfigType>\n >['userHasAccessToAllTenants'] =\n typeof pluginConfig.userHasAccessToAllTenants === 'function'\n ? pluginConfig.userHasAccessToAllTenants\n : () => false\n const tenantsCollectionSlug = (pluginConfig.tenantsSlug =\n pluginConfig.tenantsSlug || defaults.tenantCollectionSlug)\n const tenantFieldName = pluginConfig?.tenantField?.name || defaults.tenantFieldName\n const tenantsArrayFieldName =\n pluginConfig?.tenantsArrayField?.arrayFieldName || defaults.tenantsArrayFieldName\n const tenantsArrayTenantFieldName =\n pluginConfig?.tenantsArrayField?.arrayTenantFieldName || defaults.tenantsArrayTenantFieldName\n const tenantSelectorLabel = pluginConfig.tenantSelectorLabel || defaults.tenantSelectorLabel\n const basePath = pluginConfig.basePath || defaults.basePath\n\n /**\n * Add defaults for admin properties\n */\n if (!incomingConfig.admin) {\n incomingConfig.admin = {}\n }\n if (!incomingConfig.admin?.components) {\n incomingConfig.admin.components = {\n actions: [],\n beforeNavLinks: [],\n providers: [],\n }\n }\n if (!incomingConfig.admin.components?.providers) {\n incomingConfig.admin.components.providers = []\n }\n if (!incomingConfig.admin.components?.actions) {\n incomingConfig.admin.components.actions = []\n }\n if (!incomingConfig.admin.components?.beforeNavLinks) {\n incomingConfig.admin.components.beforeNavLinks = []\n }\n if (!incomingConfig.collections) {\n incomingConfig.collections = []\n }\n\n /**\n * Add tenant selector localized labels\n */\n if (typeof tenantSelectorLabel === 'object') {\n if (!incomingConfig.i18n) {\n incomingConfig.i18n = {}\n }\n Object.entries(tenantSelectorLabel).forEach(([_locale, label]) => {\n const locale = _locale as AcceptedLanguages\n if (!incomingConfig.i18n) {\n incomingConfig.i18n = {}\n }\n if (!incomingConfig.i18n.translations) {\n incomingConfig.i18n.translations = {}\n }\n if (!(locale in incomingConfig.i18n.translations)) {\n incomingConfig.i18n.translations[locale] = {}\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n if (!('multiTenant' in incomingConfig.i18n.translations[locale])) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n incomingConfig.i18n.translations[locale].multiTenant = {}\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n incomingConfig.i18n.translations[locale].multiTenant.selectorLabel = label\n })\n }\n\n /**\n * Add tenants array field to users collection\n */\n const adminUsersCollection = incomingConfig.collections.find(({ slug, auth }) => {\n if (incomingConfig.admin?.user) {\n return slug === incomingConfig.admin.user\n } else if (auth) {\n return true\n }\n })\n\n if (!adminUsersCollection) {\n throw Error('An auth enabled collection was not found')\n }\n\n /**\n * Add tenants array field to users collection\n */\n if (pluginConfig?.tenantsArrayField?.includeDefaultField !== false) {\n adminUsersCollection.fields.push(\n tenantsArrayField({\n ...(pluginConfig?.tenantsArrayField || {}),\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n }),\n )\n }\n\n addCollectionAccess({\n adminUsersSlug: adminUsersCollection.slug,\n collection: adminUsersCollection,\n fieldName: `${tenantsArrayFieldName}.${tenantsArrayTenantFieldName}`,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n\n if (pluginConfig.useUsersTenantFilter !== false) {\n if (!adminUsersCollection.admin) {\n adminUsersCollection.admin = {}\n }\n\n adminUsersCollection.admin.baseListFilter = combineListFilters({\n baseListFilter: adminUsersCollection.admin?.baseListFilter,\n customFilter: (args) =>\n filterUsersBySelectedTenant({\n req: args.req,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n }),\n })\n }\n\n let tenantCollection: CollectionConfig | undefined\n\n const [collectionSlugs, globalCollectionSlugs] = Object.keys(pluginConfig.collections).reduce<\n [string[], string[]]\n >(\n (acc, slug) => {\n if (pluginConfig?.collections?.[slug]?.isGlobal) {\n acc[1].push(slug)\n } else {\n acc[0].push(slug)\n }\n\n return acc\n },\n [[], []],\n )\n\n /**\n * Modify collections\n */\n incomingConfig.collections.forEach((collection) => {\n /**\n * Modify tenants collection\n */\n if (collection.slug === tenantsCollectionSlug) {\n tenantCollection = collection\n\n if (pluginConfig.useTenantsCollectionAccess !== false) {\n /**\n * Add access control constraint to tenants collection\n * - constrains access a users assigned tenants\n */\n addCollectionAccess({\n adminUsersSlug: adminUsersCollection.slug,\n collection,\n fieldName: 'id',\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n }\n\n if (pluginConfig.useTenantsListFilter !== false) {\n /**\n * Add list filter to tenants collection\n * - filter by selected tenant\n */\n if (!collection.admin) {\n collection.admin = {}\n }\n\n collection.admin.baseListFilter = combineListFilters({\n baseListFilter: collection.admin?.baseListFilter,\n customFilter: (args) =>\n filterTenantsBySelectedTenant({\n req: args.req,\n tenantsCollectionSlug,\n }),\n })\n }\n\n if (pluginConfig.cleanupAfterTenantDelete !== false) {\n /**\n * Add cleanup logic when tenant is deleted\n * - delete documents related to tenant\n * - remove tenant from users\n */\n addTenantCleanup({\n collection,\n enabledSlugs: [...collectionSlugs, ...globalCollectionSlugs],\n tenantFieldName,\n tenantsCollectionSlug,\n usersSlug: adminUsersCollection.slug,\n usersTenantsArrayFieldName: tenantsArrayFieldName,\n usersTenantsArrayTenantFieldName: tenantsArrayTenantFieldName,\n })\n }\n\n /**\n * Add custom tenant field that watches and dispatches updates to the selector\n */\n collection.fields.push({\n name: '_watchTenant',\n type: 'ui',\n admin: {\n components: {\n Field: {\n path: '@payloadcms/plugin-multi-tenant/client#WatchTenantCollection',\n },\n },\n },\n })\n } else if (pluginConfig.collections?.[collection.slug]) {\n const isGlobal = Boolean(pluginConfig.collections[collection.slug]?.isGlobal)\n\n if (isGlobal) {\n collection.disableDuplicate = true\n }\n\n /**\n * Modify enabled collections\n */\n addFilterOptionsToFields({\n config: incomingConfig,\n fields: collection.fields,\n tenantEnabledCollectionSlugs: collectionSlugs,\n tenantEnabledGlobalSlugs: globalCollectionSlugs,\n tenantFieldName,\n tenantsCollectionSlug,\n })\n\n /**\n * Add tenant field to enabled collections\n */\n collection.fields.splice(\n 0,\n 0,\n tenantField({\n ...(pluginConfig?.tenantField || {}),\n name: tenantFieldName,\n debug: pluginConfig.debug,\n tenantsCollectionSlug,\n unique: isGlobal,\n }),\n )\n\n if (pluginConfig.collections[collection.slug]?.useBaseListFilter !== false) {\n /**\n * Add list filter to enabled collections\n * - filters results by selected tenant\n */\n if (!collection.admin) {\n collection.admin = {}\n }\n\n collection.admin.baseListFilter = combineListFilters({\n baseListFilter: collection.admin?.baseListFilter,\n customFilter: (args) =>\n filterDocumentsBySelectedTenant({\n req: args.req,\n tenantFieldName,\n tenantsCollectionSlug,\n }),\n })\n }\n\n if (pluginConfig.collections[collection.slug]?.useTenantAccess !== false) {\n /**\n * Add access control constraint to tenant enabled collection\n */\n addCollectionAccess({\n adminUsersSlug: adminUsersCollection.slug,\n collection,\n fieldName: tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n }\n }\n })\n\n if (!tenantCollection) {\n throw new Error(`Tenants collection not found with slug: ${tenantsCollectionSlug}`)\n }\n\n /**\n * Add TenantSelectionProvider to admin providers\n */\n incomingConfig.admin.components.providers.push({\n clientProps: {\n tenantsCollectionSlug: tenantCollection.slug,\n useAsTitle: tenantCollection.admin?.useAsTitle || 'id',\n },\n path: '@payloadcms/plugin-multi-tenant/rsc#TenantSelectionProvider',\n })\n\n /**\n * Add global redirect action\n */\n if (globalCollectionSlugs.length) {\n incomingConfig.admin.components.actions.push({\n path: '@payloadcms/plugin-multi-tenant/rsc#GlobalViewRedirect',\n serverProps: {\n basePath,\n globalSlugs: globalCollectionSlugs,\n tenantFieldName,\n tenantsCollectionSlug,\n useAsTitle: tenantCollection.admin?.useAsTitle || 'id',\n },\n })\n }\n\n /**\n * Add tenant selector to admin UI\n */\n incomingConfig.admin.components.beforeNavLinks.push({\n clientProps: {\n label: tenantSelectorLabel,\n },\n path: '@payloadcms/plugin-multi-tenant/client#TenantSelector',\n })\n\n /**\n * Merge plugin translations\n */\n\n const simplifiedTranslations = Object.entries(translations).reduce(\n (acc, [key, value]) => {\n acc[key] = value.translations\n return acc\n },\n {} as Record<string, PluginDefaultTranslationsObject>,\n )\n\n incomingConfig.i18n = {\n ...incomingConfig.i18n,\n translations: deepMergeSimple(\n simplifiedTranslations,\n incomingConfig.i18n?.translations ?? {},\n ),\n }\n\n return incomingConfig\n }\n"],"names":["deepMergeSimple","defaults","tenantField","tenantsArrayField","addTenantCleanup","filterDocumentsBySelectedTenant","filterTenantsBySelectedTenant","filterUsersBySelectedTenant","translations","addCollectionAccess","addFilterOptionsToFields","combineListFilters","multiTenantPlugin","pluginConfig","incomingConfig","enabled","userHasAccessToAllTenants","tenantsCollectionSlug","tenantsSlug","tenantCollectionSlug","tenantFieldName","name","tenantsArrayFieldName","arrayFieldName","tenantsArrayTenantFieldName","arrayTenantFieldName","tenantSelectorLabel","basePath","admin","components","actions","beforeNavLinks","providers","collections","i18n","Object","entries","forEach","_locale","label","locale","multiTenant","selectorLabel","adminUsersCollection","find","slug","auth","user","Error","includeDefaultField","fields","push","adminUsersSlug","collection","fieldName","useUsersTenantFilter","baseListFilter","customFilter","args","req","tenantCollection","collectionSlugs","globalCollectionSlugs","keys","reduce","acc","isGlobal","useTenantsCollectionAccess","useTenantsListFilter","cleanupAfterTenantDelete","enabledSlugs","usersSlug","usersTenantsArrayFieldName","usersTenantsArrayTenantFieldName","type","Field","path","Boolean","disableDuplicate","config","tenantEnabledCollectionSlugs","tenantEnabledGlobalSlugs","splice","debug","unique","useBaseListFilter","useTenantAccess","clientProps","useAsTitle","length","serverProps","globalSlugs","simplifiedTranslations","key","value"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { AcceptedLanguages } from '@payloadcms/translations'\nimport type { CollectionConfig, Config } from 'payload'\n\nimport { deepMergeSimple } from 'payload'\n\nimport type { PluginDefaultTranslationsObject } from './translations/types.js'\nimport type { MultiTenantPluginConfig } from './types.js'\n\nimport { defaults } from './defaults.js'\nimport { getTenantOptionsEndpoint } from './endpoints/getTenantOptionsEndpoint.js'\nimport { tenantField } from './fields/tenantField/index.js'\nimport { tenantsArrayField } from './fields/tenantsArrayField/index.js'\nimport { addTenantCleanup } from './hooks/afterTenantDelete.js'\nimport { filterDocumentsBySelectedTenant } from './list-filters/filterDocumentsBySelectedTenant.js'\nimport { filterTenantsBySelectedTenant } from './list-filters/filterTenantsBySelectedTenant.js'\nimport { filterUsersBySelectedTenant } from './list-filters/filterUsersBySelectedTenant.js'\nimport { translations } from './translations/index.js'\nimport { addCollectionAccess } from './utilities/addCollectionAccess.js'\nimport { addFilterOptionsToFields } from './utilities/addFilterOptionsToFields.js'\nimport { combineListFilters } from './utilities/combineListFilters.js'\n\nexport const multiTenantPlugin =\n <ConfigType>(pluginConfig: MultiTenantPluginConfig<ConfigType>) =>\n (incomingConfig: Config): Config => {\n if (pluginConfig.enabled === false) {\n return incomingConfig\n }\n\n /**\n * Set defaults\n */\n const userHasAccessToAllTenants: Required<\n MultiTenantPluginConfig<ConfigType>\n >['userHasAccessToAllTenants'] =\n typeof pluginConfig.userHasAccessToAllTenants === 'function'\n ? pluginConfig.userHasAccessToAllTenants\n : () => false\n const tenantsCollectionSlug = (pluginConfig.tenantsSlug =\n pluginConfig.tenantsSlug || defaults.tenantCollectionSlug)\n const tenantFieldName = pluginConfig?.tenantField?.name || defaults.tenantFieldName\n const tenantsArrayFieldName =\n pluginConfig?.tenantsArrayField?.arrayFieldName || defaults.tenantsArrayFieldName\n const tenantsArrayTenantFieldName =\n pluginConfig?.tenantsArrayField?.arrayTenantFieldName || defaults.tenantsArrayTenantFieldName\n const tenantSelectorLabel = pluginConfig.tenantSelectorLabel || defaults.tenantSelectorLabel\n const basePath = pluginConfig.basePath || defaults.basePath\n\n /**\n * Add defaults for admin properties\n */\n if (!incomingConfig.admin) {\n incomingConfig.admin = {}\n }\n if (!incomingConfig.admin?.components) {\n incomingConfig.admin.components = {\n actions: [],\n beforeNavLinks: [],\n providers: [],\n }\n }\n if (!incomingConfig.admin.components?.providers) {\n incomingConfig.admin.components.providers = []\n }\n if (!incomingConfig.admin.components?.actions) {\n incomingConfig.admin.components.actions = []\n }\n if (!incomingConfig.admin.components?.beforeNavLinks) {\n incomingConfig.admin.components.beforeNavLinks = []\n }\n if (!incomingConfig.collections) {\n incomingConfig.collections = []\n }\n\n /**\n * Add tenant selector localized labels\n */\n if (typeof tenantSelectorLabel === 'object') {\n if (!incomingConfig.i18n) {\n incomingConfig.i18n = {}\n }\n Object.entries(tenantSelectorLabel).forEach(([_locale, label]) => {\n const locale = _locale as AcceptedLanguages\n if (!incomingConfig.i18n) {\n incomingConfig.i18n = {}\n }\n if (!incomingConfig.i18n.translations) {\n incomingConfig.i18n.translations = {}\n }\n if (!(locale in incomingConfig.i18n.translations)) {\n incomingConfig.i18n.translations[locale] = {}\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n if (!('multiTenant' in incomingConfig.i18n.translations[locale])) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n incomingConfig.i18n.translations[locale].multiTenant = {}\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n incomingConfig.i18n.translations[locale].multiTenant.selectorLabel = label\n })\n }\n\n /**\n * Add tenants array field to users collection\n */\n const adminUsersCollection = incomingConfig.collections.find(({ slug, auth }) => {\n if (incomingConfig.admin?.user) {\n return slug === incomingConfig.admin.user\n } else if (auth) {\n return true\n }\n })\n\n if (!adminUsersCollection) {\n throw Error('An auth enabled collection was not found')\n }\n\n /**\n * Add tenants array field to users collection\n */\n if (pluginConfig?.tenantsArrayField?.includeDefaultField !== false) {\n adminUsersCollection.fields.push(\n tenantsArrayField({\n ...(pluginConfig?.tenantsArrayField || {}),\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n }),\n )\n }\n\n addCollectionAccess({\n adminUsersSlug: adminUsersCollection.slug,\n collection: adminUsersCollection,\n fieldName: `${tenantsArrayFieldName}.${tenantsArrayTenantFieldName}`,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n\n if (pluginConfig.useUsersTenantFilter !== false) {\n if (!adminUsersCollection.admin) {\n adminUsersCollection.admin = {}\n }\n\n adminUsersCollection.admin.baseListFilter = combineListFilters({\n baseListFilter: adminUsersCollection.admin?.baseListFilter,\n customFilter: (args) =>\n filterUsersBySelectedTenant({\n req: args.req,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n }),\n })\n }\n\n let tenantCollection: CollectionConfig | undefined\n\n const [collectionSlugs, globalCollectionSlugs] = Object.keys(pluginConfig.collections).reduce<\n [string[], string[]]\n >(\n (acc, slug) => {\n if (pluginConfig?.collections?.[slug]?.isGlobal) {\n acc[1].push(slug)\n } else {\n acc[0].push(slug)\n }\n\n return acc\n },\n [[], []],\n )\n\n /**\n * Modify collections\n */\n incomingConfig.collections.forEach((collection) => {\n /**\n * Modify tenants collection\n */\n if (collection.slug === tenantsCollectionSlug) {\n tenantCollection = collection\n\n if (pluginConfig.useTenantsCollectionAccess !== false) {\n /**\n * Add access control constraint to tenants collection\n * - constrains access a users assigned tenants\n */\n addCollectionAccess({\n adminUsersSlug: adminUsersCollection.slug,\n collection,\n fieldName: 'id',\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n }\n\n if (pluginConfig.useTenantsListFilter !== false) {\n /**\n * Add list filter to tenants collection\n * - filter by selected tenant\n */\n if (!collection.admin) {\n collection.admin = {}\n }\n\n collection.admin.baseListFilter = combineListFilters({\n baseListFilter: collection.admin?.baseListFilter,\n customFilter: (args) =>\n filterTenantsBySelectedTenant({\n req: args.req,\n tenantsCollectionSlug,\n }),\n })\n }\n\n if (pluginConfig.cleanupAfterTenantDelete !== false) {\n /**\n * Add cleanup logic when tenant is deleted\n * - delete documents related to tenant\n * - remove tenant from users\n */\n addTenantCleanup({\n collection,\n enabledSlugs: [...collectionSlugs, ...globalCollectionSlugs],\n tenantFieldName,\n tenantsCollectionSlug,\n usersSlug: adminUsersCollection.slug,\n usersTenantsArrayFieldName: tenantsArrayFieldName,\n usersTenantsArrayTenantFieldName: tenantsArrayTenantFieldName,\n })\n }\n\n /**\n * Add custom tenant field that watches and dispatches updates to the selector\n */\n collection.fields.push({\n name: '_watchTenant',\n type: 'ui',\n admin: {\n components: {\n Field: {\n path: '@payloadcms/plugin-multi-tenant/client#WatchTenantCollection',\n },\n },\n },\n })\n\n collection.endpoints = [\n ...(collection.endpoints || []),\n getTenantOptionsEndpoint<ConfigType>({\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle: tenantCollection.admin?.useAsTitle || 'id',\n userHasAccessToAllTenants,\n }),\n ]\n } else if (pluginConfig.collections?.[collection.slug]) {\n const isGlobal = Boolean(pluginConfig.collections[collection.slug]?.isGlobal)\n\n if (isGlobal) {\n collection.disableDuplicate = true\n }\n\n /**\n * Modify enabled collections\n */\n addFilterOptionsToFields({\n config: incomingConfig,\n fields: collection.fields,\n tenantEnabledCollectionSlugs: collectionSlugs,\n tenantEnabledGlobalSlugs: globalCollectionSlugs,\n tenantFieldName,\n tenantsCollectionSlug,\n })\n\n /**\n * Add tenant field to enabled collections\n */\n collection.fields.splice(\n 0,\n 0,\n tenantField({\n ...(pluginConfig?.tenantField || {}),\n name: tenantFieldName,\n debug: pluginConfig.debug,\n tenantsCollectionSlug,\n unique: isGlobal,\n }),\n )\n\n if (pluginConfig.collections[collection.slug]?.useBaseListFilter !== false) {\n /**\n * Add list filter to enabled collections\n * - filters results by selected tenant\n */\n if (!collection.admin) {\n collection.admin = {}\n }\n\n collection.admin.baseListFilter = combineListFilters({\n baseListFilter: collection.admin?.baseListFilter,\n customFilter: (args) =>\n filterDocumentsBySelectedTenant({\n req: args.req,\n tenantFieldName,\n tenantsCollectionSlug,\n }),\n })\n }\n\n if (pluginConfig.collections[collection.slug]?.useTenantAccess !== false) {\n /**\n * Add access control constraint to tenant enabled collection\n */\n addCollectionAccess({\n adminUsersSlug: adminUsersCollection.slug,\n collection,\n fieldName: tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n }\n }\n })\n\n if (!tenantCollection) {\n throw new Error(`Tenants collection not found with slug: ${tenantsCollectionSlug}`)\n }\n\n /**\n * Add TenantSelectionProvider to admin providers\n */\n incomingConfig.admin.components.providers.push({\n clientProps: {\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug: tenantCollection.slug,\n useAsTitle: tenantCollection.admin?.useAsTitle || 'id',\n userHasAccessToAllTenants,\n },\n path: '@payloadcms/plugin-multi-tenant/rsc#TenantSelectionProvider',\n })\n\n /**\n * Add global redirect action\n */\n if (globalCollectionSlugs.length) {\n incomingConfig.admin.components.actions.push({\n path: '@payloadcms/plugin-multi-tenant/rsc#GlobalViewRedirect',\n serverProps: {\n basePath,\n globalSlugs: globalCollectionSlugs,\n tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle: tenantCollection.admin?.useAsTitle || 'id',\n userHasAccessToAllTenants,\n },\n })\n }\n\n /**\n * Add tenant selector to admin UI\n */\n incomingConfig.admin.components.beforeNavLinks.push({\n clientProps: {\n label: tenantSelectorLabel,\n },\n path: '@payloadcms/plugin-multi-tenant/client#TenantSelector',\n })\n\n /**\n * Merge plugin translations\n */\n\n const simplifiedTranslations = Object.entries(translations).reduce(\n (acc, [key, value]) => {\n acc[key] = value.translations\n return acc\n },\n {} as Record<string, PluginDefaultTranslationsObject>,\n )\n\n incomingConfig.i18n = {\n ...incomingConfig.i18n,\n translations: deepMergeSimple(\n simplifiedTranslations,\n incomingConfig.i18n?.translations ?? {},\n ),\n }\n\n return incomingConfig\n }\n"],"names":["deepMergeSimple","defaults","getTenantOptionsEndpoint","tenantField","tenantsArrayField","addTenantCleanup","filterDocumentsBySelectedTenant","filterTenantsBySelectedTenant","filterUsersBySelectedTenant","translations","addCollectionAccess","addFilterOptionsToFields","combineListFilters","multiTenantPlugin","pluginConfig","incomingConfig","enabled","userHasAccessToAllTenants","tenantsCollectionSlug","tenantsSlug","tenantCollectionSlug","tenantFieldName","name","tenantsArrayFieldName","arrayFieldName","tenantsArrayTenantFieldName","arrayTenantFieldName","tenantSelectorLabel","basePath","admin","components","actions","beforeNavLinks","providers","collections","i18n","Object","entries","forEach","_locale","label","locale","multiTenant","selectorLabel","adminUsersCollection","find","slug","auth","user","Error","includeDefaultField","fields","push","adminUsersSlug","collection","fieldName","useUsersTenantFilter","baseListFilter","customFilter","args","req","tenantCollection","collectionSlugs","globalCollectionSlugs","keys","reduce","acc","isGlobal","useTenantsCollectionAccess","useTenantsListFilter","cleanupAfterTenantDelete","enabledSlugs","usersSlug","usersTenantsArrayFieldName","usersTenantsArrayTenantFieldName","type","Field","path","endpoints","useAsTitle","Boolean","disableDuplicate","config","tenantEnabledCollectionSlugs","tenantEnabledGlobalSlugs","splice","debug","unique","useBaseListFilter","useTenantAccess","clientProps","length","serverProps","globalSlugs","simplifiedTranslations","key","value"],"mappings":"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"}
|
|
@@ -51,13 +51,11 @@ type ContextType = {
|
|
|
51
51
|
label: string;
|
|
52
52
|
}) => void;
|
|
53
53
|
};
|
|
54
|
-
export declare const TenantSelectionProviderClient: ({ children,
|
|
54
|
+
export declare const TenantSelectionProviderClient: ({ children, initialTenantOptions, initialValue, tenantsCollectionSlug, }: {
|
|
55
55
|
children: React.ReactNode;
|
|
56
|
+
initialTenantOptions: OptionObject[];
|
|
56
57
|
initialValue?: number | string;
|
|
57
|
-
tenantCookie?: string;
|
|
58
|
-
tenantOptions: OptionObject[];
|
|
59
58
|
tenantsCollectionSlug: string;
|
|
60
|
-
useAsTitle: string;
|
|
61
59
|
}) => React.JSX.Element;
|
|
62
60
|
export declare const useTenantSelection: () => ContextType;
|
|
63
61
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../../../src/providers/TenantSelectionProvider/index.client.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAI3C,OAAO,KAAwB,MAAM,OAAO,CAAA;AAE5C,KAAK,WAAW,GAAG;IACjB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAA;IAClC;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB;;OAEG;IACH,gBAAgB,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IAC7C;;OAEG;IACH,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAA;IACtF;;OAEG;IACH,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAA;IAC1D;;;;;OAKG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAA;IACjF;;OAEG;IACH,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAChC;;OAEG;IACH,aAAa,EAAE,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CACtE,CAAA;AAaD,eAAO,MAAM,6BAA6B,
|
|
1
|
+
{"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../../../src/providers/TenantSelectionProvider/index.client.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAI3C,OAAO,KAAwB,MAAM,OAAO,CAAA;AAE5C,KAAK,WAAW,GAAG;IACjB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAA;IAClC;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB;;OAEG;IACH,gBAAgB,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IAC7C;;OAEG;IACH,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAA;IACtF;;OAEG;IACH,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAA;IAC1D;;;;;OAKG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAA;IACjF;;OAEG;IACH,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAChC;;OAEG;IACH,aAAa,EAAE,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CACtE,CAAA;AAaD,eAAO,MAAM,6BAA6B,6EAKvC;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,oBAAoB,EAAE,YAAY,EAAE,CAAA;IACpC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC9B,qBAAqB,EAAE,MAAM,CAAA;CAC9B,sBAiJA,CAAA;AAED,eAAO,MAAM,kBAAkB,mBAA2B,CAAA"}
|
|
@@ -13,7 +13,7 @@ const Context = /*#__PURE__*/ createContext({
|
|
|
13
13
|
syncTenants: ()=>Promise.resolve(),
|
|
14
14
|
updateTenants: ()=>null
|
|
15
15
|
});
|
|
16
|
-
export const TenantSelectionProviderClient = ({ children,
|
|
16
|
+
export const TenantSelectionProviderClient = ({ children, initialTenantOptions, initialValue, tenantsCollectionSlug })=>{
|
|
17
17
|
const [selectedTenantID, setSelectedTenantID] = React.useState(initialValue);
|
|
18
18
|
const [modified, setModified] = React.useState(false);
|
|
19
19
|
const [entityType, setEntityType] = React.useState(undefined);
|
|
@@ -24,7 +24,7 @@ export const TenantSelectionProviderClient = ({ children, initialValue, tenantCo
|
|
|
24
24
|
]);
|
|
25
25
|
const prevUserID = React.useRef(userID);
|
|
26
26
|
const userChanged = userID !== prevUserID.current;
|
|
27
|
-
const [tenantOptions, setTenantOptions] = React.useState(()=>
|
|
27
|
+
const [tenantOptions, setTenantOptions] = React.useState(()=>initialTenantOptions);
|
|
28
28
|
const selectedTenantLabel = React.useMemo(()=>tenantOptions.find((option)=>option.value === selectedTenantID)?.label, [
|
|
29
29
|
selectedTenantID,
|
|
30
30
|
tenantOptions
|
|
@@ -79,19 +79,16 @@ export const TenantSelectionProviderClient = ({ children, initialValue, tenantCo
|
|
|
79
79
|
]);
|
|
80
80
|
const syncTenants = React.useCallback(async ()=>{
|
|
81
81
|
try {
|
|
82
|
-
const req = await fetch(`${config.serverURL}${config.routes.api}/${tenantsCollectionSlug}
|
|
82
|
+
const req = await fetch(`${config.serverURL}${config.routes.api}/${tenantsCollectionSlug}/populate-tenant-options`, {
|
|
83
83
|
credentials: 'include',
|
|
84
84
|
method: 'GET'
|
|
85
85
|
});
|
|
86
86
|
const result = await req.json();
|
|
87
|
-
if (result.
|
|
88
|
-
setTenantOptions(result.
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (result.totalDocs === 1) {
|
|
93
|
-
setSelectedTenantID(result.docs[0].id);
|
|
94
|
-
setCookie(String(result.docs[0].id));
|
|
87
|
+
if (result.tenantOptions && userID) {
|
|
88
|
+
setTenantOptions(result.tenantOptions);
|
|
89
|
+
if (result.tenantOptions.length === 1) {
|
|
90
|
+
setSelectedTenantID(result.tenantOptions[0].value);
|
|
91
|
+
setCookie(String(result.tenantOptions[0].value));
|
|
95
92
|
}
|
|
96
93
|
}
|
|
97
94
|
} catch (e) {
|
|
@@ -101,7 +98,6 @@ export const TenantSelectionProviderClient = ({ children, initialValue, tenantCo
|
|
|
101
98
|
config.serverURL,
|
|
102
99
|
config.routes.api,
|
|
103
100
|
tenantsCollectionSlug,
|
|
104
|
-
useAsTitle,
|
|
105
101
|
setCookie,
|
|
106
102
|
userID
|
|
107
103
|
]);
|
|
@@ -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 initialValue,\n tenantCookie,\n tenantOptions: tenantOptionsFromProps,\n tenantsCollectionSlug,\n useAsTitle,\n}: {\n children: React.ReactNode\n initialValue?: number | string\n tenantCookie?: string\n tenantOptions: OptionObject[]\n tenantsCollectionSlug: string\n useAsTitle: 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 () => tenantOptionsFromProps,\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}?select[${useAsTitle}]=true&limit=0&depth=0`,\n {\n credentials: 'include',\n method: 'GET',\n },\n )\n\n const result = await req.json()\n\n if (result.docs && userID) {\n setTenantOptions(\n result.docs.map((doc: Record<string, number | string>) => ({\n label: doc[useAsTitle],\n value: doc.id,\n })),\n )\n\n if (result.totalDocs === 1) {\n setSelectedTenantID(result.docs[0].id)\n setCookie(String(result.docs[0].id))\n }\n }\n } catch (e) {\n toast.error(`Error fetching tenants`)\n }\n }, [config.serverURL, config.routes.api, tenantsCollectionSlug, useAsTitle, 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","initialValue","tenantCookie","tenantOptions","tenantOptionsFromProps","tenantsCollectionSlug","useAsTitle","setSelectedTenantID","useState","modified","user","config","userID","useMemo","id","prevUserID","useRef","userChanged","current","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","docs","map","doc","totalDocs","e","error","prev","currentTenant","useEffect","span","data-selected-tenant-id","data-selected-tenant-title","useTenantSelection","use"],"mappings":"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"}
|
|
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":"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"}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import type { Payload, TypedUser } from 'payload';
|
|
2
|
-
type
|
|
2
|
+
import type { MultiTenantPluginConfig } from '../../types.js';
|
|
3
|
+
type Args<ConfigType> = {
|
|
3
4
|
children: React.ReactNode;
|
|
4
5
|
payload: Payload;
|
|
6
|
+
tenantsArrayFieldName: string;
|
|
7
|
+
tenantsArrayTenantFieldName: string;
|
|
5
8
|
tenantsCollectionSlug: string;
|
|
6
9
|
useAsTitle: string;
|
|
7
10
|
user: TypedUser;
|
|
11
|
+
userHasAccessToAllTenants: Required<MultiTenantPluginConfig<ConfigType>>['userHasAccessToAllTenants'];
|
|
8
12
|
};
|
|
9
|
-
export declare const TenantSelectionProvider: ({ children, payload, tenantsCollectionSlug, useAsTitle, user, }: Args) => Promise<import("react").JSX.Element>;
|
|
13
|
+
export declare const TenantSelectionProvider: ({ children, payload, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, user, userHasAccessToAllTenants, }: Args<any>) => Promise<import("react").JSX.Element>;
|
|
10
14
|
export {};
|
|
11
15
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/TenantSelectionProvider/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/TenantSelectionProvider/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAIjD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAK7D,KAAK,IAAI,CAAC,UAAU,IAAI;IACtB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,2BAA2B,EAAE,MAAM,CAAA;IACnC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,SAAS,CAAA;IACf,yBAAyB,EAAE,QAAQ,CACjC,uBAAuB,CAAC,UAAU,CAAC,CACpC,CAAC,2BAA2B,CAAC,CAAA;CAC/B,CAAA;AAED,eAAO,MAAM,uBAAuB,mJASjC,IAAI,CAAC,GAAG,CAAC,yCAyCX,CAAA"}
|
|
@@ -1,26 +1,19 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { cookies as getCookies } from 'next/headers.js';
|
|
3
|
-
import {
|
|
3
|
+
import { getTenantOptions } from '../../utilities/getTenantOptions.js';
|
|
4
4
|
import { TenantSelectionProviderClient } from './index.client.js';
|
|
5
|
-
export const TenantSelectionProvider = async ({ children, payload, tenantsCollectionSlug, useAsTitle, user })=>{
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
tenantOptions = docs.map((doc)=>({
|
|
16
|
-
label: String(doc[useAsTitle]),
|
|
17
|
-
value: doc.id
|
|
18
|
-
}));
|
|
19
|
-
} catch (_) {
|
|
20
|
-
// user likely does not have access
|
|
21
|
-
}
|
|
5
|
+
export const TenantSelectionProvider = async ({ children, payload, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, user, userHasAccessToAllTenants })=>{
|
|
6
|
+
const tenantOptions = await getTenantOptions({
|
|
7
|
+
payload,
|
|
8
|
+
tenantsArrayFieldName,
|
|
9
|
+
tenantsArrayTenantFieldName,
|
|
10
|
+
tenantsCollectionSlug,
|
|
11
|
+
useAsTitle,
|
|
12
|
+
user,
|
|
13
|
+
userHasAccessToAllTenants
|
|
14
|
+
});
|
|
22
15
|
const cookies = await getCookies();
|
|
23
|
-
|
|
16
|
+
const tenantCookie = cookies.get('payload-tenant')?.value;
|
|
24
17
|
let initialValue = undefined;
|
|
25
18
|
/**
|
|
26
19
|
* Ensure the cookie is a valid tenant
|
|
@@ -33,15 +26,12 @@ export const TenantSelectionProvider = async ({ children, payload, tenantsCollec
|
|
|
33
26
|
/**
|
|
34
27
|
* If the there was no cookie or the cookie was an invalid tenantID set intialValue
|
|
35
28
|
*/ if (!initialValue) {
|
|
36
|
-
tenantCookie = undefined;
|
|
37
29
|
initialValue = tenantOptions.length > 1 ? undefined : tenantOptions[0]?.value;
|
|
38
30
|
}
|
|
39
31
|
return /*#__PURE__*/ _jsx(TenantSelectionProviderClient, {
|
|
32
|
+
initialTenantOptions: tenantOptions,
|
|
40
33
|
initialValue: initialValue,
|
|
41
|
-
tenantCookie: tenantCookie,
|
|
42
|
-
tenantOptions: tenantOptions,
|
|
43
34
|
tenantsCollectionSlug: tenantsCollectionSlug,
|
|
44
|
-
useAsTitle: useAsTitle,
|
|
45
35
|
children: children
|
|
46
36
|
});
|
|
47
37
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/providers/TenantSelectionProvider/index.tsx"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"sources":["../../../src/providers/TenantSelectionProvider/index.tsx"],"sourcesContent":["import type { Payload, TypedUser } from 'payload'\n\nimport { cookies as getCookies } from 'next/headers.js'\n\nimport type { MultiTenantPluginConfig } from '../../types.js'\n\nimport { getTenantOptions } from '../../utilities/getTenantOptions.js'\nimport { TenantSelectionProviderClient } from './index.client.js'\n\ntype Args<ConfigType> = {\n children: React.ReactNode\n payload: Payload\n tenantsArrayFieldName: string\n tenantsArrayTenantFieldName: string\n tenantsCollectionSlug: string\n useAsTitle: string\n user: TypedUser\n userHasAccessToAllTenants: Required<\n MultiTenantPluginConfig<ConfigType>\n >['userHasAccessToAllTenants']\n}\n\nexport const TenantSelectionProvider = async ({\n children,\n payload,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n userHasAccessToAllTenants,\n}: Args<any>) => {\n const tenantOptions = await getTenantOptions({\n payload,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n userHasAccessToAllTenants,\n })\n\n const cookies = await getCookies()\n const tenantCookie = cookies.get('payload-tenant')?.value\n let initialValue = undefined\n\n /**\n * Ensure the cookie is a valid tenant\n */\n if (tenantCookie) {\n const matchingOption = tenantOptions.find((option) => String(option.value) === tenantCookie)\n if (matchingOption) {\n initialValue = matchingOption.value\n }\n }\n\n /**\n * If the there was no cookie or the cookie was an invalid tenantID set intialValue\n */\n if (!initialValue) {\n initialValue = tenantOptions.length > 1 ? undefined : tenantOptions[0]?.value\n }\n\n return (\n <TenantSelectionProviderClient\n initialTenantOptions={tenantOptions}\n initialValue={initialValue}\n tenantsCollectionSlug={tenantsCollectionSlug}\n >\n {children}\n </TenantSelectionProviderClient>\n )\n}\n"],"names":["cookies","getCookies","getTenantOptions","TenantSelectionProviderClient","TenantSelectionProvider","children","payload","tenantsArrayFieldName","tenantsArrayTenantFieldName","tenantsCollectionSlug","useAsTitle","user","userHasAccessToAllTenants","tenantOptions","tenantCookie","get","value","initialValue","undefined","matchingOption","find","option","String","length","initialTenantOptions"],"mappings":";AAEA,SAASA,WAAWC,UAAU,QAAQ,kBAAiB;AAIvD,SAASC,gBAAgB,QAAQ,sCAAqC;AACtE,SAASC,6BAA6B,QAAQ,oBAAmB;AAejE,OAAO,MAAMC,0BAA0B,OAAO,EAC5CC,QAAQ,EACRC,OAAO,EACPC,qBAAqB,EACrBC,2BAA2B,EAC3BC,qBAAqB,EACrBC,UAAU,EACVC,IAAI,EACJC,yBAAyB,EACf;IACV,MAAMC,gBAAgB,MAAMX,iBAAiB;QAC3CI;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;IACF;IAEA,MAAMZ,UAAU,MAAMC;IACtB,MAAMa,eAAed,QAAQe,GAAG,CAAC,mBAAmBC;IACpD,IAAIC,eAAeC;IAEnB;;GAEC,GACD,IAAIJ,cAAc;QAChB,MAAMK,iBAAiBN,cAAcO,IAAI,CAAC,CAACC,SAAWC,OAAOD,OAAOL,KAAK,MAAMF;QAC/E,IAAIK,gBAAgB;YAClBF,eAAeE,eAAeH,KAAK;QACrC;IACF;IAEA;;GAEC,GACD,IAAI,CAACC,cAAc;QACjBA,eAAeJ,cAAcU,MAAM,GAAG,IAAIL,YAAYL,aAAa,CAAC,EAAE,EAAEG;IAC1E;IAEA,qBACE,KAACb;QACCqB,sBAAsBX;QACtBI,cAAcA;QACdR,uBAAuBA;kBAEtBJ;;AAGP,EAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Payload, TypedUser, ViewTypes } from 'payload';
|
|
2
|
+
import type { MultiTenantPluginConfig } from '../types.js';
|
|
2
3
|
type Args = {
|
|
3
4
|
basePath?: string;
|
|
4
5
|
docID?: number | string;
|
|
@@ -6,11 +7,14 @@ type Args = {
|
|
|
6
7
|
payload: Payload;
|
|
7
8
|
slug: string;
|
|
8
9
|
tenantFieldName: string;
|
|
10
|
+
tenantsArrayFieldName: string;
|
|
11
|
+
tenantsArrayTenantFieldName: string;
|
|
9
12
|
tenantsCollectionSlug: string;
|
|
10
13
|
useAsTitle: string;
|
|
11
14
|
user?: TypedUser;
|
|
15
|
+
userHasAccessToAllTenants: Required<MultiTenantPluginConfig<any>>['userHasAccessToAllTenants'];
|
|
12
16
|
view: ViewTypes;
|
|
13
17
|
};
|
|
14
|
-
export declare function getGlobalViewRedirect({ slug, basePath, docID, headers, payload, tenantFieldName, tenantsCollectionSlug, useAsTitle, user, view, }: Args): Promise<string | void>;
|
|
18
|
+
export declare function getGlobalViewRedirect({ slug, basePath, docID, headers, payload, tenantFieldName, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, user, userHasAccessToAllTenants, view, }: Args): Promise<string | void>;
|
|
15
19
|
export {};
|
|
16
20
|
//# sourceMappingURL=getGlobalViewRedirect.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getGlobalViewRedirect.d.ts","sourceRoot":"","sources":["../../src/utilities/getGlobalViewRedirect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"getGlobalViewRedirect.d.ts","sourceRoot":"","sources":["../../src/utilities/getGlobalViewRedirect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAK5D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAM1D,KAAK,IAAI,GAAG;IACV,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,eAAe,EAAE,MAAM,CAAA;IACvB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,2BAA2B,EAAE,MAAM,CAAA;IACnC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,yBAAyB,EAAE,QAAQ,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAA;IAC9F,IAAI,EAAE,SAAS,CAAA;CAChB,CAAA;AACD,wBAAsB,qBAAqB,CAAC,EAC1C,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,OAAO,EACP,OAAO,EACP,eAAe,EACf,qBAAqB,EACrB,2BAA2B,EAC3B,qBAAqB,EACrB,UAAU,EACV,IAAI,EACJ,yBAAyB,EACzB,IAAI,GACL,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6E/B"}
|
|
@@ -1,23 +1,29 @@
|
|
|
1
|
+
import { unauthorized } from 'next/navigation.js';
|
|
1
2
|
import { formatAdminURL } from 'payload/shared';
|
|
2
|
-
import { findTenantOptions } from '../queries/findTenantOptions.js';
|
|
3
3
|
import { getCollectionIDType } from './getCollectionIDType.js';
|
|
4
4
|
import { getTenantFromCookie } from './getTenantFromCookie.js';
|
|
5
|
-
|
|
5
|
+
import { getTenantOptions } from './getTenantOptions.js';
|
|
6
|
+
export async function getGlobalViewRedirect({ slug, basePath, docID, headers, payload, tenantFieldName, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, user, userHasAccessToAllTenants, view }) {
|
|
6
7
|
const idType = getCollectionIDType({
|
|
7
8
|
collectionSlug: tenantsCollectionSlug,
|
|
8
9
|
payload
|
|
9
10
|
});
|
|
10
11
|
let tenant = getTenantFromCookie(headers, idType);
|
|
11
12
|
let redirectRoute = undefined;
|
|
13
|
+
if (!user) {
|
|
14
|
+
return unauthorized();
|
|
15
|
+
}
|
|
12
16
|
if (!tenant) {
|
|
13
|
-
const
|
|
14
|
-
limit: 1,
|
|
17
|
+
const tenantOptions = await getTenantOptions({
|
|
15
18
|
payload,
|
|
19
|
+
tenantsArrayFieldName,
|
|
20
|
+
tenantsArrayTenantFieldName,
|
|
16
21
|
tenantsCollectionSlug,
|
|
17
22
|
useAsTitle,
|
|
18
|
-
user
|
|
23
|
+
user,
|
|
24
|
+
userHasAccessToAllTenants
|
|
19
25
|
});
|
|
20
|
-
tenant =
|
|
26
|
+
tenant = tenantOptions[0]?.value || null;
|
|
21
27
|
}
|
|
22
28
|
try {
|
|
23
29
|
const { docs } = await payload.find({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/getGlobalViewRedirect.ts"],"sourcesContent":["import type { Payload, TypedUser, ViewTypes } from 'payload'\n\nimport { formatAdminURL } from 'payload/shared'\n\nimport {
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/getGlobalViewRedirect.ts"],"sourcesContent":["import type { Payload, TypedUser, ViewTypes } from 'payload'\n\nimport { unauthorized } from 'next/navigation.js'\nimport { formatAdminURL } from 'payload/shared'\n\nimport type { MultiTenantPluginConfig } from '../types.js'\n\nimport { getCollectionIDType } from './getCollectionIDType.js'\nimport { getTenantFromCookie } from './getTenantFromCookie.js'\nimport { getTenantOptions } from './getTenantOptions.js'\n\ntype Args = {\n basePath?: string\n docID?: number | string\n headers: Headers\n payload: Payload\n slug: string\n tenantFieldName: string\n tenantsArrayFieldName: string\n tenantsArrayTenantFieldName: string\n tenantsCollectionSlug: string\n useAsTitle: string\n user?: TypedUser\n userHasAccessToAllTenants: Required<MultiTenantPluginConfig<any>>['userHasAccessToAllTenants']\n view: ViewTypes\n}\nexport async function getGlobalViewRedirect({\n slug,\n basePath,\n docID,\n headers,\n payload,\n tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n userHasAccessToAllTenants,\n view,\n}: Args): Promise<string | void> {\n const idType = getCollectionIDType({\n collectionSlug: tenantsCollectionSlug,\n payload,\n })\n let tenant = getTenantFromCookie(headers, idType)\n let redirectRoute: `/${string}` | void = undefined\n\n if (!user) {\n return unauthorized()\n }\n\n if (!tenant) {\n const tenantOptions = await getTenantOptions({\n payload,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n userHasAccessToAllTenants,\n })\n\n tenant = tenantOptions[0]?.value || null\n }\n\n try {\n const { docs } = await payload.find({\n collection: slug,\n depth: 0,\n limit: 1,\n overrideAccess: false,\n pagination: false,\n user,\n where: {\n [tenantFieldName]: {\n equals: tenant,\n },\n },\n })\n\n const tenantDocID = docs?.[0]?.id\n\n if (view === 'document') {\n if (docID && !tenantDocID) {\n // viewing a document with an id but does not match the selected tenant, redirect to create route\n redirectRoute = `/collections/${slug}/create`\n } else if (tenantDocID && docID !== tenantDocID) {\n // tenant document already exists but does not match current route doc ID, redirect to matching tenant doc\n redirectRoute = `/collections/${slug}/${tenantDocID}`\n }\n } else if (view === 'list') {\n if (tenantDocID) {\n // tenant document exists, redirect to edit view\n redirectRoute = `/collections/${slug}/${tenantDocID}`\n } else {\n // tenant document does not exist, redirect to create route\n redirectRoute = `/collections/${slug}/create`\n }\n }\n } catch (e: unknown) {\n payload.logger.error(\n e,\n `${typeof e === 'object' && e && 'message' in e ? `e?.message - ` : ''}Multi Tenant Redirect Error`,\n )\n }\n\n if (redirectRoute) {\n return formatAdminURL({\n adminRoute: payload.config.routes.admin,\n basePath,\n path: redirectRoute,\n serverURL: payload.config.serverURL,\n })\n }\n\n return undefined\n}\n"],"names":["unauthorized","formatAdminURL","getCollectionIDType","getTenantFromCookie","getTenantOptions","getGlobalViewRedirect","slug","basePath","docID","headers","payload","tenantFieldName","tenantsArrayFieldName","tenantsArrayTenantFieldName","tenantsCollectionSlug","useAsTitle","user","userHasAccessToAllTenants","view","idType","collectionSlug","tenant","redirectRoute","undefined","tenantOptions","value","docs","find","collection","depth","limit","overrideAccess","pagination","where","equals","tenantDocID","id","e","logger","error","adminRoute","config","routes","admin","path","serverURL"],"mappings":"AAEA,SAASA,YAAY,QAAQ,qBAAoB;AACjD,SAASC,cAAc,QAAQ,iBAAgB;AAI/C,SAASC,mBAAmB,QAAQ,2BAA0B;AAC9D,SAASC,mBAAmB,QAAQ,2BAA0B;AAC9D,SAASC,gBAAgB,QAAQ,wBAAuB;AAiBxD,OAAO,eAAeC,sBAAsB,EAC1CC,IAAI,EACJC,QAAQ,EACRC,KAAK,EACLC,OAAO,EACPC,OAAO,EACPC,eAAe,EACfC,qBAAqB,EACrBC,2BAA2B,EAC3BC,qBAAqB,EACrBC,UAAU,EACVC,IAAI,EACJC,yBAAyB,EACzBC,IAAI,EACC;IACL,MAAMC,SAASjB,oBAAoB;QACjCkB,gBAAgBN;QAChBJ;IACF;IACA,IAAIW,SAASlB,oBAAoBM,SAASU;IAC1C,IAAIG,gBAAqCC;IAEzC,IAAI,CAACP,MAAM;QACT,OAAOhB;IACT;IAEA,IAAI,CAACqB,QAAQ;QACX,MAAMG,gBAAgB,MAAMpB,iBAAiB;YAC3CM;YACAE;YACAC;YACAC;YACAC;YACAC;YACAC;QACF;QAEAI,SAASG,aAAa,CAAC,EAAE,EAAEC,SAAS;IACtC;IAEA,IAAI;QACF,MAAM,EAAEC,IAAI,EAAE,GAAG,MAAMhB,QAAQiB,IAAI,CAAC;YAClCC,YAAYtB;YACZuB,OAAO;YACPC,OAAO;YACPC,gBAAgB;YAChBC,YAAY;YACZhB;YACAiB,OAAO;gBACL,CAACtB,gBAAgB,EAAE;oBACjBuB,QAAQb;gBACV;YACF;QACF;QAEA,MAAMc,cAAcT,MAAM,CAAC,EAAE,EAAEU;QAE/B,IAAIlB,SAAS,YAAY;YACvB,IAAIV,SAAS,CAAC2B,aAAa;gBACzB,iGAAiG;gBACjGb,gBAAgB,CAAC,aAAa,EAAEhB,KAAK,OAAO,CAAC;YAC/C,OAAO,IAAI6B,eAAe3B,UAAU2B,aAAa;gBAC/C,0GAA0G;gBAC1Gb,gBAAgB,CAAC,aAAa,EAAEhB,KAAK,CAAC,EAAE6B,aAAa;YACvD;QACF,OAAO,IAAIjB,SAAS,QAAQ;YAC1B,IAAIiB,aAAa;gBACf,gDAAgD;gBAChDb,gBAAgB,CAAC,aAAa,EAAEhB,KAAK,CAAC,EAAE6B,aAAa;YACvD,OAAO;gBACL,2DAA2D;gBAC3Db,gBAAgB,CAAC,aAAa,EAAEhB,KAAK,OAAO,CAAC;YAC/C;QACF;IACF,EAAE,OAAO+B,GAAY;QACnB3B,QAAQ4B,MAAM,CAACC,KAAK,CAClBF,GACA,GAAG,OAAOA,MAAM,YAAYA,KAAK,aAAaA,IAAI,CAAC,aAAa,CAAC,GAAG,GAAG,2BAA2B,CAAC;IAEvG;IAEA,IAAIf,eAAe;QACjB,OAAOrB,eAAe;YACpBuC,YAAY9B,QAAQ+B,MAAM,CAACC,MAAM,CAACC,KAAK;YACvCpC;YACAqC,MAAMtB;YACNuB,WAAWnC,QAAQ+B,MAAM,CAACI,SAAS;QACrC;IACF;IAEA,OAAOtB;AACT"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { OptionObject, Payload, TypedUser } from 'payload';
|
|
2
|
+
import type { MultiTenantPluginConfig } from '../types.js';
|
|
3
|
+
export declare const getTenantOptions: ({ payload, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, user, userHasAccessToAllTenants, }: {
|
|
4
|
+
payload: Payload;
|
|
5
|
+
tenantsArrayFieldName: string;
|
|
6
|
+
tenantsArrayTenantFieldName: string;
|
|
7
|
+
tenantsCollectionSlug: string;
|
|
8
|
+
useAsTitle: string;
|
|
9
|
+
user: TypedUser;
|
|
10
|
+
userHasAccessToAllTenants: Required<MultiTenantPluginConfig<any>>["userHasAccessToAllTenants"];
|
|
11
|
+
}) => Promise<OptionObject[]>;
|
|
12
|
+
//# sourceMappingURL=getTenantOptions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getTenantOptions.d.ts","sourceRoot":"","sources":["../../src/utilities/getTenantOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAE/D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAE1D,eAAO,MAAM,gBAAgB,yIAQ1B;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,2BAA2B,EAAE,MAAM,CAAA;IACnC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,SAAS,CAAA;IACf,yBAAyB,EAAE,QAAQ,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAA;CAC/F,KAAG,OAAO,CAAC,YAAY,EAAE,CAiEzB,CAAA"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export const getTenantOptions = async ({ payload, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, user, userHasAccessToAllTenants })=>{
|
|
2
|
+
let tenantOptions = [];
|
|
3
|
+
if (!user) {
|
|
4
|
+
return tenantOptions;
|
|
5
|
+
}
|
|
6
|
+
if (userHasAccessToAllTenants(user)) {
|
|
7
|
+
// If the user has access to all tenants get them from the DB
|
|
8
|
+
const isOrderable = payload.collections[tenantsCollectionSlug]?.config?.orderable || false;
|
|
9
|
+
const tenants = await payload.find({
|
|
10
|
+
collection: tenantsCollectionSlug,
|
|
11
|
+
depth: 0,
|
|
12
|
+
limit: 0,
|
|
13
|
+
overrideAccess: false,
|
|
14
|
+
select: {
|
|
15
|
+
[useAsTitle]: true,
|
|
16
|
+
...isOrderable ? {
|
|
17
|
+
_order: true
|
|
18
|
+
} : {}
|
|
19
|
+
},
|
|
20
|
+
sort: isOrderable ? '_order' : useAsTitle,
|
|
21
|
+
user
|
|
22
|
+
});
|
|
23
|
+
tenantOptions = tenants.docs.map((doc)=>({
|
|
24
|
+
label: String(doc[useAsTitle]),
|
|
25
|
+
value: doc.id
|
|
26
|
+
}));
|
|
27
|
+
} else {
|
|
28
|
+
const tenantsToPopulate = [];
|
|
29
|
+
(user[tenantsArrayFieldName] || []).map((tenantRow)=>{
|
|
30
|
+
const tenantField = tenantRow[tenantsArrayTenantFieldName] // tenants.tenant
|
|
31
|
+
;
|
|
32
|
+
if (typeof tenantField === 'string' || typeof tenantField === 'number') {
|
|
33
|
+
tenantsToPopulate.push(tenantField);
|
|
34
|
+
} else if (tenantField && typeof tenantField === 'object') {
|
|
35
|
+
tenantOptions.push({
|
|
36
|
+
label: String(tenantField[useAsTitle]),
|
|
37
|
+
value: tenantField.id
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
if (tenantsToPopulate.length > 0) {
|
|
42
|
+
const populatedTenants = await payload.find({
|
|
43
|
+
collection: tenantsCollectionSlug,
|
|
44
|
+
depth: 0,
|
|
45
|
+
limit: 0,
|
|
46
|
+
overrideAccess: false,
|
|
47
|
+
user,
|
|
48
|
+
where: {
|
|
49
|
+
id: {
|
|
50
|
+
in: tenantsToPopulate
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
tenantOptions = populatedTenants.docs.map((doc)=>({
|
|
55
|
+
label: String(doc[useAsTitle]),
|
|
56
|
+
value: doc.id
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return tenantOptions;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
//# sourceMappingURL=getTenantOptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/getTenantOptions.ts"],"sourcesContent":["import type { OptionObject, Payload, TypedUser } from 'payload'\n\nimport type { MultiTenantPluginConfig } from '../types.js'\n\nexport const getTenantOptions = async ({\n payload,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n userHasAccessToAllTenants,\n}: {\n payload: Payload\n tenantsArrayFieldName: string\n tenantsArrayTenantFieldName: string\n tenantsCollectionSlug: string\n useAsTitle: string\n user: TypedUser\n userHasAccessToAllTenants: Required<MultiTenantPluginConfig<any>>['userHasAccessToAllTenants']\n}): Promise<OptionObject[]> => {\n let tenantOptions: OptionObject[] = []\n\n if (!user) {\n return tenantOptions\n }\n\n if (userHasAccessToAllTenants(user)) {\n // If the user has access to all tenants get them from the DB\n const isOrderable = payload.collections[tenantsCollectionSlug]?.config?.orderable || false\n const tenants = await payload.find({\n collection: tenantsCollectionSlug,\n depth: 0,\n limit: 0,\n overrideAccess: false,\n select: {\n [useAsTitle]: true,\n ...(isOrderable ? { _order: true } : {}),\n },\n sort: isOrderable ? '_order' : useAsTitle,\n user,\n })\n\n tenantOptions = tenants.docs.map((doc) => ({\n label: String(doc[useAsTitle as 'id']), // useAsTitle is dynamic but the type thinks we are only selecting `id` | `_order`\n value: doc.id as string,\n }))\n } else {\n const tenantsToPopulate: (number | string)[] = []\n\n // i.e. users.tenants\n ;((user[tenantsArrayFieldName] as { [key: string]: any }[]) || []).map((tenantRow) => {\n const tenantField = tenantRow[tenantsArrayTenantFieldName] // tenants.tenant\n if (typeof tenantField === 'string' || typeof tenantField === 'number') {\n tenantsToPopulate.push(tenantField)\n } else if (tenantField && typeof tenantField === 'object') {\n tenantOptions.push({\n label: String(tenantField[useAsTitle]),\n value: tenantField.id,\n })\n }\n })\n\n if (tenantsToPopulate.length > 0) {\n const populatedTenants = await payload.find({\n collection: tenantsCollectionSlug,\n depth: 0,\n limit: 0,\n overrideAccess: false,\n user,\n where: {\n id: {\n in: tenantsToPopulate,\n },\n },\n })\n\n tenantOptions = populatedTenants.docs.map((doc) => ({\n label: String(doc[useAsTitle]),\n value: doc.id as string,\n }))\n }\n }\n\n return tenantOptions\n}\n"],"names":["getTenantOptions","payload","tenantsArrayFieldName","tenantsArrayTenantFieldName","tenantsCollectionSlug","useAsTitle","user","userHasAccessToAllTenants","tenantOptions","isOrderable","collections","config","orderable","tenants","find","collection","depth","limit","overrideAccess","select","_order","sort","docs","map","doc","label","String","value","id","tenantsToPopulate","tenantRow","tenantField","push","length","populatedTenants","where","in"],"mappings":"AAIA,OAAO,MAAMA,mBAAmB,OAAO,EACrCC,OAAO,EACPC,qBAAqB,EACrBC,2BAA2B,EAC3BC,qBAAqB,EACrBC,UAAU,EACVC,IAAI,EACJC,yBAAyB,EAS1B;IACC,IAAIC,gBAAgC,EAAE;IAEtC,IAAI,CAACF,MAAM;QACT,OAAOE;IACT;IAEA,IAAID,0BAA0BD,OAAO;QACnC,6DAA6D;QAC7D,MAAMG,cAAcR,QAAQS,WAAW,CAACN,sBAAsB,EAAEO,QAAQC,aAAa;QACrF,MAAMC,UAAU,MAAMZ,QAAQa,IAAI,CAAC;YACjCC,YAAYX;YACZY,OAAO;YACPC,OAAO;YACPC,gBAAgB;YAChBC,QAAQ;gBACN,CAACd,WAAW,EAAE;gBACd,GAAII,cAAc;oBAAEW,QAAQ;gBAAK,IAAI,CAAC,CAAC;YACzC;YACAC,MAAMZ,cAAc,WAAWJ;YAC/BC;QACF;QAEAE,gBAAgBK,QAAQS,IAAI,CAACC,GAAG,CAAC,CAACC,MAAS,CAAA;gBACzCC,OAAOC,OAAOF,GAAG,CAACnB,WAAmB;gBACrCsB,OAAOH,IAAII,EAAE;YACf,CAAA;IACF,OAAO;QACL,MAAMC,oBAAyC,EAAE;QAG/C,CAAA,AAACvB,IAAI,CAACJ,sBAAsB,IAAiC,EAAE,AAAD,EAAGqB,GAAG,CAAC,CAACO;YACtE,MAAMC,cAAcD,SAAS,CAAC3B,4BAA4B,CAAC,iBAAiB;;YAC5E,IAAI,OAAO4B,gBAAgB,YAAY,OAAOA,gBAAgB,UAAU;gBACtEF,kBAAkBG,IAAI,CAACD;YACzB,OAAO,IAAIA,eAAe,OAAOA,gBAAgB,UAAU;gBACzDvB,cAAcwB,IAAI,CAAC;oBACjBP,OAAOC,OAAOK,WAAW,CAAC1B,WAAW;oBACrCsB,OAAOI,YAAYH,EAAE;gBACvB;YACF;QACF;QAEA,IAAIC,kBAAkBI,MAAM,GAAG,GAAG;YAChC,MAAMC,mBAAmB,MAAMjC,QAAQa,IAAI,CAAC;gBAC1CC,YAAYX;gBACZY,OAAO;gBACPC,OAAO;gBACPC,gBAAgB;gBAChBZ;gBACA6B,OAAO;oBACLP,IAAI;wBACFQ,IAAIP;oBACN;gBACF;YACF;YAEArB,gBAAgB0B,iBAAiBZ,IAAI,CAACC,GAAG,CAAC,CAACC,MAAS,CAAA;oBAClDC,OAAOC,OAAOF,GAAG,CAACnB,WAAW;oBAC7BsB,OAAOH,IAAII,EAAE;gBACf,CAAA;QACF;IACF;IAEA,OAAOpB;AACT,EAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payloadcms/plugin-multi-tenant",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.50.0-canary.1",
|
|
4
4
|
"description": "Multi Tenant plugin for Payload",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"payload",
|
|
@@ -81,14 +81,14 @@
|
|
|
81
81
|
],
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@payloadcms/eslint-config": "3.28.0",
|
|
84
|
-
"@payloadcms/translations": "3.
|
|
85
|
-
"@payloadcms/ui": "3.
|
|
86
|
-
"payload": "3.
|
|
84
|
+
"@payloadcms/translations": "3.50.0-canary.1",
|
|
85
|
+
"@payloadcms/ui": "3.50.0-canary.1",
|
|
86
|
+
"payload": "3.50.0-canary.1"
|
|
87
87
|
},
|
|
88
88
|
"peerDependencies": {
|
|
89
89
|
"next": "^15.2.3",
|
|
90
|
-
"@payloadcms/ui": "3.
|
|
91
|
-
"payload": "3.
|
|
90
|
+
"@payloadcms/ui": "3.50.0-canary.1",
|
|
91
|
+
"payload": "3.50.0-canary.1"
|
|
92
92
|
},
|
|
93
93
|
"homepage:": "https://payloadcms.com",
|
|
94
94
|
"scripts": {
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { PaginatedDocs, Payload, TypedUser } from 'payload';
|
|
2
|
-
type Args = {
|
|
3
|
-
limit: number;
|
|
4
|
-
payload: Payload;
|
|
5
|
-
tenantsCollectionSlug: string;
|
|
6
|
-
useAsTitle: string;
|
|
7
|
-
user?: TypedUser;
|
|
8
|
-
};
|
|
9
|
-
export declare const findTenantOptions: ({ limit, payload, tenantsCollectionSlug, useAsTitle, user, }: Args) => Promise<PaginatedDocs>;
|
|
10
|
-
export {};
|
|
11
|
-
//# sourceMappingURL=findTenantOptions.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"findTenantOptions.d.ts","sourceRoot":"","sources":["../../src/queries/findTenantOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAEhE,KAAK,IAAI,GAAG;IACV,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;IAChB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB,CAAA;AACD,eAAO,MAAM,iBAAiB,iEAM3B,IAAI,KAAG,OAAO,CAAC,aAAa,CAc9B,CAAA"}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export const findTenantOptions = async ({ limit, payload, tenantsCollectionSlug, useAsTitle, user })=>{
|
|
2
|
-
const isOrderable = payload.collections[tenantsCollectionSlug]?.config?.orderable || false;
|
|
3
|
-
return payload.find({
|
|
4
|
-
collection: tenantsCollectionSlug,
|
|
5
|
-
depth: 0,
|
|
6
|
-
limit,
|
|
7
|
-
overrideAccess: false,
|
|
8
|
-
select: {
|
|
9
|
-
[useAsTitle]: true,
|
|
10
|
-
...isOrderable ? {
|
|
11
|
-
_order: true
|
|
12
|
-
} : {}
|
|
13
|
-
},
|
|
14
|
-
sort: isOrderable ? '_order' : useAsTitle,
|
|
15
|
-
user
|
|
16
|
-
});
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
//# sourceMappingURL=findTenantOptions.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/queries/findTenantOptions.ts"],"sourcesContent":["import type { PaginatedDocs, Payload, TypedUser } from 'payload'\n\ntype Args = {\n limit: number\n payload: Payload\n tenantsCollectionSlug: string\n useAsTitle: string\n user?: TypedUser\n}\nexport const findTenantOptions = async ({\n limit,\n payload,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n}: Args): Promise<PaginatedDocs> => {\n const isOrderable = payload.collections[tenantsCollectionSlug]?.config?.orderable || false\n return payload.find({\n collection: tenantsCollectionSlug,\n depth: 0,\n limit,\n overrideAccess: false,\n select: {\n [useAsTitle]: true,\n ...(isOrderable ? { _order: true } : {}),\n },\n sort: isOrderable ? '_order' : useAsTitle,\n user,\n })\n}\n"],"names":["findTenantOptions","limit","payload","tenantsCollectionSlug","useAsTitle","user","isOrderable","collections","config","orderable","find","collection","depth","overrideAccess","select","_order","sort"],"mappings":"AASA,OAAO,MAAMA,oBAAoB,OAAO,EACtCC,KAAK,EACLC,OAAO,EACPC,qBAAqB,EACrBC,UAAU,EACVC,IAAI,EACC;IACL,MAAMC,cAAcJ,QAAQK,WAAW,CAACJ,sBAAsB,EAAEK,QAAQC,aAAa;IACrF,OAAOP,QAAQQ,IAAI,CAAC;QAClBC,YAAYR;QACZS,OAAO;QACPX;QACAY,gBAAgB;QAChBC,QAAQ;YACN,CAACV,WAAW,EAAE;YACd,GAAIE,cAAc;gBAAES,QAAQ;YAAK,IAAI,CAAC,CAAC;QACzC;QACAC,MAAMV,cAAc,WAAWF;QAC/BC;IACF;AACF,EAAC"}
|