@firecms/user_management 3.0.0-beta.7 → 3.0.0-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +3 -2
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/{useFirestoreUserManagement.d.ts → useBuildUserManagement.d.ts} +8 -7
- package/dist/index.es.js +1147 -875
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +1635 -1
- package/dist/index.umd.js.map +1 -1
- package/package.json +8 -23
- 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/UserDetailsForm.tsx +11 -9
- package/src/components/users/UsersTable.tsx +4 -2
- package/src/hooks/index.ts +1 -1
- package/src/hooks/useBuildUserManagement.tsx +314 -0
- package/src/utils/permissions.ts +7 -6
- package/src/hooks/useFirestoreUserManagement.tsx +0 -277
package/dist/index.es.js
CHANGED
@@ -1,331 +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 Ye;
|
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
|
-
|
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);
|
125
169
|
return;
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
error: (p) => {
|
141
|
-
console.error("Error loading roles", p), _(p), R(!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);
|
142
184
|
}
|
185
|
+
setRolesLoading(false);
|
186
|
+
},
|
187
|
+
onError(e) {
|
188
|
+
setRoles([]);
|
189
|
+
console.error("Error loading roles", e);
|
190
|
+
setRolesError(e);
|
191
|
+
setRolesLoading(false);
|
143
192
|
}
|
144
|
-
);
|
145
|
-
}, [
|
146
|
-
|
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);
|
147
200
|
return;
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
error: (p) => {
|
163
|
-
console.error("Error loading users", p), u(p), c(!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);
|
164
215
|
}
|
216
|
+
setUsersLoading(false);
|
217
|
+
},
|
218
|
+
onError(e) {
|
219
|
+
setUsersWithRoleIds([]);
|
220
|
+
console.error("Error loading users", e);
|
221
|
+
setUsersError(e);
|
222
|
+
setUsersLoading(false);
|
165
223
|
}
|
166
|
-
);
|
167
|
-
}, [
|
168
|
-
const
|
169
|
-
if (!
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
const
|
176
|
-
|
177
|
-
...
|
178
|
-
|
179
|
-
...Z,
|
180
|
-
roles: N
|
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
|
-
|
188
|
-
|
189
|
-
|
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);
|
190
252
|
const {
|
191
|
-
id
|
192
|
-
...
|
193
|
-
} =
|
194
|
-
return
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
if (!
|
206
|
-
|
207
|
-
const
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
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
|
+
}
|
228
314
|
throw Error("Could not find a user with the provided email in the user management system.");
|
229
|
-
}, [
|
315
|
+
}, [loading, users, usersError, rolesError]);
|
316
|
+
const isAdmin = roles.some((r) => r.id === "admin");
|
230
317
|
return {
|
231
|
-
loading
|
232
|
-
roles
|
233
|
-
users
|
234
|
-
saveUser
|
235
|
-
saveRole
|
236
|
-
rolesError
|
237
|
-
deleteUser
|
238
|
-
deleteRole
|
239
|
-
usersLimit
|
240
|
-
usersError
|
241
|
-
isAdmin
|
242
|
-
canEditRoles:
|
243
|
-
allowDefaultRolesCreation:
|
244
|
-
includeCollectionConfigPermissions:
|
245
|
-
collectionPermissions
|
246
|
-
defineRolesFor
|
247
|
-
authenticator
|
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
|
248
335
|
};
|
249
336
|
}
|
250
|
-
const
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
}
|
259
|
-
|
260
|
-
|
261
|
-
}
|
262
|
-
|
263
|
-
|
264
|
-
|
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
|
265
359
|
}) {
|
266
|
-
return /* @__PURE__ */
|
360
|
+
return /* @__PURE__ */ jsx(UserManagementContext.Provider, { value: userManagement, children });
|
267
361
|
}
|
268
|
-
const
|
269
|
-
function
|
270
|
-
let
|
271
|
-
|
272
|
-
|
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,
|
273
376
|
{
|
274
|
-
colorScheme
|
275
|
-
children:
|
377
|
+
colorScheme,
|
378
|
+
children: role.name
|
276
379
|
},
|
277
|
-
|
380
|
+
role.id
|
278
381
|
);
|
279
382
|
}
|
280
|
-
const
|
281
|
-
id:
|
282
|
-
name:
|
383
|
+
const RoleYupSchema = Yup.object().shape({
|
384
|
+
id: Yup.string().required("Required"),
|
385
|
+
name: Yup.string().required("Required")
|
283
386
|
});
|
284
|
-
function
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
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
|
290
400
|
}) {
|
291
|
-
const { saveRole
|
292
|
-
|
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 ?? {
|
293
415
|
name: ""
|
294
416
|
},
|
295
|
-
onSubmit: (
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
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,
|
320
465
|
{
|
321
|
-
open
|
466
|
+
open,
|
322
467
|
maxWidth: "4xl",
|
323
|
-
children: /* @__PURE__ */
|
468
|
+
children: /* @__PURE__ */ jsx(Formex, { value: formex, children: /* @__PURE__ */ jsxs(
|
324
469
|
"form",
|
325
470
|
{
|
326
|
-
noValidate:
|
471
|
+
noValidate: true,
|
327
472
|
autoComplete: "off",
|
328
|
-
onSubmit:
|
473
|
+
onSubmit: formex.handleSubmit,
|
329
474
|
style: {
|
330
475
|
display: "flex",
|
331
476
|
flexDirection: "column",
|
@@ -333,13 +478,13 @@ function Xe({
|
|
333
478
|
height: "100%"
|
334
479
|
},
|
335
480
|
children: [
|
336
|
-
/* @__PURE__ */
|
337
|
-
/* @__PURE__ */
|
481
|
+
/* @__PURE__ */ jsxs(DialogContent, { className: "flex-grow", children: [
|
482
|
+
/* @__PURE__ */ jsx(
|
338
483
|
"div",
|
339
484
|
{
|
340
485
|
className: "flex flex-row pt-12 pb-8",
|
341
|
-
children: /* @__PURE__ */
|
342
|
-
|
486
|
+
children: /* @__PURE__ */ jsx(
|
487
|
+
Typography,
|
343
488
|
{
|
344
489
|
variant: "h4",
|
345
490
|
className: "flex-grow",
|
@@ -348,262 +493,296 @@ function Xe({
|
|
348
493
|
)
|
349
494
|
}
|
350
495
|
),
|
351
|
-
/* @__PURE__ */
|
352
|
-
/* @__PURE__ */
|
353
|
-
/* @__PURE__ */
|
354
|
-
|
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,
|
355
500
|
{
|
356
501
|
name: "name",
|
357
|
-
required:
|
358
|
-
error:
|
359
|
-
value:
|
360
|
-
disabled:
|
361
|
-
onChange:
|
502
|
+
required: true,
|
503
|
+
error: touched.name && Boolean(errors.name),
|
504
|
+
value: values.name,
|
505
|
+
disabled: isAdmin || !editable,
|
506
|
+
onChange: handleChange,
|
362
507
|
"aria-describedby": "name-helper-text",
|
363
508
|
label: "Name"
|
364
509
|
}
|
365
510
|
),
|
366
|
-
/* @__PURE__ */
|
511
|
+
/* @__PURE__ */ jsx(FieldCaption, { children: touched.name && Boolean(errors.name) ? errors.name : "Name of this role" })
|
367
512
|
] }),
|
368
|
-
/* @__PURE__ */
|
369
|
-
/* @__PURE__ */
|
370
|
-
|
513
|
+
/* @__PURE__ */ jsxs("div", { className: "col-span-12 md:col-span-4", children: [
|
514
|
+
/* @__PURE__ */ jsx(
|
515
|
+
TextField,
|
371
516
|
{
|
372
517
|
name: "id",
|
373
|
-
required:
|
374
|
-
error:
|
375
|
-
value:
|
376
|
-
disabled: !
|
377
|
-
onChange: (
|
378
|
-
|
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);
|
379
525
|
},
|
380
526
|
"aria-describedby": "id-helper-text",
|
381
527
|
label: "ID"
|
382
528
|
}
|
383
529
|
),
|
384
|
-
/* @__PURE__ */
|
530
|
+
/* @__PURE__ */ jsx(FieldCaption, { children: touched.id && Boolean(errors.id) ? errors.id : "ID of this role" })
|
385
531
|
] }),
|
386
|
-
/* @__PURE__ */
|
387
|
-
/* @__PURE__ */
|
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
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
)
|
432
|
-
|
433
|
-
|
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,
|
434
586
|
{
|
435
|
-
|
436
|
-
children: /* @__PURE__ */
|
437
|
-
|
587
|
+
title: "Create entities in collections",
|
588
|
+
children: /* @__PURE__ */ jsx(
|
589
|
+
Checkbox,
|
438
590
|
{
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
{
|
443
|
-
disabled: u || !n,
|
444
|
-
checked: (u || h) ?? !1,
|
445
|
-
onCheckedChange: (o) => b("defaultPermissions.create", o)
|
446
|
-
}
|
447
|
-
)
|
591
|
+
disabled: isAdmin || !editable,
|
592
|
+
checked: (isAdmin || defaultCreate) ?? false,
|
593
|
+
onCheckedChange: (checked) => setFieldValue("defaultPermissions.create", checked)
|
448
594
|
}
|
449
595
|
)
|
450
596
|
}
|
451
|
-
)
|
452
|
-
|
453
|
-
|
597
|
+
)
|
598
|
+
}
|
599
|
+
),
|
600
|
+
/* @__PURE__ */ jsx(
|
601
|
+
TableCell,
|
602
|
+
{
|
603
|
+
align: "center",
|
604
|
+
children: /* @__PURE__ */ jsx(
|
605
|
+
Tooltip,
|
454
606
|
{
|
455
|
-
|
456
|
-
children: /* @__PURE__ */
|
457
|
-
|
607
|
+
title: "Access all data in every collection",
|
608
|
+
children: /* @__PURE__ */ jsx(
|
609
|
+
Checkbox,
|
458
610
|
{
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
{
|
463
|
-
disabled: u || !n,
|
464
|
-
checked: (u || x) ?? !1,
|
465
|
-
onCheckedChange: (o) => b("defaultPermissions.read", o)
|
466
|
-
}
|
467
|
-
)
|
611
|
+
disabled: isAdmin || !editable,
|
612
|
+
checked: (isAdmin || defaultRead) ?? false,
|
613
|
+
onCheckedChange: (checked) => setFieldValue("defaultPermissions.read", checked)
|
468
614
|
}
|
469
615
|
)
|
470
616
|
}
|
471
|
-
)
|
472
|
-
|
473
|
-
|
617
|
+
)
|
618
|
+
}
|
619
|
+
),
|
620
|
+
/* @__PURE__ */ jsx(
|
621
|
+
TableCell,
|
622
|
+
{
|
623
|
+
align: "center",
|
624
|
+
children: /* @__PURE__ */ jsx(
|
625
|
+
Tooltip,
|
474
626
|
{
|
475
|
-
|
476
|
-
children: /* @__PURE__ */
|
477
|
-
|
627
|
+
title: "Update data in any collection",
|
628
|
+
children: /* @__PURE__ */ jsx(
|
629
|
+
Checkbox,
|
478
630
|
{
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
{
|
483
|
-
disabled: u || !n,
|
484
|
-
checked: (u || D) ?? !1,
|
485
|
-
onCheckedChange: (o) => b("defaultPermissions.edit", o)
|
486
|
-
}
|
487
|
-
)
|
631
|
+
disabled: isAdmin || !editable,
|
632
|
+
checked: (isAdmin || defaultEdit) ?? false,
|
633
|
+
onCheckedChange: (checked) => setFieldValue("defaultPermissions.edit", checked)
|
488
634
|
}
|
489
635
|
)
|
490
636
|
}
|
491
|
-
)
|
492
|
-
|
493
|
-
|
637
|
+
)
|
638
|
+
}
|
639
|
+
),
|
640
|
+
/* @__PURE__ */ jsx(
|
641
|
+
TableCell,
|
642
|
+
{
|
643
|
+
align: "center",
|
644
|
+
children: /* @__PURE__ */ jsx(
|
645
|
+
Tooltip,
|
494
646
|
{
|
495
|
-
|
496
|
-
children: /* @__PURE__ */
|
497
|
-
|
647
|
+
title: "Delete data in any collection",
|
648
|
+
children: /* @__PURE__ */ jsx(
|
649
|
+
Checkbox,
|
498
650
|
{
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
{
|
503
|
-
disabled: u || !n,
|
504
|
-
checked: (u || T) ?? !1,
|
505
|
-
onCheckedChange: (o) => b("defaultPermissions.delete", o)
|
506
|
-
}
|
507
|
-
)
|
651
|
+
disabled: isAdmin || !editable,
|
652
|
+
checked: (isAdmin || defaultDelete) ?? false,
|
653
|
+
onCheckedChange: (checked) => setFieldValue("defaultPermissions.delete", checked)
|
508
654
|
}
|
509
655
|
)
|
510
656
|
}
|
511
657
|
)
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
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,
|
516
681
|
{
|
517
|
-
|
518
|
-
|
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)
|
519
685
|
}
|
520
|
-
)
|
521
|
-
|
522
|
-
|
686
|
+
)
|
687
|
+
}
|
688
|
+
),
|
689
|
+
/* @__PURE__ */ jsx(
|
690
|
+
TableCell,
|
691
|
+
{
|
692
|
+
align: "center",
|
693
|
+
children: /* @__PURE__ */ jsx(
|
694
|
+
Checkbox,
|
523
695
|
{
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
{
|
528
|
-
disabled: u || h || !n,
|
529
|
-
checked: (u || h || J(a, `collectionPermissions.${o.path}.create`)) ?? !1,
|
530
|
-
onCheckedChange: (S) => b(`collectionPermissions.${o.path}.create`, S)
|
531
|
-
}
|
532
|
-
)
|
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)
|
533
699
|
}
|
534
|
-
)
|
535
|
-
|
536
|
-
|
700
|
+
)
|
701
|
+
}
|
702
|
+
),
|
703
|
+
/* @__PURE__ */ jsx(
|
704
|
+
TableCell,
|
705
|
+
{
|
706
|
+
align: "center",
|
707
|
+
children: /* @__PURE__ */ jsx(
|
708
|
+
Checkbox,
|
537
709
|
{
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
{
|
542
|
-
disabled: u || x || !n,
|
543
|
-
checked: (u || x || J(a, `collectionPermissions.${o.path}.read`)) ?? !1,
|
544
|
-
onCheckedChange: (S) => b(`collectionPermissions.${o.path}.read`, S)
|
545
|
-
}
|
546
|
-
)
|
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)
|
547
713
|
}
|
548
|
-
)
|
549
|
-
|
550
|
-
|
714
|
+
)
|
715
|
+
}
|
716
|
+
),
|
717
|
+
/* @__PURE__ */ jsx(
|
718
|
+
TableCell,
|
719
|
+
{
|
720
|
+
align: "center",
|
721
|
+
children: /* @__PURE__ */ jsx(
|
722
|
+
Checkbox,
|
551
723
|
{
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
{
|
556
|
-
disabled: u || D || !n,
|
557
|
-
checked: (u || D || J(a, `collectionPermissions.${o.path}.edit`)) ?? !1,
|
558
|
-
onCheckedChange: (S) => b(`collectionPermissions.${o.path}.edit`, S)
|
559
|
-
}
|
560
|
-
)
|
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)
|
561
727
|
}
|
562
|
-
)
|
563
|
-
|
564
|
-
|
728
|
+
)
|
729
|
+
}
|
730
|
+
),
|
731
|
+
/* @__PURE__ */ jsx(
|
732
|
+
TableCell,
|
733
|
+
{
|
734
|
+
align: "center",
|
735
|
+
children: /* @__PURE__ */ jsx(
|
736
|
+
Tooltip,
|
565
737
|
{
|
566
|
-
|
567
|
-
children: /* @__PURE__ */
|
568
|
-
|
738
|
+
title: "Allow all permissions in this collections",
|
739
|
+
children: /* @__PURE__ */ jsx(
|
740
|
+
Button,
|
569
741
|
{
|
570
|
-
|
571
|
-
|
572
|
-
|
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"
|
573
752
|
}
|
574
753
|
)
|
575
754
|
}
|
576
755
|
)
|
577
|
-
|
578
|
-
|
579
|
-
] })
|
580
|
-
}
|
581
|
-
),
|
582
|
-
/* @__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" })
|
583
762
|
] }),
|
584
|
-
/* @__PURE__ */
|
585
|
-
/* @__PURE__ */
|
586
|
-
|
763
|
+
/* @__PURE__ */ jsxs("div", { className: "col-span-12 md:col-span-4", children: [
|
764
|
+
/* @__PURE__ */ jsxs(
|
765
|
+
Select,
|
587
766
|
{
|
588
|
-
error:
|
767
|
+
error: touched.config && Boolean(errors.config),
|
589
768
|
id: "createCollections",
|
590
769
|
name: "createCollections",
|
591
770
|
label: "Create collections",
|
592
771
|
position: "item-aligned",
|
593
|
-
disabled:
|
594
|
-
onChange: (
|
595
|
-
value:
|
596
|
-
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",
|
597
776
|
children: [
|
598
|
-
/* @__PURE__ */
|
599
|
-
|
777
|
+
/* @__PURE__ */ jsx(
|
778
|
+
SelectItem,
|
600
779
|
{
|
601
780
|
value: "true",
|
602
781
|
children: " Yes "
|
603
782
|
}
|
604
783
|
),
|
605
|
-
/* @__PURE__ */
|
606
|
-
|
784
|
+
/* @__PURE__ */ jsx(
|
785
|
+
SelectItem,
|
607
786
|
{
|
608
787
|
value: "false",
|
609
788
|
children: " No "
|
@@ -612,38 +791,38 @@ function Xe({
|
|
612
791
|
]
|
613
792
|
}
|
614
793
|
),
|
615
|
-
/* @__PURE__ */
|
794
|
+
/* @__PURE__ */ jsx(FieldCaption, { children: touched.config && Boolean(errors.config) ? errors.config : "Can the user create collections" })
|
616
795
|
] }),
|
617
|
-
/* @__PURE__ */
|
618
|
-
/* @__PURE__ */
|
619
|
-
|
796
|
+
/* @__PURE__ */ jsxs("div", { className: "col-span-12 md:col-span-4", children: [
|
797
|
+
/* @__PURE__ */ jsxs(
|
798
|
+
Select,
|
620
799
|
{
|
621
|
-
error:
|
800
|
+
error: touched.config && Boolean(errors.config),
|
622
801
|
id: "editCollections",
|
623
802
|
name: "editCollections",
|
624
803
|
label: "Edit collections",
|
625
|
-
disabled:
|
804
|
+
disabled: isAdmin || !editable,
|
626
805
|
position: "item-aligned",
|
627
|
-
onChange: (
|
628
|
-
value:
|
629
|
-
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",
|
630
809
|
children: [
|
631
|
-
/* @__PURE__ */
|
632
|
-
|
810
|
+
/* @__PURE__ */ jsx(
|
811
|
+
SelectItem,
|
633
812
|
{
|
634
813
|
value: "true",
|
635
814
|
children: " Yes "
|
636
815
|
}
|
637
816
|
),
|
638
|
-
/* @__PURE__ */
|
639
|
-
|
817
|
+
/* @__PURE__ */ jsx(
|
818
|
+
SelectItem,
|
640
819
|
{
|
641
820
|
value: "false",
|
642
821
|
children: " No "
|
643
822
|
}
|
644
823
|
),
|
645
|
-
/* @__PURE__ */
|
646
|
-
|
824
|
+
/* @__PURE__ */ jsx(
|
825
|
+
SelectItem,
|
647
826
|
{
|
648
827
|
value: "own",
|
649
828
|
children: " Only his/her own "
|
@@ -652,38 +831,38 @@ function Xe({
|
|
652
831
|
]
|
653
832
|
}
|
654
833
|
),
|
655
|
-
/* @__PURE__ */
|
834
|
+
/* @__PURE__ */ jsx(FieldCaption, { children: touched.config && Boolean(errors.config) ? errors.config : "Can the user edit collections" })
|
656
835
|
] }),
|
657
|
-
/* @__PURE__ */
|
658
|
-
/* @__PURE__ */
|
659
|
-
|
836
|
+
/* @__PURE__ */ jsxs("div", { className: "col-span-12 md:col-span-4", children: [
|
837
|
+
/* @__PURE__ */ jsxs(
|
838
|
+
Select,
|
660
839
|
{
|
661
|
-
error:
|
840
|
+
error: touched.config && Boolean(errors.config),
|
662
841
|
id: "deleteCollections",
|
663
842
|
name: "deleteCollections",
|
664
843
|
label: "Delete collections",
|
665
|
-
disabled:
|
844
|
+
disabled: isAdmin || !editable,
|
666
845
|
position: "item-aligned",
|
667
|
-
onChange: (
|
668
|
-
value:
|
669
|
-
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",
|
670
849
|
children: [
|
671
|
-
/* @__PURE__ */
|
672
|
-
|
850
|
+
/* @__PURE__ */ jsx(
|
851
|
+
SelectItem,
|
673
852
|
{
|
674
853
|
value: "true",
|
675
854
|
children: " Yes "
|
676
855
|
}
|
677
856
|
),
|
678
|
-
/* @__PURE__ */
|
679
|
-
|
857
|
+
/* @__PURE__ */ jsx(
|
858
|
+
SelectItem,
|
680
859
|
{
|
681
860
|
value: "false",
|
682
861
|
children: " No "
|
683
862
|
}
|
684
863
|
),
|
685
|
-
/* @__PURE__ */
|
686
|
-
|
864
|
+
/* @__PURE__ */ jsx(
|
865
|
+
SelectItem,
|
687
866
|
{
|
688
867
|
value: "own",
|
689
868
|
children: " Only his/her own "
|
@@ -692,32 +871,32 @@ function Xe({
|
|
692
871
|
]
|
693
872
|
}
|
694
873
|
),
|
695
|
-
/* @__PURE__ */
|
874
|
+
/* @__PURE__ */ jsx(FieldCaption, { children: touched.config && Boolean(errors.config) ? errors.config : "Can the user delete collections" })
|
696
875
|
] })
|
697
876
|
] })
|
698
877
|
] }),
|
699
|
-
/* @__PURE__ */
|
700
|
-
|
701
|
-
/* @__PURE__ */
|
702
|
-
|
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,
|
703
882
|
{
|
704
883
|
variant: "text",
|
705
884
|
onClick: () => {
|
706
|
-
|
885
|
+
handleClose();
|
707
886
|
},
|
708
887
|
children: "Cancel"
|
709
888
|
}
|
710
889
|
),
|
711
|
-
/* @__PURE__ */
|
712
|
-
|
890
|
+
/* @__PURE__ */ jsx(
|
891
|
+
LoadingButton,
|
713
892
|
{
|
714
893
|
variant: "filled",
|
715
894
|
color: "primary",
|
716
895
|
type: "submit",
|
717
|
-
disabled: !
|
718
|
-
loading:
|
719
|
-
startIcon: /* @__PURE__ */
|
720
|
-
children:
|
896
|
+
disabled: !dirty,
|
897
|
+
loading: isSubmitting,
|
898
|
+
startIcon: /* @__PURE__ */ jsx(DoneIcon, {}),
|
899
|
+
children: isNewRole ? "Create role" : "Update"
|
721
900
|
}
|
722
901
|
)
|
723
902
|
] })
|
@@ -727,24 +906,24 @@ function Xe({
|
|
727
906
|
}
|
728
907
|
);
|
729
908
|
}
|
730
|
-
const
|
909
|
+
const DEFAULT_ROLES = [
|
731
910
|
{
|
732
911
|
id: "admin",
|
733
912
|
name: "Admin",
|
734
|
-
isAdmin:
|
913
|
+
isAdmin: true
|
735
914
|
},
|
736
915
|
{
|
737
916
|
id: "editor",
|
738
917
|
name: "Editor",
|
739
|
-
isAdmin:
|
918
|
+
isAdmin: false,
|
740
919
|
defaultPermissions: {
|
741
|
-
read:
|
742
|
-
create:
|
743
|
-
edit:
|
744
|
-
delete:
|
920
|
+
read: true,
|
921
|
+
create: true,
|
922
|
+
edit: true,
|
923
|
+
delete: true
|
745
924
|
},
|
746
925
|
config: {
|
747
|
-
createCollections:
|
926
|
+
createCollections: true,
|
748
927
|
editCollections: "own",
|
749
928
|
deleteCollections: "own"
|
750
929
|
}
|
@@ -752,78 +931,93 @@ const Se = [
|
|
752
931
|
{
|
753
932
|
id: "viewer",
|
754
933
|
name: "Viewer",
|
755
|
-
isAdmin:
|
934
|
+
isAdmin: false,
|
756
935
|
defaultPermissions: {
|
757
|
-
read:
|
758
|
-
create:
|
759
|
-
edit:
|
760
|
-
delete:
|
936
|
+
read: true,
|
937
|
+
create: false,
|
938
|
+
edit: false,
|
939
|
+
delete: false
|
761
940
|
}
|
762
941
|
}
|
763
942
|
];
|
764
|
-
function
|
765
|
-
onRoleClicked
|
766
|
-
editable
|
943
|
+
function RolesTable({
|
944
|
+
onRoleClicked,
|
945
|
+
editable
|
767
946
|
}) {
|
768
947
|
const {
|
769
|
-
roles
|
770
|
-
saveRole
|
771
|
-
deleteRole
|
772
|
-
allowDefaultRolesCreation
|
773
|
-
} =
|
774
|
-
|
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(
|
775
956
|
"div",
|
776
957
|
{
|
777
958
|
className: "w-full overflow-auto",
|
778
959
|
children: [
|
779
|
-
/* @__PURE__ */
|
780
|
-
/* @__PURE__ */
|
781
|
-
/* @__PURE__ */
|
782
|
-
/* @__PURE__ */
|
783
|
-
/* @__PURE__ */
|
784
|
-
/* @__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" })
|
785
966
|
] }),
|
786
|
-
/* @__PURE__ */
|
787
|
-
|
788
|
-
const
|
789
|
-
|
790
|
-
|
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,
|
791
975
|
{
|
792
976
|
onClick: () => {
|
793
|
-
|
977
|
+
onRoleClicked(role);
|
794
978
|
},
|
795
979
|
children: [
|
796
|
-
/* @__PURE__ */
|
797
|
-
|
980
|
+
/* @__PURE__ */ jsx(TableCell, { style: { width: "64px" }, children: !role.isAdmin && /* @__PURE__ */ jsx(
|
981
|
+
Tooltip,
|
798
982
|
{
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
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
|
+
)
|
803
997
|
}
|
804
|
-
) })
|
805
|
-
/* @__PURE__ */
|
806
|
-
/* @__PURE__ */
|
807
|
-
/* @__PURE__ */
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
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" })
|
812
1006
|
] }) })
|
813
1007
|
]
|
814
1008
|
},
|
815
|
-
|
1009
|
+
role.name
|
816
1010
|
);
|
817
1011
|
}),
|
818
|
-
(!
|
819
|
-
/* @__PURE__ */
|
820
|
-
|
821
|
-
|
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,
|
822
1016
|
{
|
823
1017
|
variant: "outlined",
|
824
1018
|
onClick: () => {
|
825
|
-
|
826
|
-
|
1019
|
+
DEFAULT_ROLES.forEach((role) => {
|
1020
|
+
saveRole(role);
|
827
1021
|
});
|
828
1022
|
},
|
829
1023
|
children: "Create default roles"
|
@@ -832,146 +1026,189 @@ function Ze({
|
|
832
1026
|
] }) }) })
|
833
1027
|
] })
|
834
1028
|
] }),
|
835
|
-
/* @__PURE__ */
|
836
|
-
|
1029
|
+
/* @__PURE__ */ jsx(
|
1030
|
+
DeleteConfirmationDialog,
|
837
1031
|
{
|
838
|
-
open:
|
839
|
-
loading:
|
1032
|
+
open: Boolean(roleToBeDeleted),
|
1033
|
+
loading: deleteInProgress,
|
840
1034
|
onAccept: () => {
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
1035
|
+
if (roleToBeDeleted) {
|
1036
|
+
setDeleteInProgress(true);
|
1037
|
+
deleteRole(roleToBeDeleted).then(() => {
|
1038
|
+
setRoleToBeDeleted(void 0);
|
1039
|
+
}).finally(() => {
|
1040
|
+
setDeleteInProgress(false);
|
1041
|
+
});
|
1042
|
+
}
|
846
1043
|
},
|
847
1044
|
onCancel: () => {
|
848
|
-
|
1045
|
+
setRoleToBeDeleted(void 0);
|
849
1046
|
},
|
850
|
-
title: /* @__PURE__ */
|
851
|
-
body: /* @__PURE__ */
|
1047
|
+
title: /* @__PURE__ */ jsx(Fragment, { children: "Delete?" }),
|
1048
|
+
body: /* @__PURE__ */ jsx(Fragment, { children: "Are you sure you want to delete this role?" })
|
852
1049
|
}
|
853
1050
|
)
|
854
1051
|
]
|
855
1052
|
}
|
856
1053
|
);
|
857
1054
|
}
|
858
|
-
const
|
859
|
-
function({ children
|
860
|
-
const { collections
|
861
|
-
|
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);
|
862
1064
|
}, []);
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
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,
|
868
1074
|
{
|
869
|
-
gutterBottom:
|
1075
|
+
gutterBottom: true,
|
870
1076
|
variant: "h4",
|
871
1077
|
className: "flex-grow",
|
872
1078
|
component: "h4",
|
873
1079
|
children: "Roles"
|
874
1080
|
}
|
875
1081
|
),
|
876
|
-
/* @__PURE__ */
|
877
|
-
|
1082
|
+
/* @__PURE__ */ jsx(
|
1083
|
+
Tooltip,
|
878
1084
|
{
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
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
|
+
)
|
884
1097
|
}
|
885
|
-
)
|
1098
|
+
)
|
886
1099
|
] }),
|
887
|
-
/* @__PURE__ */
|
888
|
-
/* @__PURE__ */
|
889
|
-
|
1100
|
+
/* @__PURE__ */ jsx(RolesTable, { onRoleClicked, editable: Boolean(canEditRoles) }),
|
1101
|
+
/* @__PURE__ */ jsx(
|
1102
|
+
RolesDetailsForm,
|
890
1103
|
{
|
891
|
-
open:
|
892
|
-
role:
|
893
|
-
editable:
|
894
|
-
collections
|
895
|
-
handleClose
|
896
|
-
g(void 0), i(!1);
|
897
|
-
}
|
1104
|
+
open: dialogOpen,
|
1105
|
+
role: selectedRole,
|
1106
|
+
editable: canEditRoles,
|
1107
|
+
collections,
|
1108
|
+
handleClose
|
898
1109
|
},
|
899
|
-
|
1110
|
+
selectedRole?.id ?? "new"
|
900
1111
|
)
|
901
1112
|
] });
|
902
1113
|
}
|
903
|
-
)
|
904
|
-
|
905
|
-
|
906
|
-
|
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)
|
907
1119
|
});
|
908
|
-
function
|
909
|
-
const
|
910
|
-
|
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) {
|
911
1125
|
throw new Error("Only admins can change roles");
|
912
|
-
|
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) {
|
913
1129
|
throw new Error("There must be at least one admin");
|
914
|
-
|
1130
|
+
}
|
1131
|
+
return true;
|
915
1132
|
}
|
916
|
-
function
|
917
|
-
open
|
918
|
-
user:
|
919
|
-
handleClose
|
1133
|
+
function UserDetailsForm({
|
1134
|
+
open,
|
1135
|
+
user: userProp,
|
1136
|
+
handleClose
|
920
1137
|
}) {
|
921
|
-
const
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
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) {
|
929
1150
|
throw new Error("Logged user not found");
|
1151
|
+
}
|
930
1152
|
try {
|
931
|
-
|
932
|
-
|
933
|
-
|
1153
|
+
canUserBeEdited(loggedInUser, savedUser, users, roles, userProp);
|
1154
|
+
return saveUser(savedUser);
|
1155
|
+
} catch (e) {
|
1156
|
+
return Promise.reject(e);
|
934
1157
|
}
|
935
|
-
}, [
|
936
|
-
|
1158
|
+
}, [roles, saveUser, userProp, users, loggedInUser]);
|
1159
|
+
const formex = useCreateFormex({
|
1160
|
+
initialValues: userProp ?? {
|
937
1161
|
displayName: "",
|
938
1162
|
email: "",
|
939
|
-
roles:
|
1163
|
+
roles: roles.filter((r) => r.id === "editor")
|
940
1164
|
},
|
941
|
-
validation: (
|
942
|
-
|
943
|
-
|
944
|
-
|
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
|
+
}, {});
|
945
1173
|
});
|
946
|
-
}
|
947
|
-
|
948
|
-
|
949
|
-
|
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
|
+
});
|
950
1186
|
});
|
951
|
-
}
|
952
|
-
})
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
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,
|
965
1202
|
{
|
966
|
-
open
|
967
|
-
onOpenChange: (
|
1203
|
+
open,
|
1204
|
+
onOpenChange: (open2) => !open2 ? handleClose() : void 0,
|
968
1205
|
maxWidth: "4xl",
|
969
|
-
children: /* @__PURE__ */
|
1206
|
+
children: /* @__PURE__ */ jsx(Formex, { value: formex, children: /* @__PURE__ */ jsxs(
|
970
1207
|
"form",
|
971
1208
|
{
|
972
|
-
onSubmit:
|
1209
|
+
onSubmit: handleSubmit,
|
973
1210
|
autoComplete: "off",
|
974
|
-
noValidate:
|
1211
|
+
noValidate: true,
|
975
1212
|
style: {
|
976
1213
|
display: "flex",
|
977
1214
|
flexDirection: "column",
|
@@ -979,13 +1216,13 @@ function rn({
|
|
979
1216
|
height: "100%"
|
980
1217
|
},
|
981
1218
|
children: [
|
982
|
-
/* @__PURE__ */
|
983
|
-
/* @__PURE__ */
|
1219
|
+
/* @__PURE__ */ jsxs(DialogContent, { className: "h-full flex-grow", children: [
|
1220
|
+
/* @__PURE__ */ jsx(
|
984
1221
|
"div",
|
985
1222
|
{
|
986
1223
|
className: "flex flex-row pt-4 pb-4",
|
987
|
-
children: /* @__PURE__ */
|
988
|
-
|
1224
|
+
children: /* @__PURE__ */ jsx(
|
1225
|
+
Typography,
|
989
1226
|
{
|
990
1227
|
variant: "h4",
|
991
1228
|
className: "flex-grow",
|
@@ -994,80 +1231,77 @@ function rn({
|
|
994
1231
|
)
|
995
1232
|
}
|
996
1233
|
),
|
997
|
-
/* @__PURE__ */
|
998
|
-
/* @__PURE__ */
|
999
|
-
/* @__PURE__ */
|
1000
|
-
|
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,
|
1001
1238
|
{
|
1002
1239
|
name: "displayName",
|
1003
|
-
required:
|
1004
|
-
error:
|
1005
|
-
value:
|
1006
|
-
onChange:
|
1240
|
+
required: true,
|
1241
|
+
error: submitCount > 0 && Boolean(errors.displayName),
|
1242
|
+
value: values.displayName ?? "",
|
1243
|
+
onChange: handleChange,
|
1007
1244
|
"aria-describedby": "name-helper-text",
|
1008
1245
|
label: "Name"
|
1009
1246
|
}
|
1010
1247
|
),
|
1011
|
-
/* @__PURE__ */
|
1248
|
+
/* @__PURE__ */ jsx(FieldCaption, { children: submitCount > 0 && Boolean(errors.displayName) ? errors.displayName : "Name of this user" })
|
1012
1249
|
] }),
|
1013
|
-
/* @__PURE__ */
|
1014
|
-
/* @__PURE__ */
|
1015
|
-
|
1250
|
+
/* @__PURE__ */ jsxs("div", { className: "col-span-12", children: [
|
1251
|
+
/* @__PURE__ */ jsx(
|
1252
|
+
TextField,
|
1016
1253
|
{
|
1017
|
-
required:
|
1018
|
-
error:
|
1254
|
+
required: true,
|
1255
|
+
error: submitCount > 0 && Boolean(errors.email),
|
1019
1256
|
name: "email",
|
1020
|
-
value:
|
1021
|
-
onChange:
|
1257
|
+
value: values.email ?? "",
|
1258
|
+
onChange: handleChange,
|
1022
1259
|
"aria-describedby": "email-helper-text",
|
1023
1260
|
label: "Email"
|
1024
1261
|
}
|
1025
1262
|
),
|
1026
|
-
/* @__PURE__ */
|
1263
|
+
/* @__PURE__ */ jsx(FieldCaption, { children: submitCount > 0 && Boolean(errors.email) ? errors.email : "Email of this user" })
|
1027
1264
|
] }),
|
1028
|
-
/* @__PURE__ */
|
1029
|
-
|
1265
|
+
/* @__PURE__ */ jsx("div", { className: "col-span-12", children: /* @__PURE__ */ jsx(
|
1266
|
+
MultiSelect,
|
1030
1267
|
{
|
1268
|
+
className: "w-full",
|
1031
1269
|
label: "Roles",
|
1032
|
-
value:
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
return x ? /* @__PURE__ */ e("div", { className: "flex flex-wrap space-x-2 space-y-2", children: /* @__PURE__ */ e(X, { role: x }, x?.id) }) : null;
|
1037
|
-
},
|
1038
|
-
children: v.map((h) => /* @__PURE__ */ e(
|
1039
|
-
Be,
|
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,
|
1040
1274
|
{
|
1041
|
-
value:
|
1042
|
-
children: /* @__PURE__ */
|
1275
|
+
value: userRole.id,
|
1276
|
+
children: /* @__PURE__ */ jsx(RoleChip, { role: userRole }, userRole?.id)
|
1043
1277
|
},
|
1044
|
-
|
1278
|
+
userRole.id
|
1045
1279
|
))
|
1046
1280
|
}
|
1047
1281
|
) })
|
1048
1282
|
] })
|
1049
1283
|
] }),
|
1050
|
-
/* @__PURE__ */
|
1051
|
-
/* @__PURE__ */
|
1052
|
-
|
1284
|
+
/* @__PURE__ */ jsxs(DialogActions, { children: [
|
1285
|
+
/* @__PURE__ */ jsx(
|
1286
|
+
Button,
|
1053
1287
|
{
|
1054
1288
|
variant: "text",
|
1055
1289
|
onClick: () => {
|
1056
|
-
|
1290
|
+
handleClose();
|
1057
1291
|
},
|
1058
1292
|
children: "Cancel"
|
1059
1293
|
}
|
1060
1294
|
),
|
1061
|
-
/* @__PURE__ */
|
1062
|
-
|
1295
|
+
/* @__PURE__ */ jsx(
|
1296
|
+
LoadingButton,
|
1063
1297
|
{
|
1064
1298
|
variant: "filled",
|
1065
1299
|
color: "primary",
|
1066
1300
|
type: "submit",
|
1067
|
-
disabled: !
|
1068
|
-
loading:
|
1069
|
-
startIcon: /* @__PURE__ */
|
1070
|
-
children:
|
1301
|
+
disabled: !dirty,
|
1302
|
+
loading: isSubmitting,
|
1303
|
+
startIcon: /* @__PURE__ */ jsx(DoneIcon, {}),
|
1304
|
+
children: isNewUser ? "Create user" : "Update"
|
1071
1305
|
}
|
1072
1306
|
)
|
1073
1307
|
] })
|
@@ -1077,79 +1311,98 @@ function rn({
|
|
1077
1311
|
}
|
1078
1312
|
);
|
1079
1313
|
}
|
1080
|
-
function
|
1314
|
+
function UsersTable({ onUserClicked }) {
|
1081
1315
|
const {
|
1082
|
-
users
|
1083
|
-
saveUser
|
1084
|
-
deleteUser
|
1085
|
-
} =
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
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" })
|
1095
1336
|
] }),
|
1096
|
-
/* @__PURE__ */
|
1097
|
-
|
1098
|
-
const
|
1099
|
-
|
1100
|
-
|
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,
|
1101
1343
|
{
|
1102
1344
|
onClick: () => {
|
1103
|
-
|
1345
|
+
onUserClicked(user);
|
1104
1346
|
},
|
1105
1347
|
children: [
|
1106
|
-
/* @__PURE__ */
|
1107
|
-
|
1348
|
+
/* @__PURE__ */ jsx(TableCell, { className: "w-10", children: /* @__PURE__ */ jsx(
|
1349
|
+
Tooltip,
|
1108
1350
|
{
|
1109
|
-
|
1110
|
-
|
1111
|
-
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
|
+
)
|
1112
1364
|
}
|
1113
|
-
) })
|
1114
|
-
/* @__PURE__ */
|
1115
|
-
/* @__PURE__ */
|
1116
|
-
/* @__PURE__ */
|
1117
|
-
/* @__PURE__ */
|
1118
|
-
(
|
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)
|
1119
1371
|
) }) : null }),
|
1120
|
-
/* @__PURE__ */
|
1372
|
+
/* @__PURE__ */ jsx(TableCell, { children: formattedDate })
|
1121
1373
|
]
|
1122
1374
|
},
|
1123
|
-
"row_" +
|
1375
|
+
"row_" + user.uid
|
1124
1376
|
);
|
1125
1377
|
}),
|
1126
|
-
(!
|
1127
|
-
/* @__PURE__ */
|
1128
|
-
/* @__PURE__ */
|
1129
|
-
|
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,
|
1130
1382
|
{
|
1131
1383
|
variant: "outlined",
|
1132
1384
|
onClick: () => {
|
1133
|
-
if (!
|
1385
|
+
if (!authController.user?.uid) {
|
1134
1386
|
throw Error("UsersTable, authController misconfiguration");
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
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,
|
1142
1395
|
roles: [{ id: "admin", name: "Admin" }],
|
1143
1396
|
created_on: /* @__PURE__ */ new Date()
|
1144
1397
|
}).then(() => {
|
1145
|
-
|
1398
|
+
snackbarController.open({
|
1146
1399
|
type: "success",
|
1147
1400
|
message: "User added successfully"
|
1148
1401
|
});
|
1149
|
-
}).catch((
|
1150
|
-
|
1402
|
+
}).catch((error) => {
|
1403
|
+
snackbarController.open({
|
1151
1404
|
type: "error",
|
1152
|
-
message: "Error adding user: " +
|
1405
|
+
message: "Error adding user: " + error.message
|
1153
1406
|
});
|
1154
1407
|
});
|
1155
1408
|
},
|
@@ -1159,193 +1412,212 @@ function on({ onUserClicked: t }) {
|
|
1159
1412
|
] }) }) })
|
1160
1413
|
] })
|
1161
1414
|
] }),
|
1162
|
-
/* @__PURE__ */
|
1163
|
-
|
1415
|
+
/* @__PURE__ */ jsx(
|
1416
|
+
DeleteConfirmationDialog,
|
1164
1417
|
{
|
1165
|
-
open:
|
1166
|
-
loading:
|
1418
|
+
open: Boolean(userToBeDeleted),
|
1419
|
+
loading: deleteInProgress,
|
1167
1420
|
onAccept: () => {
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
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);
|
1174
1432
|
});
|
1175
|
-
}
|
1176
|
-
U(!1);
|
1177
|
-
}));
|
1433
|
+
}
|
1178
1434
|
},
|
1179
1435
|
onCancel: () => {
|
1180
|
-
|
1436
|
+
setUserToBeDeleted(void 0);
|
1181
1437
|
},
|
1182
|
-
title: /* @__PURE__ */
|
1183
|
-
body: /* @__PURE__ */
|
1438
|
+
title: /* @__PURE__ */ jsx(Fragment, { children: "Delete?" }),
|
1439
|
+
body: /* @__PURE__ */ jsx(Fragment, { children: "Are you sure you want to delete this user?" })
|
1184
1440
|
}
|
1185
1441
|
)
|
1186
1442
|
] });
|
1187
1443
|
}
|
1188
|
-
const
|
1189
|
-
const [
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
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);
|
1193
1456
|
}, []);
|
1194
|
-
return /* @__PURE__ */
|
1195
|
-
|
1196
|
-
/* @__PURE__ */
|
1457
|
+
return /* @__PURE__ */ jsxs(Container, { className: "w-full flex flex-col py-4 gap-4", maxWidth: "6xl", children: [
|
1458
|
+
children,
|
1459
|
+
/* @__PURE__ */ jsxs(
|
1197
1460
|
"div",
|
1198
1461
|
{
|
1199
1462
|
className: "flex items-center mt-12",
|
1200
1463
|
children: [
|
1201
|
-
/* @__PURE__ */
|
1202
|
-
|
1464
|
+
/* @__PURE__ */ jsx(
|
1465
|
+
Typography,
|
1203
1466
|
{
|
1204
|
-
gutterBottom:
|
1467
|
+
gutterBottom: true,
|
1205
1468
|
variant: "h4",
|
1206
1469
|
className: "flex-grow",
|
1207
1470
|
component: "h4",
|
1208
1471
|
children: "Users"
|
1209
1472
|
}
|
1210
1473
|
),
|
1211
|
-
/* @__PURE__ */
|
1212
|
-
|
1474
|
+
/* @__PURE__ */ jsx(
|
1475
|
+
Button,
|
1213
1476
|
{
|
1214
1477
|
size: "large",
|
1215
|
-
disabled:
|
1216
|
-
startIcon: /* @__PURE__ */
|
1217
|
-
onClick: () =>
|
1478
|
+
disabled: reachedUsersLimit,
|
1479
|
+
startIcon: /* @__PURE__ */ jsx(AddIcon, {}),
|
1480
|
+
onClick: () => setDialogOpen(true),
|
1218
1481
|
children: "Add user"
|
1219
1482
|
}
|
1220
1483
|
)
|
1221
1484
|
]
|
1222
1485
|
}
|
1223
1486
|
),
|
1224
|
-
/* @__PURE__ */
|
1225
|
-
/* @__PURE__ */
|
1226
|
-
|
1487
|
+
/* @__PURE__ */ jsx(UsersTable, { onUserClicked }),
|
1488
|
+
/* @__PURE__ */ jsx(
|
1489
|
+
UserDetailsForm,
|
1227
1490
|
{
|
1228
|
-
open:
|
1229
|
-
user:
|
1230
|
-
handleClose
|
1491
|
+
open: dialogOpen ?? false,
|
1492
|
+
user: selectedUser,
|
1493
|
+
handleClose
|
1231
1494
|
},
|
1232
|
-
|
1495
|
+
selectedUser?.uid ?? "new"
|
1233
1496
|
)
|
1234
1497
|
] });
|
1235
1498
|
};
|
1236
|
-
function
|
1237
|
-
const
|
1499
|
+
function useUserManagementPlugin({ userManagement }) {
|
1500
|
+
const noUsers = userManagement.users.length === 0;
|
1501
|
+
const noRoles = userManagement.roles.length === 0;
|
1238
1502
|
return {
|
1239
1503
|
key: "user_management",
|
1240
|
-
loading:
|
1504
|
+
loading: userManagement.loading,
|
1241
1505
|
homePage: {
|
1242
|
-
additionalChildrenStart:
|
1243
|
-
|
1506
|
+
additionalChildrenStart: noUsers || noRoles ? /* @__PURE__ */ jsx(
|
1507
|
+
IntroWidget,
|
1244
1508
|
{
|
1245
|
-
noUsers
|
1246
|
-
noRoles
|
1247
|
-
userManagement
|
1509
|
+
noUsers,
|
1510
|
+
noRoles,
|
1511
|
+
userManagement
|
1248
1512
|
}
|
1249
1513
|
) : void 0
|
1250
1514
|
},
|
1251
1515
|
provider: {
|
1252
|
-
Component:
|
1516
|
+
Component: UserManagementProvider,
|
1253
1517
|
props: {
|
1254
|
-
userManagement
|
1518
|
+
userManagement
|
1255
1519
|
}
|
1256
1520
|
}
|
1257
1521
|
};
|
1258
1522
|
}
|
1259
|
-
function
|
1260
|
-
noUsers
|
1261
|
-
noRoles
|
1262
|
-
userManagement
|
1523
|
+
function IntroWidget({
|
1524
|
+
noUsers,
|
1525
|
+
noRoles,
|
1526
|
+
userManagement
|
1263
1527
|
}) {
|
1264
|
-
const
|
1265
|
-
|
1266
|
-
|
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,
|
1267
1533
|
{
|
1268
1534
|
className: "my-4 flex flex-col px-4 py-6 bg-white dark:bg-slate-800 gap-2",
|
1269
1535
|
children: [
|
1270
|
-
/* @__PURE__ */
|
1271
|
-
/* @__PURE__ */
|
1272
|
-
/* @__PURE__ */
|
1273
|
-
if (!
|
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) {
|
1274
1540
|
throw Error("UsersTable, authController misconfiguration");
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
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
|
+
});
|
1291
1565
|
});
|
1292
|
-
}
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1566
|
+
}
|
1567
|
+
if (noRoles) {
|
1568
|
+
DEFAULT_ROLES.forEach((role) => {
|
1569
|
+
userManagement.saveRole(role);
|
1296
1570
|
});
|
1297
|
-
}
|
1298
|
-
n.saveRole(g);
|
1299
|
-
});
|
1571
|
+
}
|
1300
1572
|
}, children: [
|
1301
|
-
/* @__PURE__ */
|
1302
|
-
|
1573
|
+
/* @__PURE__ */ jsx(AddIcon, {}),
|
1574
|
+
buttonLabel
|
1303
1575
|
] })
|
1304
1576
|
]
|
1305
1577
|
}
|
1306
1578
|
);
|
1307
1579
|
}
|
1308
|
-
const
|
1580
|
+
const userManagementAdminViews = [
|
1309
1581
|
{
|
1310
1582
|
path: "users",
|
1311
1583
|
name: "CMS Users",
|
1312
1584
|
group: "Admin",
|
1313
1585
|
icon: "face",
|
1314
|
-
view: /* @__PURE__ */
|
1586
|
+
view: /* @__PURE__ */ jsx(UsersView, {})
|
1315
1587
|
},
|
1316
1588
|
{
|
1317
1589
|
path: "roles",
|
1318
1590
|
name: "Roles",
|
1319
1591
|
group: "Admin",
|
1320
1592
|
icon: "gpp_good",
|
1321
|
-
view: /* @__PURE__ */
|
1593
|
+
view: /* @__PURE__ */ jsx(RolesView, {})
|
1322
1594
|
}
|
1323
1595
|
];
|
1324
1596
|
export {
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
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
|
1350
1622
|
};
|
1351
1623
|
//# sourceMappingURL=index.es.js.map
|