@firecms/user_management 3.0.0-beta.4.pre.2 → 3.0.0-beta.5
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/UserManagementProvider.d.ts +4 -3
- package/dist/components/roles/RoleChip.d.ts +1 -1
- package/dist/components/roles/RolesDetailsForm.d.ts +1 -2
- package/dist/components/roles/RolesTable.d.ts +1 -1
- package/dist/components/roles/default_roles.d.ts +1 -1
- package/dist/components/users/UserDetailsForm.d.ts +2 -2
- package/dist/components/users/UsersTable.d.ts +2 -2
- package/dist/hooks/useBuildFirestoreUserManagement.d.ts +1 -3
- package/dist/hooks/useUserManagement.d.ts +3 -2
- package/dist/index.es.js +461 -443
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/types/index.d.ts +1 -2
- package/dist/types/persisted_user.d.ts +5 -0
- package/dist/types/user_management.d.ts +12 -10
- package/dist/utils/permissions.d.ts +3 -4
- package/package.json +7 -9
- package/src/UserManagementProvider.tsx +4 -3
- package/src/components/roles/RoleChip.tsx +1 -1
- package/src/components/roles/RolesDetailsForm.tsx +1 -2
- package/src/components/roles/RolesTable.tsx +1 -2
- package/src/components/roles/RolesView.tsx +1 -2
- package/src/components/roles/default_roles.tsx +1 -1
- package/src/components/users/UserDetailsForm.tsx +14 -13
- package/src/components/users/UsersTable.tsx +6 -6
- package/src/components/users/UsersView.tsx +3 -3
- package/src/hooks/useBuildFirestoreUserManagement.tsx +53 -23
- package/src/hooks/useUserManagement.tsx +3 -3
- package/src/types/index.ts +1 -2
- package/src/types/persisted_user.ts +6 -0
- package/src/types/user_management.tsx +14 -11
- package/src/useUserManagementPlugin.tsx +2 -2
- package/src/utils/permissions.ts +7 -5
- package/dist/types/firecms_user.d.ts +0 -7
- package/dist/types/roles.d.ts +0 -31
- package/src/types/firecms_user.ts +0 -8
- package/src/types/roles.ts +0 -41
- package/tailwind.config.js +0 -68
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@firecms/user_management",
|
3
3
|
"type": "module",
|
4
|
-
"version": "3.0.0-beta.
|
4
|
+
"version": "3.0.0-beta.5",
|
5
5
|
"publishConfig": {
|
6
6
|
"access": "public"
|
7
7
|
},
|
@@ -22,8 +22,7 @@
|
|
22
22
|
"require": "./dist/index.umd.js",
|
23
23
|
"types": "./dist/index.d.ts"
|
24
24
|
},
|
25
|
-
"./package.json": "./package.json"
|
26
|
-
"./tailwind.config.js": "./tailwind.config.js"
|
25
|
+
"./package.json": "./package.json"
|
27
26
|
},
|
28
27
|
"packageManager": "yarn@4.1.0",
|
29
28
|
"main": "./dist/index.umd.js",
|
@@ -31,9 +30,9 @@
|
|
31
30
|
"types": "dist/index.d.ts",
|
32
31
|
"source": "src/index.ts",
|
33
32
|
"dependencies": {
|
34
|
-
"@firecms/core": "^3.0.0-beta.
|
35
|
-
"@firecms/formex": "^3.0.0-beta.
|
36
|
-
"@firecms/ui": "^3.0.0-beta.
|
33
|
+
"@firecms/core": "^3.0.0-beta.5",
|
34
|
+
"@firecms/formex": "^3.0.0-beta.5",
|
35
|
+
"@firecms/ui": "^3.0.0-beta.5",
|
37
36
|
"date-fns": "^3.6.0"
|
38
37
|
},
|
39
38
|
"peerDependencies": {
|
@@ -54,7 +53,7 @@
|
|
54
53
|
"eslint-plugin-react": "^7.34.1",
|
55
54
|
"eslint-plugin-react-hooks": "^4.6.0",
|
56
55
|
"typescript": "^5.4.2",
|
57
|
-
"vite": "^5.
|
56
|
+
"vite": "^5.2.3"
|
58
57
|
},
|
59
58
|
"scripts": {
|
60
59
|
"dev": "vite",
|
@@ -64,7 +63,6 @@
|
|
64
63
|
"files": [
|
65
64
|
"dist",
|
66
65
|
"src",
|
67
|
-
"tailwind.config.js",
|
68
66
|
"bin"
|
69
67
|
],
|
70
68
|
"eslintConfig": {
|
@@ -73,5 +71,5 @@
|
|
73
71
|
"react-app/jest"
|
74
72
|
]
|
75
73
|
},
|
76
|
-
"gitHead": "
|
74
|
+
"gitHead": "8bf864185c9617aa3f120e59c873c8b8bda8dac4"
|
77
75
|
}
|
@@ -1,13 +1,14 @@
|
|
1
1
|
import React, { PropsWithChildren } from "react";
|
2
|
-
import { UserManagement
|
2
|
+
import { UserManagement } from "./types";
|
3
|
+
import { User } from "@firecms/core";
|
3
4
|
|
4
5
|
export const UserManagementContext = React.createContext<UserManagement<any>>({} as any);
|
5
6
|
|
6
|
-
export interface UserManagementProviderProps<U extends
|
7
|
+
export interface UserManagementProviderProps<U extends User = User> {
|
7
8
|
userManagement: UserManagement<U>
|
8
9
|
}
|
9
10
|
|
10
|
-
export function UserManagementProvider<U extends
|
11
|
+
export function UserManagementProvider<U extends User = User>({
|
11
12
|
children,
|
12
13
|
userManagement
|
13
14
|
}: PropsWithChildren<UserManagementProviderProps<U>>) {
|
@@ -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, toSnakeCase, } from "@firecms/core";
|
4
|
+
import { EntityCollection, FieldCaption, Role, toSnakeCase, } from "@firecms/core";
|
5
5
|
import {
|
6
6
|
Button,
|
7
7
|
Checkbox,
|
@@ -24,7 +24,6 @@ import {
|
|
24
24
|
} from "@firecms/ui";
|
25
25
|
import { useUserManagement } from "../../hooks";
|
26
26
|
import { Formex, getIn, useCreateFormex } from "@firecms/formex";
|
27
|
-
import { Role } from "../../types";
|
28
27
|
|
29
28
|
export const RoleYupSchema = Yup.object().shape({
|
30
29
|
id: Yup.string().required("Required"),
|
@@ -13,9 +13,8 @@ import {
|
|
13
13
|
Tooltip,
|
14
14
|
Typography
|
15
15
|
} from "@firecms/ui";
|
16
|
-
import { DeleteConfirmationDialog } from "@firecms/core";
|
16
|
+
import { DeleteConfirmationDialog, Role } from "@firecms/core";
|
17
17
|
import { useUserManagement } from "../../hooks";
|
18
|
-
import { Role } from "../../types";
|
19
18
|
import { RoleChip } from "./RoleChip";
|
20
19
|
import { DEFAULT_ROLES } from "./default_roles";
|
21
20
|
|
@@ -1,11 +1,10 @@
|
|
1
1
|
import React, { useCallback, useState } from "react";
|
2
2
|
|
3
|
-
import { useNavigationController } from "@firecms/core";
|
3
|
+
import { Role, useNavigationController } from "@firecms/core";
|
4
4
|
import { AddIcon, Button, Container, Tooltip, Typography } from "@firecms/ui";
|
5
5
|
import { RolesTable } from "./RolesTable";
|
6
6
|
import { RolesDetailsForm } from "./RolesDetailsForm";
|
7
7
|
import { useUserManagement } from "../../hooks";
|
8
|
-
import { Role } from "../../types";
|
9
8
|
|
10
9
|
export const RolesView = React.memo(
|
11
10
|
function RolesView({ children }: { children?: React.ReactNode }) {
|
@@ -12,10 +12,9 @@ import {
|
|
12
12
|
TextField,
|
13
13
|
Typography,
|
14
14
|
} from "@firecms/ui";
|
15
|
-
import { FieldCaption, useSnackbarController } from "@firecms/core";
|
15
|
+
import { FieldCaption, Role, useAuthController, User, useSnackbarController } from "@firecms/core";
|
16
16
|
import { Formex, useCreateFormex } from "@firecms/formex";
|
17
17
|
|
18
|
-
import { Role, UserWithRoles } from "../../types";
|
19
18
|
import { areRolesEqual } from "../../utils";
|
20
19
|
import { useUserManagement } from "../../hooks";
|
21
20
|
import { RoleChip } from "../roles";
|
@@ -26,17 +25,17 @@ export const UserYupSchema = Yup.object().shape({
|
|
26
25
|
roles: Yup.array().min(1)
|
27
26
|
});
|
28
27
|
|
29
|
-
function canUserBeEdited(loggedUser:
|
30
|
-
const admins = users.filter(u => u.roles
|
31
|
-
const loggedUserIsAdmin = loggedUser.roles
|
32
|
-
const didRolesChange = !prevUser || !areRolesEqual(prevUser.roles, user.roles);
|
28
|
+
function canUserBeEdited(loggedUser: User, user: User, users: User[], roles: Role[], prevUser?: User) {
|
29
|
+
const admins = users.filter(u => u.roles?.map(r => r.id).includes("admin"));
|
30
|
+
const loggedUserIsAdmin = loggedUser.roles?.map(r => r.id).includes("admin");
|
31
|
+
const didRolesChange = !prevUser || !areRolesEqual(prevUser.roles ?? [], user.roles ?? []);
|
33
32
|
|
34
33
|
if (didRolesChange && !loggedUserIsAdmin) {
|
35
34
|
throw new Error("Only admins can change roles");
|
36
35
|
}
|
37
36
|
|
38
37
|
// was the admin role removed
|
39
|
-
const adminRoleRemoved = prevUser && prevUser.roles
|
38
|
+
const adminRoleRemoved = prevUser && prevUser.roles?.map(r => r.id).includes("admin") && !user.roles?.map(r => r.id).includes("admin");
|
40
39
|
|
41
40
|
// avoid removing the last admin
|
42
41
|
if (adminRoleRemoved && admins.length === 1) {
|
@@ -51,20 +50,22 @@ export function UserDetailsForm({
|
|
51
50
|
handleClose
|
52
51
|
}: {
|
53
52
|
open: boolean,
|
54
|
-
user?:
|
53
|
+
user?: User,
|
55
54
|
handleClose: () => void
|
56
55
|
}) {
|
57
56
|
|
58
57
|
const snackbarController = useSnackbarController();
|
59
58
|
const {
|
60
|
-
loggedInUser
|
59
|
+
user: loggedInUser
|
60
|
+
} = useAuthController();
|
61
|
+
const {
|
61
62
|
saveUser,
|
62
63
|
users,
|
63
64
|
roles,
|
64
65
|
} = useUserManagement();
|
65
66
|
const isNewUser = !userProp;
|
66
67
|
|
67
|
-
const onUserUpdated = useCallback((savedUser:
|
68
|
+
const onUserUpdated = useCallback((savedUser: User): Promise<User> => {
|
68
69
|
if (!loggedInUser) {
|
69
70
|
throw new Error("Logged user not found");
|
70
71
|
}
|
@@ -81,7 +82,7 @@ export function UserDetailsForm({
|
|
81
82
|
displayName: "",
|
82
83
|
email: "",
|
83
84
|
roles: roles.filter(r => r.id === "editor")
|
84
|
-
} as
|
85
|
+
} as User,
|
85
86
|
validation: (values) => {
|
86
87
|
return UserYupSchema.validate(values, { abortEarly: false })
|
87
88
|
.then(() => {
|
@@ -93,7 +94,7 @@ export function UserDetailsForm({
|
|
93
94
|
}, {});
|
94
95
|
});
|
95
96
|
},
|
96
|
-
onSubmit: (user:
|
97
|
+
onSubmit: (user: User, formexController) => {
|
97
98
|
|
98
99
|
return onUserUpdated(user)
|
99
100
|
.then(() => {
|
@@ -181,7 +182,7 @@ export function UserDetailsForm({
|
|
181
182
|
<div className={"col-span-12"}>
|
182
183
|
<MultiSelect
|
183
184
|
label="Roles"
|
184
|
-
value={values.roles
|
185
|
+
value={values.roles?.map(r => r.id) ?? []}
|
185
186
|
onMultiValueChange={(value: string[]) => setFieldValue("roles", value.map(id => roles.find(r => r.id === id) as Role))}
|
186
187
|
renderValue={(value: string) => {
|
187
188
|
const userRole = roles
|
@@ -5,9 +5,9 @@ import * as locales from "date-fns/locale";
|
|
5
5
|
|
6
6
|
import {
|
7
7
|
defaultDateFormat,
|
8
|
-
DeleteConfirmationDialog,
|
8
|
+
DeleteConfirmationDialog, Role,
|
9
9
|
useAuthController,
|
10
|
-
useCustomizationController,
|
10
|
+
useCustomizationController, User,
|
11
11
|
useSnackbarController
|
12
12
|
} from "@firecms/core";
|
13
13
|
import {
|
@@ -23,19 +23,19 @@ import {
|
|
23
23
|
Tooltip,
|
24
24
|
Typography,
|
25
25
|
} from "@firecms/ui";
|
26
|
-
import { Role, UserWithRoles } from "../../types";
|
27
26
|
import { useUserManagement } from "../../hooks";
|
28
27
|
import { RoleChip } from "../roles";
|
28
|
+
import { PersistedUser } from "../../types";
|
29
29
|
|
30
30
|
export function UsersTable({ onUserClicked }: {
|
31
|
-
onUserClicked: (user:
|
31
|
+
onUserClicked: (user: User) => void;
|
32
32
|
}) {
|
33
33
|
|
34
34
|
const {
|
35
35
|
users,
|
36
36
|
saveUser,
|
37
37
|
deleteUser
|
38
|
-
} = useUserManagement();
|
38
|
+
} = useUserManagement<PersistedUser>();
|
39
39
|
|
40
40
|
const authController = useAuthController();
|
41
41
|
const snackbarController = useSnackbarController();
|
@@ -44,7 +44,7 @@ export function UsersTable({ onUserClicked }: {
|
|
44
44
|
const dateUtilsLocale = customizationController?.locale ? locales[customizationController?.locale as keyof typeof locales] : undefined;
|
45
45
|
const dateFormat: string = customizationController?.dateTimeFormat ?? defaultDateFormat;
|
46
46
|
|
47
|
-
const [userToBeDeleted, setUserToBeDeleted] = useState<
|
47
|
+
const [userToBeDeleted, setUserToBeDeleted] = useState<User | undefined>(undefined);
|
48
48
|
const [deleteInProgress, setDeleteInProgress] = useState<boolean>(false);
|
49
49
|
|
50
50
|
return (
|
@@ -3,19 +3,19 @@ import { AddIcon, Button, Container, Typography } from "@firecms/ui";
|
|
3
3
|
import { UsersTable } from "./UsersTable";
|
4
4
|
import { UserDetailsForm } from "./UserDetailsForm";
|
5
5
|
import React, { useCallback, useState } from "react";
|
6
|
-
import { UserWithRoles } from "../../types";
|
7
6
|
import { useUserManagement } from "../../hooks/useUserManagement";
|
7
|
+
import { User } from "@firecms/core";
|
8
8
|
|
9
9
|
export const UsersView = function UsersView({ children }: { children?: React.ReactNode }) {
|
10
10
|
|
11
11
|
const [dialogOpen, setDialogOpen] = useState<boolean>();
|
12
|
-
const [selectedUser, setSelectedUser] = useState<
|
12
|
+
const [selectedUser, setSelectedUser] = useState<User | undefined>();
|
13
13
|
|
14
14
|
const { users, usersLimit } = useUserManagement();
|
15
15
|
|
16
16
|
const reachedUsersLimit = usersLimit !== undefined && (users && users.length >= usersLimit);
|
17
17
|
|
18
|
-
const onUserClicked = useCallback((user:
|
18
|
+
const onUserClicked = useCallback((user: User) => {
|
19
19
|
setSelectedUser(user);
|
20
20
|
setDialogOpen(true);
|
21
21
|
}, []);
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import React, { useCallback, useEffect, useRef } from "react";
|
2
2
|
import {
|
3
|
+
addDoc,
|
3
4
|
collection,
|
4
5
|
deleteDoc,
|
5
6
|
doc,
|
@@ -10,8 +11,8 @@ import {
|
|
10
11
|
setDoc
|
11
12
|
} from "firebase/firestore";
|
12
13
|
import { FirebaseApp } from "firebase/app";
|
13
|
-
import {
|
14
|
-
import {
|
14
|
+
import { UserManagement } from "../types";
|
15
|
+
import { Authenticator, PermissionsBuilder, Role, User } from "@firecms/core";
|
15
16
|
import { resolveUserRolePermissions } from "../utils";
|
16
17
|
|
17
18
|
type UserWithRoleIds = User & { roles: string[] };
|
@@ -41,8 +42,6 @@ export interface UserManagementParams {
|
|
41
42
|
|
42
43
|
canEditRoles?: boolean;
|
43
44
|
|
44
|
-
authController: AuthController;
|
45
|
-
|
46
45
|
/**
|
47
46
|
* If there are no roles in the database, provide a button to create the default roles.
|
48
47
|
*/
|
@@ -70,7 +69,6 @@ export function useBuildFirestoreUserManagement({
|
|
70
69
|
rolesPath = "__FIRECMS/config/roles",
|
71
70
|
usersLimit,
|
72
71
|
canEditRoles = true,
|
73
|
-
authController,
|
74
72
|
allowDefaultRolesCreation,
|
75
73
|
includeCollectionConfigPermissions
|
76
74
|
}: UserManagementParams): UserManagement {
|
@@ -85,22 +83,13 @@ export function useBuildFirestoreUserManagement({
|
|
85
83
|
const users = usersWithRoleIds.map(u => ({
|
86
84
|
...u,
|
87
85
|
roles: roles.filter(r => u.roles?.includes(r.id))
|
88
|
-
}) as
|
86
|
+
}) as User);
|
89
87
|
|
90
88
|
const [rolesError, setRolesError] = React.useState<Error | undefined>();
|
91
89
|
const [usersError, setUsersError] = React.useState<Error | undefined>();
|
92
90
|
|
93
91
|
const loading = rolesLoading || usersLoading;
|
94
92
|
|
95
|
-
const loggedInUser: UserWithRoles | undefined = users.find(u => u.email?.toLowerCase() === authController.user?.email?.toLowerCase());
|
96
|
-
// console.log("authController", authController);
|
97
|
-
// if (!loading && !authController.authLoading) {
|
98
|
-
// const user = authController.user;
|
99
|
-
// if (user) {
|
100
|
-
// loggedInUser = users.find(u => u.email?.toLowerCase() === user.email?.toLowerCase());
|
101
|
-
// }
|
102
|
-
// }
|
103
|
-
|
104
93
|
useEffect(() => {
|
105
94
|
if (!firebaseApp) return;
|
106
95
|
firestoreRef.current = getFirestore(firebaseApp);
|
@@ -155,16 +144,24 @@ export function useBuildFirestoreUserManagement({
|
|
155
144
|
);
|
156
145
|
}, [firebaseApp, usersPath]);
|
157
146
|
|
158
|
-
const saveUser = useCallback(async (user:
|
147
|
+
const saveUser = useCallback(async (user: User): Promise<User> => {
|
159
148
|
const firestore = firestoreRef.current;
|
160
149
|
if (!firestore || !usersPath) throw Error("useFirestoreConfigurationPersistence Firestore not initialised");
|
161
150
|
console.debug("Persisting user", user);
|
162
|
-
const roleIds = user.roles
|
151
|
+
const roleIds = user.roles?.map(r => r.id);
|
163
152
|
const {
|
164
153
|
uid,
|
165
154
|
...userData
|
166
155
|
} = user;
|
167
|
-
|
156
|
+
const data = {
|
157
|
+
...userData,
|
158
|
+
roles: roleIds
|
159
|
+
};
|
160
|
+
if (uid) {
|
161
|
+
return setDoc(doc(firestore, usersPath, uid), data, { merge: true }).then(() => user);
|
162
|
+
} else {
|
163
|
+
return addDoc(collection(firestore, usersPath), data).then(() => user);
|
164
|
+
}
|
168
165
|
}, [usersPath]);
|
169
166
|
|
170
167
|
const saveRole = useCallback((role: Role): Promise<void> => {
|
@@ -179,7 +176,7 @@ export function useBuildFirestoreUserManagement({
|
|
179
176
|
return setDoc(ref, roleData, { merge: true });
|
180
177
|
}, [rolesPath]);
|
181
178
|
|
182
|
-
const deleteUser = useCallback(async (user:
|
179
|
+
const deleteUser = useCallback(async (user: User): Promise<void> => {
|
183
180
|
const firestore = firestoreRef.current;
|
184
181
|
if (!firestore || !usersPath) throw Error("useFirestoreConfigurationPersistence Firestore not initialised");
|
185
182
|
console.debug("Deleting", user);
|
@@ -198,14 +195,45 @@ export function useBuildFirestoreUserManagement({
|
|
198
195
|
|
199
196
|
const collectionPermissions: PermissionsBuilder = useCallback(({
|
200
197
|
collection,
|
198
|
+
user
|
201
199
|
}) => resolveUserRolePermissions({
|
202
200
|
collection,
|
203
|
-
user
|
204
|
-
}), [
|
201
|
+
user
|
202
|
+
}), []);
|
203
|
+
|
204
|
+
const userIds = users.map(u => u.uid);
|
205
|
+
const defineRolesFor: ((user: User) => Role[] | undefined) = useCallback((user) => {
|
206
|
+
if (!users) throw Error("Users not loaded");
|
207
|
+
const mgmtUser = users.find(u => u.email?.toLowerCase() === user?.email?.toLowerCase());
|
208
|
+
return mgmtUser?.roles;
|
209
|
+
}, [userIds]);
|
210
|
+
|
211
|
+
const authenticator: Authenticator = useCallback(({ user }) => {
|
212
|
+
console.log("Authenticating user", user);
|
213
|
+
// return true;"
|
214
|
+
|
215
|
+
// console.log("authentication", user, userManagement);
|
216
|
+
if (loading) {
|
217
|
+
console.log("User management is still loading");
|
218
|
+
return false;
|
219
|
+
}
|
220
|
+
|
221
|
+
// This is an example of how you can link the access system to the user management plugin
|
222
|
+
if (users.length === 0) {
|
223
|
+
return true; // If there are no users created yet, we allow access to every user
|
224
|
+
}
|
225
|
+
|
226
|
+
const mgmtUser = users.find(u => u.email?.toLowerCase() === user?.email?.toLowerCase());
|
227
|
+
if (mgmtUser) {
|
228
|
+
// authController.setRoles(mgmtUser.roles ?? [])
|
229
|
+
return true;
|
230
|
+
}
|
231
|
+
|
232
|
+
throw Error("Could not find a user with the provided email");
|
233
|
+
}, [loading, users])
|
205
234
|
|
206
235
|
return {
|
207
236
|
loading,
|
208
|
-
loggedInUser,
|
209
237
|
roles,
|
210
238
|
users,
|
211
239
|
saveUser,
|
@@ -216,7 +244,9 @@ export function useBuildFirestoreUserManagement({
|
|
216
244
|
canEditRoles: canEditRoles === undefined ? true : canEditRoles,
|
217
245
|
allowDefaultRolesCreation: allowDefaultRolesCreation === undefined ? true : allowDefaultRolesCreation,
|
218
246
|
includeCollectionConfigPermissions: Boolean(includeCollectionConfigPermissions),
|
219
|
-
collectionPermissions
|
247
|
+
collectionPermissions,
|
248
|
+
defineRolesFor,
|
249
|
+
authenticator
|
220
250
|
}
|
221
251
|
}
|
222
252
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { useContext } from "react";
|
2
|
-
import { UserManagement } from "../types
|
2
|
+
import { UserManagement } from "../types";
|
3
3
|
import { UserManagementContext } from "../UserManagementProvider";
|
4
|
-
|
5
|
-
export const useUserManagement = () => useContext<UserManagement
|
4
|
+
import { User } from "@firecms/core";
|
5
|
+
export const useUserManagement = <USER extends User>() => useContext<UserManagement<USER>>(UserManagementContext);
|
package/src/types/index.ts
CHANGED
@@ -1,18 +1,9 @@
|
|
1
|
-
import {
|
2
|
-
import { Role } from "./roles";
|
3
|
-
import { PermissionsBuilder } from "@firecms/core";
|
1
|
+
import { Authenticator, PermissionsBuilder, Role, User } from "@firecms/core";
|
4
2
|
|
5
|
-
export type UserManagement<USER extends
|
3
|
+
export type UserManagement<USER extends User = User> = {
|
6
4
|
|
7
5
|
loading: boolean;
|
8
6
|
|
9
|
-
/**
|
10
|
-
* The user currently logged in, in the user management system.
|
11
|
-
* This is the same user that is logged in the Authenticator, but with the roles
|
12
|
-
* and permissions loaded.
|
13
|
-
*/
|
14
|
-
loggedInUser: USER | undefined;
|
15
|
-
|
16
7
|
users: USER[];
|
17
8
|
saveUser: (user: USER) => Promise<USER>;
|
18
9
|
deleteUser: (user: USER) => Promise<void>;
|
@@ -47,4 +38,16 @@ export type UserManagement<USER extends UserWithRoles = UserWithRoles> = {
|
|
47
38
|
*/
|
48
39
|
collectionPermissions: PermissionsBuilder;
|
49
40
|
|
41
|
+
/**
|
42
|
+
* Define the roles for a given user. You will typically want to plug this into your auth controller.
|
43
|
+
* @param user
|
44
|
+
*/
|
45
|
+
defineRolesFor: (user: User) => Promise<Role[]> | Role[] | undefined;
|
46
|
+
|
47
|
+
/**
|
48
|
+
* You can build an authenticator callback from the current configuration of the user management.
|
49
|
+
* It will only allow access to users with the required roles.
|
50
|
+
*/
|
51
|
+
authenticator?: Authenticator;
|
52
|
+
|
50
53
|
};
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import { FireCMSPlugin } from "@firecms/core";
|
2
2
|
import { UserManagementProvider } from "./UserManagementProvider";
|
3
3
|
import { UserManagement } from "./types";
|
4
4
|
|
@@ -6,7 +6,7 @@ export function useUserManagementPlugin({ userManagement }: {
|
|
6
6
|
userManagement: UserManagement,
|
7
7
|
}): FireCMSPlugin {
|
8
8
|
return {
|
9
|
-
|
9
|
+
key: "user_management",
|
10
10
|
loading: userManagement.loading,
|
11
11
|
provider: {
|
12
12
|
Component: UserManagementProvider,
|
package/src/utils/permissions.ts
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
import {
|
2
|
-
import { Role, UserWithRoles } from "../types";
|
1
|
+
import { EntityCollection, Permissions, Role, User } from "@firecms/core";
|
3
2
|
|
4
3
|
export const RESERVED_GROUPS = ["Admin"];
|
5
4
|
|
@@ -10,8 +9,11 @@ const DEFAULT_PERMISSIONS = {
|
|
10
9
|
delete: false
|
11
10
|
};
|
12
11
|
|
13
|
-
export function resolveUserRolePermissions<UserType extends
|
14
|
-
({
|
12
|
+
export function resolveUserRolePermissions<UserType extends User>
|
13
|
+
({
|
14
|
+
collection,
|
15
|
+
user
|
16
|
+
}: {
|
15
17
|
collection: EntityCollection<any>,
|
16
18
|
user: UserType | null
|
17
19
|
}): Permissions {
|
@@ -66,7 +68,7 @@ const mergePermissions = (permA: Permissions, permB: Permissions) => {
|
|
66
68
|
};
|
67
69
|
}
|
68
70
|
|
69
|
-
export function getUserRoles(roles: Role[], fireCMSUser:
|
71
|
+
export function getUserRoles(roles: Role[], fireCMSUser: User): Role[] | undefined {
|
70
72
|
return !roles
|
71
73
|
? undefined
|
72
74
|
: (fireCMSUser.roles
|
package/dist/types/roles.d.ts
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
import { Permissions } from "@firecms/core";
|
2
|
-
export type Role = {
|
3
|
-
/**
|
4
|
-
* ID of the role
|
5
|
-
*/
|
6
|
-
id: string;
|
7
|
-
/**
|
8
|
-
* Name of the role
|
9
|
-
*/
|
10
|
-
name: string;
|
11
|
-
/**
|
12
|
-
* If this flag is true, the user can perform any action
|
13
|
-
*/
|
14
|
-
isAdmin?: boolean;
|
15
|
-
/**
|
16
|
-
* Default permissions for all collections for this role.
|
17
|
-
* You can override this values at the collection level using
|
18
|
-
* {@link collectionPermissions}
|
19
|
-
*/
|
20
|
-
defaultPermissions?: Permissions;
|
21
|
-
/**
|
22
|
-
* Record of stripped collection ids to their permissions.
|
23
|
-
* @see stripCollectionPath
|
24
|
-
*/
|
25
|
-
collectionPermissions?: Record<string, Permissions>;
|
26
|
-
config?: {
|
27
|
-
createCollections?: boolean;
|
28
|
-
editCollections?: boolean | "own";
|
29
|
-
deleteCollections?: boolean | "own";
|
30
|
-
};
|
31
|
-
};
|
package/src/types/roles.ts
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
import { Permissions } from "@firecms/core";
|
2
|
-
|
3
|
-
export type Role = {
|
4
|
-
|
5
|
-
/**
|
6
|
-
* ID of the role
|
7
|
-
*/
|
8
|
-
id: string;
|
9
|
-
|
10
|
-
/**
|
11
|
-
* Name of the role
|
12
|
-
*/
|
13
|
-
name: string;
|
14
|
-
|
15
|
-
/**
|
16
|
-
* If this flag is true, the user can perform any action
|
17
|
-
*/
|
18
|
-
isAdmin?: boolean;
|
19
|
-
|
20
|
-
/**
|
21
|
-
* Default permissions for all collections for this role.
|
22
|
-
* You can override this values at the collection level using
|
23
|
-
* {@link collectionPermissions}
|
24
|
-
*/
|
25
|
-
defaultPermissions?: Permissions;
|
26
|
-
|
27
|
-
/**
|
28
|
-
* Record of stripped collection ids to their permissions.
|
29
|
-
* @see stripCollectionPath
|
30
|
-
*/
|
31
|
-
collectionPermissions?: Record<string, Permissions>;
|
32
|
-
|
33
|
-
config?: {
|
34
|
-
|
35
|
-
createCollections?: boolean;
|
36
|
-
|
37
|
-
editCollections?: boolean | "own";
|
38
|
-
|
39
|
-
deleteCollections?: boolean | "own";
|
40
|
-
}
|
41
|
-
}
|