roles-privileges-payload-plugin 1.1.1 → 1.2.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 (48) hide show
  1. package/README.md +15 -0
  2. package/dist/collections/roles.d.ts +2 -2
  3. package/dist/collections/roles.js +27 -45
  4. package/dist/collections/roles.js.map +1 -1
  5. package/dist/components/PrivilegesSelect.d.ts +2 -2
  6. package/dist/components/PrivilegesSelect.js +89 -71
  7. package/dist/components/PrivilegesSelect.js.map +1 -1
  8. package/dist/exports/utilities.d.ts +5 -4
  9. package/dist/exports/utilities.js +10 -8
  10. package/dist/exports/utilities.js.map +1 -1
  11. package/dist/fields/slug/SlugComponent.d.ts +9 -0
  12. package/dist/fields/slug/SlugComponent.js +83 -0
  13. package/dist/fields/slug/SlugComponent.js.map +1 -0
  14. package/dist/fields/slug/formatSlug.d.ts +3 -0
  15. package/dist/fields/slug/formatSlug.js +15 -0
  16. package/dist/fields/slug/formatSlug.js.map +1 -0
  17. package/dist/fields/slug/index.d.ts +8 -0
  18. package/dist/fields/slug/index.js +47 -0
  19. package/dist/fields/slug/index.js.map +1 -0
  20. package/dist/fields/slug/index.scss +12 -0
  21. package/dist/index.d.ts +17 -7
  22. package/dist/index.js +59 -10
  23. package/dist/index.js.map +1 -1
  24. package/dist/roles-privileges-payload-plugin-1.2.0.tgz +0 -0
  25. package/dist/translations/index.js +4 -4
  26. package/dist/translations/index.js.map +1 -1
  27. package/dist/translations/languages/en.js +19 -18
  28. package/dist/translations/languages/en.js.map +1 -1
  29. package/dist/translations/languages/fr.js +19 -18
  30. package/dist/translations/languages/fr.js.map +1 -1
  31. package/dist/translations/types.d.ts +43 -42
  32. package/dist/translations/types.js.map +1 -1
  33. package/dist/utils/assignSuperAdminToFirstUser.d.ts +10 -0
  34. package/dist/utils/assignSuperAdminToFirstUser.js +70 -0
  35. package/dist/utils/assignSuperAdminToFirstUser.js.map +1 -0
  36. package/dist/utils/createCustomPrivilege.d.ts +9 -9
  37. package/dist/utils/createCustomPrivilege.js +4 -4
  38. package/dist/utils/createCustomPrivilege.js.map +1 -1
  39. package/dist/utils/generateGlobalPrivileges.d.ts +4 -4
  40. package/dist/utils/generateGlobalPrivileges.js +4 -4
  41. package/dist/utils/generateGlobalPrivileges.js.map +1 -1
  42. package/dist/utils/generatePrivileges.d.ts +6 -6
  43. package/dist/utils/generatePrivileges.js +6 -6
  44. package/dist/utils/generatePrivileges.js.map +1 -1
  45. package/dist/utils/seedSuperAdminRole.js +7 -7
  46. package/dist/utils/seedSuperAdminRole.js.map +1 -1
  47. package/package.json +15 -15
  48. package/dist/roles-privileges-payload-plugin-1.1.1.tgz +0 -0
