@firecms/user_management 3.0.0-canary.117 → 3.0.0-canary.119

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/dist/index.es.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import React, { useEffect, useCallback, useContext, useState } from "react";
2
2
  import equal from "react-fast-compare";
3
+ import { removeUndefined, useAuthController, toSnakeCase, FieldCaption, DeleteConfirmationDialog, useNavigationController, useSnackbarController, useCustomizationController, defaultDateFormat } from "@firecms/core";
3
4
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
4
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";
5
6
  import * as Yup from "yup";
6
- import { toSnakeCase, FieldCaption, DeleteConfirmationDialog, useNavigationController, useSnackbarController, useAuthController, useCustomizationController, defaultDateFormat } from "@firecms/core";
7
7
  import { useCreateFormex, getIn, Formex } from "@firecms/formex";
8
8
  import { format } from "date-fns";
9
9
  import * as locales from "date-fns/locale";
@@ -45,8 +45,9 @@ function resolveCollectionRole(role, id) {
45
45
  edit: role.isAdmin || role.defaultPermissions?.edit,
46
46
  delete: role.isAdmin || role.defaultPermissions?.delete
47
47
  };
48
- if (role.collectionPermissions && role.collectionPermissions[id]) {
49
- return mergePermissions(role.collectionPermissions[id], basePermissions);
48
+ const thisCollectionPermissions = role.collectionPermissions?.[id];
49
+ if (thisCollectionPermissions) {
50
+ return mergePermissions(thisCollectionPermissions, basePermissions);
50
51
  } else if (role.defaultPermissions) {
51
52
  return mergePermissions(role.defaultPermissions, basePermissions);
52
53
  } else {
@@ -163,6 +164,11 @@ function useBuildUserManagement({
163
164
  useEffect(() => {
164
165
  if (!dataSourceDelegate || !rolesPath) return;
165
166
  if (dataSourceDelegate.initialised !== void 0 && !dataSourceDelegate.initialised) return;
167
+ if (dataSourceDelegate.authenticated !== void 0 && !dataSourceDelegate.authenticated) {
168
+ setRolesLoading(false);
169
+ return;
170
+ }
171
+ setRolesLoading(true);
166
172
  return dataSourceDelegate.listenCollection?.({
167
173
  path: rolesPath,
168
174
  onUpdate(entities) {
@@ -185,10 +191,15 @@ function useBuildUserManagement({
185
191
  setRolesLoading(false);
186
192
  }
187
193
  });
188
- }, [dataSourceDelegate?.initialised, rolesPath]);
194
+ }, [dataSourceDelegate?.initialised, dataSourceDelegate?.authenticated, rolesPath]);
189
195
  useEffect(() => {
190
196
  if (!dataSourceDelegate || !usersPath) return;
191
197
  if (dataSourceDelegate.initialised !== void 0 && !dataSourceDelegate.initialised) return;
198
+ if (dataSourceDelegate.authenticated !== void 0 && !dataSourceDelegate.authenticated) {
199
+ setUsersLoading(false);
200
+ return;
201
+ }
202
+ setUsersLoading(true);
192
203
  return dataSourceDelegate.listenCollection?.({
193
204
  path: usersPath,
194
205
  onUpdate(entities) {
@@ -211,7 +222,7 @@ function useBuildUserManagement({
211
222
  setUsersLoading(false);
212
223
  }
213
224
  });
214
- }, [dataSourceDelegate?.initialised, usersPath]);
225
+ }, [dataSourceDelegate?.initialised, dataSourceDelegate?.authenticated, usersPath]);
215
226
  const saveUser = useCallback(async (user) => {
216
227
  if (!dataSourceDelegate) throw Error("useBuildUserManagement Firebase not initialised");
217
228
  if (!usersPath) throw Error("useBuildUserManagement Firestore not initialised");
@@ -219,15 +230,19 @@ function useBuildUserManagement({
219
230
  const roleIds = user.roles?.map((r) => r.id);
220
231
  const email = user.email?.toLowerCase().trim();
221
232
  if (!email) throw Error("Email is required");
233
+ const userExists = users.find((u) => u.email?.toLowerCase() === email);
222
234
  const data = {
223
235
  ...user,
224
- roles: roleIds
236
+ roles: roleIds ?? []
225
237
  };
238
+ if (!userExists) {
239
+ data.created_on = /* @__PURE__ */ new Date();
240
+ }
226
241
  return dataSourceDelegate.saveEntity({
227
242
  status: "existing",
228
243
  path: usersPath,
229
244
  entityId: email,
230
- values: data
245
+ values: removeUndefined(data)
231
246
  }).then(() => user);
232
247
  }, [usersPath, dataSourceDelegate?.initialised]);
233
248
  const saveRole = useCallback((role) => {
@@ -242,7 +257,7 @@ function useBuildUserManagement({
242
257
  status: "existing",
243
258
  path: rolesPath,
244
259
  entityId: id,
245
- values: roleData
260
+ values: removeUndefined(roleData)
246
261
  }).then(() => {
247
262
  return;
248
263
  });
@@ -297,7 +312,7 @@ function useBuildUserManagement({
297
312
  return true;
298
313
  }
299
314
  throw Error("Could not find a user with the provided email in the user management system.");
300
- }, [loading, users]);
315
+ }, [loading, users, usersError, rolesError]);
301
316
  const isAdmin = roles.some((r) => r.id === "admin");
302
317
  return {
303
318
  loading,
@@ -369,6 +384,13 @@ const RoleYupSchema = Yup.object().shape({
369
384
  id: Yup.string().required("Required"),
370
385
  name: Yup.string().required("Required")
371
386
  });
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
+ }
372
394
  function RolesDetailsForm({
373
395
  open,
374
396
  role,
@@ -378,22 +400,34 @@ function RolesDetailsForm({
378
400
  }) {
379
401
  const { saveRole } = useUserManagement();
380
402
  const isNewRole = !role;
403
+ const {
404
+ user: loggedInUser
405
+ } = useAuthController();
381
406
  const [savingError, setSavingError] = useState();
382
407
  const onRoleUpdated = useCallback((role2) => {
383
408
  setSavingError(void 0);
409
+ if (!loggedInUser) throw new Error("User not found");
410
+ canRoleBeEdited(loggedInUser);
384
411
  return saveRole(role2);
385
- }, [saveRole]);
412
+ }, [saveRole, loggedInUser]);
386
413
  const formex = useCreateFormex({
387
414
  initialValues: role ?? {
388
415
  name: ""
389
416
  },
390
417
  onSubmit: (role2, formexController) => {
391
- return onRoleUpdated(role2).then(() => {
392
- formexController.resetForm({
393
- values: role2
418
+ try {
419
+ return onRoleUpdated(role2).then(() => {
420
+ formexController.resetForm({
421
+ values: role2
422
+ });
423
+ handleClose();
424
+ }).catch((e) => {
425
+ setSavingError(e);
394
426
  });
395
- handleClose();
396
- }).catch((e) => setSavingError(e));
427
+ } catch (e) {
428
+ setSavingError(e);
429
+ return Promise.resolve();
430
+ }
397
431
  },
398
432
  validation: (values2) => {
399
433
  return RoleYupSchema.validate(values2, { abortEarly: false }).then(() => ({})).catch((e) => {
@@ -842,7 +876,7 @@ function RolesDetailsForm({
842
876
  ] })
843
877
  ] }),
844
878
  /* @__PURE__ */ jsxs(DialogActions, { position: "sticky", children: [
845
- savingError && /* @__PURE__ */ jsx(Typography, { className: "text-red-500", children: "There was an error saving this role" }),
879
+ savingError && /* @__PURE__ */ jsx(Typography, { className: "text-red-500 dark:text-red-500", children: savingError.message ?? "There was an error saving this role" }),
846
880
  /* @__PURE__ */ jsx(
847
881
  Button,
848
882
  {