roles-privileges-payload-plugin 1.0.1 → 1.1.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.
Files changed (51) hide show
  1. package/README.md +5 -1
  2. package/dist/collections/roles.d.ts +32 -0
  3. package/dist/collections/roles.js +122 -0
  4. package/dist/collections/roles.js.map +1 -0
  5. package/dist/components/PrivilegesSelect.d.ts +19 -0
  6. package/dist/components/PrivilegesSelect.js +471 -0
  7. package/dist/components/PrivilegesSelect.js.map +1 -0
  8. package/dist/exports/client.d.ts +2 -0
  9. package/dist/exports/client.js +3 -0
  10. package/dist/exports/client.js.map +1 -0
  11. package/dist/exports/rsc.d.ts +1 -0
  12. package/dist/exports/rsc.js +3 -0
  13. package/dist/exports/rsc.js.map +1 -0
  14. package/dist/exports/types.d.ts +3 -0
  15. package/dist/exports/types.js +5 -0
  16. package/dist/exports/types.js.map +1 -0
  17. package/dist/exports/utilities.d.ts +6 -0
  18. package/dist/exports/utilities.js +14 -0
  19. package/dist/exports/utilities.js.map +1 -0
  20. package/dist/index.d.ts +19 -0
  21. package/dist/index.js +179 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/roles-privileges-payload-plugin-1.1.1.tgz +0 -0
  24. package/dist/translations/index.d.ts +7 -0
  25. package/dist/translations/index.js +50 -0
  26. package/dist/translations/index.js.map +1 -0
  27. package/dist/translations/languages/en.d.ts +2 -0
  28. package/dist/translations/languages/en.js +76 -0
  29. package/dist/translations/languages/en.js.map +1 -0
  30. package/dist/translations/languages/fr.d.ts +2 -0
  31. package/dist/translations/languages/fr.js +76 -0
  32. package/dist/translations/languages/fr.js.map +1 -0
  33. package/dist/translations/types.d.ts +67 -0
  34. package/dist/translations/types.js +3 -0
  35. package/dist/translations/types.js.map +1 -0
  36. package/dist/utils/createCustomPrivilege.d.ts +89 -0
  37. package/dist/utils/createCustomPrivilege.js +77 -0
  38. package/dist/utils/createCustomPrivilege.js.map +1 -0
  39. package/dist/utils/generateGlobalPrivileges.d.ts +48 -0
  40. package/dist/utils/generateGlobalPrivileges.js +133 -0
  41. package/dist/utils/generateGlobalPrivileges.js.map +1 -0
  42. package/dist/utils/generatePrivileges.d.ts +51 -0
  43. package/dist/utils/generatePrivileges.js +162 -0
  44. package/dist/utils/generatePrivileges.js.map +1 -0
  45. package/dist/utils/privilegesAccess.d.ts +71 -0
  46. package/dist/utils/privilegesAccess.js +144 -0
  47. package/dist/utils/privilegesAccess.js.map +1 -0
  48. package/dist/utils/seedSuperAdminRole.d.ts +6 -0
  49. package/dist/utils/seedSuperAdminRole.js +60 -0
  50. package/dist/utils/seedSuperAdminRole.js.map +1 -0
  51. package/package.json +12 -1
package/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Roles & Privileges Payload Plugin
2
2
 