@@ -0,0 +1,9 @@
1
+ import type { TextFieldClientProps } from 'payload';
2
+ import React from 'react';
3
+ import './index.scss';
4
+ type SlugComponentProps = {
5
+ checkboxFieldPath: string;
6
+ fieldToUse: string;
7
+ } & TextFieldClientProps;
8
+ export declare const SlugComponent: React.FC<SlugComponentProps>;
9
+ export {};
@@ -0,0 +1,83 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Button, FieldLabel, TextInput, useField, useForm, useFormFields } from '@payloadcms/ui';
4
+ import React, { useCallback, useEffect } from 'react';
5
+ import { formatSlug } from './formatSlug.js';
6
+ import './index.scss';
7
+ export const SlugComponent = ({ checkboxFieldPath: checkboxFieldPathFromProps, field, fieldToUse, path, readOnly: readOnlyFromProps })=>{
8
+ const { label } = field;
9
+ const checkboxFieldPath = path?.includes('.') ? `${path}.${checkboxFieldPathFromProps}` : checkboxFieldPathFromProps;
10
+ const { setValue, value } = useField({
11
+ path: path || field.name
12
+ });
13
+ const { dispatchFields } = useForm();
14
+ // The value of the checkbox
15
+ // We're using separate useFormFields to minimise re-renders
16
+ const checkboxValue = useFormFields(([fields])=>{
17
+ return fields[checkboxFieldPath]?.value;
18
+ });
19
+ // The value of the field we're listening to for the slug
20
+ const targetFieldValue = useFormFields(([fields])=>{
21
+ return fields[fieldToUse]?.value;
22
+ });
23
+ useEffect(()=>{
24
+ if (checkboxValue) {
25
+ if (targetFieldValue) {
26
+ const formattedSlug = formatSlug(targetFieldValue);
27
+ if (value !== formattedSlug) {
28
+ setValue(formattedSlug);
29
+ }
30
+ } else {
31
+ if (value !== '') {
32
+ setValue('');
33
+ }
34
+ }
35
+ }
36
+ }, [
37
+ targetFieldValue,
38
+ checkboxValue,
39
+ setValue,
40
+ value
41
+ ]);
42
+ const handleLock = useCallback((e)=>{
43
+ e.preventDefault();
44
+ dispatchFields({
45
+ type: 'UPDATE',
46
+ path: checkboxFieldPath,
47
+ value: !checkboxValue
48
+ });
49
+ }, [
50
+ checkboxValue,
51
+ checkboxFieldPath,
52
+ dispatchFields
53
+ ]);
54
+ const readOnly = readOnlyFromProps || checkboxValue;
55
+ return /*#__PURE__*/ _jsxs("div", {
56
+ className: "field-type slug-field-component",
57
+ children: [
58
+ /*#__PURE__*/ _jsxs("div", {
59
+ className: "label-wrapper",
60
+ children: [
61
+ /*#__PURE__*/ _jsx(FieldLabel, {
62
+ htmlFor: `field-${path}`,
63
+ label: label
64
+ }),
65
+ /*#__PURE__*/ _jsx(Button, {
66
+ buttonStyle: "none",
67
+ className: "lock-button",
68
+ onClick: handleLock,
69
+ children: checkboxValue ? 'Unlock' : 'Lock'
70
+ })
71
+ ]
72
+ }),
73
+ /*#__PURE__*/ _jsx(TextInput, {
74
+ onChange: setValue,
75
+ path: path || field.name,
76
+ readOnly: Boolean(readOnly),
77
+ value: value
78
+ })
79
+ ]
80
+ });
81
+ };
82
+
83
+ //# sourceMappingURL=SlugComponent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/fields/slug/SlugComponent.tsx"],"sourcesContent":["'use client'\nimport type { TextFieldClientProps } from 'payload'\n\nimport { Button, FieldLabel, TextInput, useField, useForm, useFormFields } from '@payloadcms/ui'\nimport React, { useCallback, useEffect } from 'react'\n\nimport { formatSlug } from './formatSlug.js'\nimport './index.scss'\n\ntype SlugComponentProps = {\n checkboxFieldPath: string\n fieldToUse: string\n} & TextFieldClientProps\n\nexport const SlugComponent: React.FC<SlugComponentProps> = ({\n checkboxFieldPath: checkboxFieldPathFromProps,\n field,\n fieldToUse,\n path,\n readOnly: readOnlyFromProps,\n}) => {\n const { label } = field\n\n const checkboxFieldPath = path?.includes('.')\n ? `${path}.${checkboxFieldPathFromProps}`\n : checkboxFieldPathFromProps\n\n const { setValue, value } = useField<string>({ path: path || field.name })\n\n const { dispatchFields } = useForm()\n\n // The value of the checkbox\n // We're using separate useFormFields to minimise re-renders\n const checkboxValue = useFormFields(([fields]) => {\n return fields[checkboxFieldPath]?.value as string\n })\n\n // The value of the field we're listening to for the slug\n const targetFieldValue = useFormFields(([fields]) => {\n return fields[fieldToUse]?.value as string\n })\n\n useEffect(() => {\n if (checkboxValue) {\n if (targetFieldValue) {\n const formattedSlug = formatSlug(targetFieldValue)\n\n if (value !== formattedSlug) {\n setValue(formattedSlug)\n }\n } else {\n if (value !== '') {\n setValue('')\n }\n }\n }\n }, [targetFieldValue, checkboxValue, setValue, value])\n\n const handleLock = useCallback(\n (e: React.MouseEvent<Element>) => {\n e.preventDefault()\n\n dispatchFields({\n type: 'UPDATE',\n path: checkboxFieldPath,\n value: !checkboxValue,\n })\n },\n [checkboxValue, checkboxFieldPath, dispatchFields],\n )\n\n const readOnly = readOnlyFromProps || checkboxValue\n\n return (\n <div className=\"field-type slug-field-component\">\n <div className=\"label-wrapper\">\n <FieldLabel htmlFor={`field-${path}`} label={label} />\n\n <Button buttonStyle=\"none\" className=\"lock-button\" onClick={handleLock}>\n {checkboxValue ? 'Unlock' : 'Lock'}\n </Button>\n </div>\n\n <TextInput\n onChange={setValue}\n path={path || field.name}\n readOnly={Boolean(readOnly)}\n value={value}\n />\n </div>\n )\n}\n"],"names":["Button","FieldLabel","TextInput","useField","useForm","useFormFields","React","useCallback","useEffect","formatSlug","SlugComponent","checkboxFieldPath","checkboxFieldPathFromProps","field","fieldToUse","path","readOnly","readOnlyFromProps","label","includes","setValue","value","name","dispatchFields","checkboxValue","fields","targetFieldValue","formattedSlug","handleLock","e","preventDefault","type","div","className","htmlFor","buttonStyle","onClick","onChange","Boolean"],"mappings":"AAAA;;AAGA,SAASA,MAAM,EAAEC,UAAU,EAAEC,SAAS,EAAEC,QAAQ,EAAEC,OAAO,EAAEC,aAAa,QAAQ,iBAAgB;AAChG,OAAOC,SAASC,WAAW,EAAEC,SAAS,QAAQ,QAAO;AAErD,SAASC,UAAU,QAAQ,kBAAiB;AAC5C,OAAO,eAAc;AAOrB,OAAO,MAAMC,gBAA8C,CAAC,EAC1DC,mBAAmBC,0BAA0B,EAC7CC,KAAK,EACLC,UAAU,EACVC,IAAI,EACJC,UAAUC,iBAAiB,EAC5B;IACC,MAAM,EAAEC,KAAK,EAAE,GAAGL;IAElB,MAAMF,oBAAoBI,MAAMI,SAAS,OACrC,GAAGJ,KAAK,CAAC,EAAEH,4BAA4B,GACvCA;IAEJ,MAAM,EAAEQ,QAAQ,EAAEC,KAAK,EAAE,GAAGlB,SAAiB;QAAEY,MAAMA,QAAQF,MAAMS,IAAI;IAAC;IAExE,MAAM,EAAEC,cAAc,EAAE,GAAGnB;IAE3B,4BAA4B;IAC5B,4DAA4D;IAC5D,MAAMoB,gBAAgBnB,cAAc,CAAC,CAACoB,OAAO;QAC3C,OAAOA,MAAM,CAACd,kBAAkB,EAAEU;IACpC;IAEA,yDAAyD;IACzD,MAAMK,mBAAmBrB,cAAc,CAAC,CAACoB,OAAO;QAC9C,OAAOA,MAAM,CAACX,WAAW,EAAEO;IAC7B;IAEAb,UAAU;QACR,IAAIgB,eAAe;YACjB,IAAIE,kBAAkB;gBACpB,MAAMC,gBAAgBlB,WAAWiB;gBAEjC,IAAIL,UAAUM,eAAe;oBAC3BP,SAASO;gBACX;YACF,OAAO;gBACL,IAAIN,UAAU,IAAI;oBAChBD,SAAS;gBACX;YACF;QACF;IACF,GAAG;QAACM;QAAkBF;QAAeJ;QAAUC;KAAM;IAErD,MAAMO,aAAarB,YACjB,CAACsB;QACCA,EAAEC,cAAc;QAEhBP,eAAe;YACbQ,MAAM;YACNhB,MAAMJ;YACNU,OAAO,CAACG;QACV;IACF,GACA;QAACA;QAAeb;QAAmBY;KAAe;IAGpD,MAAMP,WAAWC,qBAAqBO;IAEtC,qBACE,MAACQ;QAAIC,WAAU;;0BACb,MAACD;gBAAIC,WAAU;;kCACb,KAAChC;wBAAWiC,SAAS,CAAC,MAAM,EAAEnB,MAAM;wBAAEG,OAAOA;;kCAE7C,KAAClB;wBAAOmC,aAAY;wBAAOF,WAAU;wBAAcG,SAASR;kCACzDJ,gBAAgB,WAAW;;;;0BAIhC,KAACtB;gBACCmC,UAAUjB;gBACVL,MAAMA,QAAQF,MAAMS,IAAI;gBACxBN,UAAUsB,QAAQtB;gBAClBK,OAAOA;;;;AAIf,EAAC"}
@@ -0,0 +1,3 @@
1
+ import type { FieldHook } from 'payload';
2
+ export declare const formatSlug: (val: string) => string;
3
+ export declare const formatSlugHook: (fallback: string) => FieldHook;
@@ -0,0 +1,15 @@
1
+ export const formatSlug = (val)=>val.replace(/ /g, '-').replace(/[^\w-]+/g, '').toLowerCase();
2
+ export const formatSlugHook = (fallback)=>({ data, operation, value })=>{
3
+ if (typeof value === 'string') {
4
+ return formatSlug(value);
5
+ }
6
+ if (operation === 'create' || !data?.slug) {
7
+ const fallbackData = data?.[fallback] || data?.[fallback];
8
+ if (fallbackData && typeof fallbackData === 'string') {
9
+ return formatSlug(fallbackData);
10
+ }
11
+ }
12
+ return value;
13
+ };
14
+
15
+ //# sourceMappingURL=formatSlug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/fields/slug/formatSlug.ts"],"sourcesContent":["import type { FieldHook } from 'payload'\n\nexport const formatSlug = (val: string): string =>\n val\n .replace(/ /g, '-')\n .replace(/[^\\w-]+/g, '')\n .toLowerCase()\n\nexport const formatSlugHook =\n (fallback: string): FieldHook =>\n ({ data, operation, value }) => {\n if (typeof value === 'string') {\n return formatSlug(value)\n }\n\n if (operation === 'create' || !data?.slug) {\n const fallbackData = data?.[fallback] || data?.[fallback]\n\n if (fallbackData && typeof fallbackData === 'string') {\n return formatSlug(fallbackData)\n }\n }\n\n return value\n }\n"],"names":["formatSlug","val","replace","toLowerCase","formatSlugHook","fallback","data","operation","value","slug","fallbackData"],"mappings":"AAEA,OAAO,MAAMA,aAAa,CAACC,MACzBA,IACGC,OAAO,CAAC,MAAM,KACdA,OAAO,CAAC,YAAY,IACpBC,WAAW,GAAE;AAElB,OAAO,MAAMC,iBACX,CAACC,WACD,CAAC,EAAEC,IAAI,EAAEC,SAAS,EAAEC,KAAK,EAAE;QACzB,IAAI,OAAOA,UAAU,UAAU;YAC7B,OAAOR,WAAWQ;QACpB;QAEA,IAAID,cAAc,YAAY,CAACD,MAAMG,MAAM;YACzC,MAAMC,eAAeJ,MAAM,CAACD,SAAS,IAAIC,MAAM,CAACD,SAAS;YAEzD,IAAIK,gBAAgB,OAAOA,iBAAiB,UAAU;gBACpD,OAAOV,WAAWU;YACpB;QACF;QAEA,OAAOF;IACT,EAAC"}
@@ -0,0 +1,8 @@
1
+ import type { CheckboxField, TextField } from 'payload';
2
+ type Overrides = {
3
+ checkboxOverrides?: Partial<CheckboxField>;
4
+ slugOverrides?: Partial<TextField>;
5
+ };
6
+ type Slug = (fieldToUse?: string, overrides?: Overrides) => [TextField, CheckboxField];
7
+ export declare const slugField: Slug;
8
+ export {};
@@ -0,0 +1,47 @@
1
+ import { formatSlugHook } from './formatSlug.js';
2
+ export const slugField = (fieldToUse = 'title', overrides = {})=>{
3
+ const { checkboxOverrides, slugOverrides } = overrides;
4
+ const checkBoxField = {
5
+ name: 'slugLock',
6
+ type: 'checkbox',
7
+ admin: {
8
+ hidden: true,
9
+ position: 'sidebar'
10
+ },
11
+ defaultValue: true,
12
+ ...checkboxOverrides
13
+ };
14
+ // @ts-expect-error - ts mismatch Partial<TextField> with TextField
15
+ const slugField = {
16
+ name: 'slug',
17
+ type: 'text',
18
+ index: true,
19
+ label: 'Slug',
20
+ ...slugOverrides || {},
21
+ admin: {
22
+ position: 'sidebar',
23
+ ...slugOverrides?.admin || {},
24
+ components: {
25
+ Field: {
26
+ clientProps: {
27
+ checkboxFieldPath: checkBoxField.name,
28
+ fieldToUse
29
+ },
30
+ path: '@/fields/slug/SlugComponent#SlugComponent'
31
+ }
32
+ }
33
+ },
34
+ hooks: {
35
+ // Kept this in for hook or API based updates
36
+ beforeValidate: [
37
+ formatSlugHook(fieldToUse)
38
+ ]
39
+ }
40
+ };
41
+ return [
42
+ slugField,
43
+ checkBoxField
44
+ ];
45
+ };
46
+
47
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/fields/slug/index.ts"],"sourcesContent":["import type { CheckboxField, TextField } from 'payload'\n\nimport { formatSlugHook } from './formatSlug.js'\n\ntype Overrides = {\n checkboxOverrides?: Partial<CheckboxField>\n slugOverrides?: Partial<TextField>\n}\n\ntype Slug = (fieldToUse?: string, overrides?: Overrides) => [TextField, CheckboxField]\n\nexport const slugField: Slug = (fieldToUse = 'title', overrides = {}) => {\n const { checkboxOverrides, slugOverrides } = overrides\n\n const checkBoxField: CheckboxField = {\n name: 'slugLock',\n type: 'checkbox',\n admin: {\n hidden: true,\n position: 'sidebar',\n },\n defaultValue: true,\n\n ...checkboxOverrides,\n }\n\n // @ts-expect-error - ts mismatch Partial<TextField> with TextField\n const slugField: TextField = {\n name: 'slug',\n type: 'text',\n index: true,\n label: 'Slug',\n ...(slugOverrides || {}),\n admin: {\n position: 'sidebar',\n ...(slugOverrides?.admin || {}),\n components: {\n Field: {\n clientProps: {\n checkboxFieldPath: checkBoxField.name,\n fieldToUse,\n },\n path: '@/fields/slug/SlugComponent#SlugComponent',\n },\n },\n },\n hooks: {\n // Kept this in for hook or API based updates\n beforeValidate: [formatSlugHook(fieldToUse)],\n },\n }\n\n return [slugField, checkBoxField]\n}\n"],"names":["formatSlugHook","slugField","fieldToUse","overrides","checkboxOverrides","slugOverrides","checkBoxField","name","type","admin","hidden","position","defaultValue","index","label","components","Field","clientProps","checkboxFieldPath","path","hooks","beforeValidate"],"mappings":"AAEA,SAASA,cAAc,QAAQ,kBAAiB;AAShD,OAAO,MAAMC,YAAkB,CAACC,aAAa,OAAO,EAAEC,YAAY,CAAC,CAAC;IAClE,MAAM,EAAEC,iBAAiB,EAAEC,aAAa,EAAE,GAAGF;IAE7C,MAAMG,gBAA+B;QACnCC,MAAM;QACNC,MAAM;QACNC,OAAO;YACLC,QAAQ;YACRC,UAAU;QACZ;QACAC,cAAc;QAEd,GAAGR,iBAAiB;IACtB;IAEA,mEAAmE;IACnE,MAAMH,YAAuB;QAC3BM,MAAM;QACNC,MAAM;QACNK,OAAO;QACPC,OAAO;QACP,GAAIT,iBAAiB,CAAC,CAAC;QACvBI,OAAO;YACLE,UAAU;YACV,GAAIN,eAAeI,SAAS,CAAC,CAAC;YAC9BM,YAAY;gBACVC,OAAO;oBACLC,aAAa;wBACXC,mBAAmBZ,cAAcC,IAAI;wBACrCL;oBACF;oBACAiB,MAAM;gBACR;YACF;QACF;QACAC,OAAO;YACL,6CAA6C;YAC7CC,gBAAgB;gBAACrB,eAAeE;aAAY;QAC9C;IACF;IAEA,OAAO;QAACD;QAAWK;KAAc;AACnC,EAAC"}
@@ -0,0 +1,12 @@
1
+ .slug-field-component {
2
+ .label-wrapper {
3
+ display: flex;
4
+ justify-content: space-between;
5
+ align-items: center;
6
+ }
7
+
8
+ .lock-button {
9
+ margin: 0;
10
+ padding-bottom: 0.3125rem;
11
+ }
12
+ }
package/dist/index.d.ts CHANGED
@@ -1,18 +1,28 @@
1
1
  import type { CollectionConfig, Config } from 'payload';
2
2
  export type RolesPrivilegesPayloadPluginConfig = {
3
- enable?: boolean;
4
- disabled?: boolean;
5
- excludeCollections?: string[];
6
- excludeGlobals?: string[];
7
- wrapCollectionAccess?: boolean;
8
- wrapGlobalAccess?: boolean;
9
- seedSuperAdmin?: boolean;
3
+ /**
4
+ * Automatically assign Super Admin role to the first user created in the system
5
+ * @default true
6
+ */
7
+ assignSuperAdminToFirstUser?: boolean;
10
8
  /**
11
9
  * Custom roles collection configuration.
12
10
  * If provided, this collection will be used instead of the default one.
13
11
  * Use `createRolesCollection` helper to create a base configuration and customize it.
14
12
  */
15
13
  customRolesCollection?: CollectionConfig;
14
+ disabled?: boolean;
15
+ enable?: boolean;
16
+ excludeCollections?: string[];
17
+ excludeGlobals?: string[];
18
+ /**
19
+ * Name of the roles field to add to the user collection
20
+ * @default 'roles'
21
+ */
22
+ rolesFieldName?: string;
23
+ seedSuperAdmin?: boolean;
24
+ wrapCollectionAccess?: boolean;
25
+ wrapGlobalAccess?: boolean;
16
26
  };
17
27
  export * from './exports/types.js';
18
28
  export * from './exports/utilities.js';
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { createRolesCollection } from './collections/roles.js';
2
2
  import { translations } from './translations/index.js';
3
+ import { wrapUserCollectionWithSuperAdminHook } from './utils/assignSuperAdminToFirstUser.js';
3
4
  import { customPrivilegesRegistry } from './utils/createCustomPrivilege.js';
4
5
  import { allGlobalPrivilegesMap, generateGlobalPrivilegeKey, generateGlobalPrivileges } from './utils/generateGlobalPrivileges.js';
5
6
  import { allPrivilegesMap, generateCollectionPrivileges, generatePrivilegeKey } from './utils/generatePrivileges.js';
@@ -11,25 +12,31 @@ export * from './exports/utilities.js';
11
12
  let originalResult = true;
12
13
  if (original !== undefined) {
13
14
  originalResult = typeof original === 'function' ? await original(args) : original;
14
- if (originalResult === false) return false;
15
+ if (originalResult === false) {
16
+ return false;
17
+ }
15
18
  }
16
19
  const hasPriv = await hasPrivilege(privilegeKey)(args);
17
- if (!hasPriv) return false;
20
+ if (!hasPriv) {
21
+ return false;
22
+ }
18
23
  return originalResult;
19
24
  };
