@zealamic/payload-auth-rbac-plugin 1.0.0 → 1.0.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 (52) hide show
  1. package/dist/components/role-permission-matrix-client/default-data.js +2 -2
  2. package/dist/components/role-permission-matrix-client/default-data.js.map +1 -1
  3. package/dist/components/role-permission-matrix-client/index.js +2 -2
  4. package/dist/components/role-permission-matrix-client/index.js.map +1 -1
  5. package/dist/components/role-permission-matrix-client/matrix.module.scss +1 -4
  6. package/dist/components/role-permission-matrix-client/types.d.ts +4 -6
  7. package/dist/components/role-permission-matrix-client/types.js.map +1 -1
  8. package/docs/TRANSLATIONS.md +12 -5
  9. package/package.json +4 -27
  10. package/src/collections/permission-actions/default-data.ts +36 -0
  11. package/src/collections/permission-actions/index.ts +144 -0
  12. package/src/collections/permission-actions/types.ts +56 -0
  13. package/src/collections/permission-features/default-data.ts +30 -0
  14. package/src/collections/permission-features/index.ts +122 -0
  15. package/src/collections/permission-features/types.ts +47 -0
  16. package/src/collections/permissions/default-data.ts +38 -0
  17. package/src/collections/permissions/index.ts +160 -0
  18. package/src/collections/permissions/types.ts +57 -0
  19. package/src/collections/roles/default-data.ts +44 -0
  20. package/src/collections/roles/hooks/sync-permission-matrix-draft.ts +73 -0
  21. package/src/collections/roles/index.ts +178 -0
  22. package/src/collections/roles/types.ts +56 -0
  23. package/src/collections/roles-permissions/default-data.ts +28 -0
  24. package/src/collections/roles-permissions/index.ts +107 -0
  25. package/src/collections/roles-permissions/types.ts +42 -0
  26. package/src/collections/users/default-data.ts +19 -0
  27. package/src/collections/users/index.ts +148 -0
  28. package/src/collections/users/parent-path.ts +310 -0
  29. package/src/collections/users/types.ts +25 -0
  30. package/src/components/role-permission-matrix-client/default-data.ts +25 -0
  31. package/src/components/role-permission-matrix-client/index.tsx +369 -0
  32. package/src/components/role-permission-matrix-client/matrix.module.scss +66 -0
  33. package/src/components/role-permission-matrix-client/types.ts +16 -0
  34. package/src/endpoints/customEndpointHandler.ts +5 -0
  35. package/src/exports/client.ts +1 -0
  36. package/src/exports/rsc.ts +0 -0
  37. package/src/general-types.d.ts +5 -0
  38. package/src/index.ts +249 -0
  39. package/src/lib/constants/general.ts +1 -0
  40. package/src/lib/constants/index.ts +15 -0
  41. package/src/lib/constants/permission-action.ts +9 -0
  42. package/src/lib/constants/permission-feature.ts +4 -0
  43. package/src/lib/constants/permission.ts +4 -0
  44. package/src/lib/constants/role.ts +10 -0
  45. package/src/lib/constants/user.ts +1 -0
  46. package/src/lib/utils/access.ts +611 -0
  47. package/src/lib/utils/data.ts +7 -0
  48. package/src/lib/utils/fields.ts +62 -0
  49. package/src/lib/utils/index.ts +4 -0
  50. package/src/lib/utils/localization.ts +106 -0
  51. package/src/styles/variables.scss +1 -0
  52. package/src/types.ts +64 -0
