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