20
25
  function buildPrivilegesMap(autoMap, type, slugKey, labelKey) {
21
26
  const map = new Map();
22
27
  for (const entry of autoMap.values()){
23
28
  map.set(entry[slugKey], {
24
- [slugKey]: entry[slugKey],
25
29
  [labelKey]: entry[labelKey],
26
30
  privileges: {
27
31
  ...entry.privileges
28
- }
32
+ },
33
+ [slugKey]: entry[slugKey]
29
34
  });
30
35
  }
31
36
  for (const custom of customPrivilegesRegistry.values()){
32
- if (custom.type !== type) continue;
37
+ if (custom.type !== type) {
38
+ continue;
39
+ }
33
40
  const existing = map.get(custom.slug);
34
41
  if (existing) {
35
42
  existing.privileges = {
@@ -38,18 +45,18 @@ function buildPrivilegesMap(autoMap, type, slugKey, labelKey) {
38
45
  };
39
46
  } else {
40
47
  map.set(custom.slug, {
41
- [slugKey]: custom.slug,
42
48
  [labelKey]: custom.label,
43
49
  privileges: {
44
50
  ...custom.privileges
45
- }
51
+ },
52
+ [slugKey]: custom.slug
46
53
  });
47
54
  }
48
55
  }
49
56
  return Array.from(map.values());
