@firecms/user_management 3.0.0-canary.84 → 3.0.0-canary.85
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/hooks/index.d.ts +1 -1
- package/dist/hooks/{useFirestoreUserManagement.d.ts → useBuildUserManagement.d.ts} +6 -7
- package/dist/index.es.js +96 -83
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +95 -81
- package/dist/index.umd.js.map +1 -1
- package/package.json +8 -9
- package/src/hooks/index.ts +1 -1
- package/src/hooks/{useFirestoreUserManagement.tsx → useBuildUserManagement.tsx} +102 -92
@@ -1,33 +1,23 @@
|
|
1
1
|
import React, { useCallback, useEffect } from "react";
|
2
|
-
import {
|
3
|
-
addDoc,
|
4
|
-
collection,
|
5
|
-
deleteDoc,
|
6
|
-
doc,
|
7
|
-
DocumentSnapshot,
|
8
|
-
getFirestore,
|
9
|
-
onSnapshot,
|
10
|
-
setDoc
|
11
|
-
} from "@firebase/firestore";
|
12
|
-
import { FirebaseApp } from "@firebase/app";
|
13
2
|
import { UserManagement } from "../types";
|
14
|
-
import { Authenticator, PermissionsBuilder, Role, User } from "@firecms/core";
|
3
|
+
import { Authenticator, DataSourceDelegate, Entity, PermissionsBuilder, Role, User } from "@firecms/core";
|
15
4
|
import { resolveUserRolePermissions } from "../utils";
|
16
5
|
|
17
6
|
type UserWithRoleIds = User & { roles: string[] };
|
18
7
|
|
19
8
|
export interface UserManagementParams {
|
9
|
+
|
20
10
|
/**
|
21
|
-
* The
|
22
|
-
* collection indicated by `configPath`.
|
11
|
+
* The delegate in charge of persisting the data.
|
23
12
|
*/
|
24
|
-
|
13
|
+
dataSourceDelegate?: DataSourceDelegate;
|
14
|
+
|
25
15
|
/**
|
26
16
|
* Path where the plugin users configuration is stored.
|
27
17
|
* Default: __FIRECMS/config/users
|
28
18
|
* You can specify a different path if you want to store the user management configuration in a different place.
|
29
19
|
* Please keep in mind that the FireCMS users are not necessarily the same as the Firebase users (but they can be).
|
30
|
-
* The path should be relative to the root of the
|
20
|
+
* The path should be relative to the root of the database, and should always have an odd number of segments.
|
31
21
|
*/
|
32
22
|
usersPath?: string;
|
33
23
|
|
@@ -62,14 +52,14 @@ export interface UserManagementParams {
|
|
62
52
|
/**
|
63
53
|
* This hook is used to build a user management object that can be used to
|
64
54
|
* manage users and roles in a Firestore backend.
|
65
|
-
* @param
|
55
|
+
* @param dataSourceDelegate
|
66
56
|
* @param usersPath
|
67
57
|
* @param rolesPath
|
68
58
|
* @param usersLimit
|
69
59
|
* @param canEditRoles
|
70
60
|
*/
|
71
|
-
export function
|
72
|
-
|
61
|
+
export function useBuildUserManagement({
|
62
|
+
dataSourceDelegate,
|
73
63
|
usersPath = "__FIRECMS/config/users",
|
74
64
|
rolesPath = "__FIRECMS/config/roles",
|
75
65
|
usersLimit,
|
@@ -94,62 +84,61 @@ export function useFirestoreUserManagement({
|
|
94
84
|
const loading = rolesLoading || usersLoading;
|
95
85
|
|
96
86
|
useEffect(() => {
|
97
|
-
if (!
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
{
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
} catch (e) {
|
108
|
-
console.error("Error loading roles", e);
|
109
|
-
setRolesError(e as Error);
|
110
|
-
}
|
111
|
-
setRolesLoading(false);
|
112
|
-
},
|
113
|
-
error: (e) => {
|
87
|
+
if (!dataSourceDelegate || !rolesPath) return;
|
88
|
+
|
89
|
+
dataSourceDelegate.listenCollection?.({
|
90
|
+
path: rolesPath,
|
91
|
+
onUpdate(entities: Entity<any>[]): void {
|
92
|
+
setRolesError(undefined);
|
93
|
+
try {
|
94
|
+
const newRoles = entityToRoles(entities);
|
95
|
+
setRoles(newRoles);
|
96
|
+
} catch (e) {
|
114
97
|
console.error("Error loading roles", e);
|
115
|
-
setRolesError(e);
|
116
|
-
setRolesLoading(false);
|
98
|
+
setRolesError(e as Error);
|
117
99
|
}
|
100
|
+
setRolesLoading(false);
|
101
|
+
},
|
102
|
+
onError(e: any): void {
|
103
|
+
console.error("Error loading roles", e);
|
104
|
+
setRolesError(e);
|
105
|
+
setRolesLoading(false);
|
118
106
|
}
|
119
|
-
);
|
120
|
-
|
107
|
+
});
|
108
|
+
|
109
|
+
}, [dataSourceDelegate, rolesPath]);
|
121
110
|
|
122
111
|
useEffect(() => {
|
123
|
-
if (!
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
{
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
} catch (e) {
|
134
|
-
console.error("Error loading users", e);
|
135
|
-
setUsersError(e as Error);
|
136
|
-
}
|
137
|
-
setUsersLoading(false);
|
138
|
-
},
|
139
|
-
error: (e) => {
|
112
|
+
if (!dataSourceDelegate || !usersPath) return;
|
113
|
+
|
114
|
+
dataSourceDelegate.listenCollection?.({
|
115
|
+
path: usersPath,
|
116
|
+
onUpdate(entities: Entity<any>[]): void {
|
117
|
+
setUsersError(undefined);
|
118
|
+
try {
|
119
|
+
const newUsers = entitiesToUsers(entities);
|
120
|
+
setUsersWithRoleIds(newUsers);
|
121
|
+
} catch (e) {
|
140
122
|
console.error("Error loading users", e);
|
141
|
-
setUsersError(e);
|
142
|
-
setUsersLoading(false);
|
123
|
+
setUsersError(e as Error);
|
143
124
|
}
|
125
|
+
setUsersLoading(false);
|
126
|
+
},
|
127
|
+
onError(e: any): void {
|
128
|
+
console.error("Error loading users", e);
|
129
|
+
setUsersError(e);
|
130
|
+
setUsersLoading(false);
|
144
131
|
}
|
145
|
-
);
|
146
|
-
|
132
|
+
});
|
133
|
+
|
134
|
+
}, [dataSourceDelegate, usersPath]);
|
147
135
|
|
148
136
|
const saveUser = useCallback(async (user: User): Promise<User> => {
|
149
|
-
if (!
|
150
|
-
|
151
|
-
|
137
|
+
if (!dataSourceDelegate) throw Error("useFirestoreUserManagement Firebase not initialised");
|
138
|
+
if (!usersPath) throw Error("useFirestoreUserManagement Firestore not initialised");
|
139
|
+
|
152
140
|
console.debug("Persisting user", user);
|
141
|
+
|
153
142
|
const roleIds = user.roles?.map(r => r.id);
|
154
143
|
const {
|
155
144
|
uid,
|
@@ -160,43 +149,64 @@ export function useFirestoreUserManagement({
|
|
160
149
|
roles: roleIds
|
161
150
|
};
|
162
151
|
if (uid) {
|
163
|
-
return
|
152
|
+
return dataSourceDelegate.saveEntity({
|
153
|
+
status: "existing",
|
154
|
+
path: usersPath,
|
155
|
+
entityId: uid,
|
156
|
+
values: data
|
157
|
+
}).then(() => user);
|
164
158
|
} else {
|
165
|
-
return
|
159
|
+
return dataSourceDelegate.saveEntity({
|
160
|
+
status: "new",
|
161
|
+
path: usersPath,
|
162
|
+
values: data
|
163
|
+
}).then(() => user);
|
166
164
|
}
|
167
|
-
}, [usersPath,
|
165
|
+
}, [usersPath, dataSourceDelegate]);
|
168
166
|
|
169
167
|
const saveRole = useCallback((role: Role): Promise<void> => {
|
170
|
-
if (!
|
171
|
-
|
172
|
-
if (!firestore || !rolesPath) throw Error("useFirestoreUserManagement Firestore not initialised");
|
168
|
+
if (!dataSourceDelegate) throw Error("useFirestoreUserManagement Firebase not initialised");
|
169
|
+
if (!rolesPath) throw Error("useFirestoreUserManagement Firestore not initialised");
|
173
170
|
console.debug("Persisting role", role);
|
174
171
|
const {
|
175
172
|
id,
|
176
173
|
...roleData
|
177
174
|
} = role;
|
178
|
-
|
179
|
-
|
180
|
-
|
175
|
+
return dataSourceDelegate.saveEntity({
|
176
|
+
status: "existing",
|
177
|
+
path: rolesPath,
|
178
|
+
entityId: id,
|
179
|
+
values: roleData
|
180
|
+
}).then(() => {
|
181
|
+
return;
|
182
|
+
});
|
183
|
+
}, [rolesPath, dataSourceDelegate]);
|
181
184
|
|
182
185
|
const deleteUser = useCallback(async (user: User): Promise<void> => {
|
183
|
-
if (!
|
184
|
-
|
185
|
-
if (!firestore || !usersPath) throw Error("useFirestoreUserManagement Firestore not initialised");
|
186
|
+
if (!dataSourceDelegate) throw Error("useFirestoreUserManagement Firebase not initialised");
|
187
|
+
if (!usersPath) throw Error("useFirestoreUserManagement Firestore not initialised");
|
186
188
|
console.debug("Deleting", user);
|
187
189
|
const { uid } = user;
|
188
|
-
|
189
|
-
|
190
|
+
const entity: Entity<any> = {
|
191
|
+
path: usersPath,
|
192
|
+
id: uid,
|
193
|
+
values: {}
|
194
|
+
};
|
195
|
+
await dataSourceDelegate.deleteEntity({ entity })
|
196
|
+
}, [usersPath, dataSourceDelegate]);
|
190
197
|
|
191
|
-
const deleteRole = useCallback((role: Role): Promise<void> => {
|
192
|
-
if (!
|
193
|
-
|
194
|
-
if (!firestore || !rolesPath) throw Error("useFirestoreUserManagement Firestore not initialised");
|
198
|
+
const deleteRole = useCallback(async (role: Role): Promise<void> => {
|
199
|
+
if (!dataSourceDelegate) throw Error("useFirestoreUserManagement Firebase not initialised");
|
200
|
+
if (!rolesPath) throw Error("useFirestoreUserManagement Firestore not initialised");
|
195
201
|
console.debug("Deleting", role);
|
196
202
|
const { id } = role;
|
197
|
-
const
|
198
|
-
|
199
|
-
|
203
|
+
const entity: Entity<any> = {
|
204
|
+
path: usersPath,
|
205
|
+
id: id,
|
206
|
+
values: {}
|
207
|
+
};
|
208
|
+
await dataSourceDelegate.deleteEntity({ entity })
|
209
|
+
}, [rolesPath, dataSourceDelegate]);
|
200
210
|
|
201
211
|
const collectionPermissions: PermissionsBuilder = useCallback(({
|
202
212
|
collection,
|
@@ -256,22 +266,22 @@ export function useFirestoreUserManagement({
|
|
256
266
|
}
|
257
267
|
}
|
258
268
|
|
259
|
-
const
|
269
|
+
const entitiesToUsers = (docs: Entity<Omit<UserWithRoleIds, "id">>[]): (UserWithRoleIds)[] => {
|
260
270
|
return docs.map((doc) => {
|
261
|
-
const data = doc.
|
271
|
+
const data = doc.values as any;
|
262
272
|
const newVar = {
|
263
273
|
uid: doc.id,
|
264
274
|
...data,
|
265
|
-
created_on: data?.created_on
|
266
|
-
updated_on: data?.updated_on
|
275
|
+
created_on: data?.created_on,
|
276
|
+
updated_on: data?.updated_on
|
267
277
|
};
|
268
278
|
return newVar as (UserWithRoleIds);
|
269
279
|
});
|
270
280
|
}
|
271
281
|
|
272
|
-
const
|
273
|
-
return
|
282
|
+
const entityToRoles = (entities: Entity<Omit<Role, "id">>[]): Role[] => {
|
283
|
+
return entities.map((doc) => ({
|
274
284
|
id: doc.id,
|
275
|
-
...doc.
|
285
|
+
...doc.values
|
276
286
|
} as Role));
|
277
287
|
}
|