@@ -0,0 +1,178 @@
1
+ import type { CollectionConfig, Condition } from "payload";
2
+ import { DATA_SCOPE, STATUS } from "../../lib/constants/role.js";
3
+ import {
4
+ getArrayOfMergedFieldAffectingData,
5
+ getSuperAdminAccess,
6
+ toLocaleRecord,
7
+ toSelectPlaceholder,
8
+ } from "../../lib/utils/index.js";
9
+ import { syncPermissionMatrixDraftAfterChange } from "./hooks/sync-permission-matrix-draft.js";
10
+ import type { RolesCollectionParams } from "./types.js";
11
+
12
+ export const getRolesCollection = (params: RolesCollectionParams) => {
13
+ const {
14
+ translations = {},
15
+ access = {},
16
+ fields = [],
17
+ labels = {},
18
+ admin = {},
19
+ } = params || {};
20
+ const arrTranslationsKeys = Object.keys(translations);
21
+ const roles: CollectionConfig = {
22
+ slug: "roles",
23
+ labels: {
24
+ singular: toLocaleRecord(
25
+ arrTranslationsKeys,
26
+ (locale) => translations[locale]?.labels?.singular,
27
+ ),
28
+ plural: toLocaleRecord(
29
+ arrTranslationsKeys,
30
+ (locale) => translations[locale]?.labels?.plural,
31
+ ),
32
+ ...labels,
33
+ },
34
+ admin: {
35
+ group: toLocaleRecord(
36
+ arrTranslationsKeys,
37
+ (locale) => translations[locale]?.admin?.group,
38
+ ),
39
+ useAsTitle: "name",
40
+ defaultColumns: ["code", "name", "description", "status", "updatedAt"],
41
+ ...admin,
42
+ },
43
+ access: {
44
+ create: getSuperAdminAccess,
45
+ update: getSuperAdminAccess,
46
+ delete: getSuperAdminAccess,
47
+ read: getSuperAdminAccess,
48
+ readVersions: getSuperAdminAccess,
49
+ unlock: getSuperAdminAccess,
50
+ admin: ({ req }) => {
51
+ return getSuperAdminAccess({ req });
52
+ },
53
+ ...access,
54
+ },
55
+ hooks: {
56
+ afterChange: [syncPermissionMatrixDraftAfterChange],
57
+ },
58
+ fields: getArrayOfMergedFieldAffectingData({
59
+ fields,
60
+ defaultFields: [
61
+ {
62
+ name: "code",
63
+ type: "text",
64
+ required: true,
65
+ unique: true,
66
+ index: true,
67
+ label: toLocaleRecord(
68
+ arrTranslationsKeys,
69
+ (locale) => translations[locale]?.fields?.code?.label,
70
+ ),
71
+ admin: {
72
+ placeholder: toLocaleRecord(
73
+ arrTranslationsKeys,
74
+ (locale) => translations[locale]?.fields?.code?.placeholder,
75
+ ),
76
+ },
77
+ },
78
+ {
79
+ name: "name",
80
+ type: "text",
81
+ required: true,
82
+ label: toLocaleRecord(
83
+ arrTranslationsKeys,
84
+ (locale) => translations[locale]?.fields?.name?.label,
85
+ ),
86
+ admin: {
87
+ placeholder: toLocaleRecord(
88
+ arrTranslationsKeys,
89
+ (locale) => translations[locale]?.fields?.name?.placeholder,
90
+ ),
91
+ },
92
+ },
93
+ {
94
+ name: "description",
95
+ type: "text",
96
+ label: toLocaleRecord(
97
+ arrTranslationsKeys,
98
+ (locale) => translations[locale]?.fields?.description?.label,
99
+ ),
100
+ admin: {
101
+ placeholder: toLocaleRecord(
102
+ arrTranslationsKeys,
103
+ (locale) =>
104
+ translations[locale]?.fields?.description?.placeholder,
105
+ ),
106
+ },
107
+ },
108
+ {
109
+ name: "status",
110
+ type: "select",
111
+ required: true,
112
+ label: toLocaleRecord(
113
+ arrTranslationsKeys,
114
+ (locale) => translations[locale]?.fields?.status?.label,
115
+ ),
116
+ defaultValue: STATUS.ACTIVE,
117
+ options: Object.values(STATUS).map((status) => ({
118
+ label: toLocaleRecord(
119
+ arrTranslationsKeys,
120
+ (locale) =>
121
+ translations[locale]?.fields?.status?.[`${status}Label`],
122
+ ),
123
+ value: status,
124
+ })),
125
+ admin: {
126
+ placeholder: toSelectPlaceholder(
127
+ arrTranslationsKeys,
128
+ (locale) => translations[locale]?.fields?.status?.placeholder,
129
+ ),
130
+ },
131
+ },
132
+ {
133
+ name: "dataScope",
134
+ type: "select",
135
+ required: true,
136
+ label: toLocaleRecord(
137
+ arrTranslationsKeys,
138
+ (locale) => translations[locale]?.fields?.dataScope?.label,
139
+ ),
140
+ defaultValue: DATA_SCOPE.OWN,
141
+ options: Object.values(DATA_SCOPE).map((dataScope) => ({
142
+ label: toLocaleRecord(
143
+ arrTranslationsKeys,
144
+ (locale) =>
145
+ translations[locale]?.fields?.dataScope?.[`${dataScope}Label`],
146
+ ),
147
+ value: dataScope,
148
+ })),
149
+ admin: {
150
+ placeholder: toSelectPlaceholder(
151
+ arrTranslationsKeys,
152
+ (locale) => translations[locale]?.fields?.dataScope?.placeholder,
153
+ ),
154
+ },
155
+ },
156
+ {
157
+ name: "permissionMatrixDraft",
158
+ type: "json",
159
+ label: toLocaleRecord(
160
+ arrTranslationsKeys,
161
+ (locale) => translations[locale]?.fields?.permissionMatrix?.label,
162
+ ),
163
+ admin: {
164
+ components: {
165
+ Field:
166
+ "payload-auth-rbac-plugin/client#RolePermissionMatrixClient",
167
+ },
168
+ condition: ((_, __, { operation }) =>
169
+ operation === "update") satisfies Condition,
170
+ },
171
+ },
172
+ ],
173
+ }),
174
+ timestamps: true,
175
+ };
176
+
177
+ return roles;
178
+ };
@@ -0,0 +1,56 @@
1
+ import type { CollectionConfig, Field } from "payload"
2
+ import type { DATA_SCOPE, STATUS } from "../../lib/constants/role.js"
3
+
4
+ export type DataScope = (typeof DATA_SCOPE)[keyof typeof DATA_SCOPE]
5
+ export type RoleStatus = (typeof STATUS)[keyof typeof STATUS]
6
+
7
+ export type RolesCollectionTranslations = {
8
+ [locale: string]: {
9
+ labels?: {
10
+ singular?: string
11
+ plural?: string
12
+ }
13
+ admin?: {
14
+ group?: string
15
+ }
16
+ fields?: {
17
+ code?: {
18
+ label?: string
19
+ placeholder?: string
20
+ }
21
+ name?: {
22
+ label?: string
23
+ placeholder?: string
24
+ }
25
+ description?: {
26
+ label?: string
27
+ placeholder?: string
28
+ }
29
+ status?: {
30
+ label?: string
31
+ placeholder?: string
32
+ activeLabel?: string
33
+ inactiveLabel?: string
34
+ }
35
+ dataScope?: {
36
+ label?: string
37
+ placeholder?: string
38
+ allLabel?: string
39
+ ownLabel?: string
40
+ hierarchyLabel?: string
41
+ }
42
+ permissionMatrix?: {
43
+ label?: string
44
+ placeholder?: string
45
+ }
46
+ }
47
+ }
48
+ }
49
+
50
+ export type RolesCollectionParams = {
51
+ translations?: RolesCollectionTranslations
52
+ fields?: Field[]
53
+ access?: CollectionConfig["access"]
54
+ labels?: CollectionConfig["labels"]
55
+ admin?: CollectionConfig["admin"]
56
+ }
@@ -0,0 +1,28 @@
1
+ import type { RolesPermissionsCollectionTranslations } from "./types.js";
2
+
3
+ export const rolesPermissionsDefaultTranslations: RolesPermissionsCollectionTranslations =
4
+ {
5
+ en: {
6
+ labels: {
7
+ singular: "Role Permission",
8
+ plural: "Role Permissions",
9
+ },
10
+ admin: {
11
+ group: "System",
12
+ },
13
+ fields: {
14
+ role: {
15
+ label: "Role",
16
+ placeholder: "Select role",
17
+ },
18
+ permission: {
19
+ label: "Permission",
20
+ placeholder: "Select permission",
21
+ },
22
+ enabled: {
23
+ label: "Enabled",
24
+ placeholder: "Check enabled",
25
+ },
26
+ },
27
+ },
28
+ };
@@ -0,0 +1,107 @@
1
+ import type { CollectionConfig } from "payload";
2
+ import {
3
+ getArrayOfMergedFieldAffectingData,
4
+ getSuperAdminAccess,
5
+ toLocaleRecord,
6
+ toSelectPlaceholder,
7
+ } from "../../lib/utils/index.js";
8
+ import type { RolesPermissionsCollectionParams } from "./types.js";
9
+
10
+ export const getRolesPermissionsCollection = (
11
+ params: RolesPermissionsCollectionParams,
12
+ ) => {
13
+ const {
14
+ translations = {},
15
+ access = {},
16
+ fields = [],
17
+ labels = {},
18
+ admin = {},
19
+ } = params || {};
20
+ const arrTranslationsKeys = Object.keys(translations);
21
+ const rolesPermissions: CollectionConfig = {
22
+ slug: "roles-permissions",
23
+ labels: {
24
+ singular: toLocaleRecord(
25
+ arrTranslationsKeys,
26
+ (locale) => translations[locale]?.labels?.singular,
27
+ ),
28
+ plural: toLocaleRecord(
29
+ arrTranslationsKeys,
30
+ (locale) => translations[locale]?.labels?.plural,
31
+ ),
32
+ ...labels,
33
+ },
34
+ admin: {
35
+ group: toLocaleRecord(
36
+ arrTranslationsKeys,
37
+ (locale) => translations[locale]?.admin?.group,
38
+ ),
39
+ useAsTitle: "role",
40
+ defaultColumns: ["role", "permission", "enabled", "updatedAt"],
41
+ hidden: true,
42
+ ...admin,
43
+ },
44
+ access: {
45
+ create: getSuperAdminAccess,
46
+ update: getSuperAdminAccess,
47
+ delete: getSuperAdminAccess,
48
+ read: getSuperAdminAccess,
49
+ readVersions: getSuperAdminAccess,
50
+ unlock: getSuperAdminAccess,
51
+ admin: ({ req }) => {
52
+ return getSuperAdminAccess({ req });
53
+ },
54
+ ...access,
55
+ },
56
+ fields: getArrayOfMergedFieldAffectingData({
57
+ fields,
58
+ defaultFields: [
59
+ {
60
+ name: "role",
61
+ type: "relationship",
62
+ required: true,
63
+ relationTo: "roles",
64
+ label: toLocaleRecord(
65
+ arrTranslationsKeys,
66
+ (locale) => translations[locale]?.fields?.role?.label,
67
+ ),
68
+ admin: {
69
+ placeholder: toSelectPlaceholder(
70
+ arrTranslationsKeys,
71
+ (locale) => translations[locale]?.fields?.role?.placeholder,
72
+ ),
73
+ },
74
+ },
75
+ {
76
+ name: "permission",
77
+ type: "relationship",
78
+ relationTo: "permissions",
79
+ required: true,
80
+ label: toLocaleRecord(
81
+ arrTranslationsKeys,
82
+ (locale) => translations[locale]?.fields?.permission?.label,
83
+ ),
84
+ admin: {
85
+ placeholder: toSelectPlaceholder(
86
+ arrTranslationsKeys,
87
+ (locale) => translations[locale]?.fields?.permission?.placeholder,
88
+ ),
89
+ },
90
+ },
91
+ {
92
+ name: "enabled",
93
+ type: "checkbox",
94
+ required: false,
95
+ defaultValue: true,
96
+ label: toLocaleRecord(
97
+ arrTranslationsKeys,
98
+ (locale) => translations[locale]?.fields?.enabled?.label,
99
+ ),
100
+ },
101
+ ],
102
+ }),
103
+ timestamps: true,
104
+ };
105
+
106
+ return rolesPermissions;
107
+ };
@@ -0,0 +1,42 @@
1
+ import type { CollectionConfig, Field } from "payload";
2
+
3
+ export type RolesPermissionsCollectionTranslations = {
4
+ [locale: string]: {
5
+ labels?: {
6
+ singular?: string;
7
+ plural?: string;
8
+ };
9
+ admin?: {
10
+ group?: string;
11
+ };
12
+ fields?: {
13
+ role?: {
14
+ label?: string;
15
+ placeholder?: string;
16
+ };
17
+ permission?: {
18
+ label?: string;
19
+ placeholder?: string;
20
+ };
21
+ enabled?: {
22
+ label?: string;
23
+ placeholder?: string;
24
+ };
25
+ };
26
+ };
27
+ };
28
+
29
+ export type RolesPermissionsCollectionParams = {
30
+ translations?: RolesPermissionsCollectionTranslations;
31
+ fields?: Field[];
32
+ access?: CollectionConfig["access"];
33
+ labels?: CollectionConfig["labels"];
34
+ admin?: CollectionConfig["admin"];
35
+ };
36
+
37
+ export type RolePermission = {
38
+ id: string | number;
39
+ role?: string | number;
40
+ permission?: string | number;
41
+ enabled?: boolean;
42
+ };
@@ -0,0 +1,19 @@
1
+ import { UsersModificationTranslations } from "./types.js";
2
+
3
+ export const usersDefaultTranslations: UsersModificationTranslations = {
4
+ en: {
5
+ fields: {
6
+ isSuperAdmin: {
7
+ label: "Super Admin",
8
+ },
9
+ roles: {
10
+ label: "Roles",
11
+ placeholder: "Select roles",
12
+ },
13
+ parent: {
14
+ label: "Parent",
15
+ placeholder: "Select parent",
16
+ },
17
+ },
18
+ },
19
+ };
@@ -0,0 +1,148 @@
1
+ import type { Config, Field, PayloadRequest } from "payload";
2
+ import {
3
+ getArrayOfMergedFieldAffectingData,
4
+ getPermissionAccess,
5
+ toLocaleRecord,
6
+ } from "../../lib/utils/index.js";
7
+ import { mergeUserCollectionHooks } from "./parent-path.js";
8
+ import type {
9
+ UsersModificationParams,
10
+ UsersModificationTranslations,
11
+ } from "./types.js";
12
+
13
+ const buildDefaultFields = (
14
+ translations: UsersModificationTranslations,
15
+ ): Field[] => {
16
+ const locales = Object.keys(translations);
17
+ return [
18
+ {
19
+ name: "isSuperAdmin",
20
+ type: "checkbox",
21
+ defaultValue: false,
22
+ label: toLocaleRecord(
23
+ locales,
24
+ (locale) => translations[locale]?.fields?.isSuperAdmin?.label,
25
+ ),
26
+ admin: {
27
+ readOnly: true,
28
+ },
29
+ },
30
+ {
31
+ name: "roles",
32
+ type: "relationship",
33
+ relationTo: "roles",
34
+ hasMany: true,
35
+ label: toLocaleRecord(
36
+ locales,
37
+ (locale) => translations[locale]?.fields?.roles?.label,
38
+ ),
39
+ },
40
+ {
41
+ name: "parent",
42
+ type: "relationship",
43
+ relationTo: "users",
44
+ label: toLocaleRecord(
45
+ locales,
46
+ (locale) => translations[locale]?.fields?.parent?.label,
47
+ ),
48
+ filterOptions: ({ id }) => (id ? { id: { not_equals: id } } : true),
49
+ },
50
+ {
51
+ name: "parentPath",
52
+ type: "text",
53
+ index: true,
54
+ admin: {
55
+ hidden: true,
56
+ readOnly: true,
57
+ },
58
+ },
59
+ ];
60
+ };
61
+
62
+ export const modifyUsersCollection = (params: UsersModificationParams = {}) => {
63
+ const { translations = {}, fields: customFields = [] } = params;
64
+
65
+ return (incomingConfig: Config): Config => {
66
+ const config = { ...incomingConfig };
67
+ const userSlug = config.admin?.user || "users";
68
+
69
+ const customAdmin = {
70
+ defaultColumns: ["email", "roles", "isSuperAdmin", "updatedAt"],
71
+ useAsTitle: "email",
72
+ ...config.admin,
73
+ };
74
+
75
+ const pluginFields = getArrayOfMergedFieldAffectingData({
76
+ defaultFields: buildDefaultFields(translations),
77
+ fields: customFields,
78
+ });
79
+
80
+ const existing = (config.collections || []).find(
81
+ (c) => c.slug === userSlug,
82
+ );
83
+ const dataScopeOptions = {
84
+ createdByField: "id",
85
+ usersCollectionSlug: userSlug,
86
+ } as const;
87
+
88
+ const defaultAccess = {
89
+ create: getPermissionAccess({
90
+ featureCode: userSlug,
91
+ actionCode: "create",
92
+ }),
93
+ update: getPermissionAccess({
94
+ featureCode: userSlug,
95
+ actionCode: "update",
96
+ mode: "modify",
97
+ collectionSlug: userSlug,
98
+ options: dataScopeOptions,
99
+ }),
100
+ delete: getPermissionAccess({
101
+ featureCode: userSlug,
102
+ actionCode: "delete",
103
+ mode: "modify",
104
+ collectionSlug: userSlug,
105
+ options: dataScopeOptions,
106
+ }),
107
+ read: getPermissionAccess({
108
+ featureCode: userSlug,
109
+ actionCode: "read",
110
+ options: dataScopeOptions,
111
+ }),
112
+ };
113
+
114
+ if (existing) {
115
+ config.collections = (config.collections || []).map((collection) => {
116
+ if (collection.slug !== userSlug) {
117
+ return collection;
118
+ }
119
+ return {
120
+ ...collection,
121
+ fields: [...collection.fields, ...pluginFields],
122
+ access: {
123
+ ...defaultAccess,
124
+ ...collection.access,
125
+ },
126
+ hooks: mergeUserCollectionHooks({
127
+ existingHooks: collection.hooks,
128
+ userSlug,
129
+ }),
130
+ };
131
+ });
132
+ } else {
133
+ config.collections = [
134
+ ...(config.collections || []),
135
+ {
136
+ slug: userSlug,
137
+ auth: true,
138
+ admin: customAdmin,
139
+ fields: pluginFields,
140
+ access: defaultAccess,
141
+ hooks: mergeUserCollectionHooks({ userSlug }),
142
+ },
143
+ ];
144
+ }
145
+
146
+ return config;
147
+ };
148
+ };