50
57
  }
51
58
  /* -------------------------------------------------------------------------- */ /* Plugin */ /* -------------------------------------------------------------------------- */ export const rolesPrivilegesPayloadPlugin = (pluginOptions = {})=>(config)=>{
52
- const { enable = true, excludeCollections = [], excludeGlobals = [], wrapCollectionAccess = true, wrapGlobalAccess = true, seedSuperAdmin = true } = pluginOptions;
59
+ const { assignSuperAdminToFirstUser = true, enable = true, excludeCollections = [], excludeGlobals = [], rolesFieldName = 'roles', seedSuperAdmin = true, wrapCollectionAccess = true, wrapGlobalAccess = true } = pluginOptions;
53
60
  if (!enable) {
54
61
  return config;
55
62
  }
@@ -89,6 +96,44 @@ function buildPrivilegesMap(autoMap, type, slugKey, labelKey) {
89
96
  }
90
97
  }
91
98
  }
99
+ /* ---------------------------------------------------------------------- */ /* First user super admin assignment */ /* ---------------------------------------------------------------------- */ // Find the user collection from config.admin.user
100
+ const userCollectionSlug = config.admin?.user || 'users';
101
+ const userCollectionIndex = config.collections.findIndex((c)=>c.slug === userCollectionSlug);
102
+ if (userCollectionIndex !== -1) {
103
+ const userCollection = config.collections[userCollectionIndex];
104
+ // Check if roles field already exists
105
+ const hasRolesField = userCollection.fields.some((field)=>'name' in field && field.name === rolesFieldName);
106
+ // Add roles field if it doesn't exist
107
+ if (!hasRolesField) {
108
+ userCollection.fields.push({
109
+ name: rolesFieldName,
110
+ type: 'relationship',
111
+ access: {
112
+ create: async (args)=>{
113
+ const result = await hasPrivilege('roles-update')(args);
114
+ return typeof result === 'boolean' ? result : true;
115
+ },
116
+ read: async (args)=>{
117
+ const result = await hasPrivilege('roles-read')(args);
118
+ return typeof result === 'boolean' ? result : true;
119
+ },
120
+ update: async (args)=>{
121
+ const result = await hasPrivilege('roles-update')(args);
122
+ return typeof result === 'boolean' ? result : true;
123
+ }
124
+ },
125
+ admin: {
126
+ description: ({ t })=>t('plugin-roles-privileges:user-roles-field-description')
127
+ },
128
+ hasMany: true,
129
+ relationTo: 'roles'
130
+ });
131
+ }
132
+ // Wrap with super admin hook if enabled
133
+ if (assignSuperAdminToFirstUser) {
134
+ config.collections[userCollectionIndex] = wrapUserCollectionWithSuperAdminHook(userCollection, rolesFieldName);
135
+ }
136
+ }
92
137
  if (pluginOptions.disabled) {
93
138
  return config;
94
139
  }
@@ -124,7 +169,9 @@ function buildPrivilegesMap(autoMap, type, slugKey, labelKey) {
124
169
  ];