3
+ [![semantic-release: angular](https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release)
4
+ [![npm version](https://badge.fury.io/js/roles-privileges-payload-plugin.svg)](https://www.npmjs.com/package/roles-privileges-payload-plugin)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
3
7
  A powerful Payload CMS plugin that automatically generates role-based access control (RBAC) with granular CRUD privileges for all your collections.
4
8
 
5
9
  ## Features
@@ -632,4 +636,4 @@ describe('Plugin tests', () => {
632
636
  expect(...)
633
637
  })
634
638
  })
635
- ```
639
+ ```
@@ -0,0 +1,32 @@
1
+ import type { CollectionBeforeChangeHook, CollectionBeforeDeleteHook, CollectionConfig } from 'payload';
2
+ import type { GlobalPrivilege } from '../utils/generateGlobalPrivileges.js';
3
+ import type { Privilege } from '../utils/generatePrivileges.js';
4
+ export type CollectionData = {
5
+ collectionSlug: string;
6
+ collectionLabel: {
7
+ en: string;
8
+ fr: string;
9
+ };
10
+ privileges: Record<string, Privilege>;
11
+ };
12
+ export type GlobalData = {
13
+ globalSlug: string;
14
+ globalLabel: {
15
+ en: string;
16
+ fr: string;
17
+ };
18
+ privileges: Record<string, GlobalPrivilege>;
19
+ };
20
+ /**
21
+ * Hook to ensure the Super Admin role cannot be deleted
22
+ */
23
+ export declare const ensureSuperAdminDontGetDeleted: CollectionBeforeDeleteHook;
24
+ /**
25
+ * Hook to ensure the Super Admin role slug cannot be changed
26
+ */
27
+ export declare const ensureSuperAdminDontGetUpdated: CollectionBeforeChangeHook;
28
+ /**
29
+ * Roles collection configuration
30
+ * This collection manages user roles and their associated privileges
31
+ */
32
+ export declare const createRolesCollection: (collections?: CollectionData[], globals?: GlobalData[]) => CollectionConfig;
@@ -0,0 +1,122 @@
1
+ import { APIError } from 'payload';
2
+ import { hasPrivilege } from '../utils/privilegesAccess.js';
3
+ /**
4
+ * Hook to ensure the Super Admin role cannot be deleted
5
+ */ export const ensureSuperAdminDontGetDeleted = async ({ req, id })=>{
6
+ const role = await req.payload.findByID({
7
+ collection: 'roles',
8
+ id
9
+ });
10
+ if (role && role.slug === 'super-admin') {
11
+ throw new APIError(req.t('plugin-roles-privileges:error-cannot-delete-super-admin'), 400);
12
+ }
13
+ };
14
+ /**
15
+ * Hook to ensure the Super Admin role slug cannot be changed
16
+ */ export const ensureSuperAdminDontGetUpdated = async ({ data, originalDoc, req })=>{
17
+ if (originalDoc && originalDoc.slug === 'super-admin') {
18
+ if (data.slug && data.slug !== 'super-admin') {
19
+ throw new APIError(req.t('plugin-roles-privileges:error-cannot-modify-super-admin-slug'), 400);
20
+ }
21
+ }
22
+ return data;
23
+ };
24
+ /**
25
+ * Roles collection configuration
26
+ * This collection manages user roles and their associated privileges
27
+ */ export const createRolesCollection = (collections, globals)=>{
28
+ return {
29
+ slug: 'roles',
30
+ labels: {
31
+ singular: ({ t })=>t('plugin-roles-privileges:roles-collection-label-singular'),
32
+ plural: ({ t })=>t('plugin-roles-privileges:roles-collection-label-plural')
33
+ },
34
+ access: {
35
+ // Allow authenticated users to read roles (needed for user role resolution)
36
+ read: ()=>true,
37
+ // Require specific privileges for other operations
38
+ create: hasPrivilege('roles-create'),
39
+ update: hasPrivilege('roles-update'),
40
+ delete: hasPrivilege('roles-delete')
41
+ },
42
+ admin: {
43
+ useAsTitle: 'title',
44
+ defaultColumns: [
45
+ 'title',
46
+ 'slug'
47
+ ]
48
+ },
49
+ fields: [
50
+ {
51
+ name: 'title',
52
+ type: 'text',
53
+ required: true,
54
+ label: ({ t })=>t('plugin-roles-privileges:roles-field-title-label')
55
+ },
56
+ {
57
+ name: 'slug',
58
+ type: 'text',
59
+ required: true,
60
+ unique: true,
61
+ label: ({ t })=>t('plugin-roles-privileges:roles-field-slug-label'),
62
+ admin: {
63
+ description: ({ t })=>t('plugin-roles-privileges:roles-field-slug-description')
64
+ },
65
+ hooks: {
66
+ beforeValidate: [
67
+ ({ value })=>{
68
+ if (typeof value === 'string') {
69
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');
70
+ }
71
+ return value;
72
+ }
73
+ ]
74
+ }
75
+ },
76
+ {
77
+ name: 'privileges',
78
+ type: 'array',
79
+ label: ({ t })=>t('plugin-roles-privileges:roles-field-privileges-label'),
80
+ admin: {
81
+ description: ({ t })=>t('plugin-roles-privileges:roles-field-privileges-description'),
82
+ components: {
83
+ Field: {
84
+ path: 'roles-privileges-payload-plugin/client#PrivilegesSelect',
85
+ clientProps: {
86
+ collections: collections || [],
87
+ globals: globals || []
88
+ }
89
+ }
90
+ }
91
+ },
92
+ minRows: 1,
93
+ fields: [
94
+ {
95
+ name: 'privilege',
96
+ type: 'text',
97
+ required: true,
98
+ label: ({ t })=>t('plugin-roles-privileges:roles-field-privileges-label')
99
+ }
100
+ ]
101
+ },
102
+ {
103
+ name: 'description',
104
+ type: 'textarea',
105
+ label: ({ t })=>t('plugin-roles-privileges:roles-field-description-label'),
106
+ admin: {
107
+ description: ({ t })=>t('plugin-roles-privileges:roles-field-description-description')
108
+ }
109
+ }
110
+ ],
111
+ hooks: {
112
+ beforeChange: [
113
+ ensureSuperAdminDontGetUpdated
114
+ ],
115
+ beforeDelete: [
116
+ ensureSuperAdminDontGetDeleted
117
+ ]
118
+ }
119
+ };
120
+ };
121
+
122
+ //# sourceMappingURL=roles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/collections/roles.ts"],"sourcesContent":["import type {\n CollectionBeforeChangeHook,\n CollectionBeforeDeleteHook,\n CollectionConfig,\n} from 'payload'\nimport { APIError } from 'payload'\nimport type { GlobalPrivilege } from '../utils/generateGlobalPrivileges.js'\nimport type { Privilege } from '../utils/generatePrivileges.js'\nimport { hasPrivilege } from '../utils/privilegesAccess.js'\n\nexport type CollectionData = {\n collectionSlug: string\n collectionLabel: { en: string; fr: string }\n privileges: Record<string, Privilege>\n}\n\nexport type GlobalData = {\n globalSlug: string\n globalLabel: { en: string; fr: string }\n privileges: Record<string, GlobalPrivilege>\n}\n\n/**\n * Hook to ensure the Super Admin role cannot be deleted\n */\nexport const ensureSuperAdminDontGetDeleted: CollectionBeforeDeleteHook = async ({ req, id }) => {\n const role = await req.payload.findByID({\n collection: 'roles',\n id,\n })\n\n if (role && role.slug === 'super-admin') {\n throw new APIError(\n (req.t as (key: string) => string)('plugin-roles-privileges:error-cannot-delete-super-admin'),\n 400,\n )\n }\n}\n\n/**\n * Hook to ensure the Super Admin role slug cannot be changed\n */\nexport const ensureSuperAdminDontGetUpdated: CollectionBeforeChangeHook = async ({\n data,\n originalDoc,\n req,\n}) => {\n if (originalDoc && originalDoc.slug === 'super-admin') {\n if (data.slug && data.slug !== 'super-admin') {\n throw new APIError(\n (req.t as (key: string) => string)(\n 'plugin-roles-privileges:error-cannot-modify-super-admin-slug',\n ),\n 400,\n )\n }\n }\n return data\n}\n\n/**\n * Roles collection configuration\n * This collection manages user roles and their associated privileges\n */\nexport const createRolesCollection = (\n collections?: CollectionData[],\n globals?: GlobalData[],\n): CollectionConfig => {\n return {\n slug: 'roles',\n labels: {\n singular: ({ t }) =>\n (t as (key: string) => string)('plugin-roles-privileges:roles-collection-label-singular'),\n plural: ({ t }) =>\n (t as (key: string) => string)('plugin-roles-privileges:roles-collection-label-plural'),\n },\n access: {\n // Allow authenticated users to read roles (needed for user role resolution)\n read: () => true,\n // Require specific privileges for other operations\n create: hasPrivilege('roles-create'),\n update: hasPrivilege('roles-update'),\n delete: hasPrivilege('roles-delete'),\n },\n admin: {\n useAsTitle: 'title',\n defaultColumns: ['title', 'slug'],\n },\n fields: [\n {\n name: 'title',\n type: 'text',\n required: true,\n label: ({ t }) =>\n (t as (key: string) => string)('plugin-roles-privileges:roles-field-title-label'),\n },\n {\n name: 'slug',\n type: 'text',\n required: true,\n unique: true,\n label: ({ t }) =>\n (t as (key: string) => string)('plugin-roles-privileges:roles-field-slug-label'),\n admin: {\n description: ({ t }) =>\n (t as (key: string) => string)('plugin-roles-privileges:roles-field-slug-description'),\n },\n hooks: {\n beforeValidate: [\n ({ value }) => {\n if (typeof value === 'string') {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/(^-|-$)/g, '')\n }\n return value\n },\n ],\n },\n },\n {\n name: 'privileges',\n type: 'array',\n label: ({ t }) =>\n (t as (key: string) => string)('plugin-roles-privileges:roles-field-privileges-label'),\n admin: {\n description: ({ t }) =>\n (t as (key: string) => string)(\n 'plugin-roles-privileges:roles-field-privileges-description',\n ),\n components: {\n Field: {\n path: 'roles-privileges-payload-plugin/client#PrivilegesSelect',\n clientProps: {\n collections: collections || [],\n globals: globals || [],\n },\n },\n },\n },\n minRows: 1,\n fields: [\n {\n name: 'privilege',\n type: 'text',\n required: true,\n label: ({ t }) =>\n (t as (key: string) => string)(\n 'plugin-roles-privileges:roles-field-privileges-label',\n ),\n },\n ],\n },\n {\n name: 'description',\n type: 'textarea',\n label: ({ t }) =>\n (t as (key: string) => string)('plugin-roles-privileges:roles-field-description-label'),\n admin: {\n description: ({ t }) =>\n (t as (key: string) => string)(\n 'plugin-roles-privileges:roles-field-description-description',\n ),\n },\n },\n ],\n hooks: {\n beforeChange: [ensureSuperAdminDontGetUpdated],\n beforeDelete: [ensureSuperAdminDontGetDeleted],\n },\n }\n}\n"],"names":["APIError","hasPrivilege","ensureSuperAdminDontGetDeleted","req","id","role","payload","findByID","collection","slug","t","ensureSuperAdminDontGetUpdated","data","originalDoc","createRolesCollection","collections","globals","labels","singular","plural","access","read","create","update","delete","admin","useAsTitle","defaultColumns","fields","name","type","required","label","unique","description","hooks","beforeValidate","value","toLowerCase","replace","components","Field","path","clientProps","minRows","beforeChange","beforeDelete"],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { GlobalPrivilege } from '../utils/generateGlobalPrivileges.js';
2
+ import type { Privilege } from '../utils/generatePrivileges.js';
3
+ type CollectionPrivileges = {
4
+ collectionSlug: string;
5
+ collectionLabel: Record<string, string>;
6
+ privileges: Record<string, Privilege>;
7
+ };
8
+ type GlobalPrivileges = {
9
+ globalSlug: string;
10
+ globalLabel: Record<string, string>;
11
+ privileges: Record<string, GlobalPrivilege>;
12
+ };
13
+ declare const _default_1: import("react").NamedExoticComponent<{
14
+ readonly validate?: import("payload").ArrayFieldValidation;
15
+ } & import("payload").FieldPaths & {
16
+ readonly field: Omit<import("payload").ArrayFieldClient, "type"> & Partial<Pick<import("payload").ArrayFieldClient, "type">>;
17
+ } & Omit<import("payload").ClientComponentProps, "customComponents" | "field">>;
18
+ export default _default_1;
19
+ export type { CollectionPrivileges, GlobalPrivileges };