@firecms/user_management 3.0.0-canary.15 → 3.0.0-canary.151
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 +114 -21
- package/README.md +2 -2
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/useBuildUserManagement.d.ts +51 -0
- package/dist/index.es.js +1183 -818
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +1651 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/types/user_management.d.ts +10 -3
- package/dist/useUserManagementPlugin.d.ts +8 -3
- package/dist/utils/permissions.d.ts +2 -2
- package/package.json +12 -28
- package/src/components/roles/RolesDetailsForm.tsx +70 -24
- package/src/components/roles/RolesTable.tsx +6 -4
- package/src/components/roles/RolesView.tsx +3 -1
- package/src/components/users/UserDetailsForm.tsx +11 -9
- package/src/components/users/UsersTable.tsx +6 -6
- package/src/hooks/index.ts +1 -1
- package/src/hooks/useBuildUserManagement.tsx +360 -0
- package/src/types/user_management.tsx +13 -3
- package/src/useUserManagementPlugin.tsx +89 -3
- package/src/utils/permissions.ts +9 -8
- package/dist/hooks/useBuildFirestoreUserManagement.d.ts +0 -42
- package/src/hooks/useBuildFirestoreUserManagement.tsx +0 -240
package/dist/index.es.js
CHANGED
@@ -1,315 +1,494 @@
|
|
1
|
-
import
|
2
|
-
import
|
3
|
-
import {
|
4
|
-
import {
|
5
|
-
import
|
6
|
-
import
|
7
|
-
import { useCreateFormex
|
8
|
-
import { format
|
9
|
-
import * as
|
10
|
-
const
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
1
|
+
import React, { useEffect, useCallback, useContext, useState } from "react";
|
2
|
+
import equal from "react-fast-compare";
|
3
|
+
import { removeUndefined, useAuthController, toSnakeCase, FieldCaption, ConfirmationDialog, useNavigationController, useSnackbarController, useCustomizationController, defaultDateFormat } from "@firecms/core";
|
4
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
5
|
+
import { getColorSchemeForSeed, Chip, Dialog, DialogContent, Typography, TextField, Paper, Table, TableHeader, TableCell, TableBody, TableRow, Tooltip, Checkbox, Button, Select, SelectItem, DialogActions, LoadingButton, DoneIcon, IconButton, DeleteIcon, CenteredView, Container, AddIcon, MultiSelect, MultiSelectItem } from "@firecms/ui";
|
6
|
+
import * as Yup from "yup";
|
7
|
+
import { useCreateFormex, getIn, Formex } from "@firecms/formex";
|
8
|
+
import { format } from "date-fns";
|
9
|
+
import * as locales from "date-fns/locale";
|
10
|
+
const RESERVED_GROUPS = ["Admin"];
|
11
|
+
const DEFAULT_PERMISSIONS = {
|
12
|
+
read: false,
|
13
|
+
edit: false,
|
14
|
+
create: false,
|
15
|
+
delete: false
|
15
16
|
};
|
16
|
-
function
|
17
|
-
collection
|
18
|
-
user
|
17
|
+
function resolveUserRolePermissions({
|
18
|
+
collection,
|
19
|
+
user
|
19
20
|
}) {
|
20
|
-
const
|
21
|
-
if (
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
}
|
39
|
-
return Me;
|
21
|
+
const roles = user?.roles;
|
22
|
+
if (!roles) {
|
23
|
+
return DEFAULT_PERMISSIONS;
|
24
|
+
} else if (collection.ownerId === user?.uid) {
|
25
|
+
return {
|
26
|
+
read: true,
|
27
|
+
create: true,
|
28
|
+
edit: true,
|
29
|
+
delete: true
|
30
|
+
};
|
31
|
+
} else {
|
32
|
+
const basePermissions = {
|
33
|
+
read: false,
|
34
|
+
create: false,
|
35
|
+
edit: false,
|
36
|
+
delete: false
|
37
|
+
};
|
38
|
+
return roles.map((role) => resolveCollectionRole(role, collection.id)).reduce(mergePermissions, basePermissions);
|
39
|
+
}
|
40
40
|
}
|
41
|
-
function
|
42
|
-
const
|
43
|
-
read:
|
44
|
-
create:
|
45
|
-
edit:
|
46
|
-
delete:
|
41
|
+
function resolveCollectionRole(role, id) {
|
42
|
+
const basePermissions = {
|
43
|
+
read: (role.isAdmin || role.defaultPermissions?.read) ?? false,
|
44
|
+
create: (role.isAdmin || role.defaultPermissions?.create) ?? false,
|
45
|
+
edit: (role.isAdmin || role.defaultPermissions?.edit) ?? false,
|
46
|
+
delete: (role.isAdmin || role.defaultPermissions?.delete) ?? false
|
47
47
|
};
|
48
|
-
|
48
|
+
const thisCollectionPermissions = role.collectionPermissions?.[id];
|
49
|
+
if (thisCollectionPermissions) {
|
50
|
+
return mergePermissions(thisCollectionPermissions, basePermissions);
|
51
|
+
} else if (role.defaultPermissions) {
|
52
|
+
return mergePermissions(role.defaultPermissions, basePermissions);
|
53
|
+
} else {
|
54
|
+
return basePermissions;
|
55
|
+
}
|
49
56
|
}
|
50
|
-
const
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
57
|
+
const mergePermissions = (permA, permB) => {
|
58
|
+
return {
|
59
|
+
read: permA.read || permB.read,
|
60
|
+
create: permA.create || permB.create,
|
61
|
+
edit: permA.edit || permB.edit,
|
62
|
+
delete: permA.delete || permB.delete
|
63
|
+
};
|
64
|
+
};
|
65
|
+
function getUserRoles(roles, fireCMSUser) {
|
66
|
+
return !roles ? void 0 : fireCMSUser.roles ? fireCMSUser.roles.map((role) => roles.find((r) => r.id === role.id)).filter(Boolean) : [];
|
58
67
|
}
|
59
|
-
const
|
60
|
-
const
|
61
|
-
|
68
|
+
const areRolesEqual = (rolesA, rolesB) => {
|
69
|
+
const rolesAIds = rolesA.map((r) => r.id);
|
70
|
+
const rolesBIds = rolesB.map((r) => r.id);
|
71
|
+
return rolesAIds.length === rolesB.length && rolesAIds.every((role) => rolesBIds.includes(role));
|
62
72
|
};
|
63
|
-
function
|
64
|
-
if (!
|
73
|
+
function cacheDelegatedLoginToken(projectId, delegatedToken) {
|
74
|
+
if (!delegatedToken) {
|
65
75
|
return;
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
76
|
+
}
|
77
|
+
const data = parseJwt(delegatedToken);
|
78
|
+
const expiry = new Date(data.exp * 1e3);
|
79
|
+
localStorage.setItem(`auth_token::${projectId}`, JSON.stringify({
|
80
|
+
token: delegatedToken,
|
81
|
+
expiry
|
70
82
|
}));
|
71
83
|
}
|
72
|
-
function
|
73
|
-
const
|
74
|
-
if (
|
75
|
-
const
|
76
|
-
|
77
|
-
|
84
|
+
function getDelegatedLoginTokenFromCache(projectId) {
|
85
|
+
const entry = localStorage.getItem(`auth_token::${projectId}`);
|
86
|
+
if (entry) {
|
87
|
+
const data = JSON.parse(entry);
|
88
|
+
data.expiry = new Date(data.expiry);
|
89
|
+
if (data.expiry > /* @__PURE__ */ new Date()) {
|
90
|
+
return data.token;
|
91
|
+
}
|
78
92
|
}
|
93
|
+
return void 0;
|
79
94
|
}
|
80
|
-
function
|
81
|
-
for (let
|
82
|
-
const
|
83
|
-
|
95
|
+
function clearDelegatedLoginTokensCache() {
|
96
|
+
for (let i = 0; i < localStorage.length; i++) {
|
97
|
+
const key = localStorage.key(i);
|
98
|
+
if (key?.startsWith("auth_token::")) {
|
99
|
+
localStorage.removeItem(key);
|
100
|
+
}
|
84
101
|
}
|
85
102
|
}
|
86
|
-
function
|
87
|
-
if (!
|
103
|
+
function parseJwt(token) {
|
104
|
+
if (!token) {
|
88
105
|
throw new Error("No JWT token");
|
89
|
-
|
90
|
-
|
106
|
+
}
|
107
|
+
const base64Url = token.split(".")[1];
|
108
|
+
const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
|
109
|
+
const jsonPayload = decodeURIComponent(window.atob(base64).split("").map(function(c) {
|
110
|
+
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
|
91
111
|
}).join(""));
|
92
|
-
return JSON.parse(
|
112
|
+
return JSON.parse(jsonPayload);
|
93
113
|
}
|
94
|
-
function
|
95
|
-
if (!/^#([0-9A-Fa-f]{3}){1,2}$/.test(
|
114
|
+
function darkenColor(hexColor, darkenBy = 10) {
|
115
|
+
if (!/^#([0-9A-Fa-f]{3}){1,2}$/.test(hexColor)) {
|
96
116
|
throw new Error("Invalid color format");
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
117
|
+
}
|
118
|
+
let color = hexColor.substring(1).split("");
|
119
|
+
if (color.length === 3) {
|
120
|
+
color = [color[0], color[0], color[1], color[1], color[2], color[2]];
|
121
|
+
}
|
122
|
+
let r = parseInt(color[0] + color[1], 16);
|
123
|
+
let g = parseInt(color[2] + color[3], 16);
|
124
|
+
let b = parseInt(color[4] + color[5], 16);
|
125
|
+
r = Math.floor(r * (1 - darkenBy / 100));
|
126
|
+
g = Math.floor(g * (1 - darkenBy / 100));
|
127
|
+
b = Math.floor(b * (1 - darkenBy / 100));
|
128
|
+
return "#" + (r < 16 ? "0" : "") + r.toString(16) + (g < 16 ? "0" : "") + g.toString(16) + (b < 16 ? "0" : "") + b.toString(16);
|
101
129
|
}
|
102
|
-
function
|
103
|
-
if (!/^#([0-9A-Fa-f]{3}){1,2}$/.test(
|
130
|
+
function hexToRgbaWithOpacity(hexColor, opacity = 10) {
|
131
|
+
if (!/^#([0-9A-Fa-f]{3}){1,2}$/.test(hexColor)) {
|
104
132
|
throw new Error("Invalid color format");
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
133
|
+
}
|
134
|
+
let color = hexColor.substring(1).split("");
|
135
|
+
if (color.length === 3) {
|
136
|
+
color = [color[0], color[0], color[1], color[1], color[2], color[2]];
|
137
|
+
}
|
138
|
+
const r = parseInt(color[0] + color[1], 16);
|
139
|
+
const g = parseInt(color[2] + color[3], 16);
|
140
|
+
const b = parseInt(color[4] + color[5], 16);
|
141
|
+
const alpha = opacity / 100;
|
142
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
109
143
|
}
|
110
|
-
function
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
144
|
+
function useBuildUserManagement({
|
145
|
+
authController,
|
146
|
+
dataSourceDelegate,
|
147
|
+
usersPath = "__FIRECMS/config/users",
|
148
|
+
rolesPath = "__FIRECMS/config/roles",
|
149
|
+
usersLimit,
|
150
|
+
canEditRoles = true,
|
151
|
+
allowDefaultRolesCreation,
|
152
|
+
includeCollectionConfigPermissions
|
118
153
|
}) {
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
154
|
+
if (!authController) {
|
155
|
+
throw Error("useBuildUserManagement: You need to provide an authController since version 3.0.0-beta.11. Check https://firecms.co/docs/pro/migrating_from_v3_beta");
|
156
|
+
}
|
157
|
+
const [rolesLoading, setRolesLoading] = React.useState(true);
|
158
|
+
const [usersLoading, setUsersLoading] = React.useState(true);
|
159
|
+
const [roles, setRoles] = React.useState([]);
|
160
|
+
const [usersWithRoleIds, setUsersWithRoleIds] = React.useState([]);
|
161
|
+
const users = usersWithRoleIds.map((u) => ({
|
162
|
+
...u,
|
163
|
+
roles: roles.filter((r) => u.roles?.includes(r.id))
|
164
|
+
}));
|
165
|
+
const [rolesError, setRolesError] = React.useState();
|
166
|
+
const [usersError, setUsersError] = React.useState();
|
167
|
+
const _usersLoading = usersLoading;
|
168
|
+
const _rolesLoading = rolesLoading;
|
169
|
+
const loading = _rolesLoading || _usersLoading;
|
170
|
+
useEffect(() => {
|
171
|
+
if (!dataSourceDelegate || !rolesPath) return;
|
172
|
+
if (dataSourceDelegate.initialised !== void 0 && !dataSourceDelegate.initialised) return;
|
173
|
+
if (authController?.initialLoading) return;
|
174
|
+
setRolesLoading(true);
|
175
|
+
return dataSourceDelegate.listenCollection?.({
|
176
|
+
path: rolesPath,
|
177
|
+
onUpdate(entities) {
|
178
|
+
setRolesError(void 0);
|
179
|
+
try {
|
180
|
+
const newRoles = entityToRoles(entities);
|
181
|
+
if (!equal(newRoles, roles)) {
|
182
|
+
setRoles(newRoles);
|
139
183
|
}
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
184
|
+
} catch (e) {
|
185
|
+
setRoles([]);
|
186
|
+
console.error("Error loading roles", e);
|
187
|
+
setRolesError(e);
|
144
188
|
}
|
189
|
+
setRolesLoading(false);
|
190
|
+
},
|
191
|
+
onError(e) {
|
192
|
+
setRoles([]);
|
193
|
+
console.error("Error loading roles", e);
|
194
|
+
setRolesError(e);
|
195
|
+
setRolesLoading(false);
|
145
196
|
}
|
146
|
-
);
|
147
|
-
}, [
|
148
|
-
|
197
|
+
});
|
198
|
+
}, [dataSourceDelegate?.initialised, authController?.initialLoading, authController?.user?.uid, rolesPath]);
|
199
|
+
useEffect(() => {
|
200
|
+
if (!dataSourceDelegate || !usersPath) return;
|
201
|
+
if (dataSourceDelegate.initialised !== void 0 && !dataSourceDelegate.initialised) {
|
149
202
|
return;
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
}
|
164
|
-
|
165
|
-
|
203
|
+
}
|
204
|
+
if (authController?.initialLoading) {
|
205
|
+
return;
|
206
|
+
}
|
207
|
+
setUsersLoading(true);
|
208
|
+
return dataSourceDelegate.listenCollection?.({
|
209
|
+
path: usersPath,
|
210
|
+
onUpdate(entities) {
|
211
|
+
console.debug("Updating users", entities);
|
212
|
+
setUsersError(void 0);
|
213
|
+
try {
|
214
|
+
const newUsers = entitiesToUsers(entities);
|
215
|
+
setUsersWithRoleIds(newUsers);
|
216
|
+
} catch (e) {
|
217
|
+
setUsersWithRoleIds([]);
|
218
|
+
console.error("Error loading users", e);
|
219
|
+
setUsersError(e);
|
166
220
|
}
|
221
|
+
setUsersLoading(false);
|
222
|
+
},
|
223
|
+
onError(e) {
|
224
|
+
console.error("Error loading users", e);
|
225
|
+
setUsersWithRoleIds([]);
|
226
|
+
setUsersError(e);
|
227
|
+
setUsersLoading(false);
|
167
228
|
}
|
168
|
-
);
|
169
|
-
}, [
|
170
|
-
const
|
171
|
-
|
172
|
-
if (!
|
173
|
-
|
174
|
-
|
175
|
-
const
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
229
|
+
});
|
230
|
+
}, [dataSourceDelegate?.initialised, authController?.initialLoading, authController?.user?.uid, usersPath]);
|
231
|
+
const saveUser = useCallback(async (user) => {
|
232
|
+
if (!dataSourceDelegate) throw Error("useBuildUserManagement Firebase not initialised");
|
233
|
+
if (!usersPath) throw Error("useBuildUserManagement Firestore not initialised");
|
234
|
+
console.debug("Persisting user", user);
|
235
|
+
const roleIds = user.roles?.map((r) => r.id);
|
236
|
+
const email = user.email?.toLowerCase().trim();
|
237
|
+
if (!email) throw Error("Email is required");
|
238
|
+
const userExists = users.find((u) => u.email?.toLowerCase() === email);
|
239
|
+
const data = {
|
240
|
+
...user,
|
241
|
+
roles: roleIds ?? []
|
242
|
+
};
|
243
|
+
if (!userExists) {
|
244
|
+
data.created_on = /* @__PURE__ */ new Date();
|
245
|
+
}
|
246
|
+
return dataSourceDelegate.saveEntity({
|
247
|
+
status: "existing",
|
248
|
+
path: usersPath,
|
249
|
+
entityId: email,
|
250
|
+
values: removeUndefined(data)
|
251
|
+
}).then(() => user);
|
252
|
+
}, [usersPath, dataSourceDelegate?.initialised]);
|
253
|
+
const saveRole = useCallback((role) => {
|
254
|
+
if (!dataSourceDelegate) throw Error("useBuildUserManagement Firebase not initialised");
|
255
|
+
if (!rolesPath) throw Error("useBuildUserManagement Firestore not initialised");
|
256
|
+
console.debug("Persisting role", role);
|
188
257
|
const {
|
189
|
-
id
|
190
|
-
...
|
191
|
-
} =
|
192
|
-
return
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
}, [
|
201
|
-
|
202
|
-
if (!
|
203
|
-
|
204
|
-
console.debug("Deleting",
|
205
|
-
const {
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
if (!
|
215
|
-
|
216
|
-
|
217
|
-
|
258
|
+
id,
|
259
|
+
...roleData
|
260
|
+
} = role;
|
261
|
+
return dataSourceDelegate.saveEntity({
|
262
|
+
status: "existing",
|
263
|
+
path: rolesPath,
|
264
|
+
entityId: id,
|
265
|
+
values: removeUndefined(roleData)
|
266
|
+
}).then(() => {
|
267
|
+
return;
|
268
|
+
});
|
269
|
+
}, [rolesPath, dataSourceDelegate?.initialised]);
|
270
|
+
const deleteUser = useCallback(async (user) => {
|
271
|
+
if (!dataSourceDelegate) throw Error("useBuildUserManagement Firebase not initialised");
|
272
|
+
if (!usersPath) throw Error("useBuildUserManagement Firestore not initialised");
|
273
|
+
console.debug("Deleting", user);
|
274
|
+
const { uid } = user;
|
275
|
+
const entity = {
|
276
|
+
path: usersPath,
|
277
|
+
id: uid,
|
278
|
+
values: {}
|
279
|
+
};
|
280
|
+
await dataSourceDelegate.deleteEntity({ entity });
|
281
|
+
}, [usersPath, dataSourceDelegate?.initialised]);
|
282
|
+
const deleteRole = useCallback(async (role) => {
|
283
|
+
if (!dataSourceDelegate) throw Error("useBuildUserManagement Firebase not initialised");
|
284
|
+
if (!rolesPath) throw Error("useBuildUserManagement Firestore not initialised");
|
285
|
+
console.debug("Deleting", role);
|
286
|
+
const { id } = role;
|
287
|
+
const entity = {
|
288
|
+
path: rolesPath,
|
289
|
+
id,
|
290
|
+
values: {}
|
291
|
+
};
|
292
|
+
await dataSourceDelegate.deleteEntity({ entity });
|
293
|
+
}, [rolesPath, dataSourceDelegate?.initialised]);
|
294
|
+
const collectionPermissions = useCallback(({
|
295
|
+
collection,
|
296
|
+
user
|
297
|
+
}) => resolveUserRolePermissions({
|
298
|
+
collection,
|
299
|
+
user
|
300
|
+
}), []);
|
301
|
+
const defineRolesFor = useCallback((user) => {
|
302
|
+
if (!usersWithRoleIds) throw Error("Users not loaded");
|
303
|
+
const users2 = usersWithRoleIds.map((u) => ({
|
304
|
+
...u,
|
305
|
+
roles: roles.filter((r) => u.roles?.includes(r.id))
|
306
|
+
}));
|
307
|
+
const mgmtUser = users2.find((u) => u.email?.toLowerCase() === user?.email?.toLowerCase());
|
308
|
+
return mgmtUser?.roles;
|
309
|
+
}, [roles, usersWithRoleIds]);
|
310
|
+
const authenticator = useCallback(({ user }) => {
|
311
|
+
if (loading) {
|
312
|
+
return false;
|
313
|
+
}
|
314
|
+
if (users.length === 0) {
|
315
|
+
console.warn("No users created yet");
|
316
|
+
return true;
|
317
|
+
}
|
318
|
+
const mgmtUser = users.find((u) => u.email?.toLowerCase() === user?.email?.toLowerCase());
|
319
|
+
if (mgmtUser) {
|
320
|
+
console.debug("User found in user management system", mgmtUser);
|
321
|
+
return true;
|
322
|
+
}
|
323
|
+
throw Error("Could not find a user with the provided email in the user management system.");
|
324
|
+
}, [loading, users]);
|
325
|
+
const userRoles = authController.user ? defineRolesFor(authController.user) : void 0;
|
326
|
+
const isAdmin = (userRoles ?? []).some((r) => r.id === "admin");
|
218
327
|
return {
|
219
|
-
loading
|
220
|
-
roles
|
221
|
-
users
|
222
|
-
saveUser
|
223
|
-
saveRole
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
328
|
+
loading,
|
329
|
+
roles,
|
330
|
+
users,
|
331
|
+
saveUser,
|
332
|
+
saveRole,
|
333
|
+
rolesError,
|
334
|
+
deleteUser,
|
335
|
+
deleteRole,
|
336
|
+
usersLimit,
|
337
|
+
usersError,
|
338
|
+
isAdmin,
|
339
|
+
canEditRoles: canEditRoles === void 0 ? true : canEditRoles,
|
340
|
+
allowDefaultRolesCreation: allowDefaultRolesCreation === void 0 ? true : allowDefaultRolesCreation,
|
341
|
+
includeCollectionConfigPermissions: Boolean(includeCollectionConfigPermissions),
|
342
|
+
collectionPermissions,
|
343
|
+
defineRolesFor,
|
344
|
+
authenticator,
|
345
|
+
...authController,
|
346
|
+
initialLoading: authController.initialLoading || loading,
|
347
|
+
userRoles,
|
348
|
+
user: authController.user ? {
|
349
|
+
...authController.user,
|
350
|
+
roles: userRoles
|
351
|
+
} : null
|
232
352
|
};
|
233
353
|
}
|
234
|
-
const
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
}
|
243
|
-
|
244
|
-
|
245
|
-
}
|
246
|
-
|
247
|
-
|
248
|
-
|
354
|
+
const entitiesToUsers = (docs) => {
|
355
|
+
return docs.map((doc) => {
|
356
|
+
const data = doc.values;
|
357
|
+
const newVar = {
|
358
|
+
uid: doc.id,
|
359
|
+
...data,
|
360
|
+
created_on: data?.created_on,
|
361
|
+
updated_on: data?.updated_on
|
362
|
+
};
|
363
|
+
return newVar;
|
364
|
+
});
|
365
|
+
};
|
366
|
+
const entityToRoles = (entities) => {
|
367
|
+
return entities.map((doc) => ({
|
368
|
+
id: doc.id,
|
369
|
+
...doc.values
|
370
|
+
}));
|
371
|
+
};
|
372
|
+
const UserManagementContext = React.createContext({});
|
373
|
+
function UserManagementProvider({
|
374
|
+
children,
|
375
|
+
userManagement
|
249
376
|
}) {
|
250
|
-
return /* @__PURE__ */
|
377
|
+
return /* @__PURE__ */ jsx(UserManagementContext.Provider, { value: userManagement, children });
|
251
378
|
}
|
252
|
-
const
|
253
|
-
function
|
254
|
-
let
|
255
|
-
|
256
|
-
|
379
|
+
const useUserManagement = () => useContext(UserManagementContext);
|
380
|
+
function RoleChip({ role }) {
|
381
|
+
let colorScheme;
|
382
|
+
if (role.isAdmin) {
|
383
|
+
colorScheme = "blueDarker";
|
384
|
+
} else if (role.id === "editor") {
|
385
|
+
colorScheme = "yellowLight";
|
386
|
+
} else if (role.id === "viewer") {
|
387
|
+
colorScheme = "grayLight";
|
388
|
+
} else {
|
389
|
+
colorScheme = getColorSchemeForSeed(role.id);
|
390
|
+
}
|
391
|
+
return /* @__PURE__ */ jsx(
|
392
|
+
Chip,
|
257
393
|
{
|
258
|
-
colorScheme
|
259
|
-
children:
|
394
|
+
colorScheme,
|
395
|
+
children: role.name
|
260
396
|
},
|
261
|
-
|
397
|
+
role.id
|
262
398
|
);
|
263
399
|
}
|
264
|
-
const
|
265
|
-
id:
|
266
|
-
name:
|
400
|
+
const RoleYupSchema = Yup.object().shape({
|
401
|
+
id: Yup.string().required("Required"),
|
402
|
+
name: Yup.string().required("Required")
|
267
403
|
});
|
268
|
-
function
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
404
|
+
function canRoleBeEdited(loggedUser) {
|
405
|
+
const loggedUserIsAdmin = loggedUser.roles?.map((r) => r.id).includes("admin");
|
406
|
+
console.log("loggedUserIsAdmin", loggedUser);
|
407
|
+
if (!loggedUserIsAdmin) {
|
408
|
+
throw new Error("Only admins can edit roles");
|
409
|
+
}
|
410
|
+
return true;
|
411
|
+
}
|
412
|
+
function RolesDetailsForm({
|
413
|
+
open,
|
414
|
+
role,
|
415
|
+
editable,
|
416
|
+
handleClose,
|
417
|
+
collections
|
274
418
|
}) {
|
275
|
-
const { saveRole
|
276
|
-
|
419
|
+
const { saveRole } = useUserManagement();
|
420
|
+
const isNewRole = !role;
|
421
|
+
const {
|
422
|
+
user: loggedInUser
|
423
|
+
} = useAuthController();
|
424
|
+
const [savingError, setSavingError] = useState();
|
425
|
+
const onRoleUpdated = useCallback((role2) => {
|
426
|
+
setSavingError(void 0);
|
427
|
+
if (!loggedInUser) throw new Error("User not found");
|
428
|
+
canRoleBeEdited(loggedInUser);
|
429
|
+
return saveRole(role2);
|
430
|
+
}, [saveRole, loggedInUser]);
|
431
|
+
const formex = useCreateFormex({
|
432
|
+
initialValues: role ?? {
|
277
433
|
name: ""
|
278
434
|
},
|
279
|
-
onSubmit: (
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
435
|
+
onSubmit: (role2, formexController) => {
|
436
|
+
try {
|
437
|
+
return onRoleUpdated(role2).then(() => {
|
438
|
+
formexController.resetForm({
|
439
|
+
values: role2
|
440
|
+
});
|
441
|
+
handleClose();
|
442
|
+
}).catch((e) => {
|
443
|
+
setSavingError(e);
|
444
|
+
});
|
445
|
+
} catch (e) {
|
446
|
+
setSavingError(e);
|
447
|
+
return Promise.resolve();
|
448
|
+
}
|
449
|
+
},
|
450
|
+
validation: (values2) => {
|
451
|
+
return RoleYupSchema.validate(values2, { abortEarly: false }).then(() => ({})).catch((e) => {
|
452
|
+
const errors2 = {};
|
453
|
+
e.inner.forEach((error) => {
|
454
|
+
errors2[error.path] = error.message;
|
455
|
+
});
|
456
|
+
return errors2;
|
457
|
+
});
|
458
|
+
}
|
459
|
+
});
|
460
|
+
const {
|
461
|
+
isSubmitting,
|
462
|
+
touched,
|
463
|
+
values,
|
464
|
+
errors,
|
465
|
+
handleChange,
|
466
|
+
setFieldValue,
|
467
|
+
dirty,
|
468
|
+
setFieldTouched
|
469
|
+
} = formex;
|
470
|
+
const isAdmin = values.isAdmin ?? false;
|
471
|
+
const defaultCreate = values.defaultPermissions?.create ?? false;
|
472
|
+
const defaultRead = values.defaultPermissions?.read ?? false;
|
473
|
+
const defaultEdit = values.defaultPermissions?.edit ?? false;
|
474
|
+
const defaultDelete = values.defaultPermissions?.delete ?? false;
|
475
|
+
React.useEffect(() => {
|
476
|
+
const idTouched = getIn(touched, "id");
|
477
|
+
if (!idTouched && values.name) {
|
478
|
+
setFieldValue("id", toSnakeCase(values.name));
|
479
|
+
}
|
480
|
+
}, [touched, values.name]);
|
481
|
+
return /* @__PURE__ */ jsx(
|
482
|
+
Dialog,
|
304
483
|
{
|
305
|
-
open
|
484
|
+
open,
|
306
485
|
maxWidth: "4xl",
|
307
|
-
children: /* @__PURE__ */
|
486
|
+
children: /* @__PURE__ */ jsx(Formex, { value: formex, children: /* @__PURE__ */ jsxs(
|
308
487
|
"form",
|
309
488
|
{
|
310
|
-
noValidate:
|
489
|
+
noValidate: true,
|
311
490
|
autoComplete: "off",
|
312
|
-
onSubmit:
|
491
|
+
onSubmit: formex.handleSubmit,
|
313
492
|
style: {
|
314
493
|
display: "flex",
|
315
494
|
flexDirection: "column",
|
@@ -317,13 +496,13 @@ function Ke({
|
|
317
496
|
height: "100%"
|
318
497
|
},
|
319
498
|
children: [
|
320
|
-
/* @__PURE__ */
|
321
|
-
/* @__PURE__ */
|
499
|
+
/* @__PURE__ */ jsxs(DialogContent, { className: "flex-grow", children: [
|
500
|
+
/* @__PURE__ */ jsx(
|
322
501
|
"div",
|
323
502
|
{
|
324
503
|
className: "flex flex-row pt-12 pb-8",
|
325
|
-
children: /* @__PURE__ */
|
326
|
-
|
504
|
+
children: /* @__PURE__ */ jsx(
|
505
|
+
Typography,
|
327
506
|
{
|
328
507
|
variant: "h4",
|
329
508
|
className: "flex-grow",
|
@@ -332,262 +511,296 @@ function Ke({
|
|
332
511
|
)
|
333
512
|
}
|
334
513
|
),
|
335
|
-
/* @__PURE__ */
|
336
|
-
/* @__PURE__ */
|
337
|
-
/* @__PURE__ */
|
338
|
-
|
514
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-12 gap-8", children: [
|
515
|
+
/* @__PURE__ */ jsxs("div", { className: "col-span-12 md:col-span-8", children: [
|
516
|
+
/* @__PURE__ */ jsx(
|
517
|
+
TextField,
|
339
518
|
{
|
340
519
|
name: "name",
|
341
|
-
required:
|
342
|
-
error:
|
343
|
-
value:
|
344
|
-
disabled:
|
345
|
-
onChange:
|
520
|
+
required: true,
|
521
|
+
error: touched.name && Boolean(errors.name),
|
522
|
+
value: values.name,
|
523
|
+
disabled: isAdmin || !editable,
|
524
|
+
onChange: handleChange,
|
346
525
|
"aria-describedby": "name-helper-text",
|
347
526
|
label: "Name"
|
348
527
|
}
|
349
528
|
),
|
350
|
-
/* @__PURE__ */
|
529
|
+
/* @__PURE__ */ jsx(FieldCaption, { children: touched.name && Boolean(errors.name) ? errors.name : "Name of this role" })
|
351
530
|
] }),
|
352
|
-
/* @__PURE__ */
|
353
|
-
/* @__PURE__ */
|
354
|
-
|
531
|
+
/* @__PURE__ */ jsxs("div", { className: "col-span-12 md:col-span-4", children: [
|
532
|
+
/* @__PURE__ */ jsx(
|
533
|
+
TextField,
|
355
534
|
{
|
356
535
|
name: "id",
|
357
|
-
required:
|
358
|
-
error:
|
359
|
-
value:
|
360
|
-
disabled: !
|
361
|
-
onChange: (
|
362
|
-
|
536
|
+
required: true,
|
537
|
+
error: touched.id && Boolean(errors.id),
|
538
|
+
value: values.id,
|
539
|
+
disabled: !isNewRole || !editable,
|
540
|
+
onChange: (e) => {
|
541
|
+
handleChange(e);
|
542
|
+
setFieldTouched("id", true);
|
363
543
|
},
|
364
544
|
"aria-describedby": "id-helper-text",
|
365
545
|
label: "ID"
|
366
546
|
}
|
367
547
|
),
|
368
|
-
/* @__PURE__ */
|
548
|
+
/* @__PURE__ */ jsx(FieldCaption, { children: touched.id && Boolean(errors.id) ? errors.id : "ID of this role" })
|
369
549
|
] }),
|
370
|
-
/* @__PURE__ */
|
371
|
-
/* @__PURE__ */
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
)
|
416
|
-
|
417
|
-
|
550
|
+
/* @__PURE__ */ jsxs("div", { className: "col-span-12", children: [
|
551
|
+
/* @__PURE__ */ jsx(Paper, { className: "bg-inherit overflow-hidden", children: /* @__PURE__ */ jsxs(Table, { className: "w-full rounded-md", children: [
|
552
|
+
/* @__PURE__ */ jsxs(TableHeader, { className: "rounded-md", children: [
|
553
|
+
/* @__PURE__ */ jsx(TableCell, {}),
|
554
|
+
/* @__PURE__ */ jsx(
|
555
|
+
TableCell,
|
556
|
+
{
|
557
|
+
align: "center",
|
558
|
+
children: "Create entities"
|
559
|
+
}
|
560
|
+
),
|
561
|
+
/* @__PURE__ */ jsx(
|
562
|
+
TableCell,
|
563
|
+
{
|
564
|
+
align: "center",
|
565
|
+
children: "Read entities"
|
566
|
+
}
|
567
|
+
),
|
568
|
+
/* @__PURE__ */ jsx(
|
569
|
+
TableCell,
|
570
|
+
{
|
571
|
+
align: "center",
|
572
|
+
children: "Update entities"
|
573
|
+
}
|
574
|
+
),
|
575
|
+
/* @__PURE__ */ jsx(
|
576
|
+
TableCell,
|
577
|
+
{
|
578
|
+
align: "center",
|
579
|
+
children: "Delete entities"
|
580
|
+
}
|
581
|
+
),
|
582
|
+
/* @__PURE__ */ jsx(
|
583
|
+
TableCell,
|
584
|
+
{
|
585
|
+
align: "center"
|
586
|
+
}
|
587
|
+
)
|
588
|
+
] }),
|
589
|
+
/* @__PURE__ */ jsxs(TableBody, { children: [
|
590
|
+
/* @__PURE__ */ jsxs(TableRow, { children: [
|
591
|
+
/* @__PURE__ */ jsx(
|
592
|
+
TableCell,
|
593
|
+
{
|
594
|
+
scope: "row",
|
595
|
+
children: /* @__PURE__ */ jsx("strong", { children: "All collections" })
|
596
|
+
}
|
597
|
+
),
|
598
|
+
/* @__PURE__ */ jsx(
|
599
|
+
TableCell,
|
600
|
+
{
|
601
|
+
align: "center",
|
602
|
+
children: /* @__PURE__ */ jsx(
|
603
|
+
Tooltip,
|
418
604
|
{
|
419
|
-
|
420
|
-
children: /* @__PURE__ */
|
421
|
-
|
605
|
+
title: "Create entities in collections",
|
606
|
+
children: /* @__PURE__ */ jsx(
|
607
|
+
Checkbox,
|
422
608
|
{
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
{
|
427
|
-
disabled: f || !n,
|
428
|
-
checked: (f || u) ?? !1,
|
429
|
-
onCheckedChange: (o) => w("defaultPermissions.create", o)
|
430
|
-
}
|
431
|
-
)
|
609
|
+
disabled: isAdmin || !editable,
|
610
|
+
checked: (isAdmin || defaultCreate) ?? false,
|
611
|
+
onCheckedChange: (checked) => setFieldValue("defaultPermissions.create", checked)
|
432
612
|
}
|
433
613
|
)
|
434
614
|
}
|
435
|
-
)
|
436
|
-
|
437
|
-
|
615
|
+
)
|
616
|
+
}
|
617
|
+
),
|
618
|
+
/* @__PURE__ */ jsx(
|
619
|
+
TableCell,
|
620
|
+
{
|
621
|
+
align: "center",
|
622
|
+
children: /* @__PURE__ */ jsx(
|
623
|
+
Tooltip,
|
438
624
|
{
|
439
|
-
|
440
|
-
children: /* @__PURE__ */
|
441
|
-
|
625
|
+
title: "Access all data in every collection",
|
626
|
+
children: /* @__PURE__ */ jsx(
|
627
|
+
Checkbox,
|
442
628
|
{
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
{
|
447
|
-
disabled: f || !n,
|
448
|
-
checked: (f || N) ?? !1,
|
449
|
-
onCheckedChange: (o) => w("defaultPermissions.read", o)
|
450
|
-
}
|
451
|
-
)
|
629
|
+
disabled: isAdmin || !editable,
|
630
|
+
checked: (isAdmin || defaultRead) ?? false,
|
631
|
+
onCheckedChange: (checked) => setFieldValue("defaultPermissions.read", checked)
|
452
632
|
}
|
453
633
|
)
|
454
634
|
}
|
455
|
-
)
|
456
|
-
|
457
|
-
|
635
|
+
)
|
636
|
+
}
|
637
|
+
),
|
638
|
+
/* @__PURE__ */ jsx(
|
639
|
+
TableCell,
|
640
|
+
{
|
641
|
+
align: "center",
|
642
|
+
children: /* @__PURE__ */ jsx(
|
643
|
+
Tooltip,
|
458
644
|
{
|
459
|
-
|
460
|
-
children: /* @__PURE__ */
|
461
|
-
|
645
|
+
title: "Update data in any collection",
|
646
|
+
children: /* @__PURE__ */ jsx(
|
647
|
+
Checkbox,
|
462
648
|
{
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
{
|
467
|
-
disabled: f || !n,
|
468
|
-
checked: (f || U) ?? !1,
|
469
|
-
onCheckedChange: (o) => w("defaultPermissions.edit", o)
|
470
|
-
}
|
471
|
-
)
|
649
|
+
disabled: isAdmin || !editable,
|
650
|
+
checked: (isAdmin || defaultEdit) ?? false,
|
651
|
+
onCheckedChange: (checked) => setFieldValue("defaultPermissions.edit", checked)
|
472
652
|
}
|
473
653
|
)
|
474
654
|
}
|
475
|
-
)
|
476
|
-
|
477
|
-
|
655
|
+
)
|
656
|
+
}
|
657
|
+
),
|
658
|
+
/* @__PURE__ */ jsx(
|
659
|
+
TableCell,
|
660
|
+
{
|
661
|
+
align: "center",
|
662
|
+
children: /* @__PURE__ */ jsx(
|
663
|
+
Tooltip,
|
478
664
|
{
|
479
|
-
|
480
|
-
children: /* @__PURE__ */
|
481
|
-
|
665
|
+
title: "Delete data in any collection",
|
666
|
+
children: /* @__PURE__ */ jsx(
|
667
|
+
Checkbox,
|
482
668
|
{
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
{
|
487
|
-
disabled: f || !n,
|
488
|
-
checked: (f || F) ?? !1,
|
489
|
-
onCheckedChange: (o) => w("defaultPermissions.delete", o)
|
490
|
-
}
|
491
|
-
)
|
669
|
+
disabled: isAdmin || !editable,
|
670
|
+
checked: (isAdmin || defaultDelete) ?? false,
|
671
|
+
onCheckedChange: (checked) => setFieldValue("defaultPermissions.delete", checked)
|
492
672
|
}
|
493
673
|
)
|
494
674
|
}
|
495
675
|
)
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
676
|
+
}
|
677
|
+
),
|
678
|
+
/* @__PURE__ */ jsx(
|
679
|
+
TableCell,
|
680
|
+
{
|
681
|
+
align: "center"
|
682
|
+
}
|
683
|
+
)
|
684
|
+
] }),
|
685
|
+
collections && collections.map((col) => /* @__PURE__ */ jsxs(TableRow, { children: [
|
686
|
+
/* @__PURE__ */ jsx(
|
687
|
+
TableCell,
|
688
|
+
{
|
689
|
+
scope: "row",
|
690
|
+
children: col.name
|
691
|
+
}
|
692
|
+
),
|
693
|
+
/* @__PURE__ */ jsx(
|
694
|
+
TableCell,
|
695
|
+
{
|
696
|
+
align: "center",
|
697
|
+
children: /* @__PURE__ */ jsx(
|
698
|
+
Checkbox,
|
500
699
|
{
|
501
|
-
|
502
|
-
|
700
|
+
disabled: isAdmin || defaultCreate || !editable,
|
701
|
+
checked: (isAdmin || defaultCreate || getIn(values, `collectionPermissions.${col.id}.create`)) ?? false,
|
702
|
+
onCheckedChange: (checked) => setFieldValue(`collectionPermissions.${col.id}.create`, checked)
|
503
703
|
}
|
504
|
-
)
|
505
|
-
|
506
|
-
|
704
|
+
)
|
705
|
+
}
|
706
|
+
),
|
707
|
+
/* @__PURE__ */ jsx(
|
708
|
+
TableCell,
|
709
|
+
{
|
710
|
+
align: "center",
|
711
|
+
children: /* @__PURE__ */ jsx(
|
712
|
+
Checkbox,
|
507
713
|
{
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
{
|
512
|
-
disabled: f || u || !n,
|
513
|
-
checked: (f || u || j(s, `collectionPermissions.${o.path}.create`)) ?? !1,
|
514
|
-
onCheckedChange: (S) => w(`collectionPermissions.${o.path}.create`, S)
|
515
|
-
}
|
516
|
-
)
|
714
|
+
disabled: isAdmin || defaultRead || !editable,
|
715
|
+
checked: (isAdmin || defaultRead || getIn(values, `collectionPermissions.${col.id}.read`)) ?? false,
|
716
|
+
onCheckedChange: (checked) => setFieldValue(`collectionPermissions.${col.id}.read`, checked)
|
517
717
|
}
|
518
|
-
)
|
519
|
-
|
520
|
-
|
718
|
+
)
|
719
|
+
}
|
720
|
+
),
|
721
|
+
/* @__PURE__ */ jsx(
|
722
|
+
TableCell,
|
723
|
+
{
|
724
|
+
align: "center",
|
725
|
+
children: /* @__PURE__ */ jsx(
|
726
|
+
Checkbox,
|
521
727
|
{
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
{
|
526
|
-
disabled: f || N || !n,
|
527
|
-
checked: (f || N || j(s, `collectionPermissions.${o.path}.read`)) ?? !1,
|
528
|
-
onCheckedChange: (S) => w(`collectionPermissions.${o.path}.read`, S)
|
529
|
-
}
|
530
|
-
)
|
728
|
+
disabled: isAdmin || defaultEdit || !editable,
|
729
|
+
checked: (isAdmin || defaultEdit || getIn(values, `collectionPermissions.${col.id}.edit`)) ?? false,
|
730
|
+
onCheckedChange: (checked) => setFieldValue(`collectionPermissions.${col.id}.edit`, checked)
|
531
731
|
}
|
532
|
-
)
|
533
|
-
|
534
|
-
|
732
|
+
)
|
733
|
+
}
|
734
|
+
),
|
735
|
+
/* @__PURE__ */ jsx(
|
736
|
+
TableCell,
|
737
|
+
{
|
738
|
+
align: "center",
|
739
|
+
children: /* @__PURE__ */ jsx(
|
740
|
+
Checkbox,
|
535
741
|
{
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
{
|
540
|
-
disabled: f || U || !n,
|
541
|
-
checked: (f || U || j(s, `collectionPermissions.${o.path}.edit`)) ?? !1,
|
542
|
-
onCheckedChange: (S) => w(`collectionPermissions.${o.path}.edit`, S)
|
543
|
-
}
|
544
|
-
)
|
742
|
+
disabled: isAdmin || defaultDelete || !editable,
|
743
|
+
checked: (isAdmin || defaultDelete || getIn(values, `collectionPermissions.${col.id}.delete`)) ?? false,
|
744
|
+
onCheckedChange: (checked) => setFieldValue(`collectionPermissions.${col.id}.delete`, checked)
|
545
745
|
}
|
546
|
-
)
|
547
|
-
|
548
|
-
|
746
|
+
)
|
747
|
+
}
|
748
|
+
),
|
749
|
+
/* @__PURE__ */ jsx(
|
750
|
+
TableCell,
|
751
|
+
{
|
752
|
+
align: "center",
|
753
|
+
children: /* @__PURE__ */ jsx(
|
754
|
+
Tooltip,
|
549
755
|
{
|
550
|
-
|
551
|
-
children: /* @__PURE__ */
|
552
|
-
|
756
|
+
title: "Allow all permissions in this collections",
|
757
|
+
children: /* @__PURE__ */ jsx(
|
758
|
+
Button,
|
553
759
|
{
|
554
|
-
|
555
|
-
|
556
|
-
|
760
|
+
className: "color-inherit",
|
761
|
+
onClick: () => {
|
762
|
+
setFieldValue(`collectionPermissions.${col.id}.create`, true);
|
763
|
+
setFieldValue(`collectionPermissions.${col.id}.read`, true);
|
764
|
+
setFieldValue(`collectionPermissions.${col.id}.edit`, true);
|
765
|
+
setFieldValue(`collectionPermissions.${col.id}.delete`, true);
|
766
|
+
},
|
767
|
+
disabled: isAdmin || !editable,
|
768
|
+
variant: "text",
|
769
|
+
children: "All"
|
557
770
|
}
|
558
771
|
)
|
559
772
|
}
|
560
773
|
)
|
561
|
-
|
562
|
-
|
563
|
-
] })
|
564
|
-
}
|
565
|
-
),
|
566
|
-
/* @__PURE__ */
|
774
|
+
}
|
775
|
+
)
|
776
|
+
] }, col.name))
|
777
|
+
] })
|
778
|
+
] }) }),
|
779
|
+
/* @__PURE__ */ jsx(FieldCaption, { children: "You can customise the permissions that the users related to this role can perform in the entities of each collection" })
|
567
780
|
] }),
|
568
|
-
/* @__PURE__ */
|
569
|
-
/* @__PURE__ */
|
570
|
-
|
781
|
+
/* @__PURE__ */ jsxs("div", { className: "col-span-12 md:col-span-4", children: [
|
782
|
+
/* @__PURE__ */ jsxs(
|
783
|
+
Select,
|
571
784
|
{
|
572
|
-
error:
|
785
|
+
error: touched.config && Boolean(errors.config),
|
573
786
|
id: "createCollections",
|
574
787
|
name: "createCollections",
|
575
788
|
label: "Create collections",
|
576
789
|
position: "item-aligned",
|
577
|
-
disabled:
|
578
|
-
onChange: (
|
579
|
-
value:
|
580
|
-
renderValue: (
|
790
|
+
disabled: isAdmin || !editable,
|
791
|
+
onChange: (event) => setFieldValue("config.createCollections", event.target.value === "true"),
|
792
|
+
value: isAdmin || values.config?.createCollections ? "true" : "false",
|
793
|
+
renderValue: (value) => value === "true" ? "Yes" : "No",
|
581
794
|
children: [
|
582
|
-
/* @__PURE__ */
|
583
|
-
|
795
|
+
/* @__PURE__ */ jsx(
|
796
|
+
SelectItem,
|
584
797
|
{
|
585
798
|
value: "true",
|
586
799
|
children: " Yes "
|
587
800
|
}
|
588
801
|
),
|
589
|
-
/* @__PURE__ */
|
590
|
-
|
802
|
+
/* @__PURE__ */ jsx(
|
803
|
+
SelectItem,
|
591
804
|
{
|
592
805
|
value: "false",
|
593
806
|
children: " No "
|
@@ -596,38 +809,38 @@ function Ke({
|
|
596
809
|
]
|
597
810
|
}
|
598
811
|
),
|
599
|
-
/* @__PURE__ */
|
812
|
+
/* @__PURE__ */ jsx(FieldCaption, { children: touched.config && Boolean(errors.config) ? errors.config : "Can the user create collections" })
|
600
813
|
] }),
|
601
|
-
/* @__PURE__ */
|
602
|
-
/* @__PURE__ */
|
603
|
-
|
814
|
+
/* @__PURE__ */ jsxs("div", { className: "col-span-12 md:col-span-4", children: [
|
815
|
+
/* @__PURE__ */ jsxs(
|
816
|
+
Select,
|
604
817
|
{
|
605
|
-
error:
|
818
|
+
error: touched.config && Boolean(errors.config),
|
606
819
|
id: "editCollections",
|
607
820
|
name: "editCollections",
|
608
821
|
label: "Edit collections",
|
609
|
-
disabled:
|
822
|
+
disabled: isAdmin || !editable,
|
610
823
|
position: "item-aligned",
|
611
|
-
onChange: (
|
612
|
-
value:
|
613
|
-
renderValue: (
|
824
|
+
onChange: (event) => setFieldValue("config.editCollections", event.target.value === "own" ? "own" : event.target.value === "true"),
|
825
|
+
value: isAdmin ? "true" : values.config?.editCollections === "own" ? "own" : values.config?.editCollections ? "true" : "false",
|
826
|
+
renderValue: (value) => value === "own" ? "Own" : value === "true" ? "Yes" : "No",
|
614
827
|
children: [
|
615
|
-
/* @__PURE__ */
|
616
|
-
|
828
|
+
/* @__PURE__ */ jsx(
|
829
|
+
SelectItem,
|
617
830
|
{
|
618
831
|
value: "true",
|
619
832
|
children: " Yes "
|
620
833
|
}
|
621
834
|
),
|
622
|
-
/* @__PURE__ */
|
623
|
-
|
835
|
+
/* @__PURE__ */ jsx(
|
836
|
+
SelectItem,
|
624
837
|
{
|
625
838
|
value: "false",
|
626
839
|
children: " No "
|
627
840
|
}
|
628
841
|
),
|
629
|
-
/* @__PURE__ */
|
630
|
-
|
842
|
+
/* @__PURE__ */ jsx(
|
843
|
+
SelectItem,
|
631
844
|
{
|
632
845
|
value: "own",
|
633
846
|
children: " Only his/her own "
|
@@ -636,38 +849,38 @@ function Ke({
|
|
636
849
|
]
|
637
850
|
}
|
638
851
|
),
|
639
|
-
/* @__PURE__ */
|
852
|
+
/* @__PURE__ */ jsx(FieldCaption, { children: touched.config && Boolean(errors.config) ? errors.config : "Can the user edit collections" })
|
640
853
|
] }),
|
641
|
-
/* @__PURE__ */
|
642
|
-
/* @__PURE__ */
|
643
|
-
|
854
|
+
/* @__PURE__ */ jsxs("div", { className: "col-span-12 md:col-span-4", children: [
|
855
|
+
/* @__PURE__ */ jsxs(
|
856
|
+
Select,
|
644
857
|
{
|
645
|
-
error:
|
858
|
+
error: touched.config && Boolean(errors.config),
|
646
859
|
id: "deleteCollections",
|
647
860
|
name: "deleteCollections",
|
648
861
|
label: "Delete collections",
|
649
|
-
disabled:
|
862
|
+
disabled: isAdmin || !editable,
|
650
863
|
position: "item-aligned",
|
651
|
-
onChange: (
|
652
|
-
value:
|
653
|
-
renderValue: (
|
864
|
+
onChange: (event) => setFieldValue("config.deleteCollections", event.target.value === "own" ? "own" : event.target.value === "true"),
|
865
|
+
value: isAdmin ? "true" : values.config?.deleteCollections === "own" ? "own" : values.config?.deleteCollections ? "true" : "false",
|
866
|
+
renderValue: (value) => value === "own" ? "Own" : value === "true" ? "Yes" : "No",
|
654
867
|
children: [
|
655
|
-
/* @__PURE__ */
|
656
|
-
|
868
|
+
/* @__PURE__ */ jsx(
|
869
|
+
SelectItem,
|
657
870
|
{
|
658
871
|
value: "true",
|
659
872
|
children: " Yes "
|
660
873
|
}
|
661
874
|
),
|
662
|
-
/* @__PURE__ */
|
663
|
-
|
875
|
+
/* @__PURE__ */ jsx(
|
876
|
+
SelectItem,
|
664
877
|
{
|
665
878
|
value: "false",
|
666
879
|
children: " No "
|
667
880
|
}
|
668
881
|
),
|
669
|
-
/* @__PURE__ */
|
670
|
-
|
882
|
+
/* @__PURE__ */ jsx(
|
883
|
+
SelectItem,
|
671
884
|
{
|
672
885
|
value: "own",
|
673
886
|
children: " Only his/her own "
|
@@ -676,32 +889,32 @@ function Ke({
|
|
676
889
|
]
|
677
890
|
}
|
678
891
|
),
|
679
|
-
/* @__PURE__ */
|
892
|
+
/* @__PURE__ */ jsx(FieldCaption, { children: touched.config && Boolean(errors.config) ? errors.config : "Can the user delete collections" })
|
680
893
|
] })
|
681
894
|
] })
|
682
895
|
] }),
|
683
|
-
/* @__PURE__ */
|
684
|
-
|
685
|
-
/* @__PURE__ */
|
686
|
-
|
896
|
+
/* @__PURE__ */ jsxs(DialogActions, { position: "sticky", children: [
|
897
|
+
savingError && /* @__PURE__ */ jsx(Typography, { className: "text-red-500 dark:text-red-500", children: savingError.message ?? "There was an error saving this role" }),
|
898
|
+
/* @__PURE__ */ jsx(
|
899
|
+
Button,
|
687
900
|
{
|
688
901
|
variant: "text",
|
689
902
|
onClick: () => {
|
690
|
-
|
903
|
+
handleClose();
|
691
904
|
},
|
692
905
|
children: "Cancel"
|
693
906
|
}
|
694
907
|
),
|
695
|
-
/* @__PURE__ */
|
696
|
-
|
908
|
+
/* @__PURE__ */ jsx(
|
909
|
+
LoadingButton,
|
697
910
|
{
|
698
911
|
variant: "filled",
|
699
912
|
color: "primary",
|
700
913
|
type: "submit",
|
701
|
-
disabled: !
|
702
|
-
loading:
|
703
|
-
startIcon: /* @__PURE__ */
|
704
|
-
children:
|
914
|
+
disabled: !dirty,
|
915
|
+
loading: isSubmitting,
|
916
|
+
startIcon: /* @__PURE__ */ jsx(DoneIcon, {}),
|
917
|
+
children: isNewRole ? "Create role" : "Update"
|
705
918
|
}
|
706
919
|
)
|
707
920
|
] })
|
@@ -711,24 +924,24 @@ function Ke({
|
|
711
924
|
}
|
712
925
|
);
|
713
926
|
}
|
714
|
-
const
|
927
|
+
const DEFAULT_ROLES = [
|
715
928
|
{
|
716
929
|
id: "admin",
|
717
930
|
name: "Admin",
|
718
|
-
isAdmin:
|
931
|
+
isAdmin: true
|
719
932
|
},
|
720
933
|
{
|
721
934
|
id: "editor",
|
722
935
|
name: "Editor",
|
723
|
-
isAdmin:
|
936
|
+
isAdmin: false,
|
724
937
|
defaultPermissions: {
|
725
|
-
read:
|
726
|
-
create:
|
727
|
-
edit:
|
728
|
-
delete:
|
938
|
+
read: true,
|
939
|
+
create: true,
|
940
|
+
edit: true,
|
941
|
+
delete: true
|
729
942
|
},
|
730
943
|
config: {
|
731
|
-
createCollections:
|
944
|
+
createCollections: true,
|
732
945
|
editCollections: "own",
|
733
946
|
deleteCollections: "own"
|
734
947
|
}
|
@@ -736,78 +949,93 @@ const Qe = [
|
|
736
949
|
{
|
737
950
|
id: "viewer",
|
738
951
|
name: "Viewer",
|
739
|
-
isAdmin:
|
952
|
+
isAdmin: false,
|
740
953
|
defaultPermissions: {
|
741
|
-
read:
|
742
|
-
create:
|
743
|
-
edit:
|
744
|
-
delete:
|
954
|
+
read: true,
|
955
|
+
create: false,
|
956
|
+
edit: false,
|
957
|
+
delete: false
|
745
958
|
}
|
746
959
|
}
|
747
960
|
];
|
748
|
-
function
|
749
|
-
onRoleClicked
|
750
|
-
editable
|
961
|
+
function RolesTable({
|
962
|
+
onRoleClicked,
|
963
|
+
editable
|
751
964
|
}) {
|
752
965
|
const {
|
753
|
-
roles
|
754
|
-
saveRole
|
755
|
-
deleteRole
|
756
|
-
allowDefaultRolesCreation
|
757
|
-
} =
|
758
|
-
|
966
|
+
roles,
|
967
|
+
saveRole,
|
968
|
+
deleteRole,
|
969
|
+
allowDefaultRolesCreation
|
970
|
+
} = useUserManagement();
|
971
|
+
const [roleToBeDeleted, setRoleToBeDeleted] = useState(void 0);
|
972
|
+
const [deleteInProgress, setDeleteInProgress] = useState(false);
|
973
|
+
return /* @__PURE__ */ jsxs(
|
759
974
|
"div",
|
760
975
|
{
|
761
976
|
className: "w-full overflow-auto",
|
762
977
|
children: [
|
763
|
-
/* @__PURE__ */
|
764
|
-
/* @__PURE__ */
|
765
|
-
/* @__PURE__ */
|
766
|
-
/* @__PURE__ */
|
767
|
-
/* @__PURE__ */
|
768
|
-
/* @__PURE__ */
|
978
|
+
/* @__PURE__ */ jsxs(Table, { className: "w-full", children: [
|
979
|
+
/* @__PURE__ */ jsxs(TableHeader, { children: [
|
980
|
+
/* @__PURE__ */ jsx(TableCell, { header: true, className: "w-16" }),
|
981
|
+
/* @__PURE__ */ jsx(TableCell, { header: true, children: "Role" }),
|
982
|
+
/* @__PURE__ */ jsx(TableCell, { header: true, className: "items-center", children: "Is Admin" }),
|
983
|
+
/* @__PURE__ */ jsx(TableCell, { header: true, children: "Default permissions" })
|
769
984
|
] }),
|
770
|
-
/* @__PURE__ */
|
771
|
-
|
772
|
-
const
|
773
|
-
|
774
|
-
|
985
|
+
/* @__PURE__ */ jsxs(TableBody, { children: [
|
986
|
+
roles && roles.map((role) => {
|
987
|
+
const canCreateAll = role.isAdmin || role.defaultPermissions?.create;
|
988
|
+
const canReadAll = role.isAdmin || role.defaultPermissions?.read;
|
989
|
+
const canUpdateAll = role.isAdmin || role.defaultPermissions?.edit;
|
990
|
+
const canDeleteAll = role.isAdmin || role.defaultPermissions?.delete;
|
991
|
+
return /* @__PURE__ */ jsxs(
|
992
|
+
TableRow,
|
775
993
|
{
|
776
994
|
onClick: () => {
|
777
|
-
|
995
|
+
onRoleClicked(role);
|
778
996
|
},
|
779
997
|
children: [
|
780
|
-
/* @__PURE__ */
|
781
|
-
|
998
|
+
/* @__PURE__ */ jsx(TableCell, { style: { width: "64px" }, children: !role.isAdmin && /* @__PURE__ */ jsx(
|
999
|
+
Tooltip,
|
782
1000
|
{
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
1001
|
+
asChild: true,
|
1002
|
+
title: "Delete this role",
|
1003
|
+
children: /* @__PURE__ */ jsx(
|
1004
|
+
IconButton,
|
1005
|
+
{
|
1006
|
+
size: "small",
|
1007
|
+
disabled: !editable,
|
1008
|
+
onClick: (event) => {
|
1009
|
+
event.stopPropagation();
|
1010
|
+
return setRoleToBeDeleted(role);
|
1011
|
+
},
|
1012
|
+
children: /* @__PURE__ */ jsx(DeleteIcon, {})
|
1013
|
+
}
|
1014
|
+
)
|
787
1015
|
}
|
788
|
-
) })
|
789
|
-
/* @__PURE__ */
|
790
|
-
/* @__PURE__ */
|
791
|
-
/* @__PURE__ */
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
1016
|
+
) }),
|
1017
|
+
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(RoleChip, { role }) }),
|
1018
|
+
/* @__PURE__ */ jsx(TableCell, { className: "items-center", children: /* @__PURE__ */ jsx(Checkbox, { checked: role.isAdmin ?? false }) }),
|
1019
|
+
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("ul", { children: [
|
1020
|
+
canCreateAll && /* @__PURE__ */ jsx("li", { children: "Create" }),
|
1021
|
+
canReadAll && /* @__PURE__ */ jsx("li", { children: "Read" }),
|
1022
|
+
canUpdateAll && /* @__PURE__ */ jsx("li", { children: "Update" }),
|
1023
|
+
canDeleteAll && /* @__PURE__ */ jsx("li", { children: "Delete" })
|
796
1024
|
] }) })
|
797
1025
|
]
|
798
1026
|
},
|
799
|
-
|
1027
|
+
role.name
|
800
1028
|
);
|
801
1029
|
}),
|
802
|
-
(!
|
803
|
-
/* @__PURE__ */
|
804
|
-
|
805
|
-
|
1030
|
+
(!roles || roles.length === 0) && /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colspan: 4, children: /* @__PURE__ */ jsxs(CenteredView, { className: "flex flex-col gap-4 my-8 items-center", children: [
|
1031
|
+
/* @__PURE__ */ jsx(Typography, { variant: "label", children: "You don't have any roles yet." }),
|
1032
|
+
allowDefaultRolesCreation && /* @__PURE__ */ jsx(
|
1033
|
+
Button,
|
806
1034
|
{
|
807
1035
|
variant: "outlined",
|
808
1036
|
onClick: () => {
|
809
|
-
|
810
|
-
|
1037
|
+
DEFAULT_ROLES.forEach((role) => {
|
1038
|
+
saveRole(role);
|
811
1039
|
});
|
812
1040
|
},
|
813
1041
|
children: "Create default roles"
|
@@ -816,146 +1044,189 @@ function Xe({
|
|
816
1044
|
] }) }) })
|
817
1045
|
] })
|
818
1046
|
] }),
|
819
|
-
/* @__PURE__ */
|
820
|
-
|
1047
|
+
/* @__PURE__ */ jsx(
|
1048
|
+
ConfirmationDialog,
|
821
1049
|
{
|
822
|
-
open:
|
823
|
-
loading:
|
1050
|
+
open: Boolean(roleToBeDeleted),
|
1051
|
+
loading: deleteInProgress,
|
824
1052
|
onAccept: () => {
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
1053
|
+
if (roleToBeDeleted) {
|
1054
|
+
setDeleteInProgress(true);
|
1055
|
+
deleteRole(roleToBeDeleted).then(() => {
|
1056
|
+
setRoleToBeDeleted(void 0);
|
1057
|
+
}).finally(() => {
|
1058
|
+
setDeleteInProgress(false);
|
1059
|
+
});
|
1060
|
+
}
|
830
1061
|
},
|
831
1062
|
onCancel: () => {
|
832
|
-
|
1063
|
+
setRoleToBeDeleted(void 0);
|
833
1064
|
},
|
834
|
-
title: /* @__PURE__ */
|
835
|
-
body: /* @__PURE__ */
|
1065
|
+
title: /* @__PURE__ */ jsx(Fragment, { children: "Delete?" }),
|
1066
|
+
body: /* @__PURE__ */ jsx(Fragment, { children: "Are you sure you want to delete this role?" })
|
836
1067
|
}
|
837
1068
|
)
|
838
1069
|
]
|
839
1070
|
}
|
840
1071
|
);
|
841
1072
|
}
|
842
|
-
const
|
843
|
-
function({ children
|
844
|
-
const { collections
|
845
|
-
|
1073
|
+
const RolesView = React.memo(
|
1074
|
+
function RolesView2({ children }) {
|
1075
|
+
const { collections } = useNavigationController();
|
1076
|
+
const [dialogOpen, setDialogOpen] = useState(false);
|
1077
|
+
const [selectedRole, setSelectedRole] = useState();
|
1078
|
+
const { canEditRoles } = useUserManagement();
|
1079
|
+
const onRoleClicked = useCallback((user) => {
|
1080
|
+
setDialogOpen(true);
|
1081
|
+
setSelectedRole(user);
|
846
1082
|
}, []);
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
1083
|
+
const handleClose = () => {
|
1084
|
+
setSelectedRole(void 0);
|
1085
|
+
setDialogOpen(false);
|
1086
|
+
};
|
1087
|
+
return /* @__PURE__ */ jsxs(Container, { className: "w-full flex flex-col py-4 gap-4", maxWidth: "6xl", children: [
|
1088
|
+
children,
|
1089
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center mt-12", children: [
|
1090
|
+
/* @__PURE__ */ jsx(
|
1091
|
+
Typography,
|
852
1092
|
{
|
853
|
-
gutterBottom:
|
1093
|
+
gutterBottom: true,
|
854
1094
|
variant: "h4",
|
855
1095
|
className: "flex-grow",
|
856
1096
|
component: "h4",
|
857
1097
|
children: "Roles"
|
858
1098
|
}
|
859
1099
|
),
|
860
|
-
/* @__PURE__ */
|
861
|
-
|
1100
|
+
/* @__PURE__ */ jsx(
|
1101
|
+
Tooltip,
|
862
1102
|
{
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
1103
|
+
asChild: true,
|
1104
|
+
title: !canEditRoles ? "Update plans to customise roles" : void 0,
|
1105
|
+
children: /* @__PURE__ */ jsx(
|
1106
|
+
Button,
|
1107
|
+
{
|
1108
|
+
size: "large",
|
1109
|
+
disabled: !canEditRoles,
|
1110
|
+
startIcon: /* @__PURE__ */ jsx(AddIcon, {}),
|
1111
|
+
onClick: () => setDialogOpen(true),
|
1112
|
+
children: "Add role"
|
1113
|
+
}
|
1114
|
+
)
|
868
1115
|
}
|
869
|
-
)
|
1116
|
+
)
|
870
1117
|
] }),
|
871
|
-
/* @__PURE__ */
|
872
|
-
/* @__PURE__ */
|
873
|
-
|
1118
|
+
/* @__PURE__ */ jsx(RolesTable, { onRoleClicked, editable: Boolean(canEditRoles) }),
|
1119
|
+
/* @__PURE__ */ jsx(
|
1120
|
+
RolesDetailsForm,
|
874
1121
|
{
|
875
|
-
open:
|
876
|
-
role:
|
877
|
-
editable:
|
878
|
-
collections
|
879
|
-
handleClose
|
880
|
-
C(void 0), r(!1);
|
881
|
-
}
|
1122
|
+
open: dialogOpen,
|
1123
|
+
role: selectedRole,
|
1124
|
+
editable: canEditRoles,
|
1125
|
+
collections,
|
1126
|
+
handleClose
|
882
1127
|
},
|
883
|
-
|
1128
|
+
selectedRole?.id ?? "new"
|
884
1129
|
)
|
885
1130
|
] });
|
886
1131
|
}
|
887
|
-
)
|
888
|
-
|
889
|
-
|
890
|
-
|
1132
|
+
);
|
1133
|
+
const UserYupSchema = Yup.object().shape({
|
1134
|
+
displayName: Yup.string().required("Required"),
|
1135
|
+
email: Yup.string().email().required("Required"),
|
1136
|
+
roles: Yup.array().min(1)
|
891
1137
|
});
|
892
|
-
function
|
893
|
-
const
|
894
|
-
|
1138
|
+
function canUserBeEdited(loggedUser, user, users, roles, prevUser) {
|
1139
|
+
const admins = users.filter((u) => u.roles?.map((r) => r.id).includes("admin"));
|
1140
|
+
const loggedUserIsAdmin = loggedUser.roles?.map((r) => r.id).includes("admin");
|
1141
|
+
const didRolesChange = !prevUser || !areRolesEqual(prevUser.roles ?? [], user.roles ?? []);
|
1142
|
+
if (didRolesChange && !loggedUserIsAdmin) {
|
895
1143
|
throw new Error("Only admins can change roles");
|
896
|
-
|
1144
|
+
}
|
1145
|
+
const adminRoleRemoved = prevUser && prevUser.roles?.map((r) => r.id).includes("admin") && !user.roles?.map((r) => r.id).includes("admin");
|
1146
|
+
if (adminRoleRemoved && admins.length === 1) {
|
897
1147
|
throw new Error("There must be at least one admin");
|
898
|
-
|
1148
|
+
}
|
1149
|
+
return true;
|
899
1150
|
}
|
900
|
-
function
|
901
|
-
open
|
902
|
-
user:
|
903
|
-
handleClose
|
1151
|
+
function UserDetailsForm({
|
1152
|
+
open,
|
1153
|
+
user: userProp,
|
1154
|
+
handleClose
|
904
1155
|
}) {
|
905
|
-
const
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
1156
|
+
const snackbarController = useSnackbarController();
|
1157
|
+
const {
|
1158
|
+
user: loggedInUser
|
1159
|
+
} = useAuthController();
|
1160
|
+
const {
|
1161
|
+
saveUser,
|
1162
|
+
users,
|
1163
|
+
roles
|
1164
|
+
} = useUserManagement();
|
1165
|
+
const isNewUser = !userProp;
|
1166
|
+
const onUserUpdated = useCallback((savedUser) => {
|
1167
|
+
if (!loggedInUser) {
|
913
1168
|
throw new Error("Logged user not found");
|
1169
|
+
}
|
914
1170
|
try {
|
915
|
-
|
916
|
-
|
917
|
-
|
1171
|
+
canUserBeEdited(loggedInUser, savedUser, users, roles, userProp);
|
1172
|
+
return saveUser(savedUser);
|
1173
|
+
} catch (e) {
|
1174
|
+
return Promise.reject(e);
|
918
1175
|
}
|
919
|
-
}, [
|
920
|
-
|
1176
|
+
}, [roles, saveUser, userProp, users, loggedInUser]);
|
1177
|
+
const formex = useCreateFormex({
|
1178
|
+
initialValues: userProp ?? {
|
921
1179
|
displayName: "",
|
922
1180
|
email: "",
|
923
|
-
roles:
|
1181
|
+
roles: roles.filter((r) => r.id === "editor")
|
924
1182
|
},
|
925
|
-
validation: (
|
926
|
-
|
927
|
-
|
928
|
-
|
1183
|
+
validation: (values2) => {
|
1184
|
+
return UserYupSchema.validate(values2, { abortEarly: false }).then(() => {
|
1185
|
+
return {};
|
1186
|
+
}).catch((e) => {
|
1187
|
+
return e.inner.reduce((acc, error) => {
|
1188
|
+
acc[error.path] = error.message;
|
1189
|
+
return acc;
|
1190
|
+
}, {});
|
929
1191
|
});
|
930
|
-
}
|
931
|
-
|
932
|
-
|
933
|
-
|
1192
|
+
},
|
1193
|
+
onSubmit: (user, formexController) => {
|
1194
|
+
return onUserUpdated(user).then(() => {
|
1195
|
+
handleClose();
|
1196
|
+
formexController.resetForm({
|
1197
|
+
values: user
|
1198
|
+
});
|
1199
|
+
}).catch((e) => {
|
1200
|
+
snackbarController.open({
|
1201
|
+
type: "error",
|
1202
|
+
message: e.message
|
1203
|
+
});
|
934
1204
|
});
|
935
|
-
}
|
936
|
-
})
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
1205
|
+
}
|
1206
|
+
});
|
1207
|
+
const {
|
1208
|
+
isSubmitting,
|
1209
|
+
touched,
|
1210
|
+
handleChange,
|
1211
|
+
values,
|
1212
|
+
errors,
|
1213
|
+
setFieldValue,
|
1214
|
+
dirty,
|
1215
|
+
handleSubmit,
|
1216
|
+
submitCount
|
1217
|
+
} = formex;
|
1218
|
+
return /* @__PURE__ */ jsx(
|
1219
|
+
Dialog,
|
949
1220
|
{
|
950
|
-
open
|
951
|
-
onOpenChange: (
|
1221
|
+
open,
|
1222
|
+
onOpenChange: (open2) => !open2 ? handleClose() : void 0,
|
952
1223
|
maxWidth: "4xl",
|
953
|
-
children: /* @__PURE__ */
|
1224
|
+
children: /* @__PURE__ */ jsx(Formex, { value: formex, children: /* @__PURE__ */ jsxs(
|
954
1225
|
"form",
|
955
1226
|
{
|
956
|
-
onSubmit:
|
1227
|
+
onSubmit: handleSubmit,
|
957
1228
|
autoComplete: "off",
|
958
|
-
noValidate:
|
1229
|
+
noValidate: true,
|
959
1230
|
style: {
|
960
1231
|
display: "flex",
|
961
1232
|
flexDirection: "column",
|
@@ -963,13 +1234,13 @@ function tn({
|
|
963
1234
|
height: "100%"
|
964
1235
|
},
|
965
1236
|
children: [
|
966
|
-
/* @__PURE__ */
|
967
|
-
/* @__PURE__ */
|
1237
|
+
/* @__PURE__ */ jsxs(DialogContent, { className: "h-full flex-grow", children: [
|
1238
|
+
/* @__PURE__ */ jsx(
|
968
1239
|
"div",
|
969
1240
|
{
|
970
1241
|
className: "flex flex-row pt-4 pb-4",
|
971
|
-
children: /* @__PURE__ */
|
972
|
-
|
1242
|
+
children: /* @__PURE__ */ jsx(
|
1243
|
+
Typography,
|
973
1244
|
{
|
974
1245
|
variant: "h4",
|
975
1246
|
className: "flex-grow",
|
@@ -978,80 +1249,77 @@ function tn({
|
|
978
1249
|
)
|
979
1250
|
}
|
980
1251
|
),
|
981
|
-
/* @__PURE__ */
|
982
|
-
/* @__PURE__ */
|
983
|
-
/* @__PURE__ */
|
984
|
-
|
1252
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-12 gap-8", children: [
|
1253
|
+
/* @__PURE__ */ jsxs("div", { className: "col-span-12", children: [
|
1254
|
+
/* @__PURE__ */ jsx(
|
1255
|
+
TextField,
|
985
1256
|
{
|
986
1257
|
name: "displayName",
|
987
|
-
required:
|
988
|
-
error:
|
989
|
-
value:
|
990
|
-
onChange:
|
1258
|
+
required: true,
|
1259
|
+
error: submitCount > 0 && Boolean(errors.displayName),
|
1260
|
+
value: values.displayName ?? "",
|
1261
|
+
onChange: handleChange,
|
991
1262
|
"aria-describedby": "name-helper-text",
|
992
1263
|
label: "Name"
|
993
1264
|
}
|
994
1265
|
),
|
995
|
-
/* @__PURE__ */
|
1266
|
+
/* @__PURE__ */ jsx(FieldCaption, { children: submitCount > 0 && Boolean(errors.displayName) ? errors.displayName : "Name of this user" })
|
996
1267
|
] }),
|
997
|
-
/* @__PURE__ */
|
998
|
-
/* @__PURE__ */
|
999
|
-
|
1268
|
+
/* @__PURE__ */ jsxs("div", { className: "col-span-12", children: [
|
1269
|
+
/* @__PURE__ */ jsx(
|
1270
|
+
TextField,
|
1000
1271
|
{
|
1001
|
-
required:
|
1002
|
-
error:
|
1272
|
+
required: true,
|
1273
|
+
error: submitCount > 0 && Boolean(errors.email),
|
1003
1274
|
name: "email",
|
1004
|
-
value:
|
1005
|
-
onChange:
|
1275
|
+
value: values.email ?? "",
|
1276
|
+
onChange: handleChange,
|
1006
1277
|
"aria-describedby": "email-helper-text",
|
1007
1278
|
label: "Email"
|
1008
1279
|
}
|
1009
1280
|
),
|
1010
|
-
/* @__PURE__ */
|
1281
|
+
/* @__PURE__ */ jsx(FieldCaption, { children: submitCount > 0 && Boolean(errors.email) ? errors.email : "Email of this user" })
|
1011
1282
|
] }),
|
1012
|
-
/* @__PURE__ */
|
1013
|
-
|
1283
|
+
/* @__PURE__ */ jsx("div", { className: "col-span-12", children: /* @__PURE__ */ jsx(
|
1284
|
+
MultiSelect,
|
1014
1285
|
{
|
1286
|
+
className: "w-full",
|
1015
1287
|
label: "Roles",
|
1016
|
-
value:
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
return N ? /* @__PURE__ */ e("div", { className: "flex flex-wrap space-x-2 space-y-2", children: /* @__PURE__ */ e(Q, { role: N }, N?.id) }) : null;
|
1021
|
-
},
|
1022
|
-
children: h.map((u) => /* @__PURE__ */ e(
|
1023
|
-
Te,
|
1288
|
+
value: values.roles?.map((r) => r.id) ?? [],
|
1289
|
+
onValueChange: (value) => setFieldValue("roles", value.map((id) => roles.find((r) => r.id === id))),
|
1290
|
+
children: roles.map((userRole) => /* @__PURE__ */ jsx(
|
1291
|
+
MultiSelectItem,
|
1024
1292
|
{
|
1025
|
-
value:
|
1026
|
-
children: /* @__PURE__ */
|
1293
|
+
value: userRole.id,
|
1294
|
+
children: /* @__PURE__ */ jsx(RoleChip, { role: userRole }, userRole?.id)
|
1027
1295
|
},
|
1028
|
-
|
1296
|
+
userRole.id
|
1029
1297
|
))
|
1030
1298
|
}
|
1031
1299
|
) })
|
1032
1300
|
] })
|
1033
1301
|
] }),
|
1034
|
-
/* @__PURE__ */
|
1035
|
-
/* @__PURE__ */
|
1036
|
-
|
1302
|
+
/* @__PURE__ */ jsxs(DialogActions, { children: [
|
1303
|
+
/* @__PURE__ */ jsx(
|
1304
|
+
Button,
|
1037
1305
|
{
|
1038
1306
|
variant: "text",
|
1039
1307
|
onClick: () => {
|
1040
|
-
|
1308
|
+
handleClose();
|
1041
1309
|
},
|
1042
1310
|
children: "Cancel"
|
1043
1311
|
}
|
1044
1312
|
),
|
1045
|
-
/* @__PURE__ */
|
1046
|
-
|
1313
|
+
/* @__PURE__ */ jsx(
|
1314
|
+
LoadingButton,
|
1047
1315
|
{
|
1048
1316
|
variant: "filled",
|
1049
1317
|
color: "primary",
|
1050
1318
|
type: "submit",
|
1051
|
-
disabled: !
|
1052
|
-
loading:
|
1053
|
-
startIcon: /* @__PURE__ */
|
1054
|
-
children:
|
1319
|
+
disabled: !dirty,
|
1320
|
+
loading: isSubmitting,
|
1321
|
+
startIcon: /* @__PURE__ */ jsx(DoneIcon, {}),
|
1322
|
+
children: isNewUser ? "Create user" : "Update"
|
1055
1323
|
}
|
1056
1324
|
)
|
1057
1325
|
] })
|
@@ -1061,79 +1329,96 @@ function tn({
|
|
1061
1329
|
}
|
1062
1330
|
);
|
1063
1331
|
}
|
1064
|
-
function
|
1332
|
+
function UsersTable({ onUserClicked }) {
|
1065
1333
|
const {
|
1066
|
-
users
|
1067
|
-
saveUser
|
1068
|
-
deleteUser
|
1069
|
-
} =
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1334
|
+
users,
|
1335
|
+
saveUser,
|
1336
|
+
deleteUser
|
1337
|
+
} = useUserManagement();
|
1338
|
+
const authController = useAuthController();
|
1339
|
+
const snackbarController = useSnackbarController();
|
1340
|
+
const customizationController = useCustomizationController();
|
1341
|
+
const dateUtilsLocale = customizationController?.locale ? locales[customizationController?.locale] : void 0;
|
1342
|
+
const dateFormat = customizationController?.dateTimeFormat ?? defaultDateFormat;
|
1343
|
+
const [userToBeDeleted, setUserToBeDeleted] = useState(void 0);
|
1344
|
+
const [deleteInProgress, setDeleteInProgress] = useState(false);
|
1345
|
+
return /* @__PURE__ */ jsxs("div", { className: "overflow-auto", children: [
|
1346
|
+
/* @__PURE__ */ jsxs(Table, { className: "w-full", children: [
|
1347
|
+
/* @__PURE__ */ jsxs(TableHeader, { children: [
|
1348
|
+
/* @__PURE__ */ jsx(TableCell, { className: "truncate w-16" }),
|
1349
|
+
/* @__PURE__ */ jsx(TableCell, { children: "Email" }),
|
1350
|
+
/* @__PURE__ */ jsx(TableCell, { children: "Name" }),
|
1351
|
+
/* @__PURE__ */ jsx(TableCell, { children: "Roles" }),
|
1352
|
+
/* @__PURE__ */ jsx(TableCell, { children: "Created on" })
|
1079
1353
|
] }),
|
1080
|
-
/* @__PURE__ */
|
1081
|
-
|
1082
|
-
const
|
1083
|
-
|
1084
|
-
|
1354
|
+
/* @__PURE__ */ jsxs(TableBody, { children: [
|
1355
|
+
users && users.map((user) => {
|
1356
|
+
const userRoles = user.roles;
|
1357
|
+
const formattedDate = user.created_on ? format(user.created_on, dateFormat, { locale: dateUtilsLocale }) : "";
|
1358
|
+
return /* @__PURE__ */ jsxs(
|
1359
|
+
TableRow,
|
1085
1360
|
{
|
1086
1361
|
onClick: () => {
|
1087
|
-
|
1362
|
+
onUserClicked(user);
|
1088
1363
|
},
|
1089
1364
|
children: [
|
1090
|
-
/* @__PURE__ */
|
1091
|
-
|
1365
|
+
/* @__PURE__ */ jsx(TableCell, { className: "w-10", children: /* @__PURE__ */ jsx(
|
1366
|
+
Tooltip,
|
1092
1367
|
{
|
1093
|
-
|
1094
|
-
|
1095
|
-
children: /* @__PURE__ */
|
1368
|
+
asChild: true,
|
1369
|
+
title: "Delete this user",
|
1370
|
+
children: /* @__PURE__ */ jsx(
|
1371
|
+
IconButton,
|
1372
|
+
{
|
1373
|
+
size: "small",
|
1374
|
+
onClick: (event) => {
|
1375
|
+
event.stopPropagation();
|
1376
|
+
return setUserToBeDeleted(user);
|
1377
|
+
},
|
1378
|
+
children: /* @__PURE__ */ jsx(DeleteIcon, {})
|
1379
|
+
}
|
1380
|
+
)
|
1096
1381
|
}
|
1097
|
-
) })
|
1098
|
-
/* @__PURE__ */
|
1099
|
-
/* @__PURE__ */
|
1100
|
-
/* @__PURE__ */
|
1101
|
-
|
1102
|
-
(w) => /* @__PURE__ */ e(Q, { role: w }, w?.id)
|
1382
|
+
) }),
|
1383
|
+
/* @__PURE__ */ jsx(TableCell, { children: user.email }),
|
1384
|
+
/* @__PURE__ */ jsx(TableCell, { className: "font-medium align-left", children: user.displayName }),
|
1385
|
+
/* @__PURE__ */ jsx(TableCell, { className: "align-left", children: userRoles ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: userRoles.map(
|
1386
|
+
(userRole) => /* @__PURE__ */ jsx(RoleChip, { role: userRole }, userRole?.id)
|
1103
1387
|
) }) : null }),
|
1104
|
-
/* @__PURE__ */
|
1388
|
+
/* @__PURE__ */ jsx(TableCell, { children: formattedDate })
|
1105
1389
|
]
|
1106
1390
|
},
|
1107
|
-
"row_" +
|
1391
|
+
"row_" + user.uid
|
1108
1392
|
);
|
1109
1393
|
}),
|
1110
|
-
(!
|
1111
|
-
/* @__PURE__ */
|
1112
|
-
/* @__PURE__ */
|
1113
|
-
|
1394
|
+
(!users || users.length === 0) && /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colspan: 6, children: /* @__PURE__ */ jsxs(CenteredView, { className: "flex flex-col gap-4 my-8 items-center", children: [
|
1395
|
+
/* @__PURE__ */ jsx(Typography, { variant: "label", children: "There are no users yet" }),
|
1396
|
+
/* @__PURE__ */ jsx(
|
1397
|
+
Button,
|
1114
1398
|
{
|
1115
1399
|
variant: "outlined",
|
1116
1400
|
onClick: () => {
|
1117
|
-
if (!
|
1401
|
+
if (!authController.user?.uid) {
|
1118
1402
|
throw Error("UsersTable, authController misconfiguration");
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1403
|
+
}
|
1404
|
+
saveUser({
|
1405
|
+
uid: authController.user?.uid,
|
1406
|
+
email: authController.user?.email,
|
1407
|
+
displayName: authController.user?.displayName,
|
1408
|
+
photoURL: authController.user?.photoURL,
|
1409
|
+
providerId: authController.user?.providerId,
|
1410
|
+
isAnonymous: authController.user?.isAnonymous,
|
1126
1411
|
roles: [{ id: "admin", name: "Admin" }],
|
1127
1412
|
created_on: /* @__PURE__ */ new Date()
|
1128
1413
|
}).then(() => {
|
1129
|
-
|
1414
|
+
snackbarController.open({
|
1130
1415
|
type: "success",
|
1131
1416
|
message: "User added successfully"
|
1132
1417
|
});
|
1133
|
-
}).catch((
|
1134
|
-
|
1418
|
+
}).catch((error) => {
|
1419
|
+
snackbarController.open({
|
1135
1420
|
type: "error",
|
1136
|
-
message: "Error adding user: " +
|
1421
|
+
message: "Error adding user: " + error.message
|
1137
1422
|
});
|
1138
1423
|
});
|
1139
1424
|
},
|
@@ -1143,132 +1428,212 @@ function rn({ onUserClicked: t }) {
|
|
1143
1428
|
] }) }) })
|
1144
1429
|
] })
|
1145
1430
|
] }),
|
1146
|
-
/* @__PURE__ */
|
1147
|
-
|
1431
|
+
/* @__PURE__ */ jsx(
|
1432
|
+
ConfirmationDialog,
|
1148
1433
|
{
|
1149
|
-
open:
|
1150
|
-
loading:
|
1434
|
+
open: Boolean(userToBeDeleted),
|
1435
|
+
loading: deleteInProgress,
|
1151
1436
|
onAccept: () => {
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1437
|
+
if (userToBeDeleted) {
|
1438
|
+
setDeleteInProgress(true);
|
1439
|
+
deleteUser(userToBeDeleted).then(() => {
|
1440
|
+
setUserToBeDeleted(void 0);
|
1441
|
+
}).catch((error) => {
|
1442
|
+
snackbarController.open({
|
1443
|
+
type: "error",
|
1444
|
+
message: "Error deleting user: " + error.message
|
1445
|
+
});
|
1446
|
+
}).finally(() => {
|
1447
|
+
setDeleteInProgress(false);
|
1158
1448
|
});
|
1159
|
-
}
|
1160
|
-
b(!1);
|
1161
|
-
}));
|
1449
|
+
}
|
1162
1450
|
},
|
1163
1451
|
onCancel: () => {
|
1164
|
-
|
1452
|
+
setUserToBeDeleted(void 0);
|
1165
1453
|
},
|
1166
|
-
title: /* @__PURE__ */
|
1167
|
-
body: /* @__PURE__ */
|
1454
|
+
title: /* @__PURE__ */ jsx(Fragment, { children: "Delete?" }),
|
1455
|
+
body: /* @__PURE__ */ jsx(Fragment, { children: "Are you sure you want to delete this user?" })
|
1168
1456
|
}
|
1169
1457
|
)
|
1170
1458
|
] });
|
1171
1459
|
}
|
1172
|
-
const
|
1173
|
-
const [
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1460
|
+
const UsersView = function UsersView2({ children }) {
|
1461
|
+
const [dialogOpen, setDialogOpen] = useState();
|
1462
|
+
const [selectedUser, setSelectedUser] = useState();
|
1463
|
+
const { users, usersLimit } = useUserManagement();
|
1464
|
+
const reachedUsersLimit = usersLimit !== void 0 && (users && users.length >= usersLimit);
|
1465
|
+
const onUserClicked = useCallback((user) => {
|
1466
|
+
setSelectedUser(user);
|
1467
|
+
setDialogOpen(true);
|
1468
|
+
}, []);
|
1469
|
+
const handleClose = useCallback(() => {
|
1470
|
+
setDialogOpen(false);
|
1471
|
+
setSelectedUser(void 0);
|
1177
1472
|
}, []);
|
1178
|
-
return /* @__PURE__ */
|
1179
|
-
|
1180
|
-
/* @__PURE__ */
|
1473
|
+
return /* @__PURE__ */ jsxs(Container, { className: "w-full flex flex-col py-4 gap-4", maxWidth: "6xl", children: [
|
1474
|
+
children,
|
1475
|
+
/* @__PURE__ */ jsxs(
|
1181
1476
|
"div",
|
1182
1477
|
{
|
1183
1478
|
className: "flex items-center mt-12",
|
1184
1479
|
children: [
|
1185
|
-
/* @__PURE__ */
|
1186
|
-
|
1480
|
+
/* @__PURE__ */ jsx(
|
1481
|
+
Typography,
|
1187
1482
|
{
|
1188
|
-
gutterBottom:
|
1483
|
+
gutterBottom: true,
|
1189
1484
|
variant: "h4",
|
1190
1485
|
className: "flex-grow",
|
1191
1486
|
component: "h4",
|
1192
1487
|
children: "Users"
|
1193
1488
|
}
|
1194
1489
|
),
|
1195
|
-
/* @__PURE__ */
|
1196
|
-
|
1490
|
+
/* @__PURE__ */ jsx(
|
1491
|
+
Button,
|
1197
1492
|
{
|
1198
1493
|
size: "large",
|
1199
|
-
disabled:
|
1200
|
-
startIcon: /* @__PURE__ */
|
1201
|
-
onClick: () =>
|
1494
|
+
disabled: reachedUsersLimit,
|
1495
|
+
startIcon: /* @__PURE__ */ jsx(AddIcon, {}),
|
1496
|
+
onClick: () => setDialogOpen(true),
|
1202
1497
|
children: "Add user"
|
1203
1498
|
}
|
1204
1499
|
)
|
1205
1500
|
]
|
1206
1501
|
}
|
1207
1502
|
),
|
1208
|
-
/* @__PURE__ */
|
1209
|
-
/* @__PURE__ */
|
1210
|
-
|
1503
|
+
/* @__PURE__ */ jsx(UsersTable, { onUserClicked }),
|
1504
|
+
/* @__PURE__ */ jsx(
|
1505
|
+
UserDetailsForm,
|
1211
1506
|
{
|
1212
|
-
open:
|
1213
|
-
user:
|
1214
|
-
handleClose
|
1507
|
+
open: dialogOpen ?? false,
|
1508
|
+
user: selectedUser,
|
1509
|
+
handleClose
|
1215
1510
|
},
|
1216
|
-
|
1511
|
+
selectedUser?.uid ?? "new"
|
1217
1512
|
)
|
1218
1513
|
] });
|
1219
1514
|
};
|
1220
|
-
function
|
1515
|
+
function useUserManagementPlugin({ userManagement }) {
|
1516
|
+
const noUsers = userManagement.users.length === 0;
|
1517
|
+
const noRoles = userManagement.roles.length === 0;
|
1221
1518
|
return {
|
1222
1519
|
key: "user_management",
|
1223
|
-
loading:
|
1520
|
+
loading: userManagement.loading,
|
1521
|
+
homePage: {
|
1522
|
+
additionalChildrenStart: noUsers || noRoles ? /* @__PURE__ */ jsx(
|
1523
|
+
IntroWidget,
|
1524
|
+
{
|
1525
|
+
noUsers,
|
1526
|
+
noRoles,
|
1527
|
+
userManagement
|
1528
|
+
}
|
1529
|
+
) : void 0
|
1530
|
+
},
|
1224
1531
|
provider: {
|
1225
|
-
Component:
|
1532
|
+
Component: UserManagementProvider,
|
1226
1533
|
props: {
|
1227
|
-
userManagement
|
1534
|
+
userManagement
|
1228
1535
|
}
|
1229
1536
|
}
|
1230
1537
|
};
|
1231
1538
|
}
|
1232
|
-
|
1539
|
+
function IntroWidget({
|
1540
|
+
noUsers,
|
1541
|
+
noRoles,
|
1542
|
+
userManagement
|
1543
|
+
}) {
|
1544
|
+
const authController = useAuthController();
|
1545
|
+
const snackbarController = useSnackbarController();
|
1546
|
+
const buttonLabel = noUsers && noRoles ? "Create default roles and add current user as admin" : noUsers ? "Add current user as admin" : noRoles ? "Create default roles" : void 0;
|
1547
|
+
return /* @__PURE__ */ jsxs(
|
1548
|
+
Paper,
|
1549
|
+
{
|
1550
|
+
className: "my-4 flex flex-col px-4 py-6 bg-white dark:bg-surface-accent-800 gap-2",
|
1551
|
+
children: [
|
1552
|
+
/* @__PURE__ */ jsx(Typography, { variant: "subtitle2", className: "uppercase", children: "Create your users and roles" }),
|
1553
|
+
/* @__PURE__ */ jsx(Typography, { children: "You have no users or roles defined. You can create default roles and add the current user as admin." }),
|
1554
|
+
/* @__PURE__ */ jsxs(Button, { onClick: () => {
|
1555
|
+
if (!authController.user?.uid) {
|
1556
|
+
throw Error("UsersTable, authController misconfiguration");
|
1557
|
+
}
|
1558
|
+
if (noUsers) {
|
1559
|
+
userManagement.saveUser({
|
1560
|
+
uid: authController.user?.uid,
|
1561
|
+
email: authController.user?.email,
|
1562
|
+
displayName: authController.user?.displayName,
|
1563
|
+
photoURL: authController.user?.photoURL,
|
1564
|
+
providerId: authController.user?.providerId,
|
1565
|
+
isAnonymous: authController.user?.isAnonymous,
|
1566
|
+
roles: [{
|
1567
|
+
id: "admin",
|
1568
|
+
name: "Admin"
|
1569
|
+
}],
|
1570
|
+
created_on: /* @__PURE__ */ new Date()
|
1571
|
+
}).then(() => {
|
1572
|
+
snackbarController.open({
|
1573
|
+
type: "success",
|
1574
|
+
message: "User added successfully"
|
1575
|
+
});
|
1576
|
+
}).catch((error) => {
|
1577
|
+
snackbarController.open({
|
1578
|
+
type: "error",
|
1579
|
+
message: "Error adding user: " + error.message
|
1580
|
+
});
|
1581
|
+
});
|
1582
|
+
}
|
1583
|
+
if (noRoles) {
|
1584
|
+
DEFAULT_ROLES.forEach((role) => {
|
1585
|
+
userManagement.saveRole(role);
|
1586
|
+
});
|
1587
|
+
}
|
1588
|
+
}, children: [
|
1589
|
+
/* @__PURE__ */ jsx(AddIcon, {}),
|
1590
|
+
buttonLabel
|
1591
|
+
] })
|
1592
|
+
]
|
1593
|
+
}
|
1594
|
+
);
|
1595
|
+
}
|
1596
|
+
const userManagementAdminViews = [
|
1233
1597
|
{
|
1234
1598
|
path: "users",
|
1235
1599
|
name: "CMS Users",
|
1236
1600
|
group: "Admin",
|
1237
1601
|
icon: "face",
|
1238
|
-
view: /* @__PURE__ */
|
1602
|
+
view: /* @__PURE__ */ jsx(UsersView, {})
|
1239
1603
|
},
|
1240
1604
|
{
|
1241
1605
|
path: "roles",
|
1242
1606
|
name: "Roles",
|
1243
1607
|
group: "Admin",
|
1244
1608
|
icon: "gpp_good",
|
1245
|
-
view: /* @__PURE__ */
|
1609
|
+
view: /* @__PURE__ */ jsx(RolesView, {})
|
1246
1610
|
}
|
1247
1611
|
];
|
1248
1612
|
export {
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1613
|
+
IntroWidget,
|
1614
|
+
RESERVED_GROUPS,
|
1615
|
+
RoleChip,
|
1616
|
+
RoleYupSchema,
|
1617
|
+
RolesDetailsForm,
|
1618
|
+
RolesTable,
|
1619
|
+
RolesView,
|
1620
|
+
UserDetailsForm,
|
1621
|
+
UserManagementContext,
|
1622
|
+
UserManagementProvider,
|
1623
|
+
UserYupSchema,
|
1624
|
+
UsersTable,
|
1625
|
+
UsersView,
|
1626
|
+
areRolesEqual,
|
1627
|
+
cacheDelegatedLoginToken,
|
1628
|
+
clearDelegatedLoginTokensCache,
|
1629
|
+
darkenColor,
|
1630
|
+
getDelegatedLoginTokenFromCache,
|
1631
|
+
getUserRoles,
|
1632
|
+
hexToRgbaWithOpacity,
|
1633
|
+
resolveUserRolePermissions,
|
1634
|
+
useBuildUserManagement,
|
1635
|
+
useUserManagement,
|
1636
|
+
useUserManagementPlugin,
|
1637
|
+
userManagementAdminViews
|
1273
1638
|
};
|
1274
1639
|
//# sourceMappingURL=index.es.js.map
|