@zealamic/payload-auth-rbac-plugin 1.0.0-beta.1 → 1.0.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -31
- package/assets/cover-photo.jpg +0 -0
- package/dist/collections/permission-actions/default-data.d.ts +2 -0
- package/dist/collections/permission-actions/index.d.ts +3 -0
- package/dist/collections/permission-actions/types.d.ts +51 -0
- package/dist/collections/permission-features/default-data.d.ts +2 -0
- package/dist/collections/permission-features/index.d.ts +3 -0
- package/dist/collections/permission-features/types.d.ts +43 -0
- package/dist/collections/permissions/default-data.d.ts +2 -0
- package/dist/collections/permissions/index.d.ts +3 -0
- package/dist/collections/permissions/types.d.ts +54 -0
- package/dist/collections/roles/default-data.d.ts +2 -0
- package/dist/collections/roles/hooks/sync-permission-matrix-draft.d.ts +6 -0
- package/dist/collections/roles/index.d.ts +3 -0
- package/dist/collections/roles/types.d.ts +53 -0
- package/dist/collections/roles-permissions/default-data.d.ts +2 -0
- package/dist/collections/roles-permissions/index.d.ts +3 -0
- package/dist/collections/roles-permissions/types.d.ts +39 -0
- package/dist/collections/users/default-data.d.ts +2 -0
- package/dist/collections/users/index.d.ts +3 -0
- package/dist/collections/users/parent-path.d.ts +31 -0
- package/dist/collections/users/types.d.ts +23 -0
- package/dist/components/role-permission-matrix-client/default-data.d.ts +2 -0
- package/dist/components/role-permission-matrix-client/default-data.js +2 -1
- package/dist/components/role-permission-matrix-client/default-data.js.map +1 -1
- package/dist/components/role-permission-matrix-client/index.d.ts +1 -0
- package/dist/components/role-permission-matrix-client/index.js +18 -68
- package/dist/components/role-permission-matrix-client/index.js.map +1 -1
- package/dist/components/role-permission-matrix-client/matrix.module.scss +69 -0
- package/dist/components/role-permission-matrix-client/types.d.ts +18 -0
- package/dist/endpoints/customEndpointHandler.d.ts +2 -0
- package/dist/exports/client.d.ts +1 -0
- package/dist/exports/rsc.d.ts +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/lib/constants/general.d.ts +1 -0
- package/dist/lib/constants/index.d.ts +14 -0
- package/dist/lib/constants/permission-action.d.ts +8 -0
- package/dist/lib/constants/permission-feature.d.ts +4 -0
- package/dist/lib/constants/permission.d.ts +4 -0
- package/dist/lib/constants/role.d.ts +9 -0
- package/dist/lib/constants/user.d.ts +1 -0
- package/dist/lib/utils/access.d.ts +76 -0
- package/dist/lib/utils/data.d.ts +6 -0
- package/dist/lib/utils/fields.d.ts +18 -0
- package/dist/lib/utils/index.d.ts +4 -0
- package/dist/lib/utils/localization.d.ts +27 -0
- package/dist/styles/variables.scss +1 -0
- package/dist/types.d.ts +38 -0
- package/docs/COLLECTIONS.md +440 -0
- package/docs/TRANSLATIONS.md +462 -0
- package/docs/UTILS.md +226 -0
- package/package.json +21 -4
|
@@ -6,6 +6,8 @@ import { STATUS as PERMISSION_STATUS } from "../../lib/constants/permission.js";
|
|
|
6
6
|
import { STATUS as PERMISSION_ACTION_STATUS, TYPE } from "../../lib/constants/permission-action.js";
|
|
7
7
|
import { STATUS as PERMISSION_FEATURE_STATUS } from "../../lib/constants/permission-feature.js";
|
|
8
8
|
import { toID } from "../../lib/utils/data.js";
|
|
9
|
+
import styles from "./matrix.module.scss";
|
|
10
|
+
const RBAC_PREFIX = "rbac";
|
|
9
11
|
export const RolePermissionMatrixClient = ()=>{
|
|
10
12
|
const checkboxId = useId();
|
|
11
13
|
const { config } = useConfig();
|
|
@@ -103,59 +105,36 @@ export const RolePermissionMatrixClient = ()=>{
|
|
|
103
105
|
]);
|
|
104
106
|
if (!id) {
|
|
105
107
|
return /*#__PURE__*/ _jsx("div", {
|
|
106
|
-
|
|
107
|
-
opacity: 0.8,
|
|
108
|
-
padding: "8px 0"
|
|
109
|
-
},
|
|
108
|
+
className: styles[`${RBAC_PREFIX}-component-placeholder`],
|
|
110
109
|
children: t(`components:rolePermissionMatrix:viewInUpdateScreenOnly:label`)
|
|
111
110
|
});
|
|
112
111
|
}
|
|
113
112
|
if (loading) {
|
|
114
113
|
return /*#__PURE__*/ _jsx("div", {
|
|
115
|
-
|
|
116
|
-
opacity: 0.8,
|
|
117
|
-
padding: "8px 0"
|
|
118
|
-
},
|
|
114
|
+
className: styles[`${RBAC_PREFIX}-component-placeholder`],
|
|
119
115
|
children: t(`components:rolePermissionMatrix:loading:placeholder`)
|
|
120
116
|
});
|
|
121
117
|
}
|
|
122
118
|
return /*#__PURE__*/ _jsxs("div", {
|
|
123
119
|
children: [
|
|
124
120
|
/*#__PURE__*/ _jsx("div", {
|
|
125
|
-
|
|
126
|
-
fontWeight: 600,
|
|
127
|
-
marginBottom: 8
|
|
128
|
-
},
|
|
121
|
+
className: styles[`${RBAC_PREFIX}-component-title`],
|
|
129
122
|
children: t(`components:rolePermissionMatrix:title`)
|
|
130
123
|
}),
|
|
131
124
|
/*#__PURE__*/ _jsx("div", {
|
|
132
|
-
|
|
133
|
-
border: "1px solid #333",
|
|
134
|
-
borderRadius: 8
|
|
135
|
-
},
|
|
125
|
+
className: styles[`${RBAC_PREFIX}-table-container`],
|
|
136
126
|
children: /*#__PURE__*/ _jsxs("table", {
|
|
137
|
-
|
|
138
|
-
borderCollapse: "collapse",
|
|
139
|
-
width: "100%"
|
|
140
|
-
},
|
|
127
|
+
className: styles[`${RBAC_PREFIX}-table`],
|
|
141
128
|
children: [
|
|
142
129
|
/*#__PURE__*/ _jsx("thead", {
|
|
143
130
|
children: /*#__PURE__*/ _jsxs("tr", {
|
|
144
131
|
children: [
|
|
145
132
|
/*#__PURE__*/ _jsx("th", {
|
|
146
|
-
|
|
147
|
-
padding: "8px",
|
|
148
|
-
textAlign: "left",
|
|
149
|
-
borderRight: "1px solid #333",
|
|
150
|
-
width: "25%"
|
|
151
|
-
},
|
|
133
|
+
className: styles[`${RBAC_PREFIX}-table-th-feature`],
|
|
152
134
|
children: t(`components:rolePermissionMatrix:features:label`)
|
|
153
135
|
}),
|
|
154
136
|
/*#__PURE__*/ _jsx("th", {
|
|
155
|
-
|
|
156
|
-
padding: "8px",
|
|
157
|
-
textAlign: "left"
|
|
158
|
-
},
|
|
137
|
+
className: styles[`${RBAC_PREFIX}-table-th-action`],
|
|
159
138
|
colSpan: actions.filter((action)=>action.type === TYPE.MAIN).length,
|
|
160
139
|
children: t(`components:rolePermissionMatrix:actions:label`)
|
|
161
140
|
})
|
|
@@ -172,36 +151,23 @@ export const RolePermissionMatrixClient = ()=>{
|
|
|
172
151
|
/*#__PURE__*/ _jsxs("tr", {
|
|
173
152
|
children: [
|
|
174
153
|
/*#__PURE__*/ _jsx("td", {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
padding: "0.5rem",
|
|
178
|
-
borderRight: "1px solid #333"
|
|
179
|
-
},
|
|
180
|
-
children: feature.code || feature.id
|
|
154
|
+
className: styles[`${RBAC_PREFIX}-table-td-feature`],
|
|
155
|
+
children: t(`components:rolePermissionMatrix:features:${feature.code}`) || feature.id
|
|
181
156
|
}),
|
|
182
157
|
mainActions.map((action)=>{
|
|
183
158
|
const matchedPermission = permissions.find((permission)=>toID(permission.permissionFeature) === String(feature.id) && toID(permission.permissionAction) === String(action.id));
|
|
184
159
|
if (!matchedPermission) {
|
|
185
160
|
return /*#__PURE__*/ _jsx("td", {
|
|
186
|
-
|
|
187
|
-
borderTop: "1px solid #333",
|
|
188
|
-
padding: "0.5rem"
|
|
189
|
-
},
|
|
161
|
+
className: styles[`${RBAC_PREFIX}-table-td-action`],
|
|
190
162
|
children: "-"
|
|
191
163
|
}, `${feature.id}-${action.id}`);
|
|
192
164
|
}
|
|
193
165
|
const permissionID = String(matchedPermission.id);
|
|
194
166
|
const checked = typeof draftValue[permissionID] === "boolean" ? draftValue[permissionID] : enabledByPermissionID.get(permissionID) ?? false;
|
|
195
167
|
return /*#__PURE__*/ _jsx("td", {
|
|
196
|
-
|
|
197
|
-
borderTop: "1px solid #333",
|
|
198
|
-
padding: "0.5rem"
|
|
199
|
-
},
|
|
168
|
+
className: styles[`${RBAC_PREFIX}-table-td-action`],
|
|
200
169
|
children: /*#__PURE__*/ _jsxs("div", {
|
|
201
|
-
|
|
202
|
-
display: "flex",
|
|
203
|
-
alignItems: "center"
|
|
204
|
-
},
|
|
170
|
+
className: styles[`${RBAC_PREFIX}-table-td-action-container`],
|
|
205
171
|
children: [
|
|
206
172
|
/*#__PURE__*/ _jsx("input", {
|
|
207
173
|
type: "checkbox",
|
|
@@ -215,19 +181,11 @@ export const RolePermissionMatrixClient = ()=>{
|
|
|
215
181
|
[permissionID]: event.target.checked
|
|
216
182
|
});
|
|
217
183
|
},
|
|
218
|
-
|
|
219
|
-
userSelect: "none",
|
|
220
|
-
cursor: "pointer"
|
|
221
|
-
}
|
|
184
|
+
className: styles[`${RBAC_PREFIX}-table-td-action-input`]
|
|
222
185
|
}),
|
|
223
186
|
/*#__PURE__*/ _jsx("label", {
|
|
224
187
|
htmlFor: `permission-matrix-checkbox-${checkboxId}-${feature.id}-${action.id}`,
|
|
225
|
-
|
|
226
|
-
display: "inline-block",
|
|
227
|
-
paddingLeft: "0.25rem",
|
|
228
|
-
userSelect: "none",
|
|
229
|
-
cursor: "pointer"
|
|
230
|
-
},
|
|
188
|
+
className: styles[`${RBAC_PREFIX}-table-td-action-label`],
|
|
231
189
|
children: t(`components:rolePermissionMatrix:actions:${action.code}`) || action.id
|
|
232
190
|
})
|
|
233
191
|
]
|
|
@@ -239,18 +197,10 @@ export const RolePermissionMatrixClient = ()=>{
|
|
|
239
197
|
isSubActionInPermission && /*#__PURE__*/ _jsxs("tr", {
|
|
240
198
|
children: [
|
|
241
199
|
/*#__PURE__*/ _jsx("td", {
|
|
242
|
-
|
|
243
|
-
borderRight: "1px solid #333",
|
|
244
|
-
padding: "8px",
|
|
245
|
-
textAlign: "right"
|
|
246
|
-
}
|
|
200
|
+
className: styles[`${RBAC_PREFIX}-table-td-feature`]
|
|
247
201
|
}),
|
|
248
202
|
/*#__PURE__*/ _jsx("td", {
|
|
249
|
-
|
|
250
|
-
borderTop: "1px solid #333",
|
|
251
|
-
padding: "8px",
|
|
252
|
-
textAlign: "left"
|
|
253
|
-
},
|
|
203
|
+
className: styles[`${RBAC_PREFIX}-table-td-action`],
|
|
254
204
|
colSpan: mainActions.length,
|
|
255
205
|
children: subActions.map((action)=>{
|
|
256
206
|
const matchedPermission = permissions.find((permission)=>toID(permission.permissionFeature) === String(feature.id) && toID(permission.permissionAction) === String(action.id));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/role-permission-matrix-client/index.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useConfig,\n useDocumentInfo,\n useField,\n useTranslation,\n} from \"@payloadcms/ui\";\nimport { Fragment, useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport type { PermissionAction } from \"../../collections/permission-actions/types.js\";\nimport type { PermissionFeature } from \"../../collections/permission-features/types.js\";\nimport type { Permission } from \"../../collections/permissions/types.js\";\nimport type { RolePermission } from \"../../collections/roles-permissions/types.js\";\nimport { STATUS as PERMISSION_STATUS } from \"../../lib/constants/permission.js\";\nimport {\n STATUS as PERMISSION_ACTION_STATUS,\n TYPE,\n} from \"../../lib/constants/permission-action.js\";\nimport { STATUS as PERMISSION_FEATURE_STATUS } from \"../../lib/constants/permission-feature.js\";\nimport { toID } from \"../../lib/utils/data.js\";\n\ntype ApiListResponse<T> = {\n docs?: T[];\n};\n\nexport const RolePermissionMatrixClient = () => {\n const checkboxId = useId();\n const { config } = useConfig();\n const { hasSavePermission, id } = useDocumentInfo();\n const { setValue, value } = useField<Record<string, boolean> | null>({\n path: \"permissionMatrixDraft\",\n });\n const isReadOnly = !hasSavePermission;\n\n const [features, setFeatures] = useState<PermissionFeature[]>([]);\n const [actions, setActions] = useState<PermissionAction[]>([]);\n const [permissions, setPermissions] = useState<Permission[]>([]);\n const [rolePermissions, setRolePermissions] = useState<RolePermission[]>([]);\n const [loading, setLoading] = useState(true);\n const { t } = useTranslation();\n const seededForRoleIdRef = useRef<string | null>(null);\n\n useEffect(() => {\n const run = async () => {\n setLoading(true);\n try {\n const base = config?.routes?.api || \"/api\";\n\n const [featuresRes, actionsRes, permissionsRes, rolePermissionsRes] =\n await Promise.all([\n fetch(\n `${base}/permission-features?limit=0&depth=0&where[status][equals]=${PERMISSION_FEATURE_STATUS.ACTIVE}`,\n { credentials: \"include\" },\n ),\n fetch(\n `${base}/permission-actions?limit=0&depth=0&where[status][equals]=${PERMISSION_ACTION_STATUS.ACTIVE}`,\n { credentials: \"include\" },\n ),\n fetch(\n `${base}/permissions?limit=0&depth=1&where[status][equals]=${PERMISSION_STATUS.ACTIVE}`,\n { credentials: \"include\" },\n ),\n id\n ? fetch(\n `${base}/roles-permissions?limit=0&depth=0&where[role][equals]=${id}`,\n {\n credentials: \"include\",\n },\n )\n : Promise.resolve(new Response(JSON.stringify({ docs: [] }))),\n ]);\n\n const featuresJson =\n (await featuresRes.json()) as ApiListResponse<PermissionFeature>;\n const actionsJson =\n (await actionsRes.json()) as ApiListResponse<PermissionAction>;\n const permissionsJson =\n (await permissionsRes.json()) as ApiListResponse<Permission>;\n const rolePermissionsJson =\n (await rolePermissionsRes.json()) as ApiListResponse<RolePermission>;\n\n setFeatures(\n featuresJson.docs?.sort(\n (a, b) => (a?.sortOrder ?? 0) - (b?.sortOrder ?? 0),\n ) || [],\n );\n setActions(\n actionsJson.docs?.sort(\n (a, b) => (a?.sortOrder ?? 0) - (b?.sortOrder ?? 0),\n ) || [],\n );\n setPermissions(permissionsJson.docs || []);\n setRolePermissions(rolePermissionsJson.docs || []);\n } finally {\n setLoading(false);\n }\n };\n\n void run();\n }, [config?.routes?.api, id]);\n\n const enabledByPermissionID = useMemo(() => {\n const map = new Map<string, boolean>();\n for (const row of rolePermissions) {\n map.set(toID(row.permission), Boolean(row.enabled));\n }\n return map;\n }, [rolePermissions]);\n\n const draftValue = (\n value && typeof value === \"object\" && !Array.isArray(value) ? value : {}\n ) as Record<string, boolean>;\n\n useEffect(() => {\n if (!id || loading) {\n return;\n }\n\n const roleId = String(id);\n if (seededForRoleIdRef.current === roleId) {\n return;\n }\n\n const fromRolesPermissions: Record<string, boolean> = {};\n for (const [permissionID, enabled] of enabledByPermissionID.entries()) {\n if (permissionID) {\n fromRolesPermissions[permissionID] = enabled;\n }\n }\n\n const fromDocument =\n value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, boolean>)\n : {};\n\n const hasRolesPermissions = Object.keys(fromRolesPermissions).length > 0;\n const hasDocumentDraft = Object.keys(fromDocument).length > 0;\n\n if (!hasRolesPermissions && !hasDocumentDraft) {\n return;\n }\n\n seededForRoleIdRef.current = roleId;\n setValue({\n ...fromRolesPermissions,\n ...fromDocument,\n });\n }, [enabledByPermissionID, id, loading, setValue, value]);\n\n if (!id) {\n return (\n <div style={{ opacity: 0.8, padding: \"8px 0\" }}>\n {t(\n `components:rolePermissionMatrix:viewInUpdateScreenOnly:label` as Parameters<\n typeof t\n >[0],\n )}\n </div>\n );\n }\n\n if (loading) {\n return (\n <div style={{ opacity: 0.8, padding: \"8px 0\" }}>\n {t(\n `components:rolePermissionMatrix:loading:placeholder` as Parameters<\n typeof t\n >[0],\n )}\n </div>\n );\n }\n\n return (\n <div>\n <div style={{ fontWeight: 600, marginBottom: 8 }}>\n {t(`components:rolePermissionMatrix:title` as Parameters<typeof t>[0])}\n </div>\n\n <div style={{ border: \"1px solid #333\", borderRadius: 8 }}>\n <table\n style={{\n borderCollapse: \"collapse\",\n width: \"100%\",\n }}\n >\n <thead>\n <tr>\n <th\n style={{\n padding: \"8px\",\n textAlign: \"left\",\n borderRight: \"1px solid #333\",\n width: \"25%\",\n }}\n >\n {t(\n `components:rolePermissionMatrix:features:label` as Parameters<\n typeof t\n >[0],\n )}\n </th>\n <th\n style={{ padding: \"8px\", textAlign: \"left\" }}\n colSpan={\n actions.filter((action) => action.type === TYPE.MAIN).length\n }\n >\n {t(\n `components:rolePermissionMatrix:actions:label` as Parameters<\n typeof t\n >[0],\n )}\n </th>\n </tr>\n </thead>\n <tbody>\n {features.map((feature) => {\n const mainActions = actions.filter(\n (action) => action.type === TYPE.MAIN,\n );\n const subActions = actions.filter(\n (action) =>\n action.type === TYPE.SUB &&\n permissions.some(\n (permission) =>\n toID(permission.permissionAction) === String(action.id) &&\n toID(permission.permissionFeature) === String(feature.id),\n ),\n );\n const isSubActionInPermission = subActions.length > 0;\n\n return (\n <Fragment key={String(feature.id)}>\n <tr>\n <td\n style={{\n borderTop: \"1px solid #333\",\n padding: \"0.5rem\",\n borderRight: \"1px solid #333\",\n }}\n >\n {feature.code || feature.id}\n </td>\n\n {mainActions.map((action) => {\n const matchedPermission = permissions.find(\n (permission) =>\n toID(permission.permissionFeature) ===\n String(feature.id) &&\n toID(permission.permissionAction) ===\n String(action.id),\n );\n\n if (!matchedPermission) {\n return (\n <td\n key={`${feature.id}-${action.id}`}\n style={{\n borderTop: \"1px solid #333\",\n padding: \"0.5rem\",\n }}\n >\n -\n </td>\n );\n }\n\n const permissionID = String(matchedPermission.id);\n const checked =\n typeof draftValue[permissionID] === \"boolean\"\n ? draftValue[permissionID]\n : (enabledByPermissionID.get(permissionID) ?? false);\n\n return (\n <td\n key={`${feature.id}-${action.id}`}\n style={{\n borderTop: \"1px solid #333\",\n padding: \"0.5rem\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n }}\n >\n <input\n type=\"checkbox\"\n id={`permission-matrix-checkbox-${checkboxId}-${feature.id}-${action.id}`}\n name={`permission-matrix-checkbox-${checkboxId}-${feature.id}-${action.id}`}\n checked={checked}\n disabled={isReadOnly}\n onChange={(event) => {\n setValue({\n ...draftValue,\n [permissionID]: event.target.checked,\n });\n }}\n style={{\n userSelect: \"none\",\n cursor: \"pointer\",\n }}\n />\n <label\n htmlFor={`permission-matrix-checkbox-${checkboxId}-${feature.id}-${action.id}`}\n style={{\n display: \"inline-block\",\n paddingLeft: \"0.25rem\",\n userSelect: \"none\",\n cursor: \"pointer\",\n }}\n >\n {t(\n `components:rolePermissionMatrix:actions:${action.code}` as Parameters<\n typeof t\n >[0],\n ) || action.id}\n </label>\n </div>\n </td>\n );\n })}\n </tr>\n\n {isSubActionInPermission && (\n <tr>\n <td\n style={{\n borderRight: \"1px solid #333\",\n padding: \"8px\",\n textAlign: \"right\",\n }}\n ></td>\n <td\n style={{\n borderTop: \"1px solid #333\",\n padding: \"8px\",\n textAlign: \"left\",\n }}\n colSpan={mainActions.length}\n >\n {subActions.map((action) => {\n const matchedPermission = permissions.find(\n (permission) =>\n toID(permission.permissionFeature) ===\n String(feature.id) &&\n toID(permission.permissionAction) ===\n String(action.id),\n );\n\n if (!matchedPermission) {\n return null;\n }\n\n const permissionID = String(matchedPermission.id);\n const checked =\n typeof draftValue[permissionID] === \"boolean\"\n ? draftValue[permissionID]\n : (enabledByPermissionID.get(permissionID) ??\n false);\n\n return (\n <div key={`${feature.id}-${action.id}-sub`}>\n <input\n type=\"checkbox\"\n checked={checked}\n disabled={isReadOnly}\n onChange={(event) => {\n setValue({\n ...draftValue,\n [permissionID]: event.target.checked,\n });\n }}\n />{\" \"}\n <span\n style={{\n display: \"inline-block\",\n }}\n >\n {action.code || action.id}\n </span>\n </div>\n );\n })}\n </td>\n </tr>\n )}\n </Fragment>\n );\n })}\n </tbody>\n </table>\n </div>\n </div>\n );\n};\n"],"names":["useConfig","useDocumentInfo","useField","useTranslation","Fragment","useEffect","useId","useMemo","useRef","useState","STATUS","PERMISSION_STATUS","PERMISSION_ACTION_STATUS","TYPE","PERMISSION_FEATURE_STATUS","toID","RolePermissionMatrixClient","checkboxId","config","hasSavePermission","id","setValue","value","path","isReadOnly","features","setFeatures","actions","setActions","permissions","setPermissions","rolePermissions","setRolePermissions","loading","setLoading","t","seededForRoleIdRef","run","base","routes","api","featuresRes","actionsRes","permissionsRes","rolePermissionsRes","Promise","all","fetch","ACTIVE","credentials","resolve","Response","JSON","stringify","docs","featuresJson","json","actionsJson","permissionsJson","rolePermissionsJson","sort","a","b","sortOrder","enabledByPermissionID","map","Map","row","set","permission","Boolean","enabled","draftValue","Array","isArray","roleId","String","current","fromRolesPermissions","permissionID","entries","fromDocument","hasRolesPermissions","Object","keys","length","hasDocumentDraft","div","style","opacity","padding","fontWeight","marginBottom","border","borderRadius","table","borderCollapse","width","thead","tr","th","textAlign","borderRight","colSpan","filter","action","type","MAIN","tbody","feature","mainActions","subActions","SUB","some","permissionAction","permissionFeature","isSubActionInPermission","td","borderTop","code","matchedPermission","find","checked","get","display","alignItems","input","name","disabled","onChange","event","target","userSelect","cursor","label","htmlFor","paddingLeft","span"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/role-permission-matrix-client/index.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useConfig,\n useDocumentInfo,\n useField,\n useTranslation,\n} from \"@payloadcms/ui\";\nimport { Fragment, useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport type { PermissionAction } from \"../../collections/permission-actions/types.js\";\nimport type { PermissionFeature } from \"../../collections/permission-features/types.js\";\nimport type { Permission } from \"../../collections/permissions/types.js\";\nimport type { RolePermission } from \"../../collections/roles-permissions/types.js\";\nimport { STATUS as PERMISSION_STATUS } from \"../../lib/constants/permission.js\";\nimport {\n STATUS as PERMISSION_ACTION_STATUS,\n TYPE,\n} from \"../../lib/constants/permission-action.js\";\nimport { STATUS as PERMISSION_FEATURE_STATUS } from \"../../lib/constants/permission-feature.js\";\nimport { toID } from \"../../lib/utils/data.js\";\n\nimport styles from \"./matrix.module.scss\";\n\nconst RBAC_PREFIX = \"rbac\";\n\ntype ApiListResponse<T> = {\n docs?: T[];\n};\n\nexport const RolePermissionMatrixClient = () => {\n const checkboxId = useId();\n const { config } = useConfig();\n const { hasSavePermission, id } = useDocumentInfo();\n const { setValue, value } = useField<Record<string, boolean> | null>({\n path: \"permissionMatrixDraft\",\n });\n const isReadOnly = !hasSavePermission;\n\n const [features, setFeatures] = useState<PermissionFeature[]>([]);\n const [actions, setActions] = useState<PermissionAction[]>([]);\n const [permissions, setPermissions] = useState<Permission[]>([]);\n const [rolePermissions, setRolePermissions] = useState<RolePermission[]>([]);\n const [loading, setLoading] = useState(true);\n const { t } = useTranslation();\n const seededForRoleIdRef = useRef<string | null>(null);\n\n useEffect(() => {\n const run = async () => {\n setLoading(true);\n try {\n const base = config?.routes?.api || \"/api\";\n\n const [featuresRes, actionsRes, permissionsRes, rolePermissionsRes] =\n await Promise.all([\n fetch(\n `${base}/permission-features?limit=0&depth=0&where[status][equals]=${PERMISSION_FEATURE_STATUS.ACTIVE}`,\n { credentials: \"include\" },\n ),\n fetch(\n `${base}/permission-actions?limit=0&depth=0&where[status][equals]=${PERMISSION_ACTION_STATUS.ACTIVE}`,\n { credentials: \"include\" },\n ),\n fetch(\n `${base}/permissions?limit=0&depth=1&where[status][equals]=${PERMISSION_STATUS.ACTIVE}`,\n { credentials: \"include\" },\n ),\n id\n ? fetch(\n `${base}/roles-permissions?limit=0&depth=0&where[role][equals]=${id}`,\n {\n credentials: \"include\",\n },\n )\n : Promise.resolve(new Response(JSON.stringify({ docs: [] }))),\n ]);\n\n const featuresJson =\n (await featuresRes.json()) as ApiListResponse<PermissionFeature>;\n const actionsJson =\n (await actionsRes.json()) as ApiListResponse<PermissionAction>;\n const permissionsJson =\n (await permissionsRes.json()) as ApiListResponse<Permission>;\n const rolePermissionsJson =\n (await rolePermissionsRes.json()) as ApiListResponse<RolePermission>;\n\n setFeatures(\n featuresJson.docs?.sort(\n (a, b) => (a?.sortOrder ?? 0) - (b?.sortOrder ?? 0),\n ) || [],\n );\n setActions(\n actionsJson.docs?.sort(\n (a, b) => (a?.sortOrder ?? 0) - (b?.sortOrder ?? 0),\n ) || [],\n );\n setPermissions(permissionsJson.docs || []);\n setRolePermissions(rolePermissionsJson.docs || []);\n } finally {\n setLoading(false);\n }\n };\n\n void run();\n }, [config?.routes?.api, id]);\n\n const enabledByPermissionID = useMemo(() => {\n const map = new Map<string, boolean>();\n for (const row of rolePermissions) {\n map.set(toID(row.permission), Boolean(row.enabled));\n }\n return map;\n }, [rolePermissions]);\n\n const draftValue = (\n value && typeof value === \"object\" && !Array.isArray(value) ? value : {}\n ) as Record<string, boolean>;\n\n useEffect(() => {\n if (!id || loading) {\n return;\n }\n\n const roleId = String(id);\n if (seededForRoleIdRef.current === roleId) {\n return;\n }\n\n const fromRolesPermissions: Record<string, boolean> = {};\n for (const [permissionID, enabled] of enabledByPermissionID.entries()) {\n if (permissionID) {\n fromRolesPermissions[permissionID] = enabled;\n }\n }\n\n const fromDocument =\n value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, boolean>)\n : {};\n\n const hasRolesPermissions = Object.keys(fromRolesPermissions).length > 0;\n const hasDocumentDraft = Object.keys(fromDocument).length > 0;\n\n if (!hasRolesPermissions && !hasDocumentDraft) {\n return;\n }\n\n seededForRoleIdRef.current = roleId;\n setValue({\n ...fromRolesPermissions,\n ...fromDocument,\n });\n }, [enabledByPermissionID, id, loading, setValue, value]);\n\n if (!id) {\n return (\n <div className={styles[`${RBAC_PREFIX}-component-placeholder`]}>\n {t(\n `components:rolePermissionMatrix:viewInUpdateScreenOnly:label` as Parameters<\n typeof t\n >[0],\n )}\n </div>\n );\n }\n\n if (loading) {\n return (\n <div className={styles[`${RBAC_PREFIX}-component-placeholder`]}>\n {t(\n `components:rolePermissionMatrix:loading:placeholder` as Parameters<\n typeof t\n >[0],\n )}\n </div>\n );\n }\n\n return (\n <div>\n <div className={styles[`${RBAC_PREFIX}-component-title`]}>\n {t(`components:rolePermissionMatrix:title` as Parameters<typeof t>[0])}\n </div>\n\n <div className={styles[`${RBAC_PREFIX}-table-container`]}>\n <table className={styles[`${RBAC_PREFIX}-table`]}>\n <thead>\n <tr>\n <th className={styles[`${RBAC_PREFIX}-table-th-feature`]}>\n {t(\n `components:rolePermissionMatrix:features:label` as Parameters<\n typeof t\n >[0],\n )}\n </th>\n <th\n className={styles[`${RBAC_PREFIX}-table-th-action`]}\n colSpan={\n actions.filter((action) => action.type === TYPE.MAIN).length\n }\n >\n {t(\n `components:rolePermissionMatrix:actions:label` as Parameters<\n typeof t\n >[0],\n )}\n </th>\n </tr>\n </thead>\n <tbody>\n {features.map((feature) => {\n const mainActions = actions.filter(\n (action) => action.type === TYPE.MAIN,\n );\n const subActions = actions.filter(\n (action) =>\n action.type === TYPE.SUB &&\n permissions.some(\n (permission) =>\n toID(permission.permissionAction) === String(action.id) &&\n toID(permission.permissionFeature) === String(feature.id),\n ),\n );\n const isSubActionInPermission = subActions.length > 0;\n\n return (\n <Fragment key={String(feature.id)}>\n <tr>\n <td className={styles[`${RBAC_PREFIX}-table-td-feature`]}>\n {t(\n `components:rolePermissionMatrix:features:${feature.code}` as Parameters<\n typeof t\n >[0],\n ) || feature.id}\n </td>\n\n {mainActions.map((action) => {\n const matchedPermission = permissions.find(\n (permission) =>\n toID(permission.permissionFeature) ===\n String(feature.id) &&\n toID(permission.permissionAction) ===\n String(action.id),\n );\n\n if (!matchedPermission) {\n return (\n <td\n key={`${feature.id}-${action.id}`}\n className={styles[`${RBAC_PREFIX}-table-td-action`]}\n >\n -\n </td>\n );\n }\n\n const permissionID = String(matchedPermission.id);\n const checked =\n typeof draftValue[permissionID] === \"boolean\"\n ? draftValue[permissionID]\n : (enabledByPermissionID.get(permissionID) ?? false);\n\n return (\n <td\n key={`${feature.id}-${action.id}`}\n className={styles[`${RBAC_PREFIX}-table-td-action`]}\n >\n <div\n className={\n styles[`${RBAC_PREFIX}-table-td-action-container`]\n }\n >\n <input\n type=\"checkbox\"\n id={`permission-matrix-checkbox-${checkboxId}-${feature.id}-${action.id}`}\n name={`permission-matrix-checkbox-${checkboxId}-${feature.id}-${action.id}`}\n checked={checked}\n disabled={isReadOnly}\n onChange={(event) => {\n setValue({\n ...draftValue,\n [permissionID]: event.target.checked,\n });\n }}\n className={\n styles[`${RBAC_PREFIX}-table-td-action-input`]\n }\n />\n <label\n htmlFor={`permission-matrix-checkbox-${checkboxId}-${feature.id}-${action.id}`}\n className={\n styles[`${RBAC_PREFIX}-table-td-action-label`]\n }\n >\n {t(\n `components:rolePermissionMatrix:actions:${action.code}` as Parameters<\n typeof t\n >[0],\n ) || action.id}\n </label>\n </div>\n </td>\n );\n })}\n </tr>\n\n {isSubActionInPermission && (\n <tr>\n <td\n className={styles[`${RBAC_PREFIX}-table-td-feature`]}\n ></td>\n <td\n className={styles[`${RBAC_PREFIX}-table-td-action`]}\n colSpan={mainActions.length}\n >\n {subActions.map((action) => {\n const matchedPermission = permissions.find(\n (permission) =>\n toID(permission.permissionFeature) ===\n String(feature.id) &&\n toID(permission.permissionAction) ===\n String(action.id),\n );\n\n if (!matchedPermission) {\n return null;\n }\n\n const permissionID = String(matchedPermission.id);\n const checked =\n typeof draftValue[permissionID] === \"boolean\"\n ? draftValue[permissionID]\n : (enabledByPermissionID.get(permissionID) ??\n false);\n\n return (\n <div key={`${feature.id}-${action.id}-sub`}>\n <input\n type=\"checkbox\"\n checked={checked}\n disabled={isReadOnly}\n onChange={(event) => {\n setValue({\n ...draftValue,\n [permissionID]: event.target.checked,\n });\n }}\n />{\" \"}\n <span\n style={{\n display: \"inline-block\",\n }}\n >\n {action.code || action.id}\n </span>\n </div>\n );\n })}\n </td>\n </tr>\n )}\n </Fragment>\n );\n })}\n </tbody>\n </table>\n </div>\n </div>\n );\n};\n"],"names":["useConfig","useDocumentInfo","useField","useTranslation","Fragment","useEffect","useId","useMemo","useRef","useState","STATUS","PERMISSION_STATUS","PERMISSION_ACTION_STATUS","TYPE","PERMISSION_FEATURE_STATUS","toID","styles","RBAC_PREFIX","RolePermissionMatrixClient","checkboxId","config","hasSavePermission","id","setValue","value","path","isReadOnly","features","setFeatures","actions","setActions","permissions","setPermissions","rolePermissions","setRolePermissions","loading","setLoading","t","seededForRoleIdRef","run","base","routes","api","featuresRes","actionsRes","permissionsRes","rolePermissionsRes","Promise","all","fetch","ACTIVE","credentials","resolve","Response","JSON","stringify","docs","featuresJson","json","actionsJson","permissionsJson","rolePermissionsJson","sort","a","b","sortOrder","enabledByPermissionID","map","Map","row","set","permission","Boolean","enabled","draftValue","Array","isArray","roleId","String","current","fromRolesPermissions","permissionID","entries","fromDocument","hasRolesPermissions","Object","keys","length","hasDocumentDraft","div","className","table","thead","tr","th","colSpan","filter","action","type","MAIN","tbody","feature","mainActions","subActions","SUB","some","permissionAction","permissionFeature","isSubActionInPermission","td","code","matchedPermission","find","checked","get","input","name","disabled","onChange","event","target","label","htmlFor","span","style","display"],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Import Payload compile-time SCSS vars ($breakpoint-s-width, etc.).
|
|
2
|
+
// Note: @payloadcms/ui/scss/vars is not a published export — use dist/scss/vars.
|
|
3
|
+
@use "../../../node_modules/@payloadcms/ui/dist/scss/vars" as payload-vars;
|
|
4
|
+
@use "../../styles/variables" as rbac-vars;
|
|
5
|
+
|
|
6
|
+
$local-prefix: rbac-vars.$rbac-prefix;
|
|
7
|
+
|
|
8
|
+
.#{$local-prefix}-component {
|
|
9
|
+
&-label {
|
|
10
|
+
opacity: 0.8;
|
|
11
|
+
padding: 0.5rem 0;
|
|
12
|
+
}
|
|
13
|
+
&-placeholder {
|
|
14
|
+
opacity: 0.8;
|
|
15
|
+
padding: 0.5rem 0;
|
|
16
|
+
}
|
|
17
|
+
&-title {
|
|
18
|
+
font-weight: 600;
|
|
19
|
+
margin-bottom: 0.5rem;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.#{$local-prefix}-table {
|
|
24
|
+
border-collapse: collapse;
|
|
25
|
+
width: 100%;
|
|
26
|
+
&-container {
|
|
27
|
+
border-radius: var(--style-radius-m);
|
|
28
|
+
border: 1px solid var(--theme-border-color);
|
|
29
|
+
@media only screen and (min-width: payload-vars.$breakpoint-s-width) {
|
|
30
|
+
border-radius: var(--style-radius-l);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
&-th {
|
|
34
|
+
&-feature {
|
|
35
|
+
padding: 0.5rem;
|
|
36
|
+
text-align: left;
|
|
37
|
+
border-right: 1px solid var(--theme-border-color);
|
|
38
|
+
width: 25%;
|
|
39
|
+
}
|
|
40
|
+
&-action {
|
|
41
|
+
padding: 0.5rem;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
&-td {
|
|
45
|
+
&-feature {
|
|
46
|
+
border-right: 1px solid var(--theme-border-color);
|
|
47
|
+
border-top: 1px solid var(--theme-border-color);
|
|
48
|
+
padding: 0.5rem;
|
|
49
|
+
}
|
|
50
|
+
&-action {
|
|
51
|
+
border-top: 1px solid var(--theme-border-color);
|
|
52
|
+
padding: 0.5rem;
|
|
53
|
+
&-container {
|
|
54
|
+
display: flex;
|
|
55
|
+
align-items: center;
|
|
56
|
+
}
|
|
57
|
+
&-input {
|
|
58
|
+
user-select: none;
|
|
59
|
+
cursor: pointer;
|
|
60
|
+
}
|
|
61
|
+
&-label {
|
|
62
|
+
display: inline-block;
|
|
63
|
+
padding-left: 0.25rem;
|
|
64
|
+
user-select: none;
|
|
65
|
+
cursor: pointer;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type RolePermissionMatrixClientTranslations = {
|
|
2
|
+
[locale: string]: {
|
|
3
|
+
viewInUpdateScreenOnly?: {
|
|
4
|
+
label?: string;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
};
|
|
7
|
+
loading?: {
|
|
8
|
+
placeholder?: string;
|
|
9
|
+
};
|
|
10
|
+
title?: string;
|
|
11
|
+
features?: {
|
|
12
|
+
label?: string;
|
|
13
|
+
} | Record<string, string>;
|
|
14
|
+
actions?: {
|
|
15
|
+
label?: string;
|
|
16
|
+
} | Record<string, string>;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { RolePermissionMatrixClient } from "../components/role-permission-matrix-client/index.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Config } from "payload";
|
|
2
|
+
import type { PayloadAuthRbacPluginConfig } from "./types.js";
|
|
3
|
+
export * from "./lib/constants/index.js";
|
|
4
|
+
export * from "./lib/utils/index.js";
|
|
5
|
+
export declare const payloadAuthRbacPlugin: (pluginOptions: PayloadAuthRbacPluginConfig) => (config: Config) => Config;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const NAMESPACE: "plugin-rbac";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as general from "./general.js";
|
|
2
|
+
import * as permission from "./permission.js";
|
|
3
|
+
import * as permissionAction from "./permission-action.js";
|
|
4
|
+
import * as permissionFeature from "./permission-feature.js";
|
|
5
|
+
import * as role from "./role.js";
|
|
6
|
+
import * as user from "./user.js";
|
|
7
|
+
export declare const CONSTANTS: {
|
|
8
|
+
readonly GENERAL: typeof general;
|
|
9
|
+
readonly PERMISSION: typeof permission;
|
|
10
|
+
readonly PERMISSION_FEATURE: typeof permissionFeature;
|
|
11
|
+
readonly PERMISSION_ACTION: typeof permissionAction;
|
|
12
|
+
readonly ROLE: typeof role;
|
|
13
|
+
readonly USER: typeof user;
|
|
14
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const PARENT_PATH_SEPARATOR: ",";
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Access, type PayloadRequest, type Where } from "payload";
|
|
2
|
+
import type { DataScope } from "../../collections/roles/types.js";
|
|
3
|
+
export type DataScopeOptions = {
|
|
4
|
+
/** Field on business collections storing the creator user id. Default: `createdBy`. */
|
|
5
|
+
createdByField?: string;
|
|
6
|
+
/** Users collection slug. Default: `users`. */
|
|
7
|
+
usersCollectionSlug?: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Access helper: allow only super admins.
|
|
11
|
+
* Check session first, then persisted users data.
|
|
12
|
+
*/
|
|
13
|
+
export declare const getSuperAdminAccess: ({ req }: {
|
|
14
|
+
req: PayloadRequest;
|
|
15
|
+
}) => Promise<boolean>;
|
|
16
|
+
/**
|
|
17
|
+
* Access helper: allow current document owner or super admin.
|
|
18
|
+
*/
|
|
19
|
+
export declare const getAuthenticatedOrSuperAdminAccess: Access | Promise<boolean>;
|
|
20
|
+
/**
|
|
21
|
+
* Resolve effective data scope from active roles.
|
|
22
|
+
* Widest scope wins: `all` > `hierarchy` > `own`.
|
|
23
|
+
*/
|
|
24
|
+
export declare const resolveEffectiveDataScope: (req: PayloadRequest, options?: DataScopeOptions) => Promise<DataScope>;
|
|
25
|
+
/**
|
|
26
|
+
* Collect visible user IDs for hierarchy scope:
|
|
27
|
+
* current user + direct/indirect descendants from `parent` / `parentPath`.
|
|
28
|
+
*/
|
|
29
|
+
export declare const getHierarchyVisibleUserIds: (req: PayloadRequest, options?: DataScopeOptions) => Promise<string[]>;
|
|
30
|
+
/**
|
|
31
|
+
* Build a read `Where` filter from data scope.
|
|
32
|
+
* Returns `true` when no extra filtering is required (`all` scope / super admin).
|
|
33
|
+
*/
|
|
34
|
+
export declare const getDataScopeReadWhere: (req: PayloadRequest, options?: DataScopeOptions) => Promise<Where | true>;
|
|
35
|
+
/**
|
|
36
|
+
* Guard for privileged user documents.
|
|
37
|
+
* Non-super-admins cannot mutate users where `isSuperAdmin === true`.
|
|
38
|
+
*/
|
|
39
|
+
export declare const isProtectedSuperAdminUserDoc: (doc: Record<string, unknown>) => boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Document-level access check:
|
|
42
|
+
* RBAC permission (`featureCode` + `actionCode`) + data-scope evaluation.
|
|
43
|
+
* Super admins bypass.
|
|
44
|
+
*/
|
|
45
|
+
export declare const canAccessDocumentByDataScope: ({ req, doc, featureCode, actionCode, collectionSlug, options, }: {
|
|
46
|
+
req: PayloadRequest;
|
|
47
|
+
doc: Record<string, unknown>;
|
|
48
|
+
featureCode: string;
|
|
49
|
+
actionCode: string;
|
|
50
|
+
collectionSlug: string;
|
|
51
|
+
options?: DataScopeOptions;
|
|
52
|
+
}) => Promise<boolean>;
|
|
53
|
+
/**
|
|
54
|
+
* Merge an existing `where` with scope-derived constraints.
|
|
55
|
+
*/
|
|
56
|
+
export declare const mergeDataScopeWhere: (base: Where | undefined, scopeWhere: Where | true) => Where;
|
|
57
|
+
/**
|
|
58
|
+
* Unified access entrypoint.
|
|
59
|
+
*
|
|
60
|
+
* Modes:
|
|
61
|
+
* - `none`: permission-only (boolean)
|
|
62
|
+
* - `modify`: per-document mutation check (requires `collectionSlug` + runtime `id`)
|
|
63
|
+
* - implicit read mode: pass `options` to get a read `Where` filter after permission check
|
|
64
|
+
*/
|
|
65
|
+
export declare const getPermissionAccess: ({ featureCode, actionCode, mode, collectionSlug, options, }: {
|
|
66
|
+
featureCode: string;
|
|
67
|
+
actionCode: string;
|
|
68
|
+
mode?: "none" | "modify";
|
|
69
|
+
collectionSlug?: string;
|
|
70
|
+
options?: DataScopeOptions;
|
|
71
|
+
}) => (({ req }: {
|
|
72
|
+
req: PayloadRequest;
|
|
73
|
+
}) => Promise<boolean | Where>) | (({ req, id }: {
|
|
74
|
+
req: PayloadRequest;
|
|
75
|
+
id?: string | number;
|
|
76
|
+
}) => Promise<boolean>);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Field } from "payload";
|
|
2
|
+
/**
|
|
3
|
+
* Merges one plugin default field with a host override that shares the same `name`.
|
|
4
|
+
* Custom properties win (`{ ...defaultField, ...customField }`). Non-data fields
|
|
5
|
+
* (e.g. tabs, unnamed layout fields) are returned unchanged.
|
|
6
|
+
*/
|
|
7
|
+
export declare const getMergedFieldAffectingData: ({ fields, defaultField, }: {
|
|
8
|
+
fields: Field[];
|
|
9
|
+
defaultField: Field;
|
|
10
|
+
}) => Field;
|
|
11
|
+
/**
|
|
12
|
+
* Builds the final `fields` array for a collection: each default is merged by name,
|
|
13
|
+
* then host-only fields are appended (data fields with new names, plus layout fields).
|
|
14
|
+
*/
|
|
15
|
+
export declare const getArrayOfMergedFieldAffectingData: ({ fields, defaultFields, }: {
|
|
16
|
+
fields: Field[];
|
|
17
|
+
defaultFields: Field[];
|
|
18
|
+
}) => Field[];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { SelectField } from "payload";
|
|
2
|
+
/** Builds `{ [locale]: string }` from `getValue`, skipping empty values. */
|
|
3
|
+
export declare const toLocaleRecord: (locales: string[], getValue: (locale: string) => string | undefined) => Record<string, string>;
|
|
4
|
+
/**
|
|
5
|
+
* Select placeholder as per-locale strings (not `LabelFunction`) so it survives
|
|
6
|
+
* Next.js server → client serialization; Payload resolves it at render time.
|
|
7
|
+
*/
|
|
8
|
+
export declare const toSelectPlaceholder: (locales: string[], getValue: (locale: string) => string | undefined) => NonNullable<SelectField["admin"]>["placeholder"];
|
|
9
|
+
type TranslationObject = {
|
|
10
|
+
[key: string]: TranslationValue;
|
|
11
|
+
};
|
|
12
|
+
type TranslationValue = TranslationObject | string | undefined;
|
|
13
|
+
/** Plugin defaults merged with host `translations` overrides. */
|
|
14
|
+
export declare const getMergedTranslations: <T extends Record<string, TranslationValue>>({ defaultTranslations, translations, }: {
|
|
15
|
+
defaultTranslations: T;
|
|
16
|
+
translations: Partial<T>;
|
|
17
|
+
}) => T;
|
|
18
|
+
/**
|
|
19
|
+
* Picks a nested branch from each locale, e.g. path `"collections.roles"`.
|
|
20
|
+
* Use `locales: "all"` or `["en", "vi"]`.
|
|
21
|
+
*/
|
|
22
|
+
export declare const getAllTranslationsOfSpecificObject: <T = unknown>({ translations, path, locales, }: {
|
|
23
|
+
translations: Record<string, Record<string, unknown>>;
|
|
24
|
+
path: string;
|
|
25
|
+
locales?: "all" | string[];
|
|
26
|
+
}) => Record<string, T>;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
$rbac-prefix: "rbac";
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type * as PermissionActionTypes from "./collections/permission-actions/types.js";
|
|
2
|
+
import type * as PermissionFeatureTypes from "./collections/permission-features/types.js";
|
|
3
|
+
import type * as PermissionTypes from "./collections/permissions/types.js";
|
|
4
|
+
import type * as RoleTypes from "./collections/roles/types.js";
|
|
5
|
+
import type * as RolePermissionTypes from "./collections/roles-permissions/types.js";
|
|
6
|
+
import type * as UsersTypes from "./collections/users/types.js";
|
|
7
|
+
import type * as RolePermissionMatrixClientTypes from "./components/role-permission-matrix-client/types.js";
|
|
8
|
+
export * from "./collections/permission-actions/types.js";
|
|
9
|
+
export * from "./collections/permission-features/types.js";
|
|
10
|
+
export * from "./collections/permissions/types.js";
|
|
11
|
+
export * from "./collections/roles/types.js";
|
|
12
|
+
export * from "./collections/roles-permissions/types.js";
|
|
13
|
+
export * from "./collections/users/types.js";
|
|
14
|
+
export * from "./components/role-permission-matrix-client/types.js";
|
|
15
|
+
export type RBACTranslations = {
|
|
16
|
+
[locale: string]: {
|
|
17
|
+
collections?: {
|
|
18
|
+
permissionActions?: PermissionActionTypes.PermissionActionsCollectionTranslations[string];
|
|
19
|
+
permissionFeatures?: PermissionFeatureTypes.PermissionFeaturesCollectionTranslations[string];
|
|
20
|
+
permissions?: PermissionTypes.PermissionsCollectionTranslations[string];
|
|
21
|
+
roles?: RoleTypes.RolesCollectionTranslations[string];
|
|
22
|
+
rolesPermissions?: RolePermissionTypes.RolesPermissionsCollectionTranslations[string];
|
|
23
|
+
users?: UsersTypes.UsersModificationTranslations[string];
|
|
24
|
+
};
|
|
25
|
+
components?: {
|
|
26
|
+
rolePermissionMatrix?: RolePermissionMatrixClientTypes.RolePermissionMatrixClientTranslations[string];
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export type PayloadAuthRbacPluginConfig = {
|
|
31
|
+
/**
|
|
32
|
+
* Collection slugs to augment (may include plugin-only collections absent from generated `CollectionSlug`).
|
|
33
|
+
*/
|
|
34
|
+
collections?: Partial<Record<string, Omit<PermissionActionTypes.PermissionActionsCollectionParams, "translations"> | Omit<PermissionFeatureTypes.PermissionFeaturesCollectionParams, "translations"> | Omit<PermissionTypes.PermissionsCollectionParams, "translations"> | Omit<RoleTypes.RolesCollectionParams, "translations"> | Omit<RolePermissionTypes.RolesPermissionsCollectionParams, "translations">>>;
|
|
35
|
+
disabled?: boolean;
|
|
36
|
+
translations?: RBACTranslations;
|
|
37
|
+
autoModifyUsersCollection?: boolean;
|
|
38
|
+
};
|