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