@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.
@@ -1,7 +1,7 @@
1
1
  import React, { useCallback, useState } from "react";
2
2
  import * as Yup from "yup";
3
3
 
4
- import { EntityCollection, FieldCaption, Role, toSnakeCase, } from "@firecms/core";
4
+ import { EntityCollection, FieldCaption, Role, toSnakeCase, useAuthController, User, } from "@firecms/core";
5
5
  import {
6
6
  Button,
7
7
  Checkbox,
@@ -30,6 +30,15 @@ export const RoleYupSchema = Yup.object().shape({
30
30
  name: Yup.string().required("Required")
31
31
  });
32
32
 
33
+ function canRoleBeEdited(loggedUser: User) {
34
+ const loggedUserIsAdmin = loggedUser.roles?.map(r => r.id).includes("admin");
35
+ if (!loggedUserIsAdmin) {
36
+ throw new Error("Only admins can edit roles");
37
+ }
38
+
39
+ return true;
40
+ }
41
+
33
42
  export function RolesDetailsForm({
34
43
  open,
35
44
  role,
@@ -46,27 +55,39 @@ export function RolesDetailsForm({
46
55
 
47
56
  const { saveRole } = useUserManagement();
48
57
  const isNewRole = !role;
58
+ const {
59
+ user: loggedInUser
60
+ } = useAuthController();
49
61
 
50
62
  const [savingError, setSavingError] = useState<Error | undefined>();
51
63
 
52
64
  const onRoleUpdated = useCallback((role: Role) => {
53
65
  setSavingError(undefined);
66
+ if (!loggedInUser) throw new Error("User not found");
67
+ canRoleBeEdited(loggedInUser);
54
68
  return saveRole(role);
55
- }, [saveRole]);
69
+ }, [saveRole, loggedInUser]);
56
70
 
57
71
  const formex = useCreateFormex({
58
72
  initialValues: role ?? {
59
73
  name: ""
60
74
  } as Role,
61
75
  onSubmit: (role: Role, formexController) => {
62
- return onRoleUpdated(role)
63
- .then(() => {
64
- formexController.resetForm({
65
- values: role
76
+ try {
77
+ return onRoleUpdated(role)
78
+ .then(() => {
79
+ formexController.resetForm({
80
+ values: role
81
+ });
82
+ handleClose();
83
+ })
84
+ .catch(e => {
85
+ setSavingError(e);
66
86
  });
67
- handleClose();
68
- })
69
- .catch(e => setSavingError(e));
87
+ } catch (e: any) {
88
+ setSavingError(e);
89
+ return Promise.resolve();
90
+ }
70
91
  },
71
92
  validation: (values) => {
72
93
  return RoleYupSchema.validate(values, { abortEarly: false })
@@ -397,8 +418,8 @@ export function RolesDetailsForm({
397
418
  </DialogContent>
398
419
 
399
420
  <DialogActions position={"sticky"}>
400
- {savingError && <Typography className={"text-red-500"}>
401
- There was an error saving this role
421
+ {savingError && <Typography className={"text-red-500 dark:text-red-500"}>
422
+ {savingError.message ?? "There was an error saving this role"}
402
423
  </Typography>}
403
424
  <Button variant={"text"}
404
425
  onClick={() => {
@@ -2,10 +2,18 @@ import React, { useCallback, useEffect } from "react";
2
2
  import equal from "react-fast-compare"
3
3
 
4
4
  import { UserManagement } from "../types";
5
- import { Authenticator, DataSourceDelegate, Entity, PermissionsBuilder, Role, User } from "@firecms/core";
5
+ import {
6
+ Authenticator,
7
+ DataSourceDelegate,
8
+ Entity,
9
+ PermissionsBuilder,
10
+ removeUndefined,
11
+ Role,
12
+ User
13
+ } from "@firecms/core";
6
14
  import { resolveUserRolePermissions } from "../utils";
7
15
 
8
- type UserWithRoleIds = User & { roles: string[] };
16
+ type UserWithRoleIds = Omit<User, "roles"> & { roles: string[] };
9
17
 
10
18
  export interface UserManagementParams {
11
19
 
@@ -90,7 +98,12 @@ export function useBuildUserManagement({
90
98
  useEffect(() => {
91
99
  if (!dataSourceDelegate || !rolesPath) return;
92
100
  if (dataSourceDelegate.initialised !== undefined && !dataSourceDelegate.initialised) return;
101
+ if (dataSourceDelegate.authenticated !== undefined && !dataSourceDelegate.authenticated) {
102
+ setRolesLoading(false);
103
+ return;
104
+ }
93
105
 
106
+ setRolesLoading(true);
94
107
  return dataSourceDelegate.listenCollection?.({
95
108
  path: rolesPath,
96
109
  onUpdate(entities: Entity<any>[]): void {
@@ -114,12 +127,17 @@ export function useBuildUserManagement({
114
127
  }
115
128
  });
116
129
 
117
- }, [dataSourceDelegate?.initialised, rolesPath]);
130
+ }, [dataSourceDelegate?.initialised, dataSourceDelegate?.authenticated, rolesPath]);
118
131
 
119
132
  useEffect(() => {
120
133
  if (!dataSourceDelegate || !usersPath) return;
121
134
  if (dataSourceDelegate.initialised !== undefined && !dataSourceDelegate.initialised) return;
135
+ if (dataSourceDelegate.authenticated !== undefined && !dataSourceDelegate.authenticated) {
136
+ setUsersLoading(false);
137
+ return;
138
+ }
122
139
 
140
+ setUsersLoading(true);
123
141
  return dataSourceDelegate.listenCollection?.({
124
142
  path: usersPath,
125
143
  onUpdate(entities: Entity<any>[]): void {
@@ -143,7 +161,7 @@ export function useBuildUserManagement({
143
161
  }
144
162
  });
145
163
 
146
- }, [dataSourceDelegate?.initialised, usersPath]);
164
+ }, [dataSourceDelegate?.initialised, dataSourceDelegate?.authenticated, usersPath]);
147
165
 
148
166
  const saveUser = useCallback(async (user: User): Promise<User> => {
149
167
  if (!dataSourceDelegate) throw Error("useBuildUserManagement Firebase not initialised");
@@ -154,15 +172,22 @@ export function useBuildUserManagement({
154
172
  const roleIds = user.roles?.map(r => r.id);
155
173
  const email = user.email?.toLowerCase().trim();
156
174
  if (!email) throw Error("Email is required");
175
+
176
+ const userExists = users.find(u => u.email?.toLowerCase() === email);
157
177
  const data = {
158
178
  ...user,
159
- roles: roleIds
179
+ roles: roleIds ?? []
160
180
  };
181
+ if (!userExists) {
182
+ // @ts-ignore
183
+ data.created_on = new Date();
184
+ }
185
+
161
186
  return dataSourceDelegate.saveEntity({
162
187
  status: "existing",
163
188
  path: usersPath,
164
189
  entityId: email,
165
- values: data
190
+ values: removeUndefined(data)
166
191
  }).then(() => user);
167
192
  }, [usersPath, dataSourceDelegate?.initialised]);
168
193
 
@@ -178,7 +203,7 @@ export function useBuildUserManagement({
178
203
  status: "existing",
179
204
  path: rolesPath,
180
205
  entityId: id,
181
- values: roleData
206
+ values: removeUndefined(roleData)
182
207
  }).then(() => {
183
208
  return;
184
209
  });
@@ -243,7 +268,7 @@ export function useBuildUserManagement({
243
268
  }
244
269
 
245
270
  throw Error("Could not find a user with the provided email in the user management system.");
246
- }, [loading, users]);
271
+ }, [loading, users, usersError, rolesError]);
247
272
 
248
273
  const isAdmin = roles.some(r => r.id === "admin");
249
274
 
@@ -50,8 +50,9 @@ function resolveCollectionRole(role: Role, id: string): Permissions {
50
50
  edit: role.isAdmin || role.defaultPermissions?.edit,
51
51
  delete: role.isAdmin || role.defaultPermissions?.delete
52
52
  };
53
- if (role.collectionPermissions && role.collectionPermissions[id]) {
54
- return mergePermissions(role.collectionPermissions[id], basePermissions);
53
+ const thisCollectionPermissions = role.collectionPermissions?.[id];
54
+ if (thisCollectionPermissions) {
55
+ return mergePermissions(thisCollectionPermissions, basePermissions);
55
56
  } else if (role.defaultPermissions) {
56
57
  return mergePermissions(role.defaultPermissions, basePermissions);
57
58
  } else {