@firecms/user_management 3.0.0-3.0.0-beta.4.pre.1.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.
- package/LICENSE +21 -0
- package/README.md +157 -0
- package/dist/UserManagementProvider.d.ts +7 -0
- package/dist/admin_views.d.ts +2 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/roles/RoleChip.d.ts +5 -0
- package/dist/components/roles/RolesDetailsForm.d.ts +20 -0
- package/dist/components/roles/RolesTable.d.ts +5 -0
- package/dist/components/roles/RolesView.d.ts +4 -0
- package/dist/components/roles/default_roles.d.ts +2 -0
- package/dist/components/roles/index.d.ts +4 -0
- package/dist/components/users/UserDetailsForm.d.ts +20 -0
- package/dist/components/users/UsersTable.d.ts +4 -0
- package/dist/components/users/UsersView.d.ts +4 -0
- package/dist/components/users/index.d.ts +3 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/useBuildFirestoreUserManagement.d.ts +44 -0
- package/dist/hooks/useUserManagement.d.ts +2 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.es.js +1263 -0
- package/dist/index.es.js.map +1 -0
- package/dist/index.umd.js +2 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/types/firecms_user.d.ts +7 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/roles.d.ts +31 -0
- package/dist/types/user_management.d.ts +39 -0
- package/dist/useUserManagementPlugin.d.ts +5 -0
- package/dist/utils/colors.d.ts +2 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/local_storage.d.ts +3 -0
- package/dist/utils/permissions.d.ts +9 -0
- package/dist/utils/useTraceUpdate.d.ts +1 -0
- package/package.json +76 -0
- package/src/UserManagementProvider.tsx +19 -0
- package/src/admin_views.tsx +19 -0
- package/src/components/index.ts +2 -0
- package/src/components/roles/RoleChip.tsx +28 -0
- package/src/components/roles/RolesDetailsForm.tsx +402 -0
- package/src/components/roles/RolesTable.tsx +139 -0
- package/src/components/roles/RolesView.tsx +63 -0
- package/src/components/roles/default_roles.tsx +36 -0
- package/src/components/roles/index.ts +4 -0
- package/src/components/users/UserDetailsForm.tsx +230 -0
- package/src/components/users/UsersTable.tsx +178 -0
- package/src/components/users/UsersView.tsx +59 -0
- package/src/components/users/index.ts +3 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useBuildFirestoreUserManagement.tsx +241 -0
- package/src/hooks/useUserManagement.tsx +5 -0
- package/src/index.ts +7 -0
- package/src/types/firecms_user.ts +8 -0
- package/src/types/index.ts +3 -0
- package/src/types/roles.ts +41 -0
- package/src/types/user_management.tsx +50 -0
- package/src/useUserManagementPlugin.tsx +18 -0
- package/src/utils/colors.ts +52 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/local_storage.ts +53 -0
- package/src/utils/permissions.ts +83 -0
- package/src/utils/useTraceUpdate.tsx +23 -0
- package/tailwind.config.js +68 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
import { Permissions } from "@firecms/core";
|
2
|
+
export type Role = {
|
3
|
+
/**
|
4
|
+
* ID of the role
|
5
|
+
*/
|
6
|
+
id: string;
|
7
|
+
/**
|
8
|
+
* Name of the role
|
9
|
+
*/
|
10
|
+
name: string;
|
11
|
+
/**
|
12
|
+
* If this flag is true, the user can perform any action
|
13
|
+
*/
|
14
|
+
isAdmin?: boolean;
|
15
|
+
/**
|
16
|
+
* Default permissions for all collections for this role.
|
17
|
+
* You can override this values at the collection level using
|
18
|
+
* {@link collectionPermissions}
|
19
|
+
*/
|
20
|
+
defaultPermissions?: Permissions;
|
21
|
+
/**
|
22
|
+
* Record of stripped collection ids to their permissions.
|
23
|
+
* @see stripCollectionPath
|
24
|
+
*/
|
25
|
+
collectionPermissions?: Record<string, Permissions>;
|
26
|
+
config?: {
|
27
|
+
createCollections?: boolean;
|
28
|
+
editCollections?: boolean | "own";
|
29
|
+
deleteCollections?: boolean | "own";
|
30
|
+
};
|
31
|
+
};
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import { UserWithRoles } from "./firecms_user";
|
2
|
+
import { Role } from "./roles";
|
3
|
+
import { PermissionsBuilder } from "@firecms/core";
|
4
|
+
export type UserManagement<USER extends UserWithRoles = UserWithRoles> = {
|
5
|
+
loading: boolean;
|
6
|
+
/**
|
7
|
+
* The user currently logged in, in the user management system.
|
8
|
+
* This is the same user that is logged in the Authenticator, but with the roles
|
9
|
+
* and permissions loaded.
|
10
|
+
*/
|
11
|
+
loggedInUser: USER | undefined;
|
12
|
+
users: USER[];
|
13
|
+
saveUser: (user: USER) => Promise<USER>;
|
14
|
+
deleteUser: (user: USER) => Promise<void>;
|
15
|
+
roles: Role[];
|
16
|
+
saveRole: (role: Role) => Promise<void>;
|
17
|
+
deleteRole: (role: Role) => Promise<void>;
|
18
|
+
/**
|
19
|
+
* Maximum number of users that can be created.
|
20
|
+
*/
|
21
|
+
usersLimit?: number;
|
22
|
+
/**
|
23
|
+
* Can the logged user edit roles?
|
24
|
+
*/
|
25
|
+
canEditRoles?: boolean;
|
26
|
+
/**
|
27
|
+
* Include a button to create default roles, in case there are no roles in the system.
|
28
|
+
*/
|
29
|
+
allowDefaultRolesCreation?: boolean;
|
30
|
+
/**
|
31
|
+
* Include the collection config permissions in the user management system.
|
32
|
+
*/
|
33
|
+
includeCollectionConfigPermissions?: boolean;
|
34
|
+
/**
|
35
|
+
* Get a permissions builder that defines which operations can be performed by a user in a collection.
|
36
|
+
* The permission builder generated should be based in the user roles and the collection config.
|
37
|
+
*/
|
38
|
+
collectionPermissions: PermissionsBuilder;
|
39
|
+
};
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { EntityCollection, Permissions } from "@firecms/core";
|
2
|
+
import { Role, UserWithRoles } from "../types";
|
3
|
+
export declare const RESERVED_GROUPS: string[];
|
4
|
+
export declare function resolveUserRolePermissions<UserType extends UserWithRoles>({ collection, user }: {
|
5
|
+
collection: EntityCollection<any>;
|
6
|
+
user: UserType | null;
|
7
|
+
}): Permissions;
|
8
|
+
export declare function getUserRoles(roles: Role[], fireCMSUser: UserWithRoles): Role[] | undefined;
|
9
|
+
export declare const areRolesEqual: (rolesA: Role[], rolesB: Role[]) => boolean;
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare function useTraceUpdate(props: any): void;
|
package/package.json
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
{
|
2
|
+
"name": "@firecms/user_management",
|
3
|
+
"type": "module",
|
4
|
+
"version": "3.0.0-3.0.0-beta.4.pre.1.0",
|
5
|
+
"publishConfig": {
|
6
|
+
"access": "public"
|
7
|
+
},
|
8
|
+
"keywords": [
|
9
|
+
"firebase",
|
10
|
+
"cms",
|
11
|
+
"admin",
|
12
|
+
"admin panel",
|
13
|
+
"firebase panel",
|
14
|
+
"firestore",
|
15
|
+
"headless",
|
16
|
+
"headless cms",
|
17
|
+
"content manager"
|
18
|
+
],
|
19
|
+
"exports": {
|
20
|
+
".": {
|
21
|
+
"import": "./dist/index.es.js",
|
22
|
+
"require": "./dist/index.umd.js",
|
23
|
+
"types": "./dist/index.d.ts"
|
24
|
+
},
|
25
|
+
"./package.json": "./package.json",
|
26
|
+
"./tailwind.config.js": "./tailwind.config.js"
|
27
|
+
},
|
28
|
+
"packageManager": "yarn@4.1.0",
|
29
|
+
"main": "./dist/index.umd.js",
|
30
|
+
"module": "./dist/index.es.js",
|
31
|
+
"types": "dist/index.d.ts",
|
32
|
+
"source": "src/index.ts",
|
33
|
+
"dependencies": {
|
34
|
+
"@firecms/core": "^3.0.0-3.0.0-beta.4.pre.1.0",
|
35
|
+
"@firecms/formex": "^3.0.0-3.0.0-beta.4.pre.1.0",
|
36
|
+
"@firecms/ui": "^3.0.0-3.0.0-beta.4.pre.1.0"
|
37
|
+
},
|
38
|
+
"peerDependencies": {
|
39
|
+
"firebase": "^10.7.1",
|
40
|
+
"react": "^18.2.0",
|
41
|
+
"react-dom": "^18.2.0"
|
42
|
+
},
|
43
|
+
"devDependencies": {
|
44
|
+
"@types/node": "^20.11.30",
|
45
|
+
"@types/react": "^18.2.67",
|
46
|
+
"@types/react-dom": "^18.2.22",
|
47
|
+
"@typescript-eslint/parser": "^7.3.1",
|
48
|
+
"eslint": "^8.57.0",
|
49
|
+
"eslint-config-standard": "^17.1.0",
|
50
|
+
"eslint-plugin-import": "^2.29.1",
|
51
|
+
"eslint-plugin-n": "^16.6.2",
|
52
|
+
"eslint-plugin-promise": "^6.1.1",
|
53
|
+
"eslint-plugin-react": "^7.34.1",
|
54
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
55
|
+
"typescript": "^5.4.2",
|
56
|
+
"vite": "^5.1.6"
|
57
|
+
},
|
58
|
+
"scripts": {
|
59
|
+
"dev": "vite",
|
60
|
+
"build": "vite build && tsc --emitDeclarationOnly -p tsconfig.prod.json",
|
61
|
+
"clean": "rm -rf dist && find ./src -name '*.js' -type f | xargs rm -f"
|
62
|
+
},
|
63
|
+
"files": [
|
64
|
+
"dist",
|
65
|
+
"src",
|
66
|
+
"tailwind.config.js",
|
67
|
+
"bin"
|
68
|
+
],
|
69
|
+
"eslintConfig": {
|
70
|
+
"extends": [
|
71
|
+
"react-app",
|
72
|
+
"react-app/jest"
|
73
|
+
]
|
74
|
+
},
|
75
|
+
"gitHead": "bfe875c02132b5763ac0c9d8c8a885c791bb5a24"
|
76
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import React, { PropsWithChildren } from "react";
|
2
|
+
import { UserManagement, UserWithRoles } from "./types";
|
3
|
+
|
4
|
+
export const UserManagementContext = React.createContext<UserManagement<any>>({} as any);
|
5
|
+
|
6
|
+
export interface UserManagementProviderProps<U extends UserWithRoles = UserWithRoles> {
|
7
|
+
userManagement: UserManagement<U>
|
8
|
+
}
|
9
|
+
|
10
|
+
export function UserManagementProvider<U extends UserWithRoles = UserWithRoles>({
|
11
|
+
children,
|
12
|
+
userManagement
|
13
|
+
}: PropsWithChildren<UserManagementProviderProps<U>>) {
|
14
|
+
return (
|
15
|
+
<UserManagementContext.Provider value={userManagement}>
|
16
|
+
{children}
|
17
|
+
</UserManagementContext.Provider>
|
18
|
+
);
|
19
|
+
};
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import { CMSView } from "@firecms/core";
|
2
|
+
import { RolesView, UsersView } from "./components";
|
3
|
+
|
4
|
+
export const userManagementAdminViews: CMSView[] = [
|
5
|
+
{
|
6
|
+
path: "users",
|
7
|
+
name: "CMS Users",
|
8
|
+
group: "Admin",
|
9
|
+
icon: "face",
|
10
|
+
view: <UsersView/>
|
11
|
+
},
|
12
|
+
{
|
13
|
+
path: "roles",
|
14
|
+
name: "Roles",
|
15
|
+
group: "Admin",
|
16
|
+
icon: "gpp_good",
|
17
|
+
view: <RolesView/>
|
18
|
+
}
|
19
|
+
]
|
@@ -0,0 +1,28 @@
|
|
1
|
+
import { Chip, getColorSchemeForSeed } from "@firecms/ui";
|
2
|
+
import { Role } from "../../types";
|
3
|
+
|
4
|
+
export type RoleChipProps = {
|
5
|
+
role: Role;
|
6
|
+
}
|
7
|
+
|
8
|
+
export function RoleChip({ role }: RoleChipProps) {
|
9
|
+
let colorScheme;
|
10
|
+
if (role.isAdmin) {
|
11
|
+
colorScheme = "blueDarker";
|
12
|
+
} else if (role.id === "editor") {
|
13
|
+
colorScheme = "yellowLight";
|
14
|
+
} else if (role.id === "viewer") {
|
15
|
+
colorScheme = "grayLight";
|
16
|
+
} else {
|
17
|
+
colorScheme = getColorSchemeForSeed(role.id);
|
18
|
+
}
|
19
|
+
|
20
|
+
return (
|
21
|
+
<Chip
|
22
|
+
colorScheme={colorScheme}
|
23
|
+
key={role.id}>
|
24
|
+
{role.name}
|
25
|
+
</Chip>
|
26
|
+
);
|
27
|
+
|
28
|
+
}
|
@@ -0,0 +1,402 @@
|
|
1
|
+
import React, { useCallback, useState } from "react";
|
2
|
+
import * as Yup from "yup";
|
3
|
+
|
4
|
+
import { EntityCollection, FieldCaption, toSnakeCase, } from "@firecms/core";
|
5
|
+
import {
|
6
|
+
Button,
|
7
|
+
Checkbox,
|
8
|
+
Dialog,
|
9
|
+
DialogActions,
|
10
|
+
DialogContent,
|
11
|
+
DoneIcon,
|
12
|
+
LoadingButton,
|
13
|
+
Paper,
|
14
|
+
Select,
|
15
|
+
SelectItem,
|
16
|
+
Table,
|
17
|
+
TableBody,
|
18
|
+
TableCell,
|
19
|
+
TableHeader,
|
20
|
+
TableRow,
|
21
|
+
TextField,
|
22
|
+
Tooltip,
|
23
|
+
Typography
|
24
|
+
} from "@firecms/ui";
|
25
|
+
import { useUserManagement } from "../../hooks";
|
26
|
+
import { Formex, getIn, useCreateFormex } from "@firecms/formex";
|
27
|
+
import { Role } from "../../types";
|
28
|
+
|
29
|
+
export const RoleYupSchema = Yup.object().shape({
|
30
|
+
id: Yup.string().required("Required"),
|
31
|
+
name: Yup.string().required("Required")
|
32
|
+
});
|
33
|
+
|
34
|
+
export function RolesDetailsForm({
|
35
|
+
open,
|
36
|
+
role,
|
37
|
+
editable,
|
38
|
+
handleClose,
|
39
|
+
collections
|
40
|
+
}: {
|
41
|
+
open: boolean,
|
42
|
+
editable?: boolean,
|
43
|
+
role?: Role,
|
44
|
+
handleClose: () => void,
|
45
|
+
collections?: EntityCollection[]
|
46
|
+
}) {
|
47
|
+
|
48
|
+
const { saveRole } = useUserManagement();
|
49
|
+
const isNewRole = !role;
|
50
|
+
|
51
|
+
const [savingError, setSavingError] = useState<Error | undefined>();
|
52
|
+
|
53
|
+
const onRoleUpdated = useCallback((role: Role) => {
|
54
|
+
setSavingError(undefined);
|
55
|
+
return saveRole(role);
|
56
|
+
}, [saveRole]);
|
57
|
+
|
58
|
+
const formex = useCreateFormex({
|
59
|
+
initialValues: role ?? {
|
60
|
+
name: ""
|
61
|
+
} as Role,
|
62
|
+
onSubmit: (role: Role, formexController) => {
|
63
|
+
return onRoleUpdated(role)
|
64
|
+
.then(() => {
|
65
|
+
formexController.resetForm({
|
66
|
+
values: role
|
67
|
+
});
|
68
|
+
handleClose();
|
69
|
+
})
|
70
|
+
.catch(e => setSavingError(e));
|
71
|
+
},
|
72
|
+
validation: (values) => {
|
73
|
+
return RoleYupSchema.validate(values, { abortEarly: false })
|
74
|
+
.then(() => ({}))
|
75
|
+
.catch((e) => {
|
76
|
+
const errors: Record<string, string> = {};
|
77
|
+
e.inner.forEach((error: any) => {
|
78
|
+
errors[error.path] = error.message;
|
79
|
+
});
|
80
|
+
return errors;
|
81
|
+
});
|
82
|
+
}
|
83
|
+
|
84
|
+
});
|
85
|
+
|
86
|
+
const {
|
87
|
+
isSubmitting,
|
88
|
+
touched,
|
89
|
+
values,
|
90
|
+
errors,
|
91
|
+
handleChange,
|
92
|
+
setFieldValue,
|
93
|
+
dirty,
|
94
|
+
setFieldTouched
|
95
|
+
} = formex;
|
96
|
+
|
97
|
+
const isAdmin = values.isAdmin ?? false;
|
98
|
+
const defaultCreate = values.defaultPermissions?.create ?? false;
|
99
|
+
const defaultRead = values.defaultPermissions?.read ?? false;
|
100
|
+
const defaultEdit = values.defaultPermissions?.edit ?? false;
|
101
|
+
const defaultDelete = values.defaultPermissions?.delete ?? false;
|
102
|
+
|
103
|
+
React.useEffect(() => {
|
104
|
+
const idTouched = getIn(touched, "id");
|
105
|
+
if (!idTouched && values.name) {
|
106
|
+
setFieldValue("id", toSnakeCase(values.name))
|
107
|
+
}
|
108
|
+
}, [touched, values.name]);
|
109
|
+
|
110
|
+
return (
|
111
|
+
<Dialog
|
112
|
+
open={open}
|
113
|
+
maxWidth={"4xl"}
|
114
|
+
>
|
115
|
+
<Formex value={formex}>
|
116
|
+
<form noValidate
|
117
|
+
autoComplete={"off"}
|
118
|
+
onSubmit={formex.handleSubmit}
|
119
|
+
style={{
|
120
|
+
display: "flex",
|
121
|
+
flexDirection: "column",
|
122
|
+
position: "relative",
|
123
|
+
height: "100%"
|
124
|
+
}}>
|
125
|
+
<DialogContent className="flex-grow">
|
126
|
+
<div
|
127
|
+
className="flex flex-row pt-12 pb-8">
|
128
|
+
<Typography variant={"h4"}
|
129
|
+
className="flex-grow">
|
130
|
+
Role
|
131
|
+
</Typography>
|
132
|
+
</div>
|
133
|
+
|
134
|
+
<div className={"grid grid-cols-12 gap-8"}>
|
135
|
+
|
136
|
+
<div className={"col-span-12 md:col-span-8"}>
|
137
|
+
<TextField
|
138
|
+
name="name"
|
139
|
+
required
|
140
|
+
error={touched.name && Boolean(errors.name)}
|
141
|
+
value={values.name}
|
142
|
+
disabled={isAdmin || !editable}
|
143
|
+
onChange={handleChange}
|
144
|
+
aria-describedby="name-helper-text"
|
145
|
+
label="Name"
|
146
|
+
/>
|
147
|
+
<FieldCaption>
|
148
|
+
{touched.name && Boolean(errors.name) ? errors.name : "Name of this role"}
|
149
|
+
</FieldCaption>
|
150
|
+
</div>
|
151
|
+
|
152
|
+
<div className={"col-span-12 md:col-span-4"}>
|
153
|
+
<TextField
|
154
|
+
name="id"
|
155
|
+
required
|
156
|
+
error={touched.id && Boolean(errors.id)}
|
157
|
+
value={values.id}
|
158
|
+
disabled={!isNewRole || !editable}
|
159
|
+
onChange={(e) => {
|
160
|
+
handleChange(e);
|
161
|
+
setFieldTouched("id", true)
|
162
|
+
}}
|
163
|
+
aria-describedby="id-helper-text"
|
164
|
+
label="ID"
|
165
|
+
/>
|
166
|
+
<FieldCaption>
|
167
|
+
{touched.id && Boolean(errors.id) ? errors.id : "ID of this role"}
|
168
|
+
</FieldCaption>
|
169
|
+
</div>
|
170
|
+
|
171
|
+
<div className={"col-span-12"}>
|
172
|
+
<Paper
|
173
|
+
|
174
|
+
className="bg-inherit">
|
175
|
+
<Table>
|
176
|
+
<TableHeader>
|
177
|
+
<TableCell></TableCell>
|
178
|
+
<TableCell
|
179
|
+
align="center">Create
|
180
|
+
entities
|
181
|
+
</TableCell>
|
182
|
+
<TableCell
|
183
|
+
align="center">Read
|
184
|
+
entities
|
185
|
+
</TableCell>
|
186
|
+
<TableCell
|
187
|
+
align="center">Update
|
188
|
+
entities
|
189
|
+
</TableCell>
|
190
|
+
<TableCell
|
191
|
+
align="center">Delete
|
192
|
+
entities
|
193
|
+
</TableCell>
|
194
|
+
</TableHeader>
|
195
|
+
|
196
|
+
<TableBody>
|
197
|
+
<TableRow>
|
198
|
+
<TableCell
|
199
|
+
scope="row">
|
200
|
+
<strong>All
|
201
|
+
collections</strong>
|
202
|
+
</TableCell>
|
203
|
+
<TableCell
|
204
|
+
align="center">
|
205
|
+
<Tooltip
|
206
|
+
title="Create entities in collections">
|
207
|
+
<Checkbox
|
208
|
+
disabled={isAdmin || !editable}
|
209
|
+
checked={(isAdmin || defaultCreate) ?? false}
|
210
|
+
onCheckedChange={(checked) => setFieldValue("defaultPermissions.create", checked)}
|
211
|
+
/>
|
212
|
+
</Tooltip>
|
213
|
+
</TableCell>
|
214
|
+
|
215
|
+
<TableCell
|
216
|
+
align="center">
|
217
|
+
<Tooltip
|
218
|
+
title="Access all data in every collection">
|
219
|
+
<Checkbox
|
220
|
+
disabled={isAdmin || !editable}
|
221
|
+
checked={(isAdmin || defaultRead) ?? false}
|
222
|
+
onCheckedChange={(checked) => setFieldValue("defaultPermissions.read", checked)}
|
223
|
+
/>
|
224
|
+
</Tooltip>
|
225
|
+
</TableCell>
|
226
|
+
<TableCell
|
227
|
+
align="center">
|
228
|
+
<Tooltip
|
229
|
+
title="Update data in any collection">
|
230
|
+
<Checkbox
|
231
|
+
disabled={isAdmin || !editable}
|
232
|
+
checked={(isAdmin || defaultEdit) ?? false}
|
233
|
+
onCheckedChange={(checked) => setFieldValue("defaultPermissions.edit", checked)}
|
234
|
+
/>
|
235
|
+
</Tooltip>
|
236
|
+
</TableCell>
|
237
|
+
<TableCell
|
238
|
+
align="center">
|
239
|
+
<Tooltip
|
240
|
+
title="Delete data in any collection">
|
241
|
+
<Checkbox
|
242
|
+
disabled={isAdmin || !editable}
|
243
|
+
checked={(isAdmin || defaultDelete) ?? false}
|
244
|
+
onCheckedChange={(checked) => setFieldValue("defaultPermissions.delete", checked)}
|
245
|
+
/>
|
246
|
+
|
247
|
+
</Tooltip>
|
248
|
+
</TableCell>
|
249
|
+
</TableRow>
|
250
|
+
{collections && collections.map((col) => (
|
251
|
+
<TableRow key={col.name}>
|
252
|
+
<TableCell
|
253
|
+
scope="row">
|
254
|
+
{col.name}
|
255
|
+
</TableCell>
|
256
|
+
<TableCell
|
257
|
+
align="center">
|
258
|
+
<Checkbox
|
259
|
+
disabled={isAdmin || defaultCreate || !editable}
|
260
|
+
checked={(isAdmin || defaultCreate || getIn(values, `collectionPermissions.${col.path}.create`)) ?? false}
|
261
|
+
onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.create`, checked)}/>
|
262
|
+
</TableCell>
|
263
|
+
<TableCell
|
264
|
+
align="center">
|
265
|
+
<Checkbox
|
266
|
+
disabled={isAdmin || defaultRead || !editable}
|
267
|
+
checked={(isAdmin || defaultRead || getIn(values, `collectionPermissions.${col.path}.read`)) ?? false}
|
268
|
+
onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.read`, checked)}/>
|
269
|
+
</TableCell>
|
270
|
+
<TableCell
|
271
|
+
align="center">
|
272
|
+
<Checkbox
|
273
|
+
disabled={isAdmin || defaultEdit || !editable}
|
274
|
+
checked={(isAdmin || defaultEdit || getIn(values, `collectionPermissions.${col.path}.edit`)) ?? false}
|
275
|
+
onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.edit`, checked)}/>
|
276
|
+
</TableCell>
|
277
|
+
<TableCell
|
278
|
+
align="center">
|
279
|
+
<Checkbox
|
280
|
+
disabled={isAdmin || defaultDelete || !editable}
|
281
|
+
checked={(isAdmin || defaultDelete || getIn(values, `collectionPermissions.${col.path}.delete`)) ?? false}
|
282
|
+
onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.delete`, checked)}/>
|
283
|
+
</TableCell>
|
284
|
+
</TableRow>
|
285
|
+
))}
|
286
|
+
</TableBody>
|
287
|
+
</Table>
|
288
|
+
</Paper>
|
289
|
+
<FieldCaption>
|
290
|
+
You can customise the permissions
|
291
|
+
that the users related to this
|
292
|
+
role can perform in the entities
|
293
|
+
of each collection
|
294
|
+
</FieldCaption>
|
295
|
+
</div>
|
296
|
+
|
297
|
+
<div className={"col-span-12 md:col-span-4"}>
|
298
|
+
<Select
|
299
|
+
error={touched.config && Boolean(errors.config)}
|
300
|
+
id="createCollections"
|
301
|
+
name="createCollections"
|
302
|
+
label="Create collections"
|
303
|
+
position={"item-aligned"}
|
304
|
+
disabled={isAdmin || !editable}
|
305
|
+
onChange={(event) => setFieldValue("config.createCollections", event.target.value === "true")}
|
306
|
+
value={isAdmin || values.config?.createCollections ? "true" : "false"}
|
307
|
+
renderValue={(value: any) => value === "true" ? "Yes" : "No"}
|
308
|
+
>
|
309
|
+
<SelectItem
|
310
|
+
value={"true"}> Yes </SelectItem>
|
311
|
+
<SelectItem
|
312
|
+
value={"false"}> No </SelectItem>
|
313
|
+
</Select>
|
314
|
+
|
315
|
+
<FieldCaption>
|
316
|
+
{touched.config && Boolean(errors.config) ? errors.config : "Can the user create collections"}
|
317
|
+
</FieldCaption>
|
318
|
+
</div>
|
319
|
+
|
320
|
+
<div className={"col-span-12 md:col-span-4"}>
|
321
|
+
<Select
|
322
|
+
error={touched.config && Boolean(errors.config)}
|
323
|
+
id="editCollections"
|
324
|
+
name="editCollections"
|
325
|
+
label="Edit collections"
|
326
|
+
disabled={isAdmin || !editable}
|
327
|
+
position={"item-aligned"}
|
328
|
+
onChange={(event) => setFieldValue("config.editCollections", event.target.value === "own" ? "own" : event.target.value === "true")}
|
329
|
+
value={isAdmin ? "true" : (values.config?.editCollections === "own" ? "own" : (values.config?.editCollections ? "true" : "false"))}
|
330
|
+
renderValue={(value: any) => value === "own" ? "Own" : (value === "true" ? "Yes" : "No")}
|
331
|
+
>
|
332
|
+
<SelectItem
|
333
|
+
value={"true"}> Yes </SelectItem>
|
334
|
+
<SelectItem
|
335
|
+
value={"false"}> No </SelectItem>
|
336
|
+
<SelectItem
|
337
|
+
value={"own"}> Only
|
338
|
+
his/her own </SelectItem>
|
339
|
+
</Select>
|
340
|
+
|
341
|
+
<FieldCaption>
|
342
|
+
{touched.config && Boolean(errors.config) ? errors.config : "Can the user edit collections"}
|
343
|
+
</FieldCaption>
|
344
|
+
</div>
|
345
|
+
|
346
|
+
<div className={"col-span-12 md:col-span-4"}>
|
347
|
+
<Select
|
348
|
+
error={touched.config && Boolean(errors.config)}
|
349
|
+
id="deleteCollections"
|
350
|
+
name="deleteCollections"
|
351
|
+
label="Delete collections"
|
352
|
+
disabled={isAdmin || !editable}
|
353
|
+
position={"item-aligned"}
|
354
|
+
onChange={(event) => setFieldValue("config.deleteCollections", event.target.value === "own" ? "own" : event.target.value === "true")}
|
355
|
+
value={isAdmin ? "true" : (values.config?.deleteCollections === "own" ? "own" : (values.config?.deleteCollections ? "true" : "false"))}
|
356
|
+
renderValue={(value: any) => value === "own" ? "Own" : (value === "true" ? "Yes" : "No")}
|
357
|
+
>
|
358
|
+
<SelectItem
|
359
|
+
value={"true"}> Yes </SelectItem>
|
360
|
+
<SelectItem
|
361
|
+
value={"false"}> No </SelectItem>
|
362
|
+
<SelectItem
|
363
|
+
value={"own"}> Only
|
364
|
+
his/her own </SelectItem>
|
365
|
+
</Select>
|
366
|
+
|
367
|
+
<FieldCaption>
|
368
|
+
{touched.config && Boolean(errors.config) ? errors.config : "Can the user delete collections"}
|
369
|
+
</FieldCaption>
|
370
|
+
|
371
|
+
</div>
|
372
|
+
|
373
|
+
</div>
|
374
|
+
</DialogContent>
|
375
|
+
|
376
|
+
<DialogActions position={"sticky"}>
|
377
|
+
{savingError && <Typography className={"text-red-500"}>
|
378
|
+
There was an error saving this role
|
379
|
+
</Typography>}
|
380
|
+
<Button variant={"text"}
|
381
|
+
onClick={() => {
|
382
|
+
handleClose();
|
383
|
+
}}>
|
384
|
+
Cancel
|
385
|
+
</Button>
|
386
|
+
<LoadingButton
|
387
|
+
variant="filled"
|
388
|
+
color="primary"
|
389
|
+
type="submit"
|
390
|
+
disabled={!dirty}
|
391
|
+
loading={isSubmitting}
|
392
|
+
startIcon={<DoneIcon/>}
|
393
|
+
>
|
394
|
+
{isNewRole ? "Create role" : "Update"}
|
395
|
+
</LoadingButton>
|
396
|
+
</DialogActions>
|
397
|
+
</form>
|
398
|
+
|
399
|
+
</Formex>
|
400
|
+
</Dialog>
|
401
|
+
);
|
402
|
+
}
|