125
170
  if (wrapGlobalAccess) {
126
171
  for (const global of config.globals){
127
- if (excludeGlobals.includes(global.slug)) continue;
172
+ if (excludeGlobals.includes(global.slug)) {
173
+ continue;
174
+ }
128
175
  global.access ??= {};
129
176
  const originalAccess = {
130
177
  ...global.access
@@ -153,7 +200,9 @@ function buildPrivilegesMap(autoMap, type, slugKey, labelKey) {
153
200
  }
154
201
  const existingGlobals = new Set(allGlobalPrivilegesMap.keys());
155
202
  for (const slug of Object.keys(payload.globals)){
156
- if (existingGlobals.has(slug) || excludeGlobals.includes(slug)) continue;
203
+ if (existingGlobals.has(slug) || excludeGlobals.includes(slug)) {
204
+ continue;
205
+ }
157
206
  const global = payload.globals[slug];
158
207
  if (global?.config) {
159
208
  payload.logger.info(`[Roles & Privileges] Discovered late-loaded global: ${slug}`);
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 { createRolesCollection } from './collections/roles.js'\nimport { translations } from './translations/index.js'\nimport type { PluginDefaultTranslationsObject } from './translations/types.js'\n\nimport type { PayloadRequest, Where } from 'payload'\nimport { customPrivilegesRegistry } from './utils/createCustomPrivilege.js'\nimport {\n allGlobalPrivilegesMap,\n generateGlobalPrivilegeKey,\n generateGlobalPrivileges,\n} from './utils/generateGlobalPrivileges.js'\nimport {\n allPrivilegesMap,\n generateCollectionPrivileges,\n generatePrivilegeKey,\n} from './utils/generatePrivileges.js'\nimport { hasPrivilege } from './utils/privilegesAccess.js'\nimport { seedSuperAdminRole } from './utils/seedSuperAdminRole.js'\n/* -------------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------------- */\n\nexport type RolesPrivilegesPayloadPluginConfig = {\n enable?: boolean\n disabled?: boolean\n excludeCollections?: string[]\n excludeGlobals?: string[]\n wrapCollectionAccess?: boolean\n wrapGlobalAccess?: boolean\n seedSuperAdmin?: boolean\n /**\n * Custom roles collection configuration.\n * If provided, this collection will be used instead of the default one.\n * Use `createRolesCollection` helper to create a base configuration and customize it.\n */\n customRolesCollection?: CollectionConfig\n}\n\nexport * from './exports/types.js'\nexport * from './exports/utilities.js'\n\ntype AccessArgs = {\n req: PayloadRequest\n [key: string]: any\n}\n\ntype AccessResult = boolean | Where\ntype AccessFn = (args: AccessArgs) => AccessResult | Promise<AccessResult>\n\n/* -------------------------------------------------------------------------- */\n/* Helper Functions */\n/* -------------------------------------------------------------------------- */\n\nconst wrapAccess =\n (\n original: AccessFn | AccessResult | undefined,\n privilegeKey: string,\n ): ((args: AccessArgs) => Promise<boolean | Where>) =>\n async (args) => {\n let originalResult: AccessResult = true\n\n if (original !== undefined) {\n originalResult = typeof original === 'function' ? await original(args) : original\n\n if (originalResult === false) return false\n }\n\n const hasPriv = await hasPrivilege(privilegeKey)(args)\n if (!hasPriv) return false\n\n return originalResult\n }\n\nfunction buildPrivilegesMap(\n autoMap: Map<string, any>,\n type: 'collection' | 'global',\n slugKey: 'collectionSlug' | 'globalSlug',\n labelKey: 'collectionLabel' | 'globalLabel',\n) {\n const map = new Map<string, any>()\n\n for (const entry of autoMap.values()) {\n map.set(entry[slugKey], {\n [slugKey]: entry[slugKey],\n [labelKey]: entry[labelKey],\n privileges: { ...entry.privileges },\n })\n }\n\n for (const custom of customPrivilegesRegistry.values()) {\n if (custom.type !== type) continue\n\n const existing = map.get(custom.slug)\n if (existing) {\n existing.privileges = {\n ...existing.privileges,\n ...custom.privileges,\n }\n } else {\n map.set(custom.slug, {\n [slugKey]: custom.slug,\n [labelKey]: custom.label,\n privileges: { ...custom.privileges },\n })\n }\n }\n\n return Array.from(map.values())\n}\n\n/* -------------------------------------------------------------------------- */\n/* Plugin */\n/* -------------------------------------------------------------------------- */\n\nexport const rolesPrivilegesPayloadPlugin =\n (pluginOptions: RolesPrivilegesPayloadPluginConfig = {}) =>\n (config: Config): Config => {\n const {\n enable = true,\n excludeCollections = [],\n excludeGlobals = [],\n wrapCollectionAccess = true,\n wrapGlobalAccess = true,\n seedSuperAdmin = true,\n } = pluginOptions\n\n if (!enable) {\n return config\n }\n\n config.collections ??= []\n config.globals ??= []\n\n /* ---------------------------------------------------------------------- */\n /* Generate initial privileges */\n /* ---------------------------------------------------------------------- */\n\n for (const collection of config.collections) {\n if (!excludeCollections.includes(collection.slug) && collection.slug !== 'roles') {\n generateCollectionPrivileges(collection)\n }\n }\n\n for (const global of config.globals) {\n if (!excludeGlobals.includes(global.slug)) {\n generateGlobalPrivileges(global)\n }\n }\n\n /* ---------------------------------------------------------------------- */\n /* Roles collection */\n /* ---------------------------------------------------------------------- */\n\n const rolesCollectionToAdd =\n pluginOptions.customRolesCollection || createRolesCollection([], [])\n\n // Ensure the custom collection has slug 'roles'\n if (rolesCollectionToAdd.slug !== 'roles') {\n throw new Error('[Roles & Privileges Plugin] Custom roles collection must have slug \"roles\"')\n }\n\n config.collections.push(rolesCollectionToAdd)\n\n const rolesCollection = config.collections.find((c) => c.slug === 'roles')\n\n if (rolesCollection) {\n generateCollectionPrivileges(rolesCollection)\n\n const privilegesField = rolesCollection.fields.find(\n (f) => 'name' in f && f.name === 'privileges',\n )\n\n if (\n privilegesField &&\n 'admin' in privilegesField &&\n privilegesField.admin?.components?.Field\n ) {\n const fieldComponent = privilegesField.admin.components.Field\n\n if (typeof fieldComponent === 'object' && 'clientProps' in fieldComponent) {\n fieldComponent.clientProps = {\n get collections() {\n return buildPrivilegesMap(\n allPrivilegesMap,\n 'collection',\n 'collectionSlug',\n 'collectionLabel',\n )\n },\n get globals() {\n return buildPrivilegesMap(\n allGlobalPrivilegesMap,\n 'global',\n 'globalSlug',\n 'globalLabel',\n )\n },\n }\n }\n }\n }\n\n if (pluginOptions.disabled) {\n return config\n }\n\n /* ---------------------------------------------------------------------- */\n /* Collection access wrapping */\n /* ---------------------------------------------------------------------- */\n\n const COLLECTION_ACTIONS = [\n 'create',\n 'read',\n 'update',\n 'delete',\n 'admin',\n 'readVersions',\n 'unlock',\n ] as const\n\n if (wrapCollectionAccess) {\n for (const collection of config.collections) {\n if (excludeCollections.includes(collection.slug) || collection.slug === 'roles') {\n continue\n }\n\n collection.access ??= {}\n const originalAccess = { ...collection.access }\n\n for (const action of COLLECTION_ACTIONS) {\n const key = generatePrivilegeKey(collection.slug, action)\n collection.access[action] = wrapAccess(originalAccess[action], key) as any\n }\n }\n }\n\n /* ---------------------------------------------------------------------- */\n /* Global access wrapping */\n /* ---------------------------------------------------------------------- */\n\n const GLOBAL_ACTIONS = ['read', 'update', 'readDrafts', 'readVersions'] as const\n\n if (wrapGlobalAccess) {\n for (const global of config.globals) {\n if (excludeGlobals.includes(global.slug)) continue\n\n global.access ??= {}\n const originalAccess = { ...global.access }\n\n for (const action of GLOBAL_ACTIONS) {\n const key = generateGlobalPrivilegeKey(global.slug, action)\n global.access[action] = wrapAccess(originalAccess[action], key) as any\n }\n }\n }\n\n /* ---------------------------------------------------------------------- */\n /* onInit */\n /* ---------------------------------------------------------------------- */\n\n const incomingOnInit = config.onInit\n\n config.onInit = async (payload) => {\n if (incomingOnInit) {\n await incomingOnInit(payload)\n }\n\n const existingCollections = new Set(allPrivilegesMap.keys())\n\n for (const slug of Object.keys(payload.collections)) {\n if (\n existingCollections.has(slug) ||\n excludeCollections.includes(slug) ||\n slug === 'payload-preferences' ||\n slug === 'payload-migrations' ||\n slug === 'payload-locked-documents'\n ) {\n continue\n }\n\n const collection = payload.collections[slug]\n if (collection?.config) {\n payload.logger.info(`[Roles & Privileges] Discovered late-loaded collection: ${slug}`)\n generateCollectionPrivileges(collection.config)\n }\n }\n\n const existingGlobals = new Set(allGlobalPrivilegesMap.keys())\n\n for (const slug of Object.keys(payload.globals)) {\n if (existingGlobals.has(slug) || excludeGlobals.includes(slug)) continue\n\n const global = (payload.globals as any)[slug]\n if (global?.config) {\n payload.logger.info(`[Roles & Privileges] Discovered late-loaded global: ${slug}`)\n generateGlobalPrivileges(global.config)\n }\n }\n\n if (seedSuperAdmin) {\n await seedSuperAdminRole(payload)\n }\n }\n\n /* ---------------------------------------------------------------------- */\n /* Translations */\n /* ---------------------------------------------------------------------- */\n\n config.i18n ??= {}\n config.i18n.translations ??= {}\n\n for (const locale of Object.keys(translations) as AcceptedLanguages[]) {\n const pluginBlock = translations[locale]['plugin-roles-privileges']\n\n config.i18n.translations[locale] ??= {}\n ;(config.i18n.translations[locale] as PluginDefaultTranslationsObject)[\n 'plugin-roles-privileges'\n ] = {\n ...pluginBlock,\n }\n }\n\n return config\n }\n"],"names":["createRolesCollection","translations","customPrivilegesRegistry","allGlobalPrivilegesMap","generateGlobalPrivilegeKey","generateGlobalPrivileges","allPrivilegesMap","generateCollectionPrivileges","generatePrivilegeKey","hasPrivilege","seedSuperAdminRole","wrapAccess","original","privilegeKey","args","originalResult","undefined","hasPriv","buildPrivilegesMap","autoMap","type","slugKey","labelKey","map","Map","entry","values","set","privileges","custom","existing","get","slug","label","Array","from","rolesPrivilegesPayloadPlugin","pluginOptions","config","enable","excludeCollections","excludeGlobals","wrapCollectionAccess","wrapGlobalAccess","seedSuperAdmin","collections","globals","collection","includes","global","rolesCollectionToAdd","customRolesCollection","Error","push","rolesCollection","find","c","privilegesField","fields","f","name","admin","components","Field","fieldComponent","clientProps","disabled","COLLECTION_ACTIONS","access","originalAccess","action","key","GLOBAL_ACTIONS","incomingOnInit","onInit","payload","existingCollections","Set","keys","Object","has","logger","info","existingGlobals","i18n","locale","pluginBlock"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { AcceptedLanguages } from '@payloadcms/translations'\nimport type { CollectionConfig, Config, PayloadRequest, Where } from 'payload'\n\nimport type { PluginDefaultTranslationsObject } from './translations/types.js'\n\nimport { createRolesCollection } from './collections/roles.js'\nimport { translations } from './translations/index.js'\nimport { wrapUserCollectionWithSuperAdminHook } from './utils/assignSuperAdminToFirstUser.js'\nimport { customPrivilegesRegistry } from './utils/createCustomPrivilege.js'\nimport {\n allGlobalPrivilegesMap,\n generateGlobalPrivilegeKey,\n generateGlobalPrivileges,\n} from './utils/generateGlobalPrivileges.js'\nimport {\n allPrivilegesMap,\n generateCollectionPrivileges,\n generatePrivilegeKey,\n} from './utils/generatePrivileges.js'\nimport { hasPrivilege } from './utils/privilegesAccess.js'\nimport { seedSuperAdminRole } from './utils/seedSuperAdminRole.js'\n/* -------------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------------- */\n\nexport type RolesPrivilegesPayloadPluginConfig = {\n /**\n * Automatically assign Super Admin role to the first user created in the system\n * @default true\n */\n assignSuperAdminToFirstUser?: boolean\n /**\n * Custom roles collection configuration.\n * If provided, this collection will be used instead of the default one.\n * Use `createRolesCollection` helper to create a base configuration and customize it.\n */\n customRolesCollection?: CollectionConfig\n disabled?: boolean\n enable?: boolean\n excludeCollections?: string[]\n excludeGlobals?: string[]\n /**\n * Name of the roles field to add to the user collection\n * @default 'roles'\n */\n rolesFieldName?: string\n seedSuperAdmin?: boolean\n wrapCollectionAccess?: boolean\n wrapGlobalAccess?: boolean\n}\n\nexport * from './exports/types.js'\nexport * from './exports/utilities.js'\n\ntype AccessArgs = {\n [key: string]: any\n req: PayloadRequest\n}\n\ntype AccessResult = boolean | Where\ntype AccessFn = (args: AccessArgs) => AccessResult | Promise<AccessResult>\n\n/* -------------------------------------------------------------------------- */\n/* Helper Functions */\n/* -------------------------------------------------------------------------- */\n\nconst wrapAccess =\n (\n original: AccessFn | AccessResult | undefined,\n privilegeKey: string,\n ): ((args: AccessArgs) => Promise<boolean | Where>) =>\n async (args) => {\n let originalResult: AccessResult = true\n\n if (original !== undefined) {\n originalResult = typeof original === 'function' ? await original(args) : original\n\n if (originalResult === false) {\n return false\n }\n }\n\n const hasPriv = await hasPrivilege(privilegeKey)(args)\n if (!hasPriv) {\n return false\n }\n\n return originalResult\n }\n\nfunction buildPrivilegesMap(\n autoMap: Map<string, any>,\n type: 'collection' | 'global',\n slugKey: 'collectionSlug' | 'globalSlug',\n labelKey: 'collectionLabel' | 'globalLabel',\n) {\n const map = new Map<string, any>()\n\n for (const entry of autoMap.values()) {\n map.set(entry[slugKey], {\n [labelKey]: entry[labelKey],\n privileges: { ...entry.privileges },\n [slugKey]: entry[slugKey],\n })\n }\n\n for (const custom of customPrivilegesRegistry.values()) {\n if (custom.type !== type) {\n continue\n }\n\n const existing = map.get(custom.slug)\n if (existing) {\n existing.privileges = {\n ...existing.privileges,\n ...custom.privileges,\n }\n } else {\n map.set(custom.slug, {\n [labelKey]: custom.label,\n privileges: { ...custom.privileges },\n [slugKey]: custom.slug,\n })\n }\n }\n\n return Array.from(map.values())\n}\n\n/* -------------------------------------------------------------------------- */\n/* Plugin */\n/* -------------------------------------------------------------------------- */\n\nexport const rolesPrivilegesPayloadPlugin =\n (pluginOptions: RolesPrivilegesPayloadPluginConfig = {}) =>\n (config: Config): Config => {\n const {\n assignSuperAdminToFirstUser = true,\n enable = true,\n excludeCollections = [],\n excludeGlobals = [],\n rolesFieldName = 'roles',\n seedSuperAdmin = true,\n wrapCollectionAccess = true,\n wrapGlobalAccess = true,\n } = pluginOptions\n\n if (!enable) {\n return config\n }\n\n config.collections ??= []\n config.globals ??= []\n\n /* ---------------------------------------------------------------------- */\n /* Generate initial privileges */\n /* ---------------------------------------------------------------------- */\n\n for (const collection of config.collections) {\n if (!excludeCollections.includes(collection.slug) && collection.slug !== 'roles') {\n generateCollectionPrivileges(collection)\n }\n }\n\n for (const global of config.globals) {\n if (!excludeGlobals.includes(global.slug)) {\n generateGlobalPrivileges(global)\n }\n }\n\n /* ---------------------------------------------------------------------- */\n /* Roles collection */\n /* ---------------------------------------------------------------------- */\n\n const rolesCollectionToAdd =\n pluginOptions.customRolesCollection || createRolesCollection([], [])\n\n // Ensure the custom collection has slug 'roles'\n if (rolesCollectionToAdd.slug !== 'roles') {\n throw new Error('[Roles & Privileges Plugin] Custom roles collection must have slug \"roles\"')\n }\n\n config.collections.push(rolesCollectionToAdd)\n\n const rolesCollection = config.collections.find((c) => c.slug === 'roles')\n\n if (rolesCollection) {\n generateCollectionPrivileges(rolesCollection)\n\n const privilegesField = rolesCollection.fields.find(\n (f) => 'name' in f && f.name === 'privileges',\n )\n\n if (\n privilegesField &&\n 'admin' in privilegesField &&\n privilegesField.admin?.components?.Field\n ) {\n const fieldComponent = privilegesField.admin.components.Field\n\n if (typeof fieldComponent === 'object' && 'clientProps' in fieldComponent) {\n fieldComponent.clientProps = {\n get collections() {\n return buildPrivilegesMap(\n allPrivilegesMap,\n 'collection',\n 'collectionSlug',\n 'collectionLabel',\n )\n },\n get globals() {\n return buildPrivilegesMap(\n allGlobalPrivilegesMap,\n 'global',\n 'globalSlug',\n 'globalLabel',\n )\n },\n }\n }\n }\n }\n\n /* ---------------------------------------------------------------------- */\n /* First user super admin assignment */\n /* ---------------------------------------------------------------------- */\n\n // Find the user collection from config.admin.user\n const userCollectionSlug = config.admin?.user || 'users'\n const userCollectionIndex = config.collections.findIndex((c) => c.slug === userCollectionSlug)\n\n if (userCollectionIndex !== -1) {\n const userCollection = config.collections[userCollectionIndex]\n\n // Check if roles field already exists\n const hasRolesField = userCollection.fields.some(\n (field) => 'name' in field && field.name === rolesFieldName,\n )\n\n // Add roles field if it doesn't exist\n if (!hasRolesField) {\n userCollection.fields.push({\n name: rolesFieldName,\n type: 'relationship',\n access: {\n create: async (args) => {\n const result = await hasPrivilege('roles-update')(args)\n return typeof result === 'boolean' ? result : true\n },\n read: async (args) => {\n const result = await hasPrivilege('roles-read')(args)\n return typeof result === 'boolean' ? result : true\n },\n update: async (args) => {\n const result = await hasPrivilege('roles-update')(args)\n return typeof result === 'boolean' ? result : true\n },\n },\n admin: {\n description: ({ t }) =>\n (t as (key: string) => string)(\n 'plugin-roles-privileges:user-roles-field-description',\n ),\n },\n hasMany: true,\n relationTo: 'roles',\n })\n }\n\n // Wrap with super admin hook if enabled\n if (assignSuperAdminToFirstUser) {\n config.collections[userCollectionIndex] = wrapUserCollectionWithSuperAdminHook(\n userCollection,\n rolesFieldName,\n )\n }\n }\n\n if (pluginOptions.disabled) {\n return config\n }\n\n /* ---------------------------------------------------------------------- */\n /* Collection access wrapping */\n /* ---------------------------------------------------------------------- */\n\n const COLLECTION_ACTIONS = [\n 'create',\n 'read',\n 'update',\n 'delete',\n 'admin',\n 'readVersions',\n 'unlock',\n ] as const\n\n if (wrapCollectionAccess) {\n for (const collection of config.collections) {\n if (excludeCollections.includes(collection.slug) || collection.slug === 'roles') {\n continue\n }\n\n collection.access ??= {}\n const originalAccess = { ...collection.access }\n\n for (const action of COLLECTION_ACTIONS) {\n const key = generatePrivilegeKey(collection.slug, action)\n collection.access[action] = wrapAccess(originalAccess[action], key) as any\n }\n }\n }\n\n /* ---------------------------------------------------------------------- */\n /* Global access wrapping */\n /* ---------------------------------------------------------------------- */\n\n const GLOBAL_ACTIONS = ['read', 'update', 'readDrafts', 'readVersions'] as const\n\n if (wrapGlobalAccess) {\n for (const global of config.globals) {\n if (excludeGlobals.includes(global.slug)) {\n continue\n }\n\n global.access ??= {}\n const originalAccess = { ...global.access }\n\n for (const action of GLOBAL_ACTIONS) {\n const key = generateGlobalPrivilegeKey(global.slug, action)\n global.access[action] = wrapAccess(originalAccess[action], key) as any\n }\n }\n }\n\n /* ---------------------------------------------------------------------- */\n /* onInit */\n /* ---------------------------------------------------------------------- */\n\n const incomingOnInit = config.onInit\n\n config.onInit = async (payload) => {\n if (incomingOnInit) {\n await incomingOnInit(payload)\n }\n\n const existingCollections = new Set(allPrivilegesMap.keys())\n\n for (const slug of Object.keys(payload.collections)) {\n if (\n existingCollections.has(slug) ||\n excludeCollections.includes(slug) ||\n slug === 'payload-preferences' ||\n slug === 'payload-migrations' ||\n slug === 'payload-locked-documents'\n ) {\n continue\n }\n\n const collection = payload.collections[slug]\n if (collection?.config) {\n payload.logger.info(`[Roles & Privileges] Discovered late-loaded collection: ${slug}`)\n generateCollectionPrivileges(collection.config)\n }\n }\n\n const existingGlobals = new Set(allGlobalPrivilegesMap.keys())\n\n for (const slug of Object.keys(payload.globals)) {\n if (existingGlobals.has(slug) || excludeGlobals.includes(slug)) {\n continue\n }\n\n const global = (payload.globals as any)[slug]\n if (global?.config) {\n payload.logger.info(`[Roles & Privileges] Discovered late-loaded global: ${slug}`)\n generateGlobalPrivileges(global.config)\n }\n }\n\n if (seedSuperAdmin) {\n await seedSuperAdminRole(payload)\n }\n }\n\n /* ---------------------------------------------------------------------- */\n /* Translations */\n /* ---------------------------------------------------------------------- */\n\n config.i18n ??= {}\n config.i18n.translations ??= {}\n\n for (const locale of Object.keys(translations) as AcceptedLanguages[]) {\n const pluginBlock = translations[locale]['plugin-roles-privileges']\n\n ;(config.i18n.translations as any)[locale] ??= {}\n ;((config.i18n.translations as any)[locale] as PluginDefaultTranslationsObject)[\n 'plugin-roles-privileges'\n ] = {\n ...pluginBlock,\n }\n }\n\n return config\n }\n"],"names":["createRolesCollection","translations","wrapUserCollectionWithSuperAdminHook","customPrivilegesRegistry","allGlobalPrivilegesMap","generateGlobalPrivilegeKey","generateGlobalPrivileges","allPrivilegesMap","generateCollectionPrivileges","generatePrivilegeKey","hasPrivilege","seedSuperAdminRole","wrapAccess","original","privilegeKey","args","originalResult","undefined","hasPriv","buildPrivilegesMap","autoMap","type","slugKey","labelKey","map","Map","entry","values","set","privileges","custom","existing","get","slug","label","Array","from","rolesPrivilegesPayloadPlugin","pluginOptions","config","assignSuperAdminToFirstUser","enable","excludeCollections","excludeGlobals","rolesFieldName","seedSuperAdmin","wrapCollectionAccess","wrapGlobalAccess","collections","globals","collection","includes","global","rolesCollectionToAdd","customRolesCollection","Error","push","rolesCollection","find","c","privilegesField","fields","f","name","admin","components","Field","fieldComponent","clientProps","userCollectionSlug","user","userCollectionIndex","findIndex","userCollection","hasRolesField","some","field","access","create","result","read","update","description","t","hasMany","relationTo","disabled","COLLECTION_ACTIONS","originalAccess","action","key","GLOBAL_ACTIONS","incomingOnInit","onInit","payload","existingCollections","Set","keys","Object","has","logger","info","existingGlobals","i18n","locale","pluginBlock"],"mappings":"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"}
@@ -1,9 +1,12 @@
1
1
  import { enTranslations } from './languages/en.js';
2
2
  import { frTranslations } from './languages/fr.js';
3
3
  export const translations = {
4
+ id: enTranslations,
4
5
  ar: enTranslations,
5
6
  az: enTranslations,
6
7
  bg: enTranslations,
8
+ bnBd: enTranslations,
9
+ bnIn: enTranslations,
7
10
  ca: enTranslations,
8
11
  cs: enTranslations,
9
12
  da: enTranslations,
@@ -17,7 +20,6 @@ export const translations = {
17
20
  hr: enTranslations,
18
21
  hu: enTranslations,
19
22
  hy: enTranslations,
20
- id: enTranslations,
21
23
  is: enTranslations,
22
24
  it: enTranslations,
23
25
  ja: enTranslations,
@@ -42,9 +44,7 @@ export const translations = {
42
44
  uk: enTranslations,
43
45
  vi: enTranslations,
44
46
  zh: enTranslations,
45
- zhTw: enTranslations,
46
- bnBd: enTranslations,
47
- bnIn: enTranslations
47
+ zhTw: enTranslations
48
48
  };
49
49
 
50
50
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/translations/index.ts"],"sourcesContent":["import type { GenericTranslationsObject } from '@payloadcms/translations'\nimport type { PluginDefaultTranslationsObject } from './types.js'\n\nimport { enTranslations } from './languages/en.js'\nimport { frTranslations } from './languages/fr.js'\n\ntype TranslationMap = {\n [key: string]: GenericTranslationsObject & PluginDefaultTranslationsObject\n}\n\nexport const translations: TranslationMap = {\n ar: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n az: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n bg: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n ca: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n cs: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n da: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n de: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n en: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n es: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n et: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n fa: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n fr: frTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n he: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n hr: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n hu: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n hy: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n id: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n is: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n it: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n ja: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n ko: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n lt: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n lv: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n my: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n nb: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n nl: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n pl: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n pt: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n ro: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n rs: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n rsLatin: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n ru: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n sk: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n sl: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n sv: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n ta: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n th: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n tr: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n uk: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n vi: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n zh: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n zhTw: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n bnBd: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n bnIn: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n}\n"],"names":["enTranslations","frTranslations","translations","ar","az","bg","ca","cs","da","de","en","es","et","fa","fr","he","hr","hu","hy","id","is","it","ja","ko","lt","lv","my","nb","nl","pl","pt","ro","rs","rsLatin","ru","sk","sl","sv","ta","th","tr","uk","vi","zh","zhTw","bnBd","bnIn"],"mappings":"AAGA,SAASA,cAAc,QAAQ,oBAAmB;AAClD,SAASC,cAAc,QAAQ,oBAAmB;AAMlD,OAAO,MAAMC,eAA+B;IAC1CC,IAAIH;IACJI,IAAIJ;IACJK,IAAIL;IACJM,IAAIN;IACJO,IAAIP;IACJQ,IAAIR;IACJS,IAAIT;IACJU,IAAIV;IACJW,IAAIX;IACJY,IAAIZ;IACJa,IAAIb;IACJc,IAAIb;IACJc,IAAIf;IACJgB,IAAIhB;IACJiB,IAAIjB;IACJkB,IAAIlB;IACJmB,IAAInB;IACJoB,IAAIpB;IACJqB,IAAIrB;IACJsB,IAAItB;IACJuB,IAAIvB;IACJwB,IAAIxB;IACJyB,IAAIzB;IACJ0B,IAAI1B;IACJ2B,IAAI3B;IACJ4B,IAAI5B;IACJ6B,IAAI7B;IACJ8B,IAAI9B;IACJ+B,IAAI/B;IACJgC,IAAIhC;IACJiC,SAASjC;IACTkC,IAAIlC;IACJmC,IAAInC;IACJoC,IAAIpC;IACJqC,IAAIrC;IACJsC,IAAItC;IACJuC,IAAIvC;IACJwC,IAAIxC;IACJyC,IAAIzC;IACJ0C,IAAI1C;IACJ2C,IAAI3C;IACJ4C,MAAM5C;IACN6C,MAAM7C;IACN8C,MAAM9C;AACR,EAAC"}
1
+ {"version":3,"sources":["../../src/translations/index.ts"],"sourcesContent":["import type { GenericTranslationsObject } from '@payloadcms/translations'\n\nimport type { PluginDefaultTranslationsObject } from './types.js'\n\nimport { enTranslations } from './languages/en.js'\nimport { frTranslations } from './languages/fr.js'\n\ntype TranslationMap = {\n [key: string]: GenericTranslationsObject & PluginDefaultTranslationsObject\n}\n\nexport const translations: TranslationMap = {\n id: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n ar: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n az: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n bg: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n bnBd: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n bnIn: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n ca: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n cs: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n da: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n de: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n en: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n es: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n et: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n fa: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n fr: frTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n he: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n hr: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n hu: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n hy: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n is: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n it: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n ja: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n ko: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n lt: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n lv: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n my: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n nb: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n nl: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n pl: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n pt: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n ro: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n rs: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n rsLatin: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n ru: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n sk: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n sl: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n sv: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n ta: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n th: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n tr: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n uk: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n vi: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n zh: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n zhTw: enTranslations as GenericTranslationsObject & PluginDefaultTranslationsObject,\n}\n"],"names":["enTranslations","frTranslations","translations","id","ar","az","bg","bnBd","bnIn","ca","cs","da","de","en","es","et","fa","fr","he","hr","hu","hy","is","it","ja","ko","lt","lv","my","nb","nl","pl","pt","ro","rs","rsLatin","ru","sk","sl","sv","ta","th","tr","uk","vi","zh","zhTw"],"mappings":"AAIA,SAASA,cAAc,QAAQ,oBAAmB;AAClD,SAASC,cAAc,QAAQ,oBAAmB;AAMlD,OAAO,MAAMC,eAA+B;IAC1CC,IAAIH;IACJI,IAAIJ;IACJK,IAAIL;IACJM,IAAIN;IACJO,MAAMP;IACNQ,MAAMR;IACNS,IAAIT;IACJU,IAAIV;IACJW,IAAIX;IACJY,IAAIZ;IACJa,IAAIb;IACJc,IAAId;IACJe,IAAIf;IACJgB,IAAIhB;IACJiB,IAAIhB;IACJiB,IAAIlB;IACJmB,IAAInB;IACJoB,IAAIpB;IACJqB,IAAIrB;IACJsB,IAAItB;IACJuB,IAAIvB;IACJwB,IAAIxB;IACJyB,IAAIzB;IACJ0B,IAAI1B;IACJ2B,IAAI3B;IACJ4B,IAAI5B;IACJ6B,IAAI7B;IACJ8B,IAAI9B;IACJ+B,IAAI/B;IACJgC,IAAIhC;IACJiC,IAAIjC;IACJkC,IAAIlC;IACJmC,SAASnC;IACToC,IAAIpC;IACJqC,IAAIrC;IACJsC,IAAItC;IACJuC,IAAIvC;IACJwC,IAAIxC;IACJyC,IAAIzC;IACJ0C,IAAI1C;IACJ2C,IAAI3C;IACJ4C,IAAI5C;IACJ6C,IAAI7C;IACJ8C,MAAM9C;AACR,EAAC"}
@@ -1,50 +1,51 @@
1
1
  export const enTranslations = {
2
2
  'plugin-roles-privileges': {
3
3
  // Roles collection
4
- 'roles-collection-label-singular': 'Role',
5
4
  'roles-collection-label-plural': 'Roles',
6
- 'roles-field-title-label': 'Role Title',
7
- 'roles-field-slug-label': 'Slug',
8
- 'roles-field-slug-description': 'Unique identifier for this role',
9
- 'roles-field-privileges-label': 'Privileges',
10
- 'roles-field-privileges-description': 'Select the privileges this role should have',
11
- 'roles-field-description-label': 'Description',
5
+ 'roles-collection-label-singular': 'Role',
12
6
  'roles-field-description-description': 'Optional description of this role',
7
+ 'roles-field-description-label': 'Description',
8
+ 'roles-field-privileges-description': 'Select the privileges this role should have',
9
+ 'roles-field-privileges-label': 'Privileges',
10
+ 'roles-field-slug-description': 'Unique identifier for this role',
11
+ 'roles-field-slug-label': 'Slug',
12
+ 'roles-field-title-label': 'Role Title',
13
+ 'user-roles-field-description': 'Roles assigned to this user',
13
14
  // Privileges UI
14
15
  'privileges-column-collections-globals': 'Collections & Globals',
15
- 'privileges-column-privileges': 'Privileges',
16
16
  'privileges-column-description': 'Description',
17
+ 'privileges-column-privileges': 'Privileges',
17
18
  'privileges-select-placeholder': 'Select a collection or global to view privileges',
18
19
  'privileges-select-privilege-placeholder': 'Select a privilege to view its description',
19
20
  'privileges-selected-count': 'Selected Privileges',
20
21
  // Privilege operations
21
22
  'privilege-operation-create': 'Create',
23
+ 'privilege-operation-delete': 'Delete',
22
24
  'privilege-operation-read': 'Read',
23
25
  'privilege-operation-update': 'Update',
24
- 'privilege-operation-delete': 'Delete',
25
26
  // Collection privilege operation prefixes
26
27
  'privilege-prefix-admin': 'Admin Access to',
27
28
  'privilege-prefix-create': 'Create',
29
+ 'privilege-prefix-delete': 'Delete',
28
30
  'privilege-prefix-read': 'Read',
29
31
  'privilege-prefix-readVersions': 'Read Versions:',
30
- 'privilege-prefix-update': 'Update',
31
- 'privilege-prefix-delete': 'Delete',
32
32
  'privilege-prefix-unlock': 'Unlock',
33
+ 'privilege-prefix-update': 'Update',
33
34
  // Collection privilege description templates
34
35
  'privilege-template-admin': 'Access the {label} admin panel and UI',
35
36
  'privilege-template-admin-plural': 'true',
36
37
  'privilege-template-create': 'Ability to create new {label}',
37
38
  'privilege-template-create-plural': 'true',
39
+ 'privilege-template-delete': 'Remove {label} from the system',
40
+ 'privilege-template-delete-plural': 'true',
38
41
  'privilege-template-read': 'View {label} content and information',
39
42
  'privilege-template-read-plural': 'false',
40
43
  'privilege-template-readVersions': 'Access and view previous versions of {label}',
41
44
  'privilege-template-readVersions-plural': 'true',
42
- 'privilege-template-update': 'Modify existing {label} data',
43
- 'privilege-template-update-plural': 'false',
44
- 'privilege-template-delete': 'Remove {label} from the system',
45
- 'privilege-template-delete-plural': 'true',
46
45
  'privilege-template-unlock': 'Unlock {label} that are being edited by other users',
47
46
  'privilege-template-unlock-plural': 'true',
47
+ 'privilege-template-update': 'Modify existing {label} data',
48
+ 'privilege-template-update-plural': 'false',
48
49
  // Global privilege operation prefixes
49
50
  'privilege-prefix-global-read': 'Read',
50
51
  'privilege-prefix-global-readDrafts': 'Read Drafts:',
@@ -60,13 +61,13 @@ export const enTranslations = {
60
61
  'privilege-global-description': 'Manage {label} global settings',
61
62
  // Privilege descriptions
62
63
  'privilege-description-collection-create': 'Allows create operations on {{collection}} collection',
64
+ 'privilege-description-collection-delete': 'Allows delete operations on {{collection}} collection',
65
+ 'privilege-description-collection-info': 'Manage access privileges for this collection',
63
66
  'privilege-description-collection-read': 'Allows read operations on {{collection}} collection',
64
67
  'privilege-description-collection-update': 'Allows update operations on {{collection}} collection',
65
- 'privilege-description-collection-delete': 'Allows delete operations on {{collection}} collection',
68
+ 'privilege-description-global-info': 'Manage access privileges for this global',
66
69
  'privilege-description-global-read': 'Allows read access to {{global}} global',
67
70
  'privilege-description-global-update': 'Allows update access to {{global}} global',
68
- 'privilege-description-collection-info': 'Manage access privileges for this collection',
69
- 'privilege-description-global-info': 'Manage access privileges for this global',
70
71
  // Errors
71
72
  'error-cannot-delete-super-admin': 'Cannot delete the Super Admin role',
72
73
  'error-cannot-modify-super-admin-slug': 'Cannot modify the Super Admin role slug'