@firecms/user_management 3.0.0-canary.8 → 3.0.0-canary.9

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.
Files changed (38) hide show
  1. package/dist/UserManagementProvider.d.ts +4 -3
  2. package/dist/components/roles/RoleChip.d.ts +1 -1
  3. package/dist/components/roles/RolesDetailsForm.d.ts +1 -2
  4. package/dist/components/roles/RolesTable.d.ts +1 -1
  5. package/dist/components/roles/default_roles.d.ts +1 -1
  6. package/dist/components/users/UserDetailsForm.d.ts +2 -2
  7. package/dist/components/users/UsersTable.d.ts +2 -2
  8. package/dist/hooks/useUserManagement.d.ts +3 -2
  9. package/dist/index.es.js +9 -6
  10. package/dist/index.es.js.map +1 -1
  11. package/dist/index.umd.js +1 -1
  12. package/dist/index.umd.js.map +1 -1
  13. package/dist/types/index.d.ts +1 -2
  14. package/dist/types/persisted_user.d.ts +5 -0
  15. package/dist/types/user_management.d.ts +2 -4
  16. package/dist/utils/permissions.d.ts +3 -4
  17. package/package.json +6 -8
  18. package/src/UserManagementProvider.tsx +4 -3
  19. package/src/components/roles/RoleChip.tsx +1 -1
  20. package/src/components/roles/RolesDetailsForm.tsx +1 -2
  21. package/src/components/roles/RolesTable.tsx +1 -2
  22. package/src/components/roles/RolesView.tsx +1 -2
  23. package/src/components/roles/default_roles.tsx +1 -1
  24. package/src/components/users/UserDetailsForm.tsx +11 -12
  25. package/src/components/users/UsersTable.tsx +6 -6
  26. package/src/components/users/UsersView.tsx +3 -3
  27. package/src/hooks/useBuildFirestoreUserManagement.tsx +11 -8
  28. package/src/hooks/useUserManagement.tsx +3 -3
  29. package/src/types/index.ts +1 -2
  30. package/src/types/persisted_user.ts +6 -0
  31. package/src/types/user_management.tsx +2 -4
  32. package/src/useUserManagementPlugin.tsx +1 -1
  33. package/src/utils/permissions.ts +3 -4
  34. package/dist/types/firecms_user.d.ts +0 -7
  35. package/dist/types/roles.d.ts +0 -31
  36. package/src/types/firecms_user.ts +0 -8
  37. package/src/types/roles.ts +0 -41
  38. package/tailwind.config.js +0 -68
@@ -1,5 +1,5 @@
1
1
  import { Chip, getColorSchemeForSeed } from "@firecms/ui";
2
- import { Role } from "../../types";
2
+ import { Role } from "@firecms/core";
3
3
 
