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