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