4
4
  export type RoleChipProps = {
5
5
  role: Role;
@@ -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 }) {
@@ -1,4 +1,4 @@
1
- import { Role } from "../../types";
1
+ import { Role } from "@firecms/core";
2
2
 
3
3
  export const DEFAULT_ROLES: Role[] = [
4
4
  {
@@ -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, 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: UserWithRoles, user: UserWithRoles, users: UserWithRoles[], roles: Role[], prevUser?: UserWithRoles) {
30
- const admins = users.filter(u => u.roles.map(r => r.id).includes("admin"));
31
- const loggedUserIsAdmin = loggedUser.roles.map(r => r.id).includes("admin");
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.map(r => r.id).includes("admin") && !user.roles.map(r => r.id).includes("admin");
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,7 +50,7 @@ export function UserDetailsForm({
51
50
  handleClose
52
51
  }: {
53
52
  open: boolean,
54
- user?: UserWithRoles,
53
+ user?: User,
55
54
  handleClose: () => void
56
55
  }) {
57
56
 
@@ -64,7 +63,7 @@ export function UserDetailsForm({
64
63
  } = useUserManagement();
65
64
  const isNewUser = !userProp;
66
65
 
67
- const onUserUpdated = useCallback((savedUser: UserWithRoles): Promise<UserWithRoles> => {
66
+ const onUserUpdated = useCallback((savedUser: User): Promise<User> => {
68
67
  if (!loggedInUser) {
69
68
  throw new Error("Logged user not found");
70
69
  }
@@ -81,7 +80,7 @@ export function UserDetailsForm({
81
80
  displayName: "",
82
81
  email: "",
83
82
  roles: roles.filter(r => r.id === "editor")
84
- } as UserWithRoles,
83
+ } as User,
85
84
  validation: (values) => {
86
85
  return UserYupSchema.validate(values, { abortEarly: false })
87
86
  .then(() => {
@@ -93,7 +92,7 @@ export function UserDetailsForm({
93
92
  }, {});
94
93
  });
95
94
  },
96
- onSubmit: (user: UserWithRoles, formexController) => {
95
+ onSubmit: (user: User, formexController) => {
97
96
 
98
97
  return onUserUpdated(user)
99
98
  .then(() => {
@@ -181,7 +180,7 @@ export function UserDetailsForm({
181
180
  <div className={"col-span-12"}>
182
181
  <MultiSelect
183
182
  label="Roles"
184
- value={values.roles.map(r => r.id) ?? []}
183
+ value={values.roles?.map(r => r.id) ?? []}
185
184
  onMultiValueChange={(value: string[]) => setFieldValue("roles", value.map(id => roles.find(r => r.id === id) as Role))}
186
185
  renderValue={(value: string) => {
187
186
  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: UserWithRoles) => void;
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<UserWithRoles | undefined>(undefined);
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<UserWithRoles | undefined>();
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: UserWithRoles) => {
18
+ const onUserClicked = useCallback((user: User) => {
19
19
  setSelectedUser(user);
20
20
  setDialogOpen(true);
21
21
  }, []);
@@ -10,8 +10,8 @@ import {
10
10
  setDoc
11
11
  } from "firebase/firestore";
12
12
  import { FirebaseApp } from "firebase/app";
13
- import { Role, UserManagement, UserWithRoles } from "../types";
14
- import { AuthController, PermissionsBuilder, User } from "@firecms/core";
13
+ import { UserManagement } from "../types";
14
+ import { AuthController, PermissionsBuilder, Role, User } from "@firecms/core";
15
15
  import { resolveUserRolePermissions } from "../utils";
16
16
 
17
17
  type UserWithRoleIds = User & { roles: string[] };
@@ -85,14 +85,14 @@ export function useBuildFirestoreUserManagement({
85
85
  const users = usersWithRoleIds.map(u => ({
86
86
  ...u,
87
87
  roles: roles.filter(r => u.roles?.includes(r.id))
88
- }) as UserWithRoles);
88
+ }) as User);
89
89
 
90
90
  const [rolesError, setRolesError] = React.useState<Error | undefined>();
91
91
  const [usersError, setUsersError] = React.useState<Error | undefined>();
92
92
 
93
93
  const loading = rolesLoading || usersLoading;
94
94
 
95
- const loggedInUser: UserWithRoles | undefined = users.find(u => u.email?.toLowerCase() === authController.user?.email?.toLowerCase());
95
+ const loggedInUser: User | undefined = users.find(u => u.email?.toLowerCase() === authController.user?.email?.toLowerCase());
96
96
  // console.log("authController", authController);
97
97
  // if (!loading && !authController.authLoading) {
98
98
  // const user = authController.user;
@@ -155,16 +155,19 @@ export function useBuildFirestoreUserManagement({
155
155
  );
156
156
  }, [firebaseApp, usersPath]);
157
157
 
158
- const saveUser = useCallback(async (user: UserWithRoles): Promise<UserWithRoles> => {
158
+ const saveUser = useCallback(async (user: User): Promise<User> => {
159
159
  const firestore = firestoreRef.current;
160
160
  if (!firestore || !usersPath) throw Error("useFirestoreConfigurationPersistence Firestore not initialised");
161
161
  console.debug("Persisting user", user);
162
- const roleIds = user.roles.map(r => r.id);
162
+ const roleIds = user.roles?.map(r => r.id);
163
163
  const {
164
164
  uid,
165
165
  ...userData
166
166
  } = user;
167
- return setDoc(doc(firestore, usersPath, uid), { ...userData, roles: roleIds }, { merge: true }).then(() => user);
167
+ return setDoc(doc(firestore, usersPath, uid), {
168
+ ...userData,
169
+ roles: roleIds
170
+ }, { merge: true }).then(() => user);
168
171
  }, [usersPath]);
169
172
 
170
173
  const saveRole = useCallback((role: Role): Promise<void> => {
@@ -179,7 +182,7 @@ export function useBuildFirestoreUserManagement({
179
182
  return setDoc(ref, roleData, { merge: true });
180
183
  }, [rolesPath]);
181
184
 
182
- const deleteUser = useCallback(async (user: UserWithRoles): Promise<void> => {
185
+ const deleteUser = useCallback(async (user: User): Promise<void> => {
183
186
  const firestore = firestoreRef.current;
184
187
  if (!firestore || !usersPath) throw Error("useFirestoreConfigurationPersistence Firestore not initialised");
185
188
  console.debug("Deleting", user);
@@ -1,5 +1,5 @@
1
1
  import { useContext } from "react";
2
- import { UserManagement } from "../types/user_management";
2
+ import { UserManagement } from "../types";
3
3
  import { UserManagementContext } from "../UserManagementProvider";
4
-
5
- export const useUserManagement = () => useContext<UserManagement>(UserManagementContext);
4
+ import { User } from "@firecms/core";
5
+ export const useUserManagement = <USER extends User>() => useContext<UserManagement<USER>>(UserManagementContext);
@@ -1,3 +1,2 @@
1
- export * from "./firecms_user";
2
- export * from "./roles";
3
1
  export * from "./user_management";
2
+ export * from "./persisted_user";
@@ -0,0 +1,6 @@
1
+ import { User } from "@firecms/core";
2
+
3
+ export type PersistedUser = User & {
4
+ updated_on?: Date;
5
+ created_on?: Date;
6
+ }
@@ -1,8 +1,6 @@
1
- import { UserWithRoles } from "./firecms_user";
2
- import { Role } from "./roles";
3
- import { PermissionsBuilder } from "@firecms/core";
1
+ import { PermissionsBuilder, Role, User } from "@firecms/core";
4
2
 
5
- export type UserManagement<USER extends UserWithRoles = UserWithRoles> = {
3
+ export type UserManagement<USER extends User = User> = {
6
4
 
7
5
  loading: boolean;
8
6
 
@@ -1,4 +1,4 @@
1
- import { AuthController, FireCMSPlugin } from "@firecms/core";
1
+ import { FireCMSPlugin } from "@firecms/core";
2
2
  import { UserManagementProvider } from "./UserManagementProvider";
3
3
  import { UserManagement } from "./types";
4
4
 
@@ -1,5 +1,4 @@
1
- import { CMSType, EntityCollection, Permissions } from "@firecms/core";
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,7 +9,7 @@ const DEFAULT_PERMISSIONS = {
10
9
  delete: false
11
10
  };
12
11
 
13
- export function resolveUserRolePermissions<UserType extends UserWithRoles>
12
+ export function resolveUserRolePermissions<UserType extends User>
14
13
  ({ collection, user }: {
15
14
  collection: EntityCollection<any>,
16
15
  user: UserType | null
@@ -66,7 +65,7 @@ const mergePermissions = (permA: Permissions, permB: Permissions) => {
66
65
  };
67
66
  }
68
67
 
69
- export function getUserRoles(roles: Role[], fireCMSUser: UserWithRoles): Role[] | undefined {
68
+ export function getUserRoles(roles: Role[], fireCMSUser: User): Role[] | undefined {
70
69
  return !roles
71
70
  ? undefined
72
71
  : (fireCMSUser.roles
@@ -1,7 +0,0 @@
1
- import { User } from "@firecms/core";
2
- import { Role } from "./roles";
3
- export type UserWithRoles = User & {
4
- updated_on?: Date;
5
- created_on?: Date;
6
- roles: Role[];
7
- };
@@ -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
- };
@@ -1,8 +0,0 @@
1
- import { User } from "@firecms/core";
2
- import { Role } from "./roles";
3
-
4
- export type UserWithRoles = User & {
5
- updated_on?: Date;
6
- created_on?: Date;
7
- roles: Role[];
8
- }
@@ -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
- }
@@ -1,68 +0,0 @@
1
- export default {
2
- darkMode: ["selector", "[data-theme=\"dark\"]"],
3
- mode: "jit",
4
- content: [
5
- "./index.html",
6
- "./src/**/*.{js,ts,jsx,tsx}",
7
- "./node_modules/firecms/src/**/*.{js,ts,jsx,tsx}",
8
- "./node_modules/@firecms/**/src/**/*.{js,ts,jsx,tsx}"
9
- ],
10
- theme: {
11
- extend: {
12
- fontFamily: {
13
- sans: [
14
- "Rubik",
15
- "Roboto",
16
- "Helvetica",
17
- "Arial",
18
- "sans-serif"
19
- ],
20
- headers: [
21
- "Rubik",
22
- "Roboto",
23
- "Helvetica",
24
- "Arial",
25
- "sans-serif"
26
- ],
27
- mono: [
28
- "IBM Plex Mono",
29
- "Space Mono",
30
- "Lucida Console",
31
- "monospace"
32
- ]
33
- },
34
- colors: {
35
- primary: "var(--fcms-primary)",
36
- "primary-dark": "var(--fcms-primary-dark)",
37
- "primary-bg": "var(--fcms-primary-bg)",
38
- secondary: "var(--fcms-secondary)",
39
- field: {
40
- disabled: "rgb(224 224 226)",
41
- "disabled-dark": "rgb(35 35 37)"
42
- },
43
- text: {
44
- primary: "rgba(0, 0, 0, 0.87)",
45
- "primary-dark": "#ffffff",
46
- secondary: "rgba(0, 0, 0, 0.6)",
47
- "secondary-dark": "rgba(255, 255, 255, 0.7)",
48
- disabled: "rgba(0, 0, 0, 0.38)",
49
- "disabled-dark": "rgba(255, 255, 255, 0.5)",
50
- label: "rgb(131, 131, 131)"
51
- },
52
- gray: {
53
- 50: "#f8f8fc",
54
- 100: "#E7E7EB",
55
- 200: "#CFCFD6",
56
- 300: "#B7B7BF",
57
- 400: "#A0A0A9",
58
- 500: "#87878F",
59
- 600: "#6C6C75",
60
- 700: "#505058",
61
- 800: "#35353A",
62
- 900: "#18181C",
63
- 950: "#101013"
64
- }
65
- }
66
- }
67
- }
68
- };