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