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