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