@firecms/user_management 3.0.0-beta.4.pre.1 → 3.0.0-canary.8

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 +1 @@
1
- {"version":3,"file":"index.es.js","sources":["../src/utils/permissions.ts","../src/utils/local_storage.ts","../src/utils/colors.ts","../src/hooks/useBuildFirestoreUserManagement.tsx","../src/UserManagementProvider.tsx","../src/hooks/useUserManagement.tsx","../src/components/roles/RoleChip.tsx","../src/components/roles/RolesDetailsForm.tsx","../src/components/roles/default_roles.tsx","../src/components/roles/RolesTable.tsx","../src/components/roles/RolesView.tsx","../src/components/users/UserDetailsForm.tsx","../src/components/users/UsersTable.tsx","../src/components/users/UsersView.tsx","../src/useUserManagementPlugin.tsx","../src/admin_views.tsx"],"sourcesContent":["import { CMSType, EntityCollection, Permissions } from \"@firecms/core\";\nimport { Role, UserWithRoles } from \"../types\";\n\nexport const RESERVED_GROUPS = [\"Admin\"];\n\nconst DEFAULT_PERMISSIONS = {\n read: false,\n edit: false,\n create: false,\n delete: false\n};\n\nexport function resolveUserRolePermissions<UserType extends UserWithRoles>\n({ collection, user }: {\n collection: EntityCollection<any>,\n user: UserType | null\n}): Permissions {\n\n const roles = user?.roles;\n if (!roles) {\n return DEFAULT_PERMISSIONS;\n } else if (collection.ownerId === user?.uid) {\n return {\n read: true,\n create: true,\n edit: true,\n delete: true\n };\n } else {\n const basePermissions = {\n read: false,\n create: false,\n edit: false,\n delete: false\n };\n\n return roles\n .map(role => resolveCollectionRole(role, collection.id))\n .reduce(mergePermissions, basePermissions);\n }\n}\n\nfunction resolveCollectionRole(role: Role, id: string): Permissions {\n\n const basePermissions = {\n read: role.isAdmin || role.defaultPermissions?.read,\n create: role.isAdmin || role.defaultPermissions?.create,\n edit: role.isAdmin || role.defaultPermissions?.edit,\n delete: role.isAdmin || role.defaultPermissions?.delete\n };\n if (role.collectionPermissions && role.collectionPermissions[id]) {\n return mergePermissions(role.collectionPermissions[id], basePermissions);\n } else if (role.defaultPermissions) {\n return mergePermissions(role.defaultPermissions, basePermissions);\n } else {\n return basePermissions;\n }\n}\n\nconst mergePermissions = (permA: Permissions, permB: Permissions) => {\n return {\n read: permA.read || permB.read,\n create: permA.create || permB.create,\n edit: permA.edit || permB.edit,\n delete: permA.delete || permB.delete\n };\n}\n\nexport function getUserRoles(roles: Role[], fireCMSUser: UserWithRoles): Role[] | undefined {\n return !roles\n ? undefined\n : (fireCMSUser.roles\n ? fireCMSUser.roles\n .map(role => roles.find((r) => r.id === role.id))\n .filter(Boolean) as Role[]\n : []);\n}\n\nexport const areRolesEqual = (rolesA: Role[], rolesB: Role[]) => {\n const rolesAIds = rolesA.map(r => r.id);\n const rolesBIds = rolesB.map(r => r.id);\n return rolesAIds.length === rolesB.length && rolesAIds.every((role) => rolesBIds.includes(role));\n}\n","// const tokens = new Map<string, {\n// token: string,\n// expiry: Date\n// }>();\n\nexport function cacheDelegatedLoginToken(projectId: string, delegatedToken?: string) {\n if (!delegatedToken) {\n return;\n }\n\n const data = parseJwt(delegatedToken);\n // @ts-ignore\n const expiry = new Date(data.exp * 1000);\n localStorage.setItem(`auth_token::${projectId}`, JSON.stringify({\n token: delegatedToken,\n expiry\n }));\n\n}\n\nexport function getDelegatedLoginTokenFromCache(projectId: string) {\n const entry = localStorage.getItem(`auth_token::${projectId}`);\n if (entry) {\n const data = JSON.parse(entry);\n data.expiry = new Date(data.expiry);\n if (data.expiry > new Date()) {\n return data.token;\n }\n }\n return undefined;\n}\n\nexport function clearDelegatedLoginTokensCache() {\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(\"auth_token::\")) {\n localStorage.removeItem(key);\n }\n }\n}\n\nfunction parseJwt(token?: string): object {\n if (!token) {\n throw new Error(\"No JWT token\");\n }\n const base64Url = token.split(\".\")[1];\n const base64 = base64Url.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const jsonPayload = decodeURIComponent(window.atob(base64).split(\"\").map(function (c) {\n return \"%\" + (\"00\" + c.charCodeAt(0).toString(16)).slice(-2);\n }).join(\"\"));\n\n return JSON.parse(jsonPayload);\n}\n","export function darkenColor(hexColor: string, darkenBy = 10): string {\n // Check input validity\n if (!/^#([0-9A-Fa-f]{3}){1,2}$/.test(hexColor)) {\n throw new Error(\"Invalid color format\");\n }\n\n // If shorthand form, convert to full form\n let color = hexColor.substring(1).split(\"\");\n if (color.length === 3) {\n color = [color[0], color[0], color[1], color[1], color[2], color[2]];\n }\n\n // Convert to RGB values\n let r = parseInt(color[0] + color[1], 16);\n let g = parseInt(color[2] + color[3], 16);\n let b = parseInt(color[4] + color[5], 16);\n\n // Reduce each color component by the specified percentage (darkenBy)\n r = Math.floor(r * (1 - darkenBy / 100));\n g = Math.floor(g * (1 - darkenBy / 100));\n b = Math.floor(b * (1 - darkenBy / 100));\n\n // Recombine into hex and return\n return \"#\" +\n (r < 16 ? \"0\" : \"\") + r.toString(16) +\n (g < 16 ? \"0\" : \"\") + g.toString(16) +\n (b < 16 ? \"0\" : \"\") + b.toString(16);\n}\n\nexport function hexToRgbaWithOpacity(hexColor: string, opacity = 10): string {\n // Check input validity\n if (!/^#([0-9A-Fa-f]{3}){1,2}$/.test(hexColor)) {\n throw new Error(\"Invalid color format\");\n }\n\n // If shorthand form, convert to full form\n let color = hexColor.substring(1).split(\"\");\n if (color.length === 3) {\n color = [color[0], color[0], color[1], color[1], color[2], color[2]];\n }\n\n // Convert to RGB values\n const r = parseInt(color[0] + color[1], 16);\n const g = parseInt(color[2] + color[3], 16);\n const b = parseInt(color[4] + color[5], 16);\n\n // Convert opacity to a decimal for CSS\n const alpha = opacity / 100;\n\n // Construct and return the RGBA color\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n","import React, { useCallback, useEffect, useRef } from \"react\";\nimport {\n collection,\n deleteDoc,\n doc,\n DocumentSnapshot,\n Firestore,\n getFirestore,\n onSnapshot,\n setDoc\n} from \"firebase/firestore\";\nimport { FirebaseApp } from \"firebase/app\";\nimport { Role, UserManagement, UserWithRoles } from \"../types\";\nimport { AuthController, PermissionsBuilder, User } from \"@firecms/core\";\nimport { resolveUserRolePermissions } from \"../utils\";\n\ntype UserWithRoleIds = User & { roles: string[] };\n\nexport interface UserManagementParams {\n /**\n * The Firebase app to use for the user management. The config will be saved in the Firestore\n * collection indicated by `configPath`.\n */\n firebaseApp?: FirebaseApp;\n /**\n * Path where the plugin users configuration is stored.\n * Default: __FIRECMS/config/users\n * You can specify a different path if you want to store the user management configuration in a different place.\n * Please keep in mind that the FireCMS users are not necessarily the same as the Firebase users (but they can be).\n * The path should be relative to the root of the Firestore database, and should always have an odd number of segments.\n */\n usersPath?: string;\n\n /**\n * Path where the plugin roles configuration is stored.\n * Default: __FIRECMS/config/roles\n */\n rolesPath?: string;\n\n usersLimit?: number;\n\n canEditRoles?: boolean;\n\n authController: AuthController;\n\n /**\n * If there are no roles in the database, provide a button to create the default roles.\n */\n allowDefaultRolesCreation?: boolean;\n\n /**\n * Include the collection config permissions in the user management system.\n */\n includeCollectionConfigPermissions?: boolean;\n\n}\n\n/**\n * This hook is used to build a user management object that can be used to\n * manage users and roles in a Firestore backend.\n * @param backendFirebaseApp\n * @param usersPath\n * @param rolesPath\n * @param usersLimit\n * @param canEditRoles\n */\nexport function useBuildFirestoreUserManagement({\n firebaseApp,\n usersPath = \"__FIRECMS/config/users\",\n rolesPath = \"__FIRECMS/config/roles\",\n usersLimit,\n canEditRoles = true,\n authController,\n allowDefaultRolesCreation,\n includeCollectionConfigPermissions\n }: UserManagementParams): UserManagement {\n\n const firestoreRef = useRef<Firestore>();\n\n const [rolesLoading, setRolesLoading] = React.useState<boolean>(true);\n const [usersLoading, setUsersLoading] = React.useState<boolean>(true);\n const [roles, setRoles] = React.useState<Role[]>([]);\n const [usersWithRoleIds, setUsersWithRoleIds] = React.useState<UserWithRoleIds[]>([]);\n\n const users = usersWithRoleIds.map(u => ({\n ...u,\n roles: roles.filter(r => u.roles?.includes(r.id))\n }) as UserWithRoles);\n\n const [rolesError, setRolesError] = React.useState<Error | undefined>();\n const [usersError, setUsersError] = React.useState<Error | undefined>();\n\n const loading = rolesLoading || usersLoading;\n\n const loggedInUser: UserWithRoles | undefined = users.find(u => u.email?.toLowerCase() === authController.user?.email?.toLowerCase());\n // console.log(\"authController\", authController);\n // if (!loading && !authController.authLoading) {\n // const user = authController.user;\n // if (user) {\n // loggedInUser = users.find(u => u.email?.toLowerCase() === user.email?.toLowerCase());\n // }\n // }\n\n useEffect(() => {\n if (!firebaseApp) return;\n firestoreRef.current = getFirestore(firebaseApp);\n }, [firebaseApp]);\n\n useEffect(() => {\n if (!firebaseApp || !rolesPath) return;\n const firestore = getFirestore(firebaseApp);\n\n return onSnapshot(collection(firestore, rolesPath),\n {\n next: (snapshot) => {\n setRolesError(undefined);\n try {\n const newRoles = docsToRoles(snapshot.docs);\n setRoles(newRoles);\n } catch (e) {\n // console.error(e);\n setRolesError(e as Error);\n }\n setRolesLoading(false);\n },\n error: (e) => {\n setRolesError(e);\n setRolesLoading(false);\n }\n }\n );\n }, [firebaseApp, rolesPath]);\n\n useEffect(() => {\n if (!firebaseApp || !usersPath) return;\n const firestore = getFirestore(firebaseApp);\n\n return onSnapshot(collection(firestore, usersPath),\n {\n next: (snapshot) => {\n setUsersError(undefined);\n try {\n const newUsers = docsToUsers(snapshot.docs);\n setUsersWithRoleIds(newUsers);\n } catch (e) {\n setUsersError(e as Error);\n }\n setUsersLoading(false);\n },\n error: (e) => {\n setUsersError(e);\n setUsersLoading(false);\n }\n }\n );\n }, [firebaseApp, usersPath]);\n\n const saveUser = useCallback(async (user: UserWithRoles): Promise<UserWithRoles> => {\n const firestore = firestoreRef.current;\n if (!firestore || !usersPath) throw Error(\"useFirestoreConfigurationPersistence Firestore not initialised\");\n console.debug(\"Persisting user\", user);\n const roleIds = user.roles.map(r => r.id);\n const {\n uid,\n ...userData\n } = user;\n return setDoc(doc(firestore, usersPath, uid), { ...userData, roles: roleIds }, { merge: true }).then(() => user);\n }, [usersPath]);\n\n const saveRole = useCallback((role: Role): Promise<void> => {\n const firestore = firestoreRef.current;\n if (!firestore || !rolesPath) throw Error(\"useFirestoreConfigurationPersistence Firestore not initialised\");\n console.debug(\"Persisting role\", role);\n const {\n id,\n ...roleData\n } = role;\n const ref = doc(firestore, rolesPath, id);\n return setDoc(ref, roleData, { merge: true });\n }, [rolesPath]);\n\n const deleteUser = useCallback(async (user: UserWithRoles): Promise<void> => {\n const firestore = firestoreRef.current;\n if (!firestore || !usersPath) throw Error(\"useFirestoreConfigurationPersistence Firestore not initialised\");\n console.debug(\"Deleting\", user);\n const { uid } = user;\n return deleteDoc(doc(firestore, usersPath, uid));\n }, [usersPath]);\n\n const deleteRole = useCallback((role: Role): Promise<void> => {\n const firestore = firestoreRef.current;\n if (!firestore || !rolesPath) throw Error(\"useFirestoreConfigurationPersistence Firestore not initialised\");\n console.debug(\"Deleting\", role);\n const { id } = role;\n const ref = doc(firestore, rolesPath, id);\n return deleteDoc(ref);\n }, [rolesPath]);\n\n const collectionPermissions: PermissionsBuilder = useCallback(({\n collection,\n }) => resolveUserRolePermissions({\n collection,\n user: loggedInUser ?? null\n }), [loggedInUser?.uid]);\n\n return {\n loading,\n loggedInUser,\n roles,\n users,\n saveUser,\n saveRole,\n deleteUser,\n deleteRole,\n usersLimit,\n canEditRoles: canEditRoles === undefined ? true : canEditRoles,\n allowDefaultRolesCreation: allowDefaultRolesCreation === undefined ? true : allowDefaultRolesCreation,\n includeCollectionConfigPermissions: Boolean(includeCollectionConfigPermissions),\n collectionPermissions\n }\n}\n\nconst docsToUsers = (docs: DocumentSnapshot[]): (UserWithRoleIds)[] => {\n return docs.map((doc) => {\n const data = doc.data() as any;\n const newVar = {\n uid: doc.id,\n ...data,\n created_on: data?.created_on?.toDate(),\n updated_on: data?.updated_on?.toDate()\n };\n return newVar as (UserWithRoleIds);\n });\n}\n\nconst docsToRoles = (docs: DocumentSnapshot[]): Role[] => {\n return docs.map((doc) => ({\n id: doc.id,\n ...doc.data()\n } as Role));\n}\n","import React, { PropsWithChildren } from \"react\";\nimport { UserManagement, UserWithRoles } from \"./types\";\n\nexport const UserManagementContext = React.createContext<UserManagement<any>>({} as any);\n\nexport interface UserManagementProviderProps<U extends UserWithRoles = UserWithRoles> {\n userManagement: UserManagement<U>\n}\n\nexport function UserManagementProvider<U extends UserWithRoles = UserWithRoles>({\n children,\n userManagement\n }: PropsWithChildren<UserManagementProviderProps<U>>) {\n return (\n <UserManagementContext.Provider value={userManagement}>\n {children}\n </UserManagementContext.Provider>\n );\n};\n","import { useContext } from \"react\";\nimport { UserManagement } from \"../types/user_management\";\nimport { UserManagementContext } from \"../UserManagementProvider\";\n\nexport const useUserManagement = () => useContext<UserManagement>(UserManagementContext);\n","import { Chip, getColorSchemeForSeed } from \"@firecms/ui\";\nimport { Role } from \"../../types\";\n\nexport type RoleChipProps = {\n role: Role;\n}\n\nexport function RoleChip({ role }: RoleChipProps) {\n let colorScheme;\n if (role.isAdmin) {\n colorScheme = \"blueDarker\";\n } else if (role.id === \"editor\") {\n colorScheme = \"yellowLight\";\n } else if (role.id === \"viewer\") {\n colorScheme = \"grayLight\";\n } else {\n colorScheme = getColorSchemeForSeed(role.id);\n }\n\n return (\n <Chip\n colorScheme={colorScheme}\n key={role.id}>\n {role.name}\n </Chip>\n );\n\n}\n","import React, { useCallback, useState } from \"react\";\nimport * as Yup from \"yup\";\n\nimport { EntityCollection, FieldCaption, toSnakeCase, } from \"@firecms/core\";\nimport {\n Button,\n Checkbox,\n Dialog,\n DialogActions,\n DialogContent,\n DoneIcon,\n LoadingButton,\n Paper,\n Select,\n SelectItem,\n Table,\n TableBody,\n TableCell,\n TableHeader,\n TableRow,\n TextField,\n Tooltip,\n Typography\n} from \"@firecms/ui\";\nimport { useUserManagement } from \"../../hooks\";\nimport { Formex, getIn, useCreateFormex } from \"@firecms/formex\";\nimport { Role } from \"../../types\";\n\nexport const RoleYupSchema = Yup.object().shape({\n id: Yup.string().required(\"Required\"),\n name: Yup.string().required(\"Required\")\n});\n\nexport function RolesDetailsForm({\n open,\n role,\n editable,\n handleClose,\n collections\n }: {\n open: boolean,\n editable?: boolean,\n role?: Role,\n handleClose: () => void,\n collections?: EntityCollection[]\n}) {\n\n const { saveRole } = useUserManagement();\n const isNewRole = !role;\n\n const [savingError, setSavingError] = useState<Error | undefined>();\n\n const onRoleUpdated = useCallback((role: Role) => {\n setSavingError(undefined);\n return saveRole(role);\n }, [saveRole]);\n\n const formex = useCreateFormex({\n initialValues: role ?? {\n name: \"\"\n } as Role,\n onSubmit: (role: Role, formexController) => {\n return onRoleUpdated(role)\n .then(() => {\n formexController.resetForm({\n values: role\n });\n handleClose();\n })\n .catch(e => setSavingError(e));\n },\n validation: (values) => {\n return RoleYupSchema.validate(values, { abortEarly: false })\n .then(() => ({}))\n .catch((e) => {\n const errors: Record<string, string> = {};\n e.inner.forEach((error: any) => {\n errors[error.path] = error.message;\n });\n return errors;\n });\n }\n\n });\n\n const {\n isSubmitting,\n touched,\n values,\n errors,\n handleChange,\n setFieldValue,\n dirty,\n setFieldTouched\n } = formex;\n\n const isAdmin = values.isAdmin ?? false;\n const defaultCreate = values.defaultPermissions?.create ?? false;\n const defaultRead = values.defaultPermissions?.read ?? false;\n const defaultEdit = values.defaultPermissions?.edit ?? false;\n const defaultDelete = values.defaultPermissions?.delete ?? false;\n\n React.useEffect(() => {\n const idTouched = getIn(touched, \"id\");\n if (!idTouched && values.name) {\n setFieldValue(\"id\", toSnakeCase(values.name))\n }\n }, [touched, values.name]);\n\n return (\n <Dialog\n open={open}\n maxWidth={\"4xl\"}\n >\n <Formex value={formex}>\n <form noValidate\n autoComplete={\"off\"}\n onSubmit={formex.handleSubmit}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n position: \"relative\",\n height: \"100%\"\n }}>\n <DialogContent className=\"flex-grow\">\n <div\n className=\"flex flex-row pt-12 pb-8\">\n <Typography variant={\"h4\"}\n className=\"flex-grow\">\n Role\n </Typography>\n </div>\n\n <div className={\"grid grid-cols-12 gap-8\"}>\n\n <div className={\"col-span-12 md:col-span-8\"}>\n <TextField\n name=\"name\"\n required\n error={touched.name && Boolean(errors.name)}\n value={values.name}\n disabled={isAdmin || !editable}\n onChange={handleChange}\n aria-describedby=\"name-helper-text\"\n label=\"Name\"\n />\n <FieldCaption>\n {touched.name && Boolean(errors.name) ? errors.name : \"Name of this role\"}\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12 md:col-span-4\"}>\n <TextField\n name=\"id\"\n required\n error={touched.id && Boolean(errors.id)}\n value={values.id}\n disabled={!isNewRole || !editable}\n onChange={(e) => {\n handleChange(e);\n setFieldTouched(\"id\", true)\n }}\n aria-describedby=\"id-helper-text\"\n label=\"ID\"\n />\n <FieldCaption>\n {touched.id && Boolean(errors.id) ? errors.id : \"ID of this role\"}\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12\"}>\n <Paper\n\n className=\"bg-inherit\">\n <Table>\n <TableHeader>\n <TableCell></TableCell>\n <TableCell\n align=\"center\">Create\n entities\n </TableCell>\n <TableCell\n align=\"center\">Read\n entities\n </TableCell>\n <TableCell\n align=\"center\">Update\n entities\n </TableCell>\n <TableCell\n align=\"center\">Delete\n entities\n </TableCell>\n </TableHeader>\n\n <TableBody>\n <TableRow>\n <TableCell\n scope=\"row\">\n <strong>All\n collections</strong>\n </TableCell>\n <TableCell\n align=\"center\">\n <Tooltip\n title=\"Create entities in collections\">\n <Checkbox\n disabled={isAdmin || !editable}\n checked={(isAdmin || defaultCreate) ?? false}\n onCheckedChange={(checked) => setFieldValue(\"defaultPermissions.create\", checked)}\n />\n </Tooltip>\n </TableCell>\n\n <TableCell\n align=\"center\">\n <Tooltip\n title=\"Access all data in every collection\">\n <Checkbox\n disabled={isAdmin || !editable}\n checked={(isAdmin || defaultRead) ?? false}\n onCheckedChange={(checked) => setFieldValue(\"defaultPermissions.read\", checked)}\n />\n </Tooltip>\n </TableCell>\n <TableCell\n align=\"center\">\n <Tooltip\n title=\"Update data in any collection\">\n <Checkbox\n disabled={isAdmin || !editable}\n checked={(isAdmin || defaultEdit) ?? false}\n onCheckedChange={(checked) => setFieldValue(\"defaultPermissions.edit\", checked)}\n />\n </Tooltip>\n </TableCell>\n <TableCell\n align=\"center\">\n <Tooltip\n title=\"Delete data in any collection\">\n <Checkbox\n disabled={isAdmin || !editable}\n checked={(isAdmin || defaultDelete) ?? false}\n onCheckedChange={(checked) => setFieldValue(\"defaultPermissions.delete\", checked)}\n />\n\n </Tooltip>\n </TableCell>\n </TableRow>\n {collections && collections.map((col) => (\n <TableRow key={col.name}>\n <TableCell\n scope=\"row\">\n {col.name}\n </TableCell>\n <TableCell\n align=\"center\">\n <Checkbox\n disabled={isAdmin || defaultCreate || !editable}\n checked={(isAdmin || defaultCreate || getIn(values, `collectionPermissions.${col.path}.create`)) ?? false}\n onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.create`, checked)}/>\n </TableCell>\n <TableCell\n align=\"center\">\n <Checkbox\n disabled={isAdmin || defaultRead || !editable}\n checked={(isAdmin || defaultRead || getIn(values, `collectionPermissions.${col.path}.read`)) ?? false}\n onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.read`, checked)}/>\n </TableCell>\n <TableCell\n align=\"center\">\n <Checkbox\n disabled={isAdmin || defaultEdit || !editable}\n checked={(isAdmin || defaultEdit || getIn(values, `collectionPermissions.${col.path}.edit`)) ?? false}\n onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.edit`, checked)}/>\n </TableCell>\n <TableCell\n align=\"center\">\n <Checkbox\n disabled={isAdmin || defaultDelete || !editable}\n checked={(isAdmin || defaultDelete || getIn(values, `collectionPermissions.${col.path}.delete`)) ?? false}\n onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.delete`, checked)}/>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </Paper>\n <FieldCaption>\n You can customise the permissions\n that the users related to this\n role can perform in the entities\n of each collection\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12 md:col-span-4\"}>\n <Select\n error={touched.config && Boolean(errors.config)}\n id=\"createCollections\"\n name=\"createCollections\"\n label=\"Create collections\"\n position={\"item-aligned\"}\n disabled={isAdmin || !editable}\n onChange={(event) => setFieldValue(\"config.createCollections\", event.target.value === \"true\")}\n value={isAdmin || values.config?.createCollections ? \"true\" : \"false\"}\n renderValue={(value: any) => value === \"true\" ? \"Yes\" : \"No\"}\n >\n <SelectItem\n value={\"true\"}> Yes </SelectItem>\n <SelectItem\n value={\"false\"}> No </SelectItem>\n </Select>\n\n <FieldCaption>\n {touched.config && Boolean(errors.config) ? errors.config : \"Can the user create collections\"}\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12 md:col-span-4\"}>\n <Select\n error={touched.config && Boolean(errors.config)}\n id=\"editCollections\"\n name=\"editCollections\"\n label=\"Edit collections\"\n disabled={isAdmin || !editable}\n position={\"item-aligned\"}\n onChange={(event) => setFieldValue(\"config.editCollections\", event.target.value === \"own\" ? \"own\" : event.target.value === \"true\")}\n value={isAdmin ? \"true\" : (values.config?.editCollections === \"own\" ? \"own\" : (values.config?.editCollections ? \"true\" : \"false\"))}\n renderValue={(value: any) => value === \"own\" ? \"Own\" : (value === \"true\" ? \"Yes\" : \"No\")}\n >\n <SelectItem\n value={\"true\"}> Yes </SelectItem>\n <SelectItem\n value={\"false\"}> No </SelectItem>\n <SelectItem\n value={\"own\"}> Only\n his/her own </SelectItem>\n </Select>\n\n <FieldCaption>\n {touched.config && Boolean(errors.config) ? errors.config : \"Can the user edit collections\"}\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12 md:col-span-4\"}>\n <Select\n error={touched.config && Boolean(errors.config)}\n id=\"deleteCollections\"\n name=\"deleteCollections\"\n label=\"Delete collections\"\n disabled={isAdmin || !editable}\n position={\"item-aligned\"}\n onChange={(event) => setFieldValue(\"config.deleteCollections\", event.target.value === \"own\" ? \"own\" : event.target.value === \"true\")}\n value={isAdmin ? \"true\" : (values.config?.deleteCollections === \"own\" ? \"own\" : (values.config?.deleteCollections ? \"true\" : \"false\"))}\n renderValue={(value: any) => value === \"own\" ? \"Own\" : (value === \"true\" ? \"Yes\" : \"No\")}\n >\n <SelectItem\n value={\"true\"}> Yes </SelectItem>\n <SelectItem\n value={\"false\"}> No </SelectItem>\n <SelectItem\n value={\"own\"}> Only\n his/her own </SelectItem>\n </Select>\n\n <FieldCaption>\n {touched.config && Boolean(errors.config) ? errors.config : \"Can the user delete collections\"}\n </FieldCaption>\n\n </div>\n\n </div>\n </DialogContent>\n\n <DialogActions position={\"sticky\"}>\n {savingError && <Typography className={\"text-red-500\"}>\n There was an error saving this role\n </Typography>}\n <Button variant={\"text\"}\n onClick={() => {\n handleClose();\n }}>\n Cancel\n </Button>\n <LoadingButton\n variant=\"filled\"\n color=\"primary\"\n type=\"submit\"\n disabled={!dirty}\n loading={isSubmitting}\n startIcon={<DoneIcon/>}\n >\n {isNewRole ? \"Create role\" : \"Update\"}\n </LoadingButton>\n </DialogActions>\n </form>\n\n </Formex>\n </Dialog>\n );\n}\n","import { Role } from \"../../types\";\n\nexport const DEFAULT_ROLES: Role[] = [\n {\n id: \"admin\",\n name: \"Admin\",\n isAdmin: true\n },\n {\n id: \"editor\",\n name: \"Editor\",\n isAdmin: false,\n defaultPermissions: {\n read: true,\n create: true,\n edit: true,\n delete: true\n },\n config: {\n createCollections: true,\n editCollections: \"own\",\n deleteCollections: \"own\"\n }\n },\n {\n id: \"viewer\",\n name: \"Viewer\",\n isAdmin: false,\n defaultPermissions: {\n read: true,\n create: false,\n edit: false,\n delete: false\n }\n }\n];\n","import { useState } from \"react\";\nimport {\n Button,\n CenteredView,\n Checkbox,\n DeleteIcon,\n IconButton,\n Table,\n TableBody,\n TableCell,\n TableHeader,\n TableRow,\n Tooltip,\n Typography\n} from \"@firecms/ui\";\nimport { DeleteConfirmationDialog } from \"@firecms/core\";\nimport { useUserManagement } from \"../../hooks\";\nimport { Role } from \"../../types\";\nimport { RoleChip } from \"./RoleChip\";\nimport { DEFAULT_ROLES } from \"./default_roles\";\n\nexport function RolesTable({\n onRoleClicked,\n editable\n }: {\n onRoleClicked: (role: Role) => void;\n editable: boolean;\n}) {\n\n const {\n roles,\n saveRole,\n deleteRole,\n allowDefaultRolesCreation\n } = useUserManagement();\n\n const [roleToBeDeleted, setRoleToBeDeleted] = useState<Role | undefined>(undefined);\n const [deleteInProgress, setDeleteInProgress] = useState<boolean>(false);\n\n return <div\n className=\"w-full overflow-auto\">\n <Table>\n <TableHeader>\n <TableCell header={true} className=\"w-16\"></TableCell>\n <TableCell header={true}>Role</TableCell>\n <TableCell header={true} className={\"items-center\"}>Is Admin</TableCell>\n <TableCell header={true}>Default permissions</TableCell>\n </TableHeader>\n\n <TableBody>\n {roles && roles.map((role) => {\n const canCreateAll = role.isAdmin || role.defaultPermissions?.create;\n const canReadAll = role.isAdmin || role.defaultPermissions?.read;\n const canUpdateAll = role.isAdmin || role.defaultPermissions?.edit;\n const canDeleteAll = role.isAdmin || role.defaultPermissions?.delete;\n return (\n <TableRow\n key={role.name}\n onClick={() => {\n onRoleClicked(role);\n }}\n >\n <TableCell style={{ width: \"64px\" }}>\n {!role.isAdmin &&\n <Tooltip title={\"Delete this role\"}>\n <IconButton\n size={\"small\"}\n disabled={!editable}\n onClick={(event) => {\n event.stopPropagation();\n return setRoleToBeDeleted(role);\n }}>\n <DeleteIcon/>\n </IconButton>\n </Tooltip>}\n </TableCell>\n <TableCell>\n <RoleChip role={role}/>\n </TableCell>\n <TableCell className={\"items-center\"}>\n <Checkbox checked={role.isAdmin ?? false}/>\n </TableCell>\n <TableCell>\n <ul>\n {canCreateAll && <li>Create</li>}\n {canReadAll && <li>Read</li>}\n {canUpdateAll && <li>Update</li>}\n {canDeleteAll && <li>Delete</li>}\n </ul>\n </TableCell>\n </TableRow>\n );\n })}\n\n {(!roles || roles.length === 0) && <TableRow>\n <TableCell colspan={4}>\n <CenteredView className={\"flex flex-col gap-4 my-8 items-center\"}>\n <Typography variant={\"label\"}>\n You don&apos;t have any roles yet.\n </Typography>\n {allowDefaultRolesCreation && <Button variant={\"outlined\"}\n onClick={() => {\n DEFAULT_ROLES.forEach((role) => {\n saveRole(role);\n });\n }}>\n Create default roles\n </Button>}\n </CenteredView>\n </TableCell>\n </TableRow>}\n\n </TableBody>\n\n </Table>\n\n <DeleteConfirmationDialog\n open={Boolean(roleToBeDeleted)}\n loading={deleteInProgress}\n onAccept={() => {\n if (roleToBeDeleted) {\n setDeleteInProgress(true);\n deleteRole(roleToBeDeleted)\n .then(() => {\n setRoleToBeDeleted(undefined);\n })\n .finally(() => {\n setDeleteInProgress(false);\n })\n }\n }}\n onCancel={() => {\n setRoleToBeDeleted(undefined);\n }}\n title={<>Delete?</>}\n body={<>Are you sure you want to delete this role?</>}/>\n\n </div>;\n}\n","import React, { useCallback, useState } from \"react\";\n\nimport { useNavigationController } from \"@firecms/core\";\nimport { AddIcon, Button, Container, Tooltip, Typography } from \"@firecms/ui\";\nimport { RolesTable } from \"./RolesTable\";\nimport { RolesDetailsForm } from \"./RolesDetailsForm\";\nimport { useUserManagement } from \"../../hooks\";\nimport { Role } from \"../../types\";\n\nexport const RolesView = React.memo(\n function RolesView({ children }: { children?: React.ReactNode }) {\n\n const { collections } = useNavigationController();\n const [dialogOpen, setDialogOpen] = useState(false);\n const [selectedRole, setSelectedRole] = useState<Role | undefined>();\n\n const { canEditRoles } = useUserManagement();\n\n const onRoleClicked = useCallback((user: Role) => {\n setDialogOpen(true);\n setSelectedRole(user);\n }, []);\n\n const handleClose = () => {\n setSelectedRole(undefined);\n setDialogOpen(false);\n };\n\n return (\n <Container className=\"w-full flex flex-col py-4 gap-4\" maxWidth={\"6xl\"}>\n\n {children}\n\n <div className=\"flex items-center mt-12\">\n <Typography gutterBottom variant=\"h4\"\n className=\"flex-grow\"\n component=\"h4\">\n Roles\n </Typography>\n <Tooltip title={!canEditRoles ? \"Update plans to customise roles\" : undefined}>\n <Button\n size={\"large\"}\n disabled={!canEditRoles}\n startIcon={<AddIcon/>}\n onClick={() => setDialogOpen(true)}>\n Add role\n </Button>\n </Tooltip>\n </div>\n\n <RolesTable onRoleClicked={onRoleClicked} editable={Boolean(canEditRoles)}/>\n\n <RolesDetailsForm\n key={selectedRole?.id ?? \"new\"}\n open={dialogOpen}\n role={selectedRole}\n editable={canEditRoles}\n collections={collections}\n handleClose={handleClose}/>\n\n </Container>\n )\n });\n","import React, { useCallback } from \"react\";\nimport * as Yup from \"yup\";\nimport {\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DoneIcon,\n LoadingButton,\n MultiSelect,\n MultiSelectItem,\n TextField,\n Typography,\n} from \"@firecms/ui\";\nimport { FieldCaption, useSnackbarController } from \"@firecms/core\";\nimport { Formex, useCreateFormex } from \"@firecms/formex\";\n\nimport { Role, UserWithRoles } from \"../../types\";\nimport { areRolesEqual } from \"../../utils\";\nimport { useUserManagement } from \"../../hooks\";\nimport { RoleChip } from \"../roles\";\n\nexport const UserYupSchema = Yup.object().shape({\n displayName: Yup.string().required(\"Required\"),\n email: Yup.string().email().required(\"Required\"),\n roles: Yup.array().min(1)\n});\n\nfunction canUserBeEdited(loggedUser: UserWithRoles, user: UserWithRoles, users: UserWithRoles[], roles: Role[], prevUser?: UserWithRoles) {\n const admins = users.filter(u => u.roles.map(r => r.id).includes(\"admin\"));\n const loggedUserIsAdmin = loggedUser.roles.map(r => r.id).includes(\"admin\");\n const didRolesChange = !prevUser || !areRolesEqual(prevUser.roles, user.roles);\n\n if (didRolesChange && !loggedUserIsAdmin) {\n throw new Error(\"Only admins can change roles\");\n }\n\n // was the admin role removed\n const adminRoleRemoved = prevUser && prevUser.roles.map(r => r.id).includes(\"admin\") && !user.roles.map(r => r.id).includes(\"admin\");\n\n // avoid removing the last admin\n if (adminRoleRemoved && admins.length === 1) {\n throw new Error(\"There must be at least one admin\");\n }\n return true;\n}\n\nexport function UserDetailsForm({\n open,\n user: userProp,\n handleClose\n }: {\n open: boolean,\n user?: UserWithRoles,\n handleClose: () => void\n}) {\n\n const snackbarController = useSnackbarController();\n const {\n loggedInUser,\n saveUser,\n users,\n roles,\n } = useUserManagement();\n const isNewUser = !userProp;\n\n const onUserUpdated = useCallback((savedUser: UserWithRoles): Promise<UserWithRoles> => {\n if (!loggedInUser) {\n throw new Error(\"Logged user not found\");\n }\n try {\n canUserBeEdited(loggedInUser, savedUser, users, roles, userProp);\n return saveUser(savedUser);\n } catch (e: any) {\n return Promise.reject(e);\n }\n }, [roles, saveUser, userProp, users, loggedInUser]);\n\n const formex = useCreateFormex({\n initialValues: userProp ?? {\n displayName: \"\",\n email: \"\",\n roles: roles.filter(r => r.id === \"editor\")\n } as UserWithRoles,\n validation: (values) => {\n return UserYupSchema.validate(values, { abortEarly: false })\n .then(() => {\n return {};\n }).catch((e) => {\n return e.inner.reduce((acc: any, error: any) => {\n acc[error.path] = error.message;\n return acc;\n }, {});\n });\n },\n onSubmit: (user: UserWithRoles, formexController) => {\n\n return onUserUpdated(user)\n .then(() => {\n handleClose();\n formexController.resetForm({\n values: user\n });\n }).catch((e) => {\n snackbarController.open({\n type: \"error\",\n message: e.message\n });\n });\n }\n });\n\n const {\n isSubmitting,\n touched,\n handleChange,\n values,\n errors,\n setFieldValue,\n dirty,\n handleSubmit,\n submitCount\n } = formex;\n\n return (\n <Dialog\n open={open}\n onOpenChange={(open) => !open ? handleClose() : undefined}\n maxWidth={\"4xl\"}\n >\n <Formex value={formex}>\n <form\n onSubmit={handleSubmit}\n autoComplete={\"off\"}\n noValidate\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n position: \"relative\",\n height: \"100%\"\n }}>\n <DialogContent className=\"h-full flex-grow\">\n <div\n className=\"flex flex-row pt-4 pb-4\">\n <Typography variant={\"h4\"}\n className=\"flex-grow\">\n User\n </Typography>\n </div>\n\n <div className={\"grid grid-cols-12 gap-8\"}>\n\n <div className={\"col-span-12\"}>\n <TextField\n name=\"displayName\"\n required\n error={submitCount > 0 && Boolean(errors.displayName)}\n value={values.displayName ?? \"\"}\n onChange={handleChange}\n aria-describedby=\"name-helper-text\"\n label=\"Name\"\n />\n <FieldCaption>\n {submitCount > 0 && Boolean(errors.displayName) ? errors.displayName : \"Name of this user\"}\n </FieldCaption>\n </div>\n <div className={\"col-span-12\"}>\n <TextField\n required\n error={submitCount > 0 && Boolean(errors.email)}\n name=\"email\"\n value={values.email ?? \"\"}\n onChange={handleChange}\n aria-describedby=\"email-helper-text\"\n label=\"Email\"\n />\n <FieldCaption>\n {submitCount > 0 && Boolean(errors.email) ? errors.email : \"Email of this user\"}\n </FieldCaption>\n </div>\n <div className={\"col-span-12\"}>\n <MultiSelect\n label=\"Roles\"\n value={values.roles.map(r => r.id) ?? []}\n onMultiValueChange={(value: string[]) => setFieldValue(\"roles\", value.map(id => roles.find(r => r.id === id) as Role))}\n renderValue={(value: string) => {\n const userRole = roles\n .find((role) => role.id === value);\n if (!userRole) return null;\n return <div className=\"flex flex-wrap space-x-2 space-y-2\">\n <RoleChip key={userRole?.id} role={userRole}/>\n </div>;\n }}>\n {roles.map(userRole => <MultiSelectItem key={userRole.id}\n value={userRole.id}>\n <RoleChip key={userRole?.id} role={userRole}/>\n </MultiSelectItem>)}\n </MultiSelect>\n </div>\n\n </div>\n\n </DialogContent>\n\n <DialogActions>\n\n <Button variant={\"text\"}\n onClick={() => {\n handleClose();\n }}>\n Cancel\n </Button>\n\n <LoadingButton\n variant=\"filled\"\n color=\"primary\"\n type=\"submit\"\n disabled={!dirty}\n loading={isSubmitting}\n startIcon={<DoneIcon/>}\n >\n {isNewUser ? \"Create user\" : \"Update\"}\n </LoadingButton>\n </DialogActions>\n </form>\n </Formex>\n\n </Dialog>\n );\n}\n","import { useState } from \"react\";\nimport { User as FirebaseUser } from \"firebase/auth\";\n\nimport { format } from \"date-fns\";\nimport * as locales from \"date-fns/locale\";\n\nimport {\n defaultDateFormat,\n DeleteConfirmationDialog,\n useAuthController,\n useCustomizationController,\n useSnackbarController\n} from \"@firecms/core\";\nimport {\n Button,\n CenteredView,\n DeleteIcon,\n IconButton,\n Table,\n TableBody,\n TableCell,\n TableHeader,\n TableRow,\n Tooltip,\n Typography,\n} from \"@firecms/ui\";\nimport { Role, UserWithRoles } from \"../../types\";\nimport { useUserManagement } from \"../../hooks/useUserManagement\";\nimport { RoleChip } from \"../roles/RoleChip\";\n\nexport function UsersTable({ onUserClicked }: {\n onUserClicked: (user: UserWithRoles) => void;\n}) {\n\n const {\n users,\n saveUser,\n deleteUser\n } = useUserManagement();\n\n const authController = useAuthController<FirebaseUser>();\n const snackbarController = useSnackbarController();\n\n const customizationController = useCustomizationController();\n const dateUtilsLocale = customizationController?.locale ? locales[customizationController?.locale as keyof typeof locales] : undefined;\n const dateFormat: string = customizationController?.dateTimeFormat ?? defaultDateFormat;\n\n const [userToBeDeleted, setUserToBeDeleted] = useState<UserWithRoles | undefined>(undefined);\n const [deleteInProgress, setDeleteInProgress] = useState<boolean>(false);\n\n return (\n <div className=\"overflow-auto\">\n\n <Table>\n\n <TableHeader>\n <TableCell className=\"truncate w-16\"></TableCell>\n <TableCell>ID</TableCell>\n <TableCell>Email</TableCell>\n <TableCell>Name</TableCell>\n <TableCell>Roles</TableCell>\n <TableCell>Created on</TableCell>\n </TableHeader>\n <TableBody>\n {users && users.map((user) => {\n\n const userRoles: Role[] | undefined = user.roles;\n\n const formattedDate = user.created_on ? format(user.created_on, dateFormat, { locale: dateUtilsLocale }) : \"\";\n\n return (\n <TableRow\n key={\"row_\" + user.uid}\n onClick={() => {\n onUserClicked(user);\n }}\n >\n <TableCell className={\"w-10\"}>\n <Tooltip title={\"Delete this user\"}>\n <IconButton\n size={\"small\"}\n onClick={(event) => {\n event.stopPropagation();\n return setUserToBeDeleted(user);\n }}>\n <DeleteIcon/>\n </IconButton>\n </Tooltip>\n </TableCell>\n <TableCell>{user.uid}</TableCell>\n <TableCell>{user.email}</TableCell>\n <TableCell className={\"font-medium align-left\"}>{user.displayName}</TableCell>\n <TableCell className=\"align-left\">\n {userRoles\n ? <div className=\"flex flex-wrap gap-2\">\n {userRoles.map(userRole =>\n <RoleChip key={userRole?.id} role={userRole}/>\n )}\n </div>\n : null}\n </TableCell>\n <TableCell>{formattedDate}</TableCell>\n </TableRow>\n );\n })}\n\n {(!users || users.length === 0) && <TableRow>\n <TableCell colspan={6}>\n <CenteredView className={\"flex flex-col gap-4 my-8 items-center\"}>\n <Typography variant={\"label\"}>\n There are no users yet\n </Typography>\n <Button variant={\"outlined\"}\n onClick={() => {\n if (!authController.user?.uid) {\n throw Error(\"UsersTable, authController misconfiguration\");\n }\n saveUser({\n uid: authController.user?.uid,\n email: authController.user?.email,\n displayName: authController.user?.displayName,\n photoURL: authController.user?.photoURL,\n providerId: authController.user?.providerId,\n isAnonymous: authController.user?.isAnonymous,\n roles: [{ id: \"admin\", name: \"Admin\" }],\n created_on: new Date()\n })\n .then(() => {\n snackbarController.open({\n type: \"success\",\n message: \"User added successfully\"\n })\n })\n .catch((error) => {\n snackbarController.open({\n type: \"error\",\n message: \"Error adding user: \" + error.message,\n })\n });\n }}>\n\n Add the logged user as an admin\n </Button>\n </CenteredView>\n </TableCell>\n </TableRow>}\n\n </TableBody>\n </Table>\n\n <DeleteConfirmationDialog\n open={Boolean(userToBeDeleted)}\n loading={deleteInProgress}\n onAccept={() => {\n if (userToBeDeleted) {\n setDeleteInProgress(true);\n deleteUser(userToBeDeleted)\n .then(() => {\n setUserToBeDeleted(undefined);\n })\n .catch((error) => {\n snackbarController.open({\n type: \"error\",\n message: \"Error deleting user: \" + error.message,\n })\n })\n .finally(() => {\n setDeleteInProgress(false);\n })\n }\n }}\n onCancel={() => {\n setUserToBeDeleted(undefined);\n }}\n title={<>Delete?</>}\n body={<>Are you sure you want to delete this user?</>}/>\n </div>);\n}\n","import { AddIcon, Button, Container, Typography } from \"@firecms/ui\";\n\nimport { UsersTable } from \"./UsersTable\";\nimport { UserDetailsForm } from \"./UserDetailsForm\";\nimport React, { useCallback, useState } from \"react\";\nimport { UserWithRoles } from \"../../types\";\nimport { useUserManagement } from \"../../hooks/useUserManagement\";\n\nexport const UsersView = function UsersView({ children }: { children?: React.ReactNode }) {\n\n const [dialogOpen, setDialogOpen] = useState<boolean>();\n const [selectedUser, setSelectedUser] = useState<UserWithRoles | undefined>();\n\n const { users, usersLimit } = useUserManagement();\n\n const reachedUsersLimit = usersLimit !== undefined && (users && users.length >= usersLimit);\n\n const onUserClicked = useCallback((user: UserWithRoles) => {\n setSelectedUser(user);\n setDialogOpen(true);\n }, []);\n\n const handleClose = useCallback(() => {\n setDialogOpen(false);\n setSelectedUser(undefined);\n }, []);\n\n return (\n <Container className=\"w-full flex flex-col py-4 gap-4\" maxWidth={\"6xl\"}>\n\n {children}\n\n <div\n className=\"flex items-center mt-12\">\n <Typography gutterBottom variant=\"h4\"\n className=\"flex-grow\"\n component=\"h4\">\n Users\n </Typography>\n <Button\n size={\"large\"}\n disabled={reachedUsersLimit}\n startIcon={<AddIcon/>}\n onClick={() => setDialogOpen(true)}>\n Add user\n </Button>\n </div>\n\n <UsersTable onUserClicked={onUserClicked}/>\n\n <UserDetailsForm\n key={selectedUser?.uid ?? \"new\"}\n open={dialogOpen ?? false}\n user={selectedUser}\n handleClose={handleClose}/>\n\n </Container>\n )\n};\n","import { AuthController, FireCMSPlugin } from \"@firecms/core\";\nimport { UserManagementProvider } from \"./UserManagementProvider\";\nimport { UserManagement } from \"./types\";\n\nexport function useUserManagementPlugin({ userManagement }: {\n userManagement: UserManagement,\n}): FireCMSPlugin {\n return {\n name: \"User management plugin\",\n loading: userManagement.loading,\n provider: {\n Component: UserManagementProvider,\n props: {\n userManagement\n }\n }\n }\n}\n","import { CMSView } from \"@firecms/core\";\nimport { RolesView, UsersView } from \"./components\";\n\nexport const userManagementAdminViews: CMSView[] = [\n {\n path: \"users\",\n name: \"CMS Users\",\n group: \"Admin\",\n icon: \"face\",\n view: <UsersView/>\n },\n {\n path: \"roles\",\n name: \"Roles\",\n group: \"Admin\",\n icon: \"gpp_good\",\n view: <RolesView/>\n }\n]\n"],"names":["RESERVED_GROUPS","DEFAULT_PERMISSIONS","resolveUserRolePermissions","collection","user","roles","basePermissions","role","resolveCollectionRole","mergePermissions","id","permA","permB","getUserRoles","fireCMSUser","r","areRolesEqual","rolesA","rolesB","rolesAIds","rolesBIds","cacheDelegatedLoginToken","projectId","delegatedToken","data","parseJwt","expiry","getDelegatedLoginTokenFromCache","entry","clearDelegatedLoginTokensCache","i","key","token","base64","jsonPayload","c","darkenColor","hexColor","darkenBy","color","g","b","hexToRgbaWithOpacity","opacity","alpha","useBuildFirestoreUserManagement","firebaseApp","usersPath","rolesPath","usersLimit","canEditRoles","authController","allowDefaultRolesCreation","includeCollectionConfigPermissions","firestoreRef","useRef","rolesLoading","setRolesLoading","React","usersLoading","setUsersLoading","setRoles","usersWithRoleIds","setUsersWithRoleIds","users","u","rolesError","setRolesError","usersError","setUsersError","loading","loggedInUser","useEffect","getFirestore","firestore","onSnapshot","snapshot","newRoles","docsToRoles","e","newUsers","docsToUsers","saveUser","useCallback","roleIds","uid","userData","setDoc","doc","saveRole","roleData","ref","deleteUser","deleteDoc","deleteRole","collectionPermissions","docs","UserManagementContext","UserManagementProvider","children","userManagement","useUserManagement","useContext","RoleChip","colorScheme","getColorSchemeForSeed","jsx","Chip","RoleYupSchema","Yup","RolesDetailsForm","open","editable","handleClose","collections","isNewRole","savingError","setSavingError","useState","onRoleUpdated","formex","useCreateFormex","formexController","values","errors","error","isSubmitting","touched","handleChange","setFieldValue","dirty","setFieldTouched","isAdmin","defaultCreate","defaultRead","defaultEdit","defaultDelete","getIn","toSnakeCase","Dialog","Formex","jsxs","DialogContent","Typography","TextField","FieldCaption","Paper","Table","TableHeader","TableCell","TableBody","TableRow","Tooltip","Checkbox","checked","col","Select","event","value","SelectItem","DialogActions","Button","LoadingButton","DoneIcon","DEFAULT_ROLES","RolesTable","onRoleClicked","roleToBeDeleted","setRoleToBeDeleted","deleteInProgress","setDeleteInProgress","canCreateAll","canReadAll","canUpdateAll","canDeleteAll","IconButton","DeleteIcon","CenteredView","DeleteConfirmationDialog","RolesView","useNavigationController","dialogOpen","setDialogOpen","selectedRole","setSelectedRole","Container","AddIcon","UserYupSchema","canUserBeEdited","loggedUser","prevUser","admins","loggedUserIsAdmin","UserDetailsForm","userProp","snackbarController","useSnackbarController","isNewUser","onUserUpdated","savedUser","acc","handleSubmit","submitCount","MultiSelect","userRole","MultiSelectItem","UsersTable","onUserClicked","useAuthController","customizationController","useCustomizationController","dateUtilsLocale","locales","dateFormat","defaultDateFormat","userToBeDeleted","setUserToBeDeleted","userRoles","formattedDate","format","UsersView","selectedUser","setSelectedUser","reachedUsersLimit","useUserManagementPlugin","userManagementAdminViews"],"mappings":"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"}
1
+ {"version":3,"file":"index.es.js","sources":["../src/utils/permissions.ts","../src/utils/local_storage.ts","../src/utils/colors.ts","../src/hooks/useBuildFirestoreUserManagement.tsx","../src/UserManagementProvider.tsx","../src/hooks/useUserManagement.tsx","../src/components/roles/RoleChip.tsx","../src/components/roles/RolesDetailsForm.tsx","../src/components/roles/default_roles.tsx","../src/components/roles/RolesTable.tsx","../src/components/roles/RolesView.tsx","../src/components/users/UserDetailsForm.tsx","../src/components/users/UsersTable.tsx","../src/components/users/UsersView.tsx","../src/useUserManagementPlugin.tsx","../src/admin_views.tsx"],"sourcesContent":["import { CMSType, EntityCollection, Permissions } from \"@firecms/core\";\nimport { Role, UserWithRoles } from \"../types\";\n\nexport const RESERVED_GROUPS = [\"Admin\"];\n\nconst DEFAULT_PERMISSIONS = {\n read: false,\n edit: false,\n create: false,\n delete: false\n};\n\nexport function resolveUserRolePermissions<UserType extends UserWithRoles>\n({ collection, user }: {\n collection: EntityCollection<any>,\n user: UserType | null\n}): Permissions {\n\n const roles = user?.roles;\n if (!roles) {\n return DEFAULT_PERMISSIONS;\n } else if (collection.ownerId === user?.uid) {\n return {\n read: true,\n create: true,\n edit: true,\n delete: true\n };\n } else {\n const basePermissions = {\n read: false,\n create: false,\n edit: false,\n delete: false\n };\n\n return roles\n .map(role => resolveCollectionRole(role, collection.id))\n .reduce(mergePermissions, basePermissions);\n }\n}\n\nfunction resolveCollectionRole(role: Role, id: string): Permissions {\n\n const basePermissions = {\n read: role.isAdmin || role.defaultPermissions?.read,\n create: role.isAdmin || role.defaultPermissions?.create,\n edit: role.isAdmin || role.defaultPermissions?.edit,\n delete: role.isAdmin || role.defaultPermissions?.delete\n };\n if (role.collectionPermissions && role.collectionPermissions[id]) {\n return mergePermissions(role.collectionPermissions[id], basePermissions);\n } else if (role.defaultPermissions) {\n return mergePermissions(role.defaultPermissions, basePermissions);\n } else {\n return basePermissions;\n }\n}\n\nconst mergePermissions = (permA: Permissions, permB: Permissions) => {\n return {\n read: permA.read || permB.read,\n create: permA.create || permB.create,\n edit: permA.edit || permB.edit,\n delete: permA.delete || permB.delete\n };\n}\n\nexport function getUserRoles(roles: Role[], fireCMSUser: UserWithRoles): Role[] | undefined {\n return !roles\n ? undefined\n : (fireCMSUser.roles\n ? fireCMSUser.roles\n .map(role => roles.find((r) => r.id === role.id))\n .filter(Boolean) as Role[]\n : []);\n}\n\nexport const areRolesEqual = (rolesA: Role[], rolesB: Role[]) => {\n const rolesAIds = rolesA.map(r => r.id);\n const rolesBIds = rolesB.map(r => r.id);\n return rolesAIds.length === rolesB.length && rolesAIds.every((role) => rolesBIds.includes(role));\n}\n","// const tokens = new Map<string, {\n// token: string,\n// expiry: Date\n// }>();\n\nexport function cacheDelegatedLoginToken(projectId: string, delegatedToken?: string) {\n if (!delegatedToken) {\n return;\n }\n\n const data = parseJwt(delegatedToken);\n // @ts-ignore\n const expiry = new Date(data.exp * 1000);\n localStorage.setItem(`auth_token::${projectId}`, JSON.stringify({\n token: delegatedToken,\n expiry\n }));\n\n}\n\nexport function getDelegatedLoginTokenFromCache(projectId: string) {\n const entry = localStorage.getItem(`auth_token::${projectId}`);\n if (entry) {\n const data = JSON.parse(entry);\n data.expiry = new Date(data.expiry);\n if (data.expiry > new Date()) {\n return data.token;\n }\n }\n return undefined;\n}\n\nexport function clearDelegatedLoginTokensCache() {\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(\"auth_token::\")) {\n localStorage.removeItem(key);\n }\n }\n}\n\nfunction parseJwt(token?: string): object {\n if (!token) {\n throw new Error(\"No JWT token\");\n }\n const base64Url = token.split(\".\")[1];\n const base64 = base64Url.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const jsonPayload = decodeURIComponent(window.atob(base64).split(\"\").map(function (c) {\n return \"%\" + (\"00\" + c.charCodeAt(0).toString(16)).slice(-2);\n }).join(\"\"));\n\n return JSON.parse(jsonPayload);\n}\n","export function darkenColor(hexColor: string, darkenBy = 10): string {\n // Check input validity\n if (!/^#([0-9A-Fa-f]{3}){1,2}$/.test(hexColor)) {\n throw new Error(\"Invalid color format\");\n }\n\n // If shorthand form, convert to full form\n let color = hexColor.substring(1).split(\"\");\n if (color.length === 3) {\n color = [color[0], color[0], color[1], color[1], color[2], color[2]];\n }\n\n // Convert to RGB values\n let r = parseInt(color[0] + color[1], 16);\n let g = parseInt(color[2] + color[3], 16);\n let b = parseInt(color[4] + color[5], 16);\n\n // Reduce each color component by the specified percentage (darkenBy)\n r = Math.floor(r * (1 - darkenBy / 100));\n g = Math.floor(g * (1 - darkenBy / 100));\n b = Math.floor(b * (1 - darkenBy / 100));\n\n // Recombine into hex and return\n return \"#\" +\n (r < 16 ? \"0\" : \"\") + r.toString(16) +\n (g < 16 ? \"0\" : \"\") + g.toString(16) +\n (b < 16 ? \"0\" : \"\") + b.toString(16);\n}\n\nexport function hexToRgbaWithOpacity(hexColor: string, opacity = 10): string {\n // Check input validity\n if (!/^#([0-9A-Fa-f]{3}){1,2}$/.test(hexColor)) {\n throw new Error(\"Invalid color format\");\n }\n\n // If shorthand form, convert to full form\n let color = hexColor.substring(1).split(\"\");\n if (color.length === 3) {\n color = [color[0], color[0], color[1], color[1], color[2], color[2]];\n }\n\n // Convert to RGB values\n const r = parseInt(color[0] + color[1], 16);\n const g = parseInt(color[2] + color[3], 16);\n const b = parseInt(color[4] + color[5], 16);\n\n // Convert opacity to a decimal for CSS\n const alpha = opacity / 100;\n\n // Construct and return the RGBA color\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n","import React, { useCallback, useEffect, useRef } from \"react\";\nimport {\n collection,\n deleteDoc,\n doc,\n DocumentSnapshot,\n Firestore,\n getFirestore,\n onSnapshot,\n setDoc\n} from \"firebase/firestore\";\nimport { FirebaseApp } from \"firebase/app\";\nimport { Role, UserManagement, UserWithRoles } from \"../types\";\nimport { AuthController, PermissionsBuilder, User } from \"@firecms/core\";\nimport { resolveUserRolePermissions } from \"../utils\";\n\ntype UserWithRoleIds = User & { roles: string[] };\n\nexport interface UserManagementParams {\n /**\n * The Firebase app to use for the user management. The config will be saved in the Firestore\n * collection indicated by `configPath`.\n */\n firebaseApp?: FirebaseApp;\n /**\n * Path where the plugin users configuration is stored.\n * Default: __FIRECMS/config/users\n * You can specify a different path if you want to store the user management configuration in a different place.\n * Please keep in mind that the FireCMS users are not necessarily the same as the Firebase users (but they can be).\n * The path should be relative to the root of the Firestore database, and should always have an odd number of segments.\n */\n usersPath?: string;\n\n /**\n * Path where the plugin roles configuration is stored.\n * Default: __FIRECMS/config/roles\n */\n rolesPath?: string;\n\n usersLimit?: number;\n\n canEditRoles?: boolean;\n\n authController: AuthController;\n\n /**\n * If there are no roles in the database, provide a button to create the default roles.\n */\n allowDefaultRolesCreation?: boolean;\n\n /**\n * Include the collection config permissions in the user management system.\n */\n includeCollectionConfigPermissions?: boolean;\n\n}\n\n/**\n * This hook is used to build a user management object that can be used to\n * manage users and roles in a Firestore backend.\n * @param backendFirebaseApp\n * @param usersPath\n * @param rolesPath\n * @param usersLimit\n * @param canEditRoles\n */\nexport function useBuildFirestoreUserManagement({\n firebaseApp,\n usersPath = \"__FIRECMS/config/users\",\n rolesPath = \"__FIRECMS/config/roles\",\n usersLimit,\n canEditRoles = true,\n authController,\n allowDefaultRolesCreation,\n includeCollectionConfigPermissions\n }: UserManagementParams): UserManagement {\n\n const firestoreRef = useRef<Firestore>();\n\n const [rolesLoading, setRolesLoading] = React.useState<boolean>(true);\n const [usersLoading, setUsersLoading] = React.useState<boolean>(true);\n const [roles, setRoles] = React.useState<Role[]>([]);\n const [usersWithRoleIds, setUsersWithRoleIds] = React.useState<UserWithRoleIds[]>([]);\n\n const users = usersWithRoleIds.map(u => ({\n ...u,\n roles: roles.filter(r => u.roles?.includes(r.id))\n }) as UserWithRoles);\n\n const [rolesError, setRolesError] = React.useState<Error | undefined>();\n const [usersError, setUsersError] = React.useState<Error | undefined>();\n\n const loading = rolesLoading || usersLoading;\n\n const loggedInUser: UserWithRoles | undefined = users.find(u => u.email?.toLowerCase() === authController.user?.email?.toLowerCase());\n // console.log(\"authController\", authController);\n // if (!loading && !authController.authLoading) {\n // const user = authController.user;\n // if (user) {\n // loggedInUser = users.find(u => u.email?.toLowerCase() === user.email?.toLowerCase());\n // }\n // }\n\n useEffect(() => {\n if (!firebaseApp) return;\n firestoreRef.current = getFirestore(firebaseApp);\n }, [firebaseApp]);\n\n useEffect(() => {\n if (!firebaseApp || !rolesPath) return;\n const firestore = getFirestore(firebaseApp);\n\n return onSnapshot(collection(firestore, rolesPath),\n {\n next: (snapshot) => {\n setRolesError(undefined);\n try {\n const newRoles = docsToRoles(snapshot.docs);\n setRoles(newRoles);\n } catch (e) {\n // console.error(e);\n setRolesError(e as Error);\n }\n setRolesLoading(false);\n },\n error: (e) => {\n setRolesError(e);\n setRolesLoading(false);\n }\n }\n );\n }, [firebaseApp, rolesPath]);\n\n useEffect(() => {\n if (!firebaseApp || !usersPath) return;\n const firestore = getFirestore(firebaseApp);\n\n return onSnapshot(collection(firestore, usersPath),\n {\n next: (snapshot) => {\n setUsersError(undefined);\n try {\n const newUsers = docsToUsers(snapshot.docs);\n setUsersWithRoleIds(newUsers);\n } catch (e) {\n setUsersError(e as Error);\n }\n setUsersLoading(false);\n },\n error: (e) => {\n setUsersError(e);\n setUsersLoading(false);\n }\n }\n );\n }, [firebaseApp, usersPath]);\n\n const saveUser = useCallback(async (user: UserWithRoles): Promise<UserWithRoles> => {\n const firestore = firestoreRef.current;\n if (!firestore || !usersPath) throw Error(\"useFirestoreConfigurationPersistence Firestore not initialised\");\n console.debug(\"Persisting user\", user);\n const roleIds = user.roles.map(r => r.id);\n const {\n uid,\n ...userData\n } = user;\n return setDoc(doc(firestore, usersPath, uid), { ...userData, roles: roleIds }, { merge: true }).then(() => user);\n }, [usersPath]);\n\n const saveRole = useCallback((role: Role): Promise<void> => {\n const firestore = firestoreRef.current;\n if (!firestore || !rolesPath) throw Error(\"useFirestoreConfigurationPersistence Firestore not initialised\");\n console.debug(\"Persisting role\", role);\n const {\n id,\n ...roleData\n } = role;\n const ref = doc(firestore, rolesPath, id);\n return setDoc(ref, roleData, { merge: true });\n }, [rolesPath]);\n\n const deleteUser = useCallback(async (user: UserWithRoles): Promise<void> => {\n const firestore = firestoreRef.current;\n if (!firestore || !usersPath) throw Error(\"useFirestoreConfigurationPersistence Firestore not initialised\");\n console.debug(\"Deleting\", user);\n const { uid } = user;\n return deleteDoc(doc(firestore, usersPath, uid));\n }, [usersPath]);\n\n const deleteRole = useCallback((role: Role): Promise<void> => {\n const firestore = firestoreRef.current;\n if (!firestore || !rolesPath) throw Error(\"useFirestoreConfigurationPersistence Firestore not initialised\");\n console.debug(\"Deleting\", role);\n const { id } = role;\n const ref = doc(firestore, rolesPath, id);\n return deleteDoc(ref);\n }, [rolesPath]);\n\n const collectionPermissions: PermissionsBuilder = useCallback(({\n collection,\n }) => resolveUserRolePermissions({\n collection,\n user: loggedInUser ?? null\n }), [loggedInUser?.uid]);\n\n return {\n loading,\n loggedInUser,\n roles,\n users,\n saveUser,\n saveRole,\n deleteUser,\n deleteRole,\n usersLimit,\n canEditRoles: canEditRoles === undefined ? true : canEditRoles,\n allowDefaultRolesCreation: allowDefaultRolesCreation === undefined ? true : allowDefaultRolesCreation,\n includeCollectionConfigPermissions: Boolean(includeCollectionConfigPermissions),\n collectionPermissions\n }\n}\n\nconst docsToUsers = (docs: DocumentSnapshot[]): (UserWithRoleIds)[] => {\n return docs.map((doc) => {\n const data = doc.data() as any;\n const newVar = {\n uid: doc.id,\n ...data,\n created_on: data?.created_on?.toDate(),\n updated_on: data?.updated_on?.toDate()\n };\n return newVar as (UserWithRoleIds);\n });\n}\n\nconst docsToRoles = (docs: DocumentSnapshot[]): Role[] => {\n return docs.map((doc) => ({\n id: doc.id,\n ...doc.data()\n } as Role));\n}\n","import React, { PropsWithChildren } from \"react\";\nimport { UserManagement, UserWithRoles } from \"./types\";\n\nexport const UserManagementContext = React.createContext<UserManagement<any>>({} as any);\n\nexport interface UserManagementProviderProps<U extends UserWithRoles = UserWithRoles> {\n userManagement: UserManagement<U>\n}\n\nexport function UserManagementProvider<U extends UserWithRoles = UserWithRoles>({\n children,\n userManagement\n }: PropsWithChildren<UserManagementProviderProps<U>>) {\n return (\n <UserManagementContext.Provider value={userManagement}>\n {children}\n </UserManagementContext.Provider>\n );\n};\n","import { useContext } from \"react\";\nimport { UserManagement } from \"../types/user_management\";\nimport { UserManagementContext } from \"../UserManagementProvider\";\n\nexport const useUserManagement = () => useContext<UserManagement>(UserManagementContext);\n","import { Chip, getColorSchemeForSeed } from \"@firecms/ui\";\nimport { Role } from \"../../types\";\n\nexport type RoleChipProps = {\n role: Role;\n}\n\nexport function RoleChip({ role }: RoleChipProps) {\n let colorScheme;\n if (role.isAdmin) {\n colorScheme = \"blueDarker\";\n } else if (role.id === \"editor\") {\n colorScheme = \"yellowLight\";\n } else if (role.id === \"viewer\") {\n colorScheme = \"grayLight\";\n } else {\n colorScheme = getColorSchemeForSeed(role.id);\n }\n\n return (\n <Chip\n colorScheme={colorScheme}\n key={role.id}>\n {role.name}\n </Chip>\n );\n\n}\n","import React, { useCallback, useState } from \"react\";\nimport * as Yup from \"yup\";\n\nimport { EntityCollection, FieldCaption, toSnakeCase, } from \"@firecms/core\";\nimport {\n Button,\n Checkbox,\n Dialog,\n DialogActions,\n DialogContent,\n DoneIcon,\n LoadingButton,\n Paper,\n Select,\n SelectItem,\n Table,\n TableBody,\n TableCell,\n TableHeader,\n TableRow,\n TextField,\n Tooltip,\n Typography\n} from \"@firecms/ui\";\nimport { useUserManagement } from \"../../hooks\";\nimport { Formex, getIn, useCreateFormex } from \"@firecms/formex\";\nimport { Role } from \"../../types\";\n\nexport const RoleYupSchema = Yup.object().shape({\n id: Yup.string().required(\"Required\"),\n name: Yup.string().required(\"Required\")\n});\n\nexport function RolesDetailsForm({\n open,\n role,\n editable,\n handleClose,\n collections\n }: {\n open: boolean,\n editable?: boolean,\n role?: Role,\n handleClose: () => void,\n collections?: EntityCollection[]\n}) {\n\n const { saveRole } = useUserManagement();\n const isNewRole = !role;\n\n const [savingError, setSavingError] = useState<Error | undefined>();\n\n const onRoleUpdated = useCallback((role: Role) => {\n setSavingError(undefined);\n return saveRole(role);\n }, [saveRole]);\n\n const formex = useCreateFormex({\n initialValues: role ?? {\n name: \"\"\n } as Role,\n onSubmit: (role: Role, formexController) => {\n return onRoleUpdated(role)\n .then(() => {\n formexController.resetForm({\n values: role\n });\n handleClose();\n })\n .catch(e => setSavingError(e));\n },\n validation: (values) => {\n return RoleYupSchema.validate(values, { abortEarly: false })\n .then(() => ({}))\n .catch((e) => {\n const errors: Record<string, string> = {};\n e.inner.forEach((error: any) => {\n errors[error.path] = error.message;\n });\n return errors;\n });\n }\n\n });\n\n const {\n isSubmitting,\n touched,\n values,\n errors,\n handleChange,\n setFieldValue,\n dirty,\n setFieldTouched\n } = formex;\n\n const isAdmin = values.isAdmin ?? false;\n const defaultCreate = values.defaultPermissions?.create ?? false;\n const defaultRead = values.defaultPermissions?.read ?? false;\n const defaultEdit = values.defaultPermissions?.edit ?? false;\n const defaultDelete = values.defaultPermissions?.delete ?? false;\n\n React.useEffect(() => {\n const idTouched = getIn(touched, \"id\");\n if (!idTouched && values.name) {\n setFieldValue(\"id\", toSnakeCase(values.name))\n }\n }, [touched, values.name]);\n\n return (\n <Dialog\n open={open}\n maxWidth={\"4xl\"}\n >\n <Formex value={formex}>\n <form noValidate\n autoComplete={\"off\"}\n onSubmit={formex.handleSubmit}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n position: \"relative\",\n height: \"100%\"\n }}>\n <DialogContent className=\"flex-grow\">\n <div\n className=\"flex flex-row pt-12 pb-8\">\n <Typography variant={\"h4\"}\n className=\"flex-grow\">\n Role\n </Typography>\n </div>\n\n <div className={\"grid grid-cols-12 gap-8\"}>\n\n <div className={\"col-span-12 md:col-span-8\"}>\n <TextField\n name=\"name\"\n required\n error={touched.name && Boolean(errors.name)}\n value={values.name}\n disabled={isAdmin || !editable}\n onChange={handleChange}\n aria-describedby=\"name-helper-text\"\n label=\"Name\"\n />\n <FieldCaption>\n {touched.name && Boolean(errors.name) ? errors.name : \"Name of this role\"}\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12 md:col-span-4\"}>\n <TextField\n name=\"id\"\n required\n error={touched.id && Boolean(errors.id)}\n value={values.id}\n disabled={!isNewRole || !editable}\n onChange={(e) => {\n handleChange(e);\n setFieldTouched(\"id\", true)\n }}\n aria-describedby=\"id-helper-text\"\n label=\"ID\"\n />\n <FieldCaption>\n {touched.id && Boolean(errors.id) ? errors.id : \"ID of this role\"}\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12\"}>\n <Paper\n\n className=\"bg-inherit\">\n <Table>\n <TableHeader>\n <TableCell></TableCell>\n <TableCell\n align=\"center\">Create\n entities\n </TableCell>\n <TableCell\n align=\"center\">Read\n entities\n </TableCell>\n <TableCell\n align=\"center\">Update\n entities\n </TableCell>\n <TableCell\n align=\"center\">Delete\n entities\n </TableCell>\n </TableHeader>\n\n <TableBody>\n <TableRow>\n <TableCell\n scope=\"row\">\n <strong>All\n collections</strong>\n </TableCell>\n <TableCell\n align=\"center\">\n <Tooltip\n title=\"Create entities in collections\">\n <Checkbox\n disabled={isAdmin || !editable}\n checked={(isAdmin || defaultCreate) ?? false}\n onCheckedChange={(checked) => setFieldValue(\"defaultPermissions.create\", checked)}\n />\n </Tooltip>\n </TableCell>\n\n <TableCell\n align=\"center\">\n <Tooltip\n title=\"Access all data in every collection\">\n <Checkbox\n disabled={isAdmin || !editable}\n checked={(isAdmin || defaultRead) ?? false}\n onCheckedChange={(checked) => setFieldValue(\"defaultPermissions.read\", checked)}\n />\n </Tooltip>\n </TableCell>\n <TableCell\n align=\"center\">\n <Tooltip\n title=\"Update data in any collection\">\n <Checkbox\n disabled={isAdmin || !editable}\n checked={(isAdmin || defaultEdit) ?? false}\n onCheckedChange={(checked) => setFieldValue(\"defaultPermissions.edit\", checked)}\n />\n </Tooltip>\n </TableCell>\n <TableCell\n align=\"center\">\n <Tooltip\n title=\"Delete data in any collection\">\n <Checkbox\n disabled={isAdmin || !editable}\n checked={(isAdmin || defaultDelete) ?? false}\n onCheckedChange={(checked) => setFieldValue(\"defaultPermissions.delete\", checked)}\n />\n\n </Tooltip>\n </TableCell>\n </TableRow>\n {collections && collections.map((col) => (\n <TableRow key={col.name}>\n <TableCell\n scope=\"row\">\n {col.name}\n </TableCell>\n <TableCell\n align=\"center\">\n <Checkbox\n disabled={isAdmin || defaultCreate || !editable}\n checked={(isAdmin || defaultCreate || getIn(values, `collectionPermissions.${col.path}.create`)) ?? false}\n onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.create`, checked)}/>\n </TableCell>\n <TableCell\n align=\"center\">\n <Checkbox\n disabled={isAdmin || defaultRead || !editable}\n checked={(isAdmin || defaultRead || getIn(values, `collectionPermissions.${col.path}.read`)) ?? false}\n onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.read`, checked)}/>\n </TableCell>\n <TableCell\n align=\"center\">\n <Checkbox\n disabled={isAdmin || defaultEdit || !editable}\n checked={(isAdmin || defaultEdit || getIn(values, `collectionPermissions.${col.path}.edit`)) ?? false}\n onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.edit`, checked)}/>\n </TableCell>\n <TableCell\n align=\"center\">\n <Checkbox\n disabled={isAdmin || defaultDelete || !editable}\n checked={(isAdmin || defaultDelete || getIn(values, `collectionPermissions.${col.path}.delete`)) ?? false}\n onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.delete`, checked)}/>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </Paper>\n <FieldCaption>\n You can customise the permissions\n that the users related to this\n role can perform in the entities\n of each collection\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12 md:col-span-4\"}>\n <Select\n error={touched.config && Boolean(errors.config)}\n id=\"createCollections\"\n name=\"createCollections\"\n label=\"Create collections\"\n position={\"item-aligned\"}\n disabled={isAdmin || !editable}\n onChange={(event) => setFieldValue(\"config.createCollections\", event.target.value === \"true\")}\n value={isAdmin || values.config?.createCollections ? \"true\" : \"false\"}\n renderValue={(value: any) => value === \"true\" ? \"Yes\" : \"No\"}\n >\n <SelectItem\n value={\"true\"}> Yes </SelectItem>\n <SelectItem\n value={\"false\"}> No </SelectItem>\n </Select>\n\n <FieldCaption>\n {touched.config && Boolean(errors.config) ? errors.config : \"Can the user create collections\"}\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12 md:col-span-4\"}>\n <Select\n error={touched.config && Boolean(errors.config)}\n id=\"editCollections\"\n name=\"editCollections\"\n label=\"Edit collections\"\n disabled={isAdmin || !editable}\n position={\"item-aligned\"}\n onChange={(event) => setFieldValue(\"config.editCollections\", event.target.value === \"own\" ? \"own\" : event.target.value === \"true\")}\n value={isAdmin ? \"true\" : (values.config?.editCollections === \"own\" ? \"own\" : (values.config?.editCollections ? \"true\" : \"false\"))}\n renderValue={(value: any) => value === \"own\" ? \"Own\" : (value === \"true\" ? \"Yes\" : \"No\")}\n >\n <SelectItem\n value={\"true\"}> Yes </SelectItem>\n <SelectItem\n value={\"false\"}> No </SelectItem>\n <SelectItem\n value={\"own\"}> Only\n his/her own </SelectItem>\n </Select>\n\n <FieldCaption>\n {touched.config && Boolean(errors.config) ? errors.config : \"Can the user edit collections\"}\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12 md:col-span-4\"}>\n <Select\n error={touched.config && Boolean(errors.config)}\n id=\"deleteCollections\"\n name=\"deleteCollections\"\n label=\"Delete collections\"\n disabled={isAdmin || !editable}\n position={\"item-aligned\"}\n onChange={(event) => setFieldValue(\"config.deleteCollections\", event.target.value === \"own\" ? \"own\" : event.target.value === \"true\")}\n value={isAdmin ? \"true\" : (values.config?.deleteCollections === \"own\" ? \"own\" : (values.config?.deleteCollections ? \"true\" : \"false\"))}\n renderValue={(value: any) => value === \"own\" ? \"Own\" : (value === \"true\" ? \"Yes\" : \"No\")}\n >\n <SelectItem\n value={\"true\"}> Yes </SelectItem>\n <SelectItem\n value={\"false\"}> No </SelectItem>\n <SelectItem\n value={\"own\"}> Only\n his/her own </SelectItem>\n </Select>\n\n <FieldCaption>\n {touched.config && Boolean(errors.config) ? errors.config : \"Can the user delete collections\"}\n </FieldCaption>\n\n </div>\n\n </div>\n </DialogContent>\n\n <DialogActions position={\"sticky\"}>\n {savingError && <Typography className={\"text-red-500\"}>\n There was an error saving this role\n </Typography>}\n <Button variant={\"text\"}\n onClick={() => {\n handleClose();\n }}>\n Cancel\n </Button>\n <LoadingButton\n variant=\"filled\"\n color=\"primary\"\n type=\"submit\"\n disabled={!dirty}\n loading={isSubmitting}\n startIcon={<DoneIcon/>}\n >\n {isNewRole ? \"Create role\" : \"Update\"}\n </LoadingButton>\n </DialogActions>\n </form>\n\n </Formex>\n </Dialog>\n );\n}\n","import { Role } from \"../../types\";\n\nexport const DEFAULT_ROLES: Role[] = [\n {\n id: \"admin\",\n name: \"Admin\",\n isAdmin: true\n },\n {\n id: \"editor\",\n name: \"Editor\",\n isAdmin: false,\n defaultPermissions: {\n read: true,\n create: true,\n edit: true,\n delete: true\n },\n config: {\n createCollections: true,\n editCollections: \"own\",\n deleteCollections: \"own\"\n }\n },\n {\n id: \"viewer\",\n name: \"Viewer\",\n isAdmin: false,\n defaultPermissions: {\n read: true,\n create: false,\n edit: false,\n delete: false\n }\n }\n];\n","import { useState } from \"react\";\nimport {\n Button,\n CenteredView,\n Checkbox,\n DeleteIcon,\n IconButton,\n Table,\n TableBody,\n TableCell,\n TableHeader,\n TableRow,\n Tooltip,\n Typography\n} from \"@firecms/ui\";\nimport { DeleteConfirmationDialog } from \"@firecms/core\";\nimport { useUserManagement } from \"../../hooks\";\nimport { Role } from \"../../types\";\nimport { RoleChip } from \"./RoleChip\";\nimport { DEFAULT_ROLES } from \"./default_roles\";\n\nexport function RolesTable({\n onRoleClicked,\n editable\n }: {\n onRoleClicked: (role: Role) => void;\n editable: boolean;\n}) {\n\n const {\n roles,\n saveRole,\n deleteRole,\n allowDefaultRolesCreation\n } = useUserManagement();\n\n const [roleToBeDeleted, setRoleToBeDeleted] = useState<Role | undefined>(undefined);\n const [deleteInProgress, setDeleteInProgress] = useState<boolean>(false);\n\n return <div\n className=\"w-full overflow-auto\">\n <Table>\n <TableHeader>\n <TableCell header={true} className=\"w-16\"></TableCell>\n <TableCell header={true}>Role</TableCell>\n <TableCell header={true} className={\"items-center\"}>Is Admin</TableCell>\n <TableCell header={true}>Default permissions</TableCell>\n </TableHeader>\n\n <TableBody>\n {roles && roles.map((role) => {\n const canCreateAll = role.isAdmin || role.defaultPermissions?.create;\n const canReadAll = role.isAdmin || role.defaultPermissions?.read;\n const canUpdateAll = role.isAdmin || role.defaultPermissions?.edit;\n const canDeleteAll = role.isAdmin || role.defaultPermissions?.delete;\n return (\n <TableRow\n key={role.name}\n onClick={() => {\n onRoleClicked(role);\n }}\n >\n <TableCell style={{ width: \"64px\" }}>\n {!role.isAdmin &&\n <Tooltip title={\"Delete this role\"}>\n <IconButton\n size={\"small\"}\n disabled={!editable}\n onClick={(event) => {\n event.stopPropagation();\n return setRoleToBeDeleted(role);\n }}>\n <DeleteIcon/>\n </IconButton>\n </Tooltip>}\n </TableCell>\n <TableCell>\n <RoleChip role={role}/>\n </TableCell>\n <TableCell className={\"items-center\"}>\n <Checkbox checked={role.isAdmin ?? false}/>\n </TableCell>\n <TableCell>\n <ul>\n {canCreateAll && <li>Create</li>}\n {canReadAll && <li>Read</li>}\n {canUpdateAll && <li>Update</li>}\n {canDeleteAll && <li>Delete</li>}\n </ul>\n </TableCell>\n </TableRow>\n );\n })}\n\n {(!roles || roles.length === 0) && <TableRow>\n <TableCell colspan={4}>\n <CenteredView className={\"flex flex-col gap-4 my-8 items-center\"}>\n <Typography variant={\"label\"}>\n You don&apos;t have any roles yet.\n </Typography>\n {allowDefaultRolesCreation && <Button variant={\"outlined\"}\n onClick={() => {\n DEFAULT_ROLES.forEach((role) => {\n saveRole(role);\n });\n }}>\n Create default roles\n </Button>}\n </CenteredView>\n </TableCell>\n </TableRow>}\n\n </TableBody>\n\n </Table>\n\n <DeleteConfirmationDialog\n open={Boolean(roleToBeDeleted)}\n loading={deleteInProgress}\n onAccept={() => {\n if (roleToBeDeleted) {\n setDeleteInProgress(true);\n deleteRole(roleToBeDeleted)\n .then(() => {\n setRoleToBeDeleted(undefined);\n })\n .finally(() => {\n setDeleteInProgress(false);\n })\n }\n }}\n onCancel={() => {\n setRoleToBeDeleted(undefined);\n }}\n title={<>Delete?</>}\n body={<>Are you sure you want to delete this role?</>}/>\n\n </div>;\n}\n","import React, { useCallback, useState } from \"react\";\n\nimport { useNavigationController } from \"@firecms/core\";\nimport { AddIcon, Button, Container, Tooltip, Typography } from \"@firecms/ui\";\nimport { RolesTable } from \"./RolesTable\";\nimport { RolesDetailsForm } from \"./RolesDetailsForm\";\nimport { useUserManagement } from \"../../hooks\";\nimport { Role } from \"../../types\";\n\nexport const RolesView = React.memo(\n function RolesView({ children }: { children?: React.ReactNode }) {\n\n const { collections } = useNavigationController();\n const [dialogOpen, setDialogOpen] = useState(false);\n const [selectedRole, setSelectedRole] = useState<Role | undefined>();\n\n const { canEditRoles } = useUserManagement();\n\n const onRoleClicked = useCallback((user: Role) => {\n setDialogOpen(true);\n setSelectedRole(user);\n }, []);\n\n const handleClose = () => {\n setSelectedRole(undefined);\n setDialogOpen(false);\n };\n\n return (\n <Container className=\"w-full flex flex-col py-4 gap-4\" maxWidth={\"6xl\"}>\n\n {children}\n\n <div className=\"flex items-center mt-12\">\n <Typography gutterBottom variant=\"h4\"\n className=\"flex-grow\"\n component=\"h4\">\n Roles\n </Typography>\n <Tooltip title={!canEditRoles ? \"Update plans to customise roles\" : undefined}>\n <Button\n size={\"large\"}\n disabled={!canEditRoles}\n startIcon={<AddIcon/>}\n onClick={() => setDialogOpen(true)}>\n Add role\n </Button>\n </Tooltip>\n </div>\n\n <RolesTable onRoleClicked={onRoleClicked} editable={Boolean(canEditRoles)}/>\n\n <RolesDetailsForm\n key={selectedRole?.id ?? \"new\"}\n open={dialogOpen}\n role={selectedRole}\n editable={canEditRoles}\n collections={collections}\n handleClose={handleClose}/>\n\n </Container>\n )\n });\n","import React, { useCallback } from \"react\";\nimport * as Yup from \"yup\";\nimport {\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DoneIcon,\n LoadingButton,\n MultiSelect,\n MultiSelectItem,\n TextField,\n Typography,\n} from \"@firecms/ui\";\nimport { FieldCaption, useSnackbarController } from \"@firecms/core\";\nimport { Formex, useCreateFormex } from \"@firecms/formex\";\n\nimport { Role, UserWithRoles } from \"../../types\";\nimport { areRolesEqual } from \"../../utils\";\nimport { useUserManagement } from \"../../hooks\";\nimport { RoleChip } from \"../roles\";\n\nexport const UserYupSchema = Yup.object().shape({\n displayName: Yup.string().required(\"Required\"),\n email: Yup.string().email().required(\"Required\"),\n roles: Yup.array().min(1)\n});\n\nfunction canUserBeEdited(loggedUser: UserWithRoles, user: UserWithRoles, users: UserWithRoles[], roles: Role[], prevUser?: UserWithRoles) {\n const admins = users.filter(u => u.roles.map(r => r.id).includes(\"admin\"));\n const loggedUserIsAdmin = loggedUser.roles.map(r => r.id).includes(\"admin\");\n const didRolesChange = !prevUser || !areRolesEqual(prevUser.roles, user.roles);\n\n if (didRolesChange && !loggedUserIsAdmin) {\n throw new Error(\"Only admins can change roles\");\n }\n\n // was the admin role removed\n const adminRoleRemoved = prevUser && prevUser.roles.map(r => r.id).includes(\"admin\") && !user.roles.map(r => r.id).includes(\"admin\");\n\n // avoid removing the last admin\n if (adminRoleRemoved && admins.length === 1) {\n throw new Error(\"There must be at least one admin\");\n }\n return true;\n}\n\nexport function UserDetailsForm({\n open,\n user: userProp,\n handleClose\n }: {\n open: boolean,\n user?: UserWithRoles,\n handleClose: () => void\n}) {\n\n const snackbarController = useSnackbarController();\n const {\n loggedInUser,\n saveUser,\n users,\n roles,\n } = useUserManagement();\n const isNewUser = !userProp;\n\n const onUserUpdated = useCallback((savedUser: UserWithRoles): Promise<UserWithRoles> => {\n if (!loggedInUser) {\n throw new Error(\"Logged user not found\");\n }\n try {\n canUserBeEdited(loggedInUser, savedUser, users, roles, userProp);\n return saveUser(savedUser);\n } catch (e: any) {\n return Promise.reject(e);\n }\n }, [roles, saveUser, userProp, users, loggedInUser]);\n\n const formex = useCreateFormex({\n initialValues: userProp ?? {\n displayName: \"\",\n email: \"\",\n roles: roles.filter(r => r.id === \"editor\")\n } as UserWithRoles,\n validation: (values) => {\n return UserYupSchema.validate(values, { abortEarly: false })\n .then(() => {\n return {};\n }).catch((e) => {\n return e.inner.reduce((acc: any, error: any) => {\n acc[error.path] = error.message;\n return acc;\n }, {});\n });\n },\n onSubmit: (user: UserWithRoles, formexController) => {\n\n return onUserUpdated(user)\n .then(() => {\n handleClose();\n formexController.resetForm({\n values: user\n });\n }).catch((e) => {\n snackbarController.open({\n type: \"error\",\n message: e.message\n });\n });\n }\n });\n\n const {\n isSubmitting,\n touched,\n handleChange,\n values,\n errors,\n setFieldValue,\n dirty,\n handleSubmit,\n submitCount\n } = formex;\n\n return (\n <Dialog\n open={open}\n onOpenChange={(open) => !open ? handleClose() : undefined}\n maxWidth={\"4xl\"}\n >\n <Formex value={formex}>\n <form\n onSubmit={handleSubmit}\n autoComplete={\"off\"}\n noValidate\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n position: \"relative\",\n height: \"100%\"\n }}>\n <DialogContent className=\"h-full flex-grow\">\n <div\n className=\"flex flex-row pt-4 pb-4\">\n <Typography variant={\"h4\"}\n className=\"flex-grow\">\n User\n </Typography>\n </div>\n\n <div className={\"grid grid-cols-12 gap-8\"}>\n\n <div className={\"col-span-12\"}>\n <TextField\n name=\"displayName\"\n required\n error={submitCount > 0 && Boolean(errors.displayName)}\n value={values.displayName ?? \"\"}\n onChange={handleChange}\n aria-describedby=\"name-helper-text\"\n label=\"Name\"\n />\n <FieldCaption>\n {submitCount > 0 && Boolean(errors.displayName) ? errors.displayName : \"Name of this user\"}\n </FieldCaption>\n </div>\n <div className={\"col-span-12\"}>\n <TextField\n required\n error={submitCount > 0 && Boolean(errors.email)}\n name=\"email\"\n value={values.email ?? \"\"}\n onChange={handleChange}\n aria-describedby=\"email-helper-text\"\n label=\"Email\"\n />\n <FieldCaption>\n {submitCount > 0 && Boolean(errors.email) ? errors.email : \"Email of this user\"}\n </FieldCaption>\n </div>\n <div className={\"col-span-12\"}>\n <MultiSelect\n label=\"Roles\"\n value={values.roles.map(r => r.id) ?? []}\n onMultiValueChange={(value: string[]) => setFieldValue(\"roles\", value.map(id => roles.find(r => r.id === id) as Role))}\n renderValue={(value: string) => {\n const userRole = roles\n .find((role) => role.id === value);\n if (!userRole) return null;\n return <div className=\"flex flex-wrap space-x-2 space-y-2\">\n <RoleChip key={userRole?.id} role={userRole}/>\n </div>;\n }}>\n {roles.map(userRole => <MultiSelectItem key={userRole.id}\n value={userRole.id}>\n <RoleChip key={userRole?.id} role={userRole}/>\n </MultiSelectItem>)}\n </MultiSelect>\n </div>\n\n </div>\n\n </DialogContent>\n\n <DialogActions>\n\n <Button variant={\"text\"}\n onClick={() => {\n handleClose();\n }}>\n Cancel\n </Button>\n\n <LoadingButton\n variant=\"filled\"\n color=\"primary\"\n type=\"submit\"\n disabled={!dirty}\n loading={isSubmitting}\n startIcon={<DoneIcon/>}\n >\n {isNewUser ? \"Create user\" : \"Update\"}\n </LoadingButton>\n </DialogActions>\n </form>\n </Formex>\n\n </Dialog>\n );\n}\n","import { useState } from \"react\";\n\nimport { format } from \"date-fns\";\nimport * as locales from \"date-fns/locale\";\n\nimport {\n defaultDateFormat,\n DeleteConfirmationDialog,\n useAuthController,\n useCustomizationController,\n useSnackbarController\n} from \"@firecms/core\";\nimport {\n Button,\n CenteredView,\n DeleteIcon,\n IconButton,\n Table,\n TableBody,\n TableCell,\n TableHeader,\n TableRow,\n Tooltip,\n Typography,\n} from \"@firecms/ui\";\nimport { Role, UserWithRoles } from \"../../types\";\nimport { useUserManagement } from \"../../hooks\";\nimport { RoleChip } from \"../roles\";\n\nexport function UsersTable({ onUserClicked }: {\n onUserClicked: (user: UserWithRoles) => void;\n}) {\n\n const {\n users,\n saveUser,\n deleteUser\n } = useUserManagement();\n\n const authController = useAuthController();\n const snackbarController = useSnackbarController();\n\n const customizationController = useCustomizationController();\n const dateUtilsLocale = customizationController?.locale ? locales[customizationController?.locale as keyof typeof locales] : undefined;\n const dateFormat: string = customizationController?.dateTimeFormat ?? defaultDateFormat;\n\n const [userToBeDeleted, setUserToBeDeleted] = useState<UserWithRoles | undefined>(undefined);\n const [deleteInProgress, setDeleteInProgress] = useState<boolean>(false);\n\n return (\n <div className=\"overflow-auto\">\n\n <Table>\n\n <TableHeader>\n <TableCell className=\"truncate w-16\"></TableCell>\n <TableCell>ID</TableCell>\n <TableCell>Email</TableCell>\n <TableCell>Name</TableCell>\n <TableCell>Roles</TableCell>\n <TableCell>Created on</TableCell>\n </TableHeader>\n <TableBody>\n {users && users.map((user) => {\n\n const userRoles: Role[] | undefined = user.roles;\n\n const formattedDate = user.created_on ? format(user.created_on, dateFormat, { locale: dateUtilsLocale }) : \"\";\n\n return (\n <TableRow\n key={\"row_\" + user.uid}\n onClick={() => {\n onUserClicked(user);\n }}\n >\n <TableCell className={\"w-10\"}>\n <Tooltip title={\"Delete this user\"}>\n <IconButton\n size={\"small\"}\n onClick={(event) => {\n event.stopPropagation();\n return setUserToBeDeleted(user);\n }}>\n <DeleteIcon/>\n </IconButton>\n </Tooltip>\n </TableCell>\n <TableCell>{user.uid}</TableCell>\n <TableCell>{user.email}</TableCell>\n <TableCell className={\"font-medium align-left\"}>{user.displayName}</TableCell>\n <TableCell className=\"align-left\">\n {userRoles\n ? <div className=\"flex flex-wrap gap-2\">\n {userRoles.map(userRole =>\n <RoleChip key={userRole?.id} role={userRole}/>\n )}\n </div>\n : null}\n </TableCell>\n <TableCell>{formattedDate}</TableCell>\n </TableRow>\n );\n })}\n\n {(!users || users.length === 0) && <TableRow>\n <TableCell colspan={6}>\n <CenteredView className={\"flex flex-col gap-4 my-8 items-center\"}>\n <Typography variant={\"label\"}>\n There are no users yet\n </Typography>\n <Button variant={\"outlined\"}\n onClick={() => {\n if (!authController.user?.uid) {\n throw Error(\"UsersTable, authController misconfiguration\");\n }\n saveUser({\n uid: authController.user?.uid,\n email: authController.user?.email,\n displayName: authController.user?.displayName,\n photoURL: authController.user?.photoURL,\n providerId: authController.user?.providerId,\n isAnonymous: authController.user?.isAnonymous,\n roles: [{ id: \"admin\", name: \"Admin\" }],\n created_on: new Date()\n })\n .then(() => {\n snackbarController.open({\n type: \"success\",\n message: \"User added successfully\"\n })\n })\n .catch((error) => {\n snackbarController.open({\n type: \"error\",\n message: \"Error adding user: \" + error.message,\n })\n });\n }}>\n\n Add the logged user as an admin\n </Button>\n </CenteredView>\n </TableCell>\n </TableRow>}\n\n </TableBody>\n </Table>\n\n <DeleteConfirmationDialog\n open={Boolean(userToBeDeleted)}\n loading={deleteInProgress}\n onAccept={() => {\n if (userToBeDeleted) {\n setDeleteInProgress(true);\n deleteUser(userToBeDeleted)\n .then(() => {\n setUserToBeDeleted(undefined);\n })\n .catch((error) => {\n snackbarController.open({\n type: \"error\",\n message: \"Error deleting user: \" + error.message,\n })\n })\n .finally(() => {\n setDeleteInProgress(false);\n })\n }\n }}\n onCancel={() => {\n setUserToBeDeleted(undefined);\n }}\n title={<>Delete?</>}\n body={<>Are you sure you want to delete this user?</>}/>\n </div>);\n}\n","import { AddIcon, Button, Container, Typography } from \"@firecms/ui\";\n\nimport { UsersTable } from \"./UsersTable\";\nimport { UserDetailsForm } from \"./UserDetailsForm\";\nimport React, { useCallback, useState } from \"react\";\nimport { UserWithRoles } from \"../../types\";\nimport { useUserManagement } from \"../../hooks/useUserManagement\";\n\nexport const UsersView = function UsersView({ children }: { children?: React.ReactNode }) {\n\n const [dialogOpen, setDialogOpen] = useState<boolean>();\n const [selectedUser, setSelectedUser] = useState<UserWithRoles | undefined>();\n\n const { users, usersLimit } = useUserManagement();\n\n const reachedUsersLimit = usersLimit !== undefined && (users && users.length >= usersLimit);\n\n const onUserClicked = useCallback((user: UserWithRoles) => {\n setSelectedUser(user);\n setDialogOpen(true);\n }, []);\n\n const handleClose = useCallback(() => {\n setDialogOpen(false);\n setSelectedUser(undefined);\n }, []);\n\n return (\n <Container className=\"w-full flex flex-col py-4 gap-4\" maxWidth={\"6xl\"}>\n\n {children}\n\n <div\n className=\"flex items-center mt-12\">\n <Typography gutterBottom variant=\"h4\"\n className=\"flex-grow\"\n component=\"h4\">\n Users\n </Typography>\n <Button\n size={\"large\"}\n disabled={reachedUsersLimit}\n startIcon={<AddIcon/>}\n onClick={() => setDialogOpen(true)}>\n Add user\n </Button>\n </div>\n\n <UsersTable onUserClicked={onUserClicked}/>\n\n <UserDetailsForm\n key={selectedUser?.uid ?? \"new\"}\n open={dialogOpen ?? false}\n user={selectedUser}\n handleClose={handleClose}/>\n\n </Container>\n )\n};\n","import { AuthController, FireCMSPlugin } from \"@firecms/core\";\nimport { UserManagementProvider } from \"./UserManagementProvider\";\nimport { UserManagement } from \"./types\";\n\nexport function useUserManagementPlugin({ userManagement }: {\n userManagement: UserManagement,\n}): FireCMSPlugin {\n return {\n name: \"User management plugin\",\n loading: userManagement.loading,\n provider: {\n Component: UserManagementProvider,\n props: {\n userManagement\n }\n }\n }\n}\n","import { CMSView } from \"@firecms/core\";\nimport { RolesView, UsersView } from \"./components\";\n\nexport const userManagementAdminViews: CMSView[] = [\n {\n path: \"users\",\n name: \"CMS Users\",\n group: \"Admin\",\n icon: \"face\",\n view: <UsersView/>\n },\n {\n path: \"roles\",\n name: \"Roles\",\n group: \"Admin\",\n icon: \"gpp_good\",\n view: <RolesView/>\n }\n]\n"],"names":["RESERVED_GROUPS","DEFAULT_PERMISSIONS","resolveUserRolePermissions","collection","user","roles","basePermissions","role","resolveCollectionRole","mergePermissions","id","permA","permB","getUserRoles","fireCMSUser","r","areRolesEqual","rolesA","rolesB","rolesAIds","rolesBIds","cacheDelegatedLoginToken","projectId","delegatedToken","data","parseJwt","expiry","getDelegatedLoginTokenFromCache","entry","clearDelegatedLoginTokensCache","i","key","token","base64","jsonPayload","c","darkenColor","hexColor","darkenBy","color","g","b","hexToRgbaWithOpacity","opacity","alpha","useBuildFirestoreUserManagement","firebaseApp","usersPath","rolesPath","usersLimit","canEditRoles","authController","allowDefaultRolesCreation","includeCollectionConfigPermissions","firestoreRef","useRef","rolesLoading","setRolesLoading","React","usersLoading","setUsersLoading","setRoles","usersWithRoleIds","setUsersWithRoleIds","users","u","rolesError","setRolesError","usersError","setUsersError","loading","loggedInUser","useEffect","getFirestore","firestore","onSnapshot","snapshot","newRoles","docsToRoles","e","newUsers","docsToUsers","saveUser","useCallback","roleIds","uid","userData","setDoc","doc","saveRole","roleData","ref","deleteUser","deleteDoc","deleteRole","collectionPermissions","docs","UserManagementContext","UserManagementProvider","children","userManagement","useUserManagement","useContext","RoleChip","colorScheme","getColorSchemeForSeed","jsx","Chip","RoleYupSchema","Yup","RolesDetailsForm","open","editable","handleClose","collections","isNewRole","savingError","setSavingError","useState","onRoleUpdated","formex","useCreateFormex","formexController","values","errors","error","isSubmitting","touched","handleChange","setFieldValue","dirty","setFieldTouched","isAdmin","defaultCreate","defaultRead","defaultEdit","defaultDelete","getIn","toSnakeCase","Dialog","Formex","jsxs","DialogContent","Typography","TextField","FieldCaption","Paper","Table","TableHeader","TableCell","TableBody","TableRow","Tooltip","Checkbox","checked","col","Select","event","value","SelectItem","DialogActions","Button","LoadingButton","DoneIcon","DEFAULT_ROLES","RolesTable","onRoleClicked","roleToBeDeleted","setRoleToBeDeleted","deleteInProgress","setDeleteInProgress","canCreateAll","canReadAll","canUpdateAll","canDeleteAll","IconButton","DeleteIcon","CenteredView","DeleteConfirmationDialog","RolesView","useNavigationController","dialogOpen","setDialogOpen","selectedRole","setSelectedRole","Container","AddIcon","UserYupSchema","canUserBeEdited","loggedUser","prevUser","admins","loggedUserIsAdmin","UserDetailsForm","userProp","snackbarController","useSnackbarController","isNewUser","onUserUpdated","savedUser","acc","handleSubmit","submitCount","MultiSelect","userRole","MultiSelectItem","UsersTable","onUserClicked","useAuthController","customizationController","useCustomizationController","dateUtilsLocale","locales","dateFormat","defaultDateFormat","userToBeDeleted","setUserToBeDeleted","userRoles","formattedDate","format","UsersView","selectedUser","setSelectedUser","reachedUsersLimit","useUserManagementPlugin","userManagementAdminViews"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.umd.js","sources":["../src/utils/permissions.ts","../src/utils/local_storage.ts","../src/utils/colors.ts","../src/hooks/useBuildFirestoreUserManagement.tsx","../src/UserManagementProvider.tsx","../src/hooks/useUserManagement.tsx","../src/components/roles/RoleChip.tsx","../src/components/roles/RolesDetailsForm.tsx","../src/components/roles/default_roles.tsx","../src/components/roles/RolesTable.tsx","../src/components/roles/RolesView.tsx","../src/components/users/UserDetailsForm.tsx","../src/components/users/UsersTable.tsx","../src/components/users/UsersView.tsx","../src/useUserManagementPlugin.tsx","../src/admin_views.tsx"],"sourcesContent":["import { CMSType, EntityCollection, Permissions } from \"@firecms/core\";\nimport { Role, UserWithRoles } from \"../types\";\n\nexport const RESERVED_GROUPS = [\"Admin\"];\n\nconst DEFAULT_PERMISSIONS = {\n read: false,\n edit: false,\n create: false,\n delete: false\n};\n\nexport function resolveUserRolePermissions<UserType extends UserWithRoles>\n({ collection, user }: {\n collection: EntityCollection<any>,\n user: UserType | null\n}): Permissions {\n\n const roles = user?.roles;\n if (!roles) {\n return DEFAULT_PERMISSIONS;\n } else if (collection.ownerId === user?.uid) {\n return {\n read: true,\n create: true,\n edit: true,\n delete: true\n };\n } else {\n const basePermissions = {\n read: false,\n create: false,\n edit: false,\n delete: false\n };\n\n return roles\n .map(role => resolveCollectionRole(role, collection.id))\n .reduce(mergePermissions, basePermissions);\n }\n}\n\nfunction resolveCollectionRole(role: Role, id: string): Permissions {\n\n const basePermissions = {\n read: role.isAdmin || role.defaultPermissions?.read,\n create: role.isAdmin || role.defaultPermissions?.create,\n edit: role.isAdmin || role.defaultPermissions?.edit,\n delete: role.isAdmin || role.defaultPermissions?.delete\n };\n if (role.collectionPermissions && role.collectionPermissions[id]) {\n return mergePermissions(role.collectionPermissions[id], basePermissions);\n } else if (role.defaultPermissions) {\n return mergePermissions(role.defaultPermissions, basePermissions);\n } else {\n return basePermissions;\n }\n}\n\nconst mergePermissions = (permA: Permissions, permB: Permissions) => {\n return {\n read: permA.read || permB.read,\n create: permA.create || permB.create,\n edit: permA.edit || permB.edit,\n delete: permA.delete || permB.delete\n };\n}\n\nexport function getUserRoles(roles: Role[], fireCMSUser: UserWithRoles): Role[] | undefined {\n return !roles\n ? undefined\n : (fireCMSUser.roles\n ? fireCMSUser.roles\n .map(role => roles.find((r) => r.id === role.id))\n .filter(Boolean) as Role[]\n : []);\n}\n\nexport const areRolesEqual = (rolesA: Role[], rolesB: Role[]) => {\n const rolesAIds = rolesA.map(r => r.id);\n const rolesBIds = rolesB.map(r => r.id);\n return rolesAIds.length === rolesB.length && rolesAIds.every((role) => rolesBIds.includes(role));\n}\n","// const tokens = new Map<string, {\n// token: string,\n// expiry: Date\n// }>();\n\nexport function cacheDelegatedLoginToken(projectId: string, delegatedToken?: string) {\n if (!delegatedToken) {\n return;\n }\n\n const data = parseJwt(delegatedToken);\n // @ts-ignore\n const expiry = new Date(data.exp * 1000);\n localStorage.setItem(`auth_token::${projectId}`, JSON.stringify({\n token: delegatedToken,\n expiry\n }));\n\n}\n\nexport function getDelegatedLoginTokenFromCache(projectId: string) {\n const entry = localStorage.getItem(`auth_token::${projectId}`);\n if (entry) {\n const data = JSON.parse(entry);\n data.expiry = new Date(data.expiry);\n if (data.expiry > new Date()) {\n return data.token;\n }\n }\n return undefined;\n}\n\nexport function clearDelegatedLoginTokensCache() {\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(\"auth_token::\")) {\n localStorage.removeItem(key);\n }\n }\n}\n\nfunction parseJwt(token?: string): object {\n if (!token) {\n throw new Error(\"No JWT token\");\n }\n const base64Url = token.split(\".\")[1];\n const base64 = base64Url.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const jsonPayload = decodeURIComponent(window.atob(base64).split(\"\").map(function (c) {\n return \"%\" + (\"00\" + c.charCodeAt(0).toString(16)).slice(-2);\n }).join(\"\"));\n\n return JSON.parse(jsonPayload);\n}\n","export function darkenColor(hexColor: string, darkenBy = 10): string {\n // Check input validity\n if (!/^#([0-9A-Fa-f]{3}){1,2}$/.test(hexColor)) {\n throw new Error(\"Invalid color format\");\n }\n\n // If shorthand form, convert to full form\n let color = hexColor.substring(1).split(\"\");\n if (color.length === 3) {\n color = [color[0], color[0], color[1], color[1], color[2], color[2]];\n }\n\n // Convert to RGB values\n let r = parseInt(color[0] + color[1], 16);\n let g = parseInt(color[2] + color[3], 16);\n let b = parseInt(color[4] + color[5], 16);\n\n // Reduce each color component by the specified percentage (darkenBy)\n r = Math.floor(r * (1 - darkenBy / 100));\n g = Math.floor(g * (1 - darkenBy / 100));\n b = Math.floor(b * (1 - darkenBy / 100));\n\n // Recombine into hex and return\n return \"#\" +\n (r < 16 ? \"0\" : \"\") + r.toString(16) +\n (g < 16 ? \"0\" : \"\") + g.toString(16) +\n (b < 16 ? \"0\" : \"\") + b.toString(16);\n}\n\nexport function hexToRgbaWithOpacity(hexColor: string, opacity = 10): string {\n // Check input validity\n if (!/^#([0-9A-Fa-f]{3}){1,2}$/.test(hexColor)) {\n throw new Error(\"Invalid color format\");\n }\n\n // If shorthand form, convert to full form\n let color = hexColor.substring(1).split(\"\");\n if (color.length === 3) {\n color = [color[0], color[0], color[1], color[1], color[2], color[2]];\n }\n\n // Convert to RGB values\n const r = parseInt(color[0] + color[1], 16);\n const g = parseInt(color[2] + color[3], 16);\n const b = parseInt(color[4] + color[5], 16);\n\n // Convert opacity to a decimal for CSS\n const alpha = opacity / 100;\n\n // Construct and return the RGBA color\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n","import React, { useCallback, useEffect, useRef } from \"react\";\nimport {\n collection,\n deleteDoc,\n doc,\n DocumentSnapshot,\n Firestore,\n getFirestore,\n onSnapshot,\n setDoc\n} from \"firebase/firestore\";\nimport { FirebaseApp } from \"firebase/app\";\nimport { Role, UserManagement, UserWithRoles } from \"../types\";\nimport { AuthController, PermissionsBuilder, User } from \"@firecms/core\";\nimport { resolveUserRolePermissions } from \"../utils\";\n\ntype UserWithRoleIds = User & { roles: string[] };\n\nexport interface UserManagementParams {\n /**\n * The Firebase app to use for the user management. The config will be saved in the Firestore\n * collection indicated by `configPath`.\n */\n firebaseApp?: FirebaseApp;\n /**\n * Path where the plugin users configuration is stored.\n * Default: __FIRECMS/config/users\n * You can specify a different path if you want to store the user management configuration in a different place.\n * Please keep in mind that the FireCMS users are not necessarily the same as the Firebase users (but they can be).\n * The path should be relative to the root of the Firestore database, and should always have an odd number of segments.\n */\n usersPath?: string;\n\n /**\n * Path where the plugin roles configuration is stored.\n * Default: __FIRECMS/config/roles\n */\n rolesPath?: string;\n\n usersLimit?: number;\n\n canEditRoles?: boolean;\n\n authController: AuthController;\n\n /**\n * If there are no roles in the database, provide a button to create the default roles.\n */\n allowDefaultRolesCreation?: boolean;\n\n /**\n * Include the collection config permissions in the user management system.\n */\n includeCollectionConfigPermissions?: boolean;\n\n}\n\n/**\n * This hook is used to build a user management object that can be used to\n * manage users and roles in a Firestore backend.\n * @param backendFirebaseApp\n * @param usersPath\n * @param rolesPath\n * @param usersLimit\n * @param canEditRoles\n */\nexport function useBuildFirestoreUserManagement({\n firebaseApp,\n usersPath = \"__FIRECMS/config/users\",\n rolesPath = \"__FIRECMS/config/roles\",\n usersLimit,\n canEditRoles = true,\n authController,\n allowDefaultRolesCreation,\n includeCollectionConfigPermissions\n }: UserManagementParams): UserManagement {\n\n const firestoreRef = useRef<Firestore>();\n\n const [rolesLoading, setRolesLoading] = React.useState<boolean>(true);\n const [usersLoading, setUsersLoading] = React.useState<boolean>(true);\n const [roles, setRoles] = React.useState<Role[]>([]);\n const [usersWithRoleIds, setUsersWithRoleIds] = React.useState<UserWithRoleIds[]>([]);\n\n const users = usersWithRoleIds.map(u => ({\n ...u,\n roles: roles.filter(r => u.roles?.includes(r.id))\n }) as UserWithRoles);\n\n const [rolesError, setRolesError] = React.useState<Error | undefined>();\n const [usersError, setUsersError] = React.useState<Error | undefined>();\n\n const loading = rolesLoading || usersLoading;\n\n const loggedInUser: UserWithRoles | undefined = users.find(u => u.email?.toLowerCase() === authController.user?.email?.toLowerCase());\n // console.log(\"authController\", authController);\n // if (!loading && !authController.authLoading) {\n // const user = authController.user;\n // if (user) {\n // loggedInUser = users.find(u => u.email?.toLowerCase() === user.email?.toLowerCase());\n // }\n // }\n\n useEffect(() => {\n if (!firebaseApp) return;\n firestoreRef.current = getFirestore(firebaseApp);\n }, [firebaseApp]);\n\n useEffect(() => {\n if (!firebaseApp || !rolesPath) return;\n const firestore = getFirestore(firebaseApp);\n\n return onSnapshot(collection(firestore, rolesPath),\n {\n next: (snapshot) => {\n setRolesError(undefined);\n try {\n const newRoles = docsToRoles(snapshot.docs);\n setRoles(newRoles);\n } catch (e) {\n // console.error(e);\n setRolesError(e as Error);\n }\n setRolesLoading(false);\n },\n error: (e) => {\n setRolesError(e);\n setRolesLoading(false);\n }\n }\n );\n }, [firebaseApp, rolesPath]);\n\n useEffect(() => {\n if (!firebaseApp || !usersPath) return;\n const firestore = getFirestore(firebaseApp);\n\n return onSnapshot(collection(firestore, usersPath),\n {\n next: (snapshot) => {\n setUsersError(undefined);\n try {\n const newUsers = docsToUsers(snapshot.docs);\n setUsersWithRoleIds(newUsers);\n } catch (e) {\n setUsersError(e as Error);\n }\n setUsersLoading(false);\n },\n error: (e) => {\n setUsersError(e);\n setUsersLoading(false);\n }\n }\n );\n }, [firebaseApp, usersPath]);\n\n const saveUser = useCallback(async (user: UserWithRoles): Promise<UserWithRoles> => {\n const firestore = firestoreRef.current;\n if (!firestore || !usersPath) throw Error(\"useFirestoreConfigurationPersistence Firestore not initialised\");\n console.debug(\"Persisting user\", user);\n const roleIds = user.roles.map(r => r.id);\n const {\n uid,\n ...userData\n } = user;\n return setDoc(doc(firestore, usersPath, uid), { ...userData, roles: roleIds }, { merge: true }).then(() => user);\n }, [usersPath]);\n\n const saveRole = useCallback((role: Role): Promise<void> => {\n const firestore = firestoreRef.current;\n if (!firestore || !rolesPath) throw Error(\"useFirestoreConfigurationPersistence Firestore not initialised\");\n console.debug(\"Persisting role\", role);\n const {\n id,\n ...roleData\n } = role;\n const ref = doc(firestore, rolesPath, id);\n return setDoc(ref, roleData, { merge: true });\n }, [rolesPath]);\n\n const deleteUser = useCallback(async (user: UserWithRoles): Promise<void> => {\n const firestore = firestoreRef.current;\n if (!firestore || !usersPath) throw Error(\"useFirestoreConfigurationPersistence Firestore not initialised\");\n console.debug(\"Deleting\", user);\n const { uid } = user;\n return deleteDoc(doc(firestore, usersPath, uid));\n }, [usersPath]);\n\n const deleteRole = useCallback((role: Role): Promise<void> => {\n const firestore = firestoreRef.current;\n if (!firestore || !rolesPath) throw Error(\"useFirestoreConfigurationPersistence Firestore not initialised\");\n console.debug(\"Deleting\", role);\n const { id } = role;\n const ref = doc(firestore, rolesPath, id);\n return deleteDoc(ref);\n }, [rolesPath]);\n\n const collectionPermissions: PermissionsBuilder = useCallback(({\n collection,\n }) => resolveUserRolePermissions({\n collection,\n user: loggedInUser ?? null\n }), [loggedInUser?.uid]);\n\n return {\n loading,\n loggedInUser,\n roles,\n users,\n saveUser,\n saveRole,\n deleteUser,\n deleteRole,\n usersLimit,\n canEditRoles: canEditRoles === undefined ? true : canEditRoles,\n allowDefaultRolesCreation: allowDefaultRolesCreation === undefined ? true : allowDefaultRolesCreation,\n includeCollectionConfigPermissions: Boolean(includeCollectionConfigPermissions),\n collectionPermissions\n }\n}\n\nconst docsToUsers = (docs: DocumentSnapshot[]): (UserWithRoleIds)[] => {\n return docs.map((doc) => {\n const data = doc.data() as any;\n const newVar = {\n uid: doc.id,\n ...data,\n created_on: data?.created_on?.toDate(),\n updated_on: data?.updated_on?.toDate()\n };\n return newVar as (UserWithRoleIds);\n });\n}\n\nconst docsToRoles = (docs: DocumentSnapshot[]): Role[] => {\n return docs.map((doc) => ({\n id: doc.id,\n ...doc.data()\n } as Role));\n}\n","import React, { PropsWithChildren } from \"react\";\nimport { UserManagement, UserWithRoles } from \"./types\";\n\nexport const UserManagementContext = React.createContext<UserManagement<any>>({} as any);\n\nexport interface UserManagementProviderProps<U extends UserWithRoles = UserWithRoles> {\n userManagement: UserManagement<U>\n}\n\nexport function UserManagementProvider<U extends UserWithRoles = UserWithRoles>({\n children,\n userManagement\n }: PropsWithChildren<UserManagementProviderProps<U>>) {\n return (\n <UserManagementContext.Provider value={userManagement}>\n {children}\n </UserManagementContext.Provider>\n );\n};\n","import { useContext } from \"react\";\nimport { UserManagement } from \"../types/user_management\";\nimport { UserManagementContext } from \"../UserManagementProvider\";\n\nexport const useUserManagement = () => useContext<UserManagement>(UserManagementContext);\n","import { Chip, getColorSchemeForSeed } from \"@firecms/ui\";\nimport { Role } from \"../../types\";\n\nexport type RoleChipProps = {\n role: Role;\n}\n\nexport function RoleChip({ role }: RoleChipProps) {\n let colorScheme;\n if (role.isAdmin) {\n colorScheme = \"blueDarker\";\n } else if (role.id === \"editor\") {\n colorScheme = \"yellowLight\";\n } else if (role.id === \"viewer\") {\n colorScheme = \"grayLight\";\n } else {\n colorScheme = getColorSchemeForSeed(role.id);\n }\n\n return (\n <Chip\n colorScheme={colorScheme}\n key={role.id}>\n {role.name}\n </Chip>\n );\n\n}\n","import React, { useCallback, useState } from \"react\";\nimport * as Yup from \"yup\";\n\nimport { EntityCollection, FieldCaption, toSnakeCase, } from \"@firecms/core\";\nimport {\n Button,\n Checkbox,\n Dialog,\n DialogActions,\n DialogContent,\n DoneIcon,\n LoadingButton,\n Paper,\n Select,\n SelectItem,\n Table,\n TableBody,\n TableCell,\n TableHeader,\n TableRow,\n TextField,\n Tooltip,\n Typography\n} from \"@firecms/ui\";\nimport { useUserManagement } from \"../../hooks\";\nimport { Formex, getIn, useCreateFormex } from \"@firecms/formex\";\nimport { Role } from \"../../types\";\n\nexport const RoleYupSchema = Yup.object().shape({\n id: Yup.string().required(\"Required\"),\n name: Yup.string().required(\"Required\")\n});\n\nexport function RolesDetailsForm({\n open,\n role,\n editable,\n handleClose,\n collections\n }: {\n open: boolean,\n editable?: boolean,\n role?: Role,\n handleClose: () => void,\n collections?: EntityCollection[]\n}) {\n\n const { saveRole } = useUserManagement();\n const isNewRole = !role;\n\n const [savingError, setSavingError] = useState<Error | undefined>();\n\n const onRoleUpdated = useCallback((role: Role) => {\n setSavingError(undefined);\n return saveRole(role);\n }, [saveRole]);\n\n const formex = useCreateFormex({\n initialValues: role ?? {\n name: \"\"\n } as Role,\n onSubmit: (role: Role, formexController) => {\n return onRoleUpdated(role)\n .then(() => {\n formexController.resetForm({\n values: role\n });\n handleClose();\n })\n .catch(e => setSavingError(e));\n },\n validation: (values) => {\n return RoleYupSchema.validate(values, { abortEarly: false })\n .then(() => ({}))\n .catch((e) => {\n const errors: Record<string, string> = {};\n e.inner.forEach((error: any) => {\n errors[error.path] = error.message;\n });\n return errors;\n });\n }\n\n });\n\n const {\n isSubmitting,\n touched,\n values,\n errors,\n handleChange,\n setFieldValue,\n dirty,\n setFieldTouched\n } = formex;\n\n const isAdmin = values.isAdmin ?? false;\n const defaultCreate = values.defaultPermissions?.create ?? false;\n const defaultRead = values.defaultPermissions?.read ?? false;\n const defaultEdit = values.defaultPermissions?.edit ?? false;\n const defaultDelete = values.defaultPermissions?.delete ?? false;\n\n React.useEffect(() => {\n const idTouched = getIn(touched, \"id\");\n if (!idTouched && values.name) {\n setFieldValue(\"id\", toSnakeCase(values.name))\n }\n }, [touched, values.name]);\n\n return (\n <Dialog\n open={open}\n maxWidth={\"4xl\"}\n >\n <Formex value={formex}>\n <form noValidate\n autoComplete={\"off\"}\n onSubmit={formex.handleSubmit}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n position: \"relative\",\n height: \"100%\"\n }}>\n <DialogContent className=\"flex-grow\">\n <div\n className=\"flex flex-row pt-12 pb-8\">\n <Typography variant={\"h4\"}\n className=\"flex-grow\">\n Role\n </Typography>\n </div>\n\n <div className={\"grid grid-cols-12 gap-8\"}>\n\n <div className={\"col-span-12 md:col-span-8\"}>\n <TextField\n name=\"name\"\n required\n error={touched.name && Boolean(errors.name)}\n value={values.name}\n disabled={isAdmin || !editable}\n onChange={handleChange}\n aria-describedby=\"name-helper-text\"\n label=\"Name\"\n />\n <FieldCaption>\n {touched.name && Boolean(errors.name) ? errors.name : \"Name of this role\"}\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12 md:col-span-4\"}>\n <TextField\n name=\"id\"\n required\n error={touched.id && Boolean(errors.id)}\n value={values.id}\n disabled={!isNewRole || !editable}\n onChange={(e) => {\n handleChange(e);\n setFieldTouched(\"id\", true)\n }}\n aria-describedby=\"id-helper-text\"\n label=\"ID\"\n />\n <FieldCaption>\n {touched.id && Boolean(errors.id) ? errors.id : \"ID of this role\"}\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12\"}>\n <Paper\n\n className=\"bg-inherit\">\n <Table>\n <TableHeader>\n <TableCell></TableCell>\n <TableCell\n align=\"center\">Create\n entities\n </TableCell>\n <TableCell\n align=\"center\">Read\n entities\n </TableCell>\n <TableCell\n align=\"center\">Update\n entities\n </TableCell>\n <TableCell\n align=\"center\">Delete\n entities\n </TableCell>\n </TableHeader>\n\n <TableBody>\n <TableRow>\n <TableCell\n scope=\"row\">\n <strong>All\n collections</strong>\n </TableCell>\n <TableCell\n align=\"center\">\n <Tooltip\n title=\"Create entities in collections\">\n <Checkbox\n disabled={isAdmin || !editable}\n checked={(isAdmin || defaultCreate) ?? false}\n onCheckedChange={(checked) => setFieldValue(\"defaultPermissions.create\", checked)}\n />\n </Tooltip>\n </TableCell>\n\n <TableCell\n align=\"center\">\n <Tooltip\n title=\"Access all data in every collection\">\n <Checkbox\n disabled={isAdmin || !editable}\n checked={(isAdmin || defaultRead) ?? false}\n onCheckedChange={(checked) => setFieldValue(\"defaultPermissions.read\", checked)}\n />\n </Tooltip>\n </TableCell>\n <TableCell\n align=\"center\">\n <Tooltip\n title=\"Update data in any collection\">\n <Checkbox\n disabled={isAdmin || !editable}\n checked={(isAdmin || defaultEdit) ?? false}\n onCheckedChange={(checked) => setFieldValue(\"defaultPermissions.edit\", checked)}\n />\n </Tooltip>\n </TableCell>\n <TableCell\n align=\"center\">\n <Tooltip\n title=\"Delete data in any collection\">\n <Checkbox\n disabled={isAdmin || !editable}\n checked={(isAdmin || defaultDelete) ?? false}\n onCheckedChange={(checked) => setFieldValue(\"defaultPermissions.delete\", checked)}\n />\n\n </Tooltip>\n </TableCell>\n </TableRow>\n {collections && collections.map((col) => (\n <TableRow key={col.name}>\n <TableCell\n scope=\"row\">\n {col.name}\n </TableCell>\n <TableCell\n align=\"center\">\n <Checkbox\n disabled={isAdmin || defaultCreate || !editable}\n checked={(isAdmin || defaultCreate || getIn(values, `collectionPermissions.${col.path}.create`)) ?? false}\n onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.create`, checked)}/>\n </TableCell>\n <TableCell\n align=\"center\">\n <Checkbox\n disabled={isAdmin || defaultRead || !editable}\n checked={(isAdmin || defaultRead || getIn(values, `collectionPermissions.${col.path}.read`)) ?? false}\n onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.read`, checked)}/>\n </TableCell>\n <TableCell\n align=\"center\">\n <Checkbox\n disabled={isAdmin || defaultEdit || !editable}\n checked={(isAdmin || defaultEdit || getIn(values, `collectionPermissions.${col.path}.edit`)) ?? false}\n onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.edit`, checked)}/>\n </TableCell>\n <TableCell\n align=\"center\">\n <Checkbox\n disabled={isAdmin || defaultDelete || !editable}\n checked={(isAdmin || defaultDelete || getIn(values, `collectionPermissions.${col.path}.delete`)) ?? false}\n onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.delete`, checked)}/>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </Paper>\n <FieldCaption>\n You can customise the permissions\n that the users related to this\n role can perform in the entities\n of each collection\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12 md:col-span-4\"}>\n <Select\n error={touched.config && Boolean(errors.config)}\n id=\"createCollections\"\n name=\"createCollections\"\n label=\"Create collections\"\n position={\"item-aligned\"}\n disabled={isAdmin || !editable}\n onChange={(event) => setFieldValue(\"config.createCollections\", event.target.value === \"true\")}\n value={isAdmin || values.config?.createCollections ? \"true\" : \"false\"}\n renderValue={(value: any) => value === \"true\" ? \"Yes\" : \"No\"}\n >\n <SelectItem\n value={\"true\"}> Yes </SelectItem>\n <SelectItem\n value={\"false\"}> No </SelectItem>\n </Select>\n\n <FieldCaption>\n {touched.config && Boolean(errors.config) ? errors.config : \"Can the user create collections\"}\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12 md:col-span-4\"}>\n <Select\n error={touched.config && Boolean(errors.config)}\n id=\"editCollections\"\n name=\"editCollections\"\n label=\"Edit collections\"\n disabled={isAdmin || !editable}\n position={\"item-aligned\"}\n onChange={(event) => setFieldValue(\"config.editCollections\", event.target.value === \"own\" ? \"own\" : event.target.value === \"true\")}\n value={isAdmin ? \"true\" : (values.config?.editCollections === \"own\" ? \"own\" : (values.config?.editCollections ? \"true\" : \"false\"))}\n renderValue={(value: any) => value === \"own\" ? \"Own\" : (value === \"true\" ? \"Yes\" : \"No\")}\n >\n <SelectItem\n value={\"true\"}> Yes </SelectItem>\n <SelectItem\n value={\"false\"}> No </SelectItem>\n <SelectItem\n value={\"own\"}> Only\n his/her own </SelectItem>\n </Select>\n\n <FieldCaption>\n {touched.config && Boolean(errors.config) ? errors.config : \"Can the user edit collections\"}\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12 md:col-span-4\"}>\n <Select\n error={touched.config && Boolean(errors.config)}\n id=\"deleteCollections\"\n name=\"deleteCollections\"\n label=\"Delete collections\"\n disabled={isAdmin || !editable}\n position={\"item-aligned\"}\n onChange={(event) => setFieldValue(\"config.deleteCollections\", event.target.value === \"own\" ? \"own\" : event.target.value === \"true\")}\n value={isAdmin ? \"true\" : (values.config?.deleteCollections === \"own\" ? \"own\" : (values.config?.deleteCollections ? \"true\" : \"false\"))}\n renderValue={(value: any) => value === \"own\" ? \"Own\" : (value === \"true\" ? \"Yes\" : \"No\")}\n >\n <SelectItem\n value={\"true\"}> Yes </SelectItem>\n <SelectItem\n value={\"false\"}> No </SelectItem>\n <SelectItem\n value={\"own\"}> Only\n his/her own </SelectItem>\n </Select>\n\n <FieldCaption>\n {touched.config && Boolean(errors.config) ? errors.config : \"Can the user delete collections\"}\n </FieldCaption>\n\n </div>\n\n </div>\n </DialogContent>\n\n <DialogActions position={\"sticky\"}>\n {savingError && <Typography className={\"text-red-500\"}>\n There was an error saving this role\n </Typography>}\n <Button variant={\"text\"}\n onClick={() => {\n handleClose();\n }}>\n Cancel\n </Button>\n <LoadingButton\n variant=\"filled\"\n color=\"primary\"\n type=\"submit\"\n disabled={!dirty}\n loading={isSubmitting}\n startIcon={<DoneIcon/>}\n >\n {isNewRole ? \"Create role\" : \"Update\"}\n </LoadingButton>\n </DialogActions>\n </form>\n\n </Formex>\n </Dialog>\n );\n}\n","import { Role } from \"../../types\";\n\nexport const DEFAULT_ROLES: Role[] = [\n {\n id: \"admin\",\n name: \"Admin\",\n isAdmin: true\n },\n {\n id: \"editor\",\n name: \"Editor\",\n isAdmin: false,\n defaultPermissions: {\n read: true,\n create: true,\n edit: true,\n delete: true\n },\n config: {\n createCollections: true,\n editCollections: \"own\",\n deleteCollections: \"own\"\n }\n },\n {\n id: \"viewer\",\n name: \"Viewer\",\n isAdmin: false,\n defaultPermissions: {\n read: true,\n create: false,\n edit: false,\n delete: false\n }\n }\n];\n","import { useState } from \"react\";\nimport {\n Button,\n CenteredView,\n Checkbox,\n DeleteIcon,\n IconButton,\n Table,\n TableBody,\n TableCell,\n TableHeader,\n TableRow,\n Tooltip,\n Typography\n} from \"@firecms/ui\";\nimport { DeleteConfirmationDialog } from \"@firecms/core\";\nimport { useUserManagement } from \"../../hooks\";\nimport { Role } from \"../../types\";\nimport { RoleChip } from \"./RoleChip\";\nimport { DEFAULT_ROLES } from \"./default_roles\";\n\nexport function RolesTable({\n onRoleClicked,\n editable\n }: {\n onRoleClicked: (role: Role) => void;\n editable: boolean;\n}) {\n\n const {\n roles,\n saveRole,\n deleteRole,\n allowDefaultRolesCreation\n } = useUserManagement();\n\n const [roleToBeDeleted, setRoleToBeDeleted] = useState<Role | undefined>(undefined);\n const [deleteInProgress, setDeleteInProgress] = useState<boolean>(false);\n\n return <div\n className=\"w-full overflow-auto\">\n <Table>\n <TableHeader>\n <TableCell header={true} className=\"w-16\"></TableCell>\n <TableCell header={true}>Role</TableCell>\n <TableCell header={true} className={\"items-center\"}>Is Admin</TableCell>\n <TableCell header={true}>Default permissions</TableCell>\n </TableHeader>\n\n <TableBody>\n {roles && roles.map((role) => {\n const canCreateAll = role.isAdmin || role.defaultPermissions?.create;\n const canReadAll = role.isAdmin || role.defaultPermissions?.read;\n const canUpdateAll = role.isAdmin || role.defaultPermissions?.edit;\n const canDeleteAll = role.isAdmin || role.defaultPermissions?.delete;\n return (\n <TableRow\n key={role.name}\n onClick={() => {\n onRoleClicked(role);\n }}\n >\n <TableCell style={{ width: \"64px\" }}>\n {!role.isAdmin &&\n <Tooltip title={\"Delete this role\"}>\n <IconButton\n size={\"small\"}\n disabled={!editable}\n onClick={(event) => {\n event.stopPropagation();\n return setRoleToBeDeleted(role);\n }}>\n <DeleteIcon/>\n </IconButton>\n </Tooltip>}\n </TableCell>\n <TableCell>\n <RoleChip role={role}/>\n </TableCell>\n <TableCell className={\"items-center\"}>\n <Checkbox checked={role.isAdmin ?? false}/>\n </TableCell>\n <TableCell>\n <ul>\n {canCreateAll && <li>Create</li>}\n {canReadAll && <li>Read</li>}\n {canUpdateAll && <li>Update</li>}\n {canDeleteAll && <li>Delete</li>}\n </ul>\n </TableCell>\n </TableRow>\n );\n })}\n\n {(!roles || roles.length === 0) && <TableRow>\n <TableCell colspan={4}>\n <CenteredView className={\"flex flex-col gap-4 my-8 items-center\"}>\n <Typography variant={\"label\"}>\n You don&apos;t have any roles yet.\n </Typography>\n {allowDefaultRolesCreation && <Button variant={\"outlined\"}\n onClick={() => {\n DEFAULT_ROLES.forEach((role) => {\n saveRole(role);\n });\n }}>\n Create default roles\n </Button>}\n </CenteredView>\n </TableCell>\n </TableRow>}\n\n </TableBody>\n\n </Table>\n\n <DeleteConfirmationDialog\n open={Boolean(roleToBeDeleted)}\n loading={deleteInProgress}\n onAccept={() => {\n if (roleToBeDeleted) {\n setDeleteInProgress(true);\n deleteRole(roleToBeDeleted)\n .then(() => {\n setRoleToBeDeleted(undefined);\n })\n .finally(() => {\n setDeleteInProgress(false);\n })\n }\n }}\n onCancel={() => {\n setRoleToBeDeleted(undefined);\n }}\n title={<>Delete?</>}\n body={<>Are you sure you want to delete this role?</>}/>\n\n </div>;\n}\n","import React, { useCallback, useState } from \"react\";\n\nimport { useNavigationController } from \"@firecms/core\";\nimport { AddIcon, Button, Container, Tooltip, Typography } from \"@firecms/ui\";\nimport { RolesTable } from \"./RolesTable\";\nimport { RolesDetailsForm } from \"./RolesDetailsForm\";\nimport { useUserManagement } from \"../../hooks\";\nimport { Role } from \"../../types\";\n\nexport const RolesView = React.memo(\n function RolesView({ children }: { children?: React.ReactNode }) {\n\n const { collections } = useNavigationController();\n const [dialogOpen, setDialogOpen] = useState(false);\n const [selectedRole, setSelectedRole] = useState<Role | undefined>();\n\n const { canEditRoles } = useUserManagement();\n\n const onRoleClicked = useCallback((user: Role) => {\n setDialogOpen(true);\n setSelectedRole(user);\n }, []);\n\n const handleClose = () => {\n setSelectedRole(undefined);\n setDialogOpen(false);\n };\n\n return (\n <Container className=\"w-full flex flex-col py-4 gap-4\" maxWidth={\"6xl\"}>\n\n {children}\n\n <div className=\"flex items-center mt-12\">\n <Typography gutterBottom variant=\"h4\"\n className=\"flex-grow\"\n component=\"h4\">\n Roles\n </Typography>\n <Tooltip title={!canEditRoles ? \"Update plans to customise roles\" : undefined}>\n <Button\n size={\"large\"}\n disabled={!canEditRoles}\n startIcon={<AddIcon/>}\n onClick={() => setDialogOpen(true)}>\n Add role\n </Button>\n </Tooltip>\n </div>\n\n <RolesTable onRoleClicked={onRoleClicked} editable={Boolean(canEditRoles)}/>\n\n <RolesDetailsForm\n key={selectedRole?.id ?? \"new\"}\n open={dialogOpen}\n role={selectedRole}\n editable={canEditRoles}\n collections={collections}\n handleClose={handleClose}/>\n\n </Container>\n )\n });\n","import React, { useCallback } from \"react\";\nimport * as Yup from \"yup\";\nimport {\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DoneIcon,\n LoadingButton,\n MultiSelect,\n MultiSelectItem,\n TextField,\n Typography,\n} from \"@firecms/ui\";\nimport { FieldCaption, useSnackbarController } from \"@firecms/core\";\nimport { Formex, useCreateFormex } from \"@firecms/formex\";\n\nimport { Role, UserWithRoles } from \"../../types\";\nimport { areRolesEqual } from \"../../utils\";\nimport { useUserManagement } from \"../../hooks\";\nimport { RoleChip } from \"../roles\";\n\nexport const UserYupSchema = Yup.object().shape({\n displayName: Yup.string().required(\"Required\"),\n email: Yup.string().email().required(\"Required\"),\n roles: Yup.array().min(1)\n});\n\nfunction canUserBeEdited(loggedUser: UserWithRoles, user: UserWithRoles, users: UserWithRoles[], roles: Role[], prevUser?: UserWithRoles) {\n const admins = users.filter(u => u.roles.map(r => r.id).includes(\"admin\"));\n const loggedUserIsAdmin = loggedUser.roles.map(r => r.id).includes(\"admin\");\n const didRolesChange = !prevUser || !areRolesEqual(prevUser.roles, user.roles);\n\n if (didRolesChange && !loggedUserIsAdmin) {\n throw new Error(\"Only admins can change roles\");\n }\n\n // was the admin role removed\n const adminRoleRemoved = prevUser && prevUser.roles.map(r => r.id).includes(\"admin\") && !user.roles.map(r => r.id).includes(\"admin\");\n\n // avoid removing the last admin\n if (adminRoleRemoved && admins.length === 1) {\n throw new Error(\"There must be at least one admin\");\n }\n return true;\n}\n\nexport function UserDetailsForm({\n open,\n user: userProp,\n handleClose\n }: {\n open: boolean,\n user?: UserWithRoles,\n handleClose: () => void\n}) {\n\n const snackbarController = useSnackbarController();\n const {\n loggedInUser,\n saveUser,\n users,\n roles,\n } = useUserManagement();\n const isNewUser = !userProp;\n\n const onUserUpdated = useCallback((savedUser: UserWithRoles): Promise<UserWithRoles> => {\n if (!loggedInUser) {\n throw new Error(\"Logged user not found\");\n }\n try {\n canUserBeEdited(loggedInUser, savedUser, users, roles, userProp);\n return saveUser(savedUser);\n } catch (e: any) {\n return Promise.reject(e);\n }\n }, [roles, saveUser, userProp, users, loggedInUser]);\n\n const formex = useCreateFormex({\n initialValues: userProp ?? {\n displayName: \"\",\n email: \"\",\n roles: roles.filter(r => r.id === \"editor\")\n } as UserWithRoles,\n validation: (values) => {\n return UserYupSchema.validate(values, { abortEarly: false })\n .then(() => {\n return {};\n }).catch((e) => {\n return e.inner.reduce((acc: any, error: any) => {\n acc[error.path] = error.message;\n return acc;\n }, {});\n });\n },\n onSubmit: (user: UserWithRoles, formexController) => {\n\n return onUserUpdated(user)\n .then(() => {\n handleClose();\n formexController.resetForm({\n values: user\n });\n }).catch((e) => {\n snackbarController.open({\n type: \"error\",\n message: e.message\n });\n });\n }\n });\n\n const {\n isSubmitting,\n touched,\n handleChange,\n values,\n errors,\n setFieldValue,\n dirty,\n handleSubmit,\n submitCount\n } = formex;\n\n return (\n <Dialog\n open={open}\n onOpenChange={(open) => !open ? handleClose() : undefined}\n maxWidth={\"4xl\"}\n >\n <Formex value={formex}>\n <form\n onSubmit={handleSubmit}\n autoComplete={\"off\"}\n noValidate\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n position: \"relative\",\n height: \"100%\"\n }}>\n <DialogContent className=\"h-full flex-grow\">\n <div\n className=\"flex flex-row pt-4 pb-4\">\n <Typography variant={\"h4\"}\n className=\"flex-grow\">\n User\n </Typography>\n </div>\n\n <div className={\"grid grid-cols-12 gap-8\"}>\n\n <div className={\"col-span-12\"}>\n <TextField\n name=\"displayName\"\n required\n error={submitCount > 0 && Boolean(errors.displayName)}\n value={values.displayName ?? \"\"}\n onChange={handleChange}\n aria-describedby=\"name-helper-text\"\n label=\"Name\"\n />\n <FieldCaption>\n {submitCount > 0 && Boolean(errors.displayName) ? errors.displayName : \"Name of this user\"}\n </FieldCaption>\n </div>\n <div className={\"col-span-12\"}>\n <TextField\n required\n error={submitCount > 0 && Boolean(errors.email)}\n name=\"email\"\n value={values.email ?? \"\"}\n onChange={handleChange}\n aria-describedby=\"email-helper-text\"\n label=\"Email\"\n />\n <FieldCaption>\n {submitCount > 0 && Boolean(errors.email) ? errors.email : \"Email of this user\"}\n </FieldCaption>\n </div>\n <div className={\"col-span-12\"}>\n <MultiSelect\n label=\"Roles\"\n value={values.roles.map(r => r.id) ?? []}\n onMultiValueChange={(value: string[]) => setFieldValue(\"roles\", value.map(id => roles.find(r => r.id === id) as Role))}\n renderValue={(value: string) => {\n const userRole = roles\n .find((role) => role.id === value);\n if (!userRole) return null;\n return <div className=\"flex flex-wrap space-x-2 space-y-2\">\n <RoleChip key={userRole?.id} role={userRole}/>\n </div>;\n }}>\n {roles.map(userRole => <MultiSelectItem key={userRole.id}\n value={userRole.id}>\n <RoleChip key={userRole?.id} role={userRole}/>\n </MultiSelectItem>)}\n </MultiSelect>\n </div>\n\n </div>\n\n </DialogContent>\n\n <DialogActions>\n\n <Button variant={\"text\"}\n onClick={() => {\n handleClose();\n }}>\n Cancel\n </Button>\n\n <LoadingButton\n variant=\"filled\"\n color=\"primary\"\n type=\"submit\"\n disabled={!dirty}\n loading={isSubmitting}\n startIcon={<DoneIcon/>}\n >\n {isNewUser ? \"Create user\" : \"Update\"}\n </LoadingButton>\n </DialogActions>\n </form>\n </Formex>\n\n </Dialog>\n );\n}\n","import { useState } from \"react\";\nimport { User as FirebaseUser } from \"firebase/auth\";\n\nimport { format } from \"date-fns\";\nimport * as locales from \"date-fns/locale\";\n\nimport {\n defaultDateFormat,\n DeleteConfirmationDialog,\n useAuthController,\n useCustomizationController,\n useSnackbarController\n} from \"@firecms/core\";\nimport {\n Button,\n CenteredView,\n DeleteIcon,\n IconButton,\n Table,\n TableBody,\n TableCell,\n TableHeader,\n TableRow,\n Tooltip,\n Typography,\n} from \"@firecms/ui\";\nimport { Role, UserWithRoles } from \"../../types\";\nimport { useUserManagement } from \"../../hooks/useUserManagement\";\nimport { RoleChip } from \"../roles/RoleChip\";\n\nexport function UsersTable({ onUserClicked }: {\n onUserClicked: (user: UserWithRoles) => void;\n}) {\n\n const {\n users,\n saveUser,\n deleteUser\n } = useUserManagement();\n\n const authController = useAuthController<FirebaseUser>();\n const snackbarController = useSnackbarController();\n\n const customizationController = useCustomizationController();\n const dateUtilsLocale = customizationController?.locale ? locales[customizationController?.locale as keyof typeof locales] : undefined;\n const dateFormat: string = customizationController?.dateTimeFormat ?? defaultDateFormat;\n\n const [userToBeDeleted, setUserToBeDeleted] = useState<UserWithRoles | undefined>(undefined);\n const [deleteInProgress, setDeleteInProgress] = useState<boolean>(false);\n\n return (\n <div className=\"overflow-auto\">\n\n <Table>\n\n <TableHeader>\n <TableCell className=\"truncate w-16\"></TableCell>\n <TableCell>ID</TableCell>\n <TableCell>Email</TableCell>\n <TableCell>Name</TableCell>\n <TableCell>Roles</TableCell>\n <TableCell>Created on</TableCell>\n </TableHeader>\n <TableBody>\n {users && users.map((user) => {\n\n const userRoles: Role[] | undefined = user.roles;\n\n const formattedDate = user.created_on ? format(user.created_on, dateFormat, { locale: dateUtilsLocale }) : \"\";\n\n return (\n <TableRow\n key={\"row_\" + user.uid}\n onClick={() => {\n onUserClicked(user);\n }}\n >\n <TableCell className={\"w-10\"}>\n <Tooltip title={\"Delete this user\"}>\n <IconButton\n size={\"small\"}\n onClick={(event) => {\n event.stopPropagation();\n return setUserToBeDeleted(user);\n }}>\n <DeleteIcon/>\n </IconButton>\n </Tooltip>\n </TableCell>\n <TableCell>{user.uid}</TableCell>\n <TableCell>{user.email}</TableCell>\n <TableCell className={\"font-medium align-left\"}>{user.displayName}</TableCell>\n <TableCell className=\"align-left\">\n {userRoles\n ? <div className=\"flex flex-wrap gap-2\">\n {userRoles.map(userRole =>\n <RoleChip key={userRole?.id} role={userRole}/>\n )}\n </div>\n : null}\n </TableCell>\n <TableCell>{formattedDate}</TableCell>\n </TableRow>\n );\n })}\n\n {(!users || users.length === 0) && <TableRow>\n <TableCell colspan={6}>\n <CenteredView className={\"flex flex-col gap-4 my-8 items-center\"}>\n <Typography variant={\"label\"}>\n There are no users yet\n </Typography>\n <Button variant={\"outlined\"}\n onClick={() => {\n if (!authController.user?.uid) {\n throw Error(\"UsersTable, authController misconfiguration\");\n }\n saveUser({\n uid: authController.user?.uid,\n email: authController.user?.email,\n displayName: authController.user?.displayName,\n photoURL: authController.user?.photoURL,\n providerId: authController.user?.providerId,\n isAnonymous: authController.user?.isAnonymous,\n roles: [{ id: \"admin\", name: \"Admin\" }],\n created_on: new Date()\n })\n .then(() => {\n snackbarController.open({\n type: \"success\",\n message: \"User added successfully\"\n })\n })\n .catch((error) => {\n snackbarController.open({\n type: \"error\",\n message: \"Error adding user: \" + error.message,\n })\n });\n }}>\n\n Add the logged user as an admin\n </Button>\n </CenteredView>\n </TableCell>\n </TableRow>}\n\n </TableBody>\n </Table>\n\n <DeleteConfirmationDialog\n open={Boolean(userToBeDeleted)}\n loading={deleteInProgress}\n onAccept={() => {\n if (userToBeDeleted) {\n setDeleteInProgress(true);\n deleteUser(userToBeDeleted)\n .then(() => {\n setUserToBeDeleted(undefined);\n })\n .catch((error) => {\n snackbarController.open({\n type: \"error\",\n message: \"Error deleting user: \" + error.message,\n })\n })\n .finally(() => {\n setDeleteInProgress(false);\n })\n }\n }}\n onCancel={() => {\n setUserToBeDeleted(undefined);\n }}\n title={<>Delete?</>}\n body={<>Are you sure you want to delete this user?</>}/>\n </div>);\n}\n","import { AddIcon, Button, Container, Typography } from \"@firecms/ui\";\n\nimport { UsersTable } from \"./UsersTable\";\nimport { UserDetailsForm } from \"./UserDetailsForm\";\nimport React, { useCallback, useState } from \"react\";\nimport { UserWithRoles } from \"../../types\";\nimport { useUserManagement } from \"../../hooks/useUserManagement\";\n\nexport const UsersView = function UsersView({ children }: { children?: React.ReactNode }) {\n\n const [dialogOpen, setDialogOpen] = useState<boolean>();\n const [selectedUser, setSelectedUser] = useState<UserWithRoles | undefined>();\n\n const { users, usersLimit } = useUserManagement();\n\n const reachedUsersLimit = usersLimit !== undefined && (users && users.length >= usersLimit);\n\n const onUserClicked = useCallback((user: UserWithRoles) => {\n setSelectedUser(user);\n setDialogOpen(true);\n }, []);\n\n const handleClose = useCallback(() => {\n setDialogOpen(false);\n setSelectedUser(undefined);\n }, []);\n\n return (\n <Container className=\"w-full flex flex-col py-4 gap-4\" maxWidth={\"6xl\"}>\n\n {children}\n\n <div\n className=\"flex items-center mt-12\">\n <Typography gutterBottom variant=\"h4\"\n className=\"flex-grow\"\n component=\"h4\">\n Users\n </Typography>\n <Button\n size={\"large\"}\n disabled={reachedUsersLimit}\n startIcon={<AddIcon/>}\n onClick={() => setDialogOpen(true)}>\n Add user\n </Button>\n </div>\n\n <UsersTable onUserClicked={onUserClicked}/>\n\n <UserDetailsForm\n key={selectedUser?.uid ?? \"new\"}\n open={dialogOpen ?? false}\n user={selectedUser}\n handleClose={handleClose}/>\n\n </Container>\n )\n};\n","import { AuthController, FireCMSPlugin } from \"@firecms/core\";\nimport { UserManagementProvider } from \"./UserManagementProvider\";\nimport { UserManagement } from \"./types\";\n\nexport function useUserManagementPlugin({ userManagement }: {\n userManagement: UserManagement,\n}): FireCMSPlugin {\n return {\n name: \"User management plugin\",\n loading: userManagement.loading,\n provider: {\n Component: UserManagementProvider,\n props: {\n userManagement\n }\n }\n }\n}\n","import { CMSView } from \"@firecms/core\";\nimport { RolesView, UsersView } from \"./components\";\n\nexport const userManagementAdminViews: CMSView[] = [\n {\n path: \"users\",\n name: \"CMS Users\",\n group: \"Admin\",\n icon: \"face\",\n view: <UsersView/>\n },\n {\n path: \"roles\",\n name: \"Roles\",\n group: \"Admin\",\n icon: \"gpp_good\",\n view: <RolesView/>\n }\n]\n"],"names":["RESERVED_GROUPS","DEFAULT_PERMISSIONS","resolveUserRolePermissions","collection","user","roles","basePermissions","role","resolveCollectionRole","mergePermissions","id","permA","permB","getUserRoles","fireCMSUser","r","areRolesEqual","rolesA","rolesB","rolesAIds","rolesBIds","cacheDelegatedLoginToken","projectId","delegatedToken","data","parseJwt","expiry","getDelegatedLoginTokenFromCache","entry","clearDelegatedLoginTokensCache","i","key","token","base64","jsonPayload","c","darkenColor","hexColor","darkenBy","color","g","b","hexToRgbaWithOpacity","opacity","alpha","useBuildFirestoreUserManagement","firebaseApp","usersPath","rolesPath","usersLimit","canEditRoles","authController","allowDefaultRolesCreation","includeCollectionConfigPermissions","firestoreRef","useRef","rolesLoading","setRolesLoading","React","usersLoading","setUsersLoading","setRoles","usersWithRoleIds","setUsersWithRoleIds","users","u","rolesError","setRolesError","usersError","setUsersError","loading","loggedInUser","useEffect","getFirestore","firestore","onSnapshot","snapshot","newRoles","docsToRoles","e","newUsers","docsToUsers","saveUser","useCallback","roleIds","uid","userData","setDoc","doc","saveRole","roleData","ref","deleteUser","deleteDoc","deleteRole","collectionPermissions","docs","UserManagementContext","UserManagementProvider","children","userManagement","useUserManagement","useContext","RoleChip","colorScheme","getColorSchemeForSeed","jsx","Chip","RoleYupSchema","Yup","RolesDetailsForm","open","editable","handleClose","collections","isNewRole","savingError","setSavingError","useState","onRoleUpdated","formex","useCreateFormex","formexController","values","errors","error","isSubmitting","touched","handleChange","setFieldValue","dirty","setFieldTouched","isAdmin","defaultCreate","defaultRead","defaultEdit","defaultDelete","getIn","toSnakeCase","Dialog","Formex","jsxs","DialogContent","Typography","TextField","FieldCaption","Paper","Table","TableHeader","TableCell","TableBody","TableRow","Tooltip","Checkbox","checked","col","Select","event","value","SelectItem","DialogActions","Button","LoadingButton","DoneIcon","DEFAULT_ROLES","RolesTable","onRoleClicked","roleToBeDeleted","setRoleToBeDeleted","deleteInProgress","setDeleteInProgress","canCreateAll","canReadAll","canUpdateAll","canDeleteAll","IconButton","DeleteIcon","CenteredView","DeleteConfirmationDialog","RolesView","useNavigationController","dialogOpen","setDialogOpen","selectedRole","setSelectedRole","Container","AddIcon","UserYupSchema","canUserBeEdited","loggedUser","prevUser","admins","loggedUserIsAdmin","UserDetailsForm","userProp","snackbarController","useSnackbarController","isNewUser","onUserUpdated","savedUser","acc","handleSubmit","submitCount","MultiSelect","userRole","MultiSelectItem","UsersTable","onUserClicked","useAuthController","customizationController","useCustomizationController","dateUtilsLocale","locales","dateFormat","defaultDateFormat","userToBeDeleted","setUserToBeDeleted","userRoles","formattedDate","format","UsersView","selectedUser","setSelectedUser","reachedUsersLimit","useUserManagementPlugin","userManagementAdminViews"],"mappings":"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"}
1
+ {"version":3,"file":"index.umd.js","sources":["../src/utils/permissions.ts","../src/utils/local_storage.ts","../src/utils/colors.ts","../src/hooks/useBuildFirestoreUserManagement.tsx","../src/UserManagementProvider.tsx","../src/hooks/useUserManagement.tsx","../src/components/roles/RoleChip.tsx","../src/components/roles/RolesDetailsForm.tsx","../src/components/roles/default_roles.tsx","../src/components/roles/RolesTable.tsx","../src/components/roles/RolesView.tsx","../src/components/users/UserDetailsForm.tsx","../src/components/users/UsersTable.tsx","../src/components/users/UsersView.tsx","../src/useUserManagementPlugin.tsx","../src/admin_views.tsx"],"sourcesContent":["import { CMSType, EntityCollection, Permissions } from \"@firecms/core\";\nimport { Role, UserWithRoles } from \"../types\";\n\nexport const RESERVED_GROUPS = [\"Admin\"];\n\nconst DEFAULT_PERMISSIONS = {\n read: false,\n edit: false,\n create: false,\n delete: false\n};\n\nexport function resolveUserRolePermissions<UserType extends UserWithRoles>\n({ collection, user }: {\n collection: EntityCollection<any>,\n user: UserType | null\n}): Permissions {\n\n const roles = user?.roles;\n if (!roles) {\n return DEFAULT_PERMISSIONS;\n } else if (collection.ownerId === user?.uid) {\n return {\n read: true,\n create: true,\n edit: true,\n delete: true\n };\n } else {\n const basePermissions = {\n read: false,\n create: false,\n edit: false,\n delete: false\n };\n\n return roles\n .map(role => resolveCollectionRole(role, collection.id))\n .reduce(mergePermissions, basePermissions);\n }\n}\n\nfunction resolveCollectionRole(role: Role, id: string): Permissions {\n\n const basePermissions = {\n read: role.isAdmin || role.defaultPermissions?.read,\n create: role.isAdmin || role.defaultPermissions?.create,\n edit: role.isAdmin || role.defaultPermissions?.edit,\n delete: role.isAdmin || role.defaultPermissions?.delete\n };\n if (role.collectionPermissions && role.collectionPermissions[id]) {\n return mergePermissions(role.collectionPermissions[id], basePermissions);\n } else if (role.defaultPermissions) {\n return mergePermissions(role.defaultPermissions, basePermissions);\n } else {\n return basePermissions;\n }\n}\n\nconst mergePermissions = (permA: Permissions, permB: Permissions) => {\n return {\n read: permA.read || permB.read,\n create: permA.create || permB.create,\n edit: permA.edit || permB.edit,\n delete: permA.delete || permB.delete\n };\n}\n\nexport function getUserRoles(roles: Role[], fireCMSUser: UserWithRoles): Role[] | undefined {\n return !roles\n ? undefined\n : (fireCMSUser.roles\n ? fireCMSUser.roles\n .map(role => roles.find((r) => r.id === role.id))\n .filter(Boolean) as Role[]\n : []);\n}\n\nexport const areRolesEqual = (rolesA: Role[], rolesB: Role[]) => {\n const rolesAIds = rolesA.map(r => r.id);\n const rolesBIds = rolesB.map(r => r.id);\n return rolesAIds.length === rolesB.length && rolesAIds.every((role) => rolesBIds.includes(role));\n}\n","// const tokens = new Map<string, {\n// token: string,\n// expiry: Date\n// }>();\n\nexport function cacheDelegatedLoginToken(projectId: string, delegatedToken?: string) {\n if (!delegatedToken) {\n return;\n }\n\n const data = parseJwt(delegatedToken);\n // @ts-ignore\n const expiry = new Date(data.exp * 1000);\n localStorage.setItem(`auth_token::${projectId}`, JSON.stringify({\n token: delegatedToken,\n expiry\n }));\n\n}\n\nexport function getDelegatedLoginTokenFromCache(projectId: string) {\n const entry = localStorage.getItem(`auth_token::${projectId}`);\n if (entry) {\n const data = JSON.parse(entry);\n data.expiry = new Date(data.expiry);\n if (data.expiry > new Date()) {\n return data.token;\n }\n }\n return undefined;\n}\n\nexport function clearDelegatedLoginTokensCache() {\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(\"auth_token::\")) {\n localStorage.removeItem(key);\n }\n }\n}\n\nfunction parseJwt(token?: string): object {\n if (!token) {\n throw new Error(\"No JWT token\");\n }\n const base64Url = token.split(\".\")[1];\n const base64 = base64Url.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const jsonPayload = decodeURIComponent(window.atob(base64).split(\"\").map(function (c) {\n return \"%\" + (\"00\" + c.charCodeAt(0).toString(16)).slice(-2);\n }).join(\"\"));\n\n return JSON.parse(jsonPayload);\n}\n","export function darkenColor(hexColor: string, darkenBy = 10): string {\n // Check input validity\n if (!/^#([0-9A-Fa-f]{3}){1,2}$/.test(hexColor)) {\n throw new Error(\"Invalid color format\");\n }\n\n // If shorthand form, convert to full form\n let color = hexColor.substring(1).split(\"\");\n if (color.length === 3) {\n color = [color[0], color[0], color[1], color[1], color[2], color[2]];\n }\n\n // Convert to RGB values\n let r = parseInt(color[0] + color[1], 16);\n let g = parseInt(color[2] + color[3], 16);\n let b = parseInt(color[4] + color[5], 16);\n\n // Reduce each color component by the specified percentage (darkenBy)\n r = Math.floor(r * (1 - darkenBy / 100));\n g = Math.floor(g * (1 - darkenBy / 100));\n b = Math.floor(b * (1 - darkenBy / 100));\n\n // Recombine into hex and return\n return \"#\" +\n (r < 16 ? \"0\" : \"\") + r.toString(16) +\n (g < 16 ? \"0\" : \"\") + g.toString(16) +\n (b < 16 ? \"0\" : \"\") + b.toString(16);\n}\n\nexport function hexToRgbaWithOpacity(hexColor: string, opacity = 10): string {\n // Check input validity\n if (!/^#([0-9A-Fa-f]{3}){1,2}$/.test(hexColor)) {\n throw new Error(\"Invalid color format\");\n }\n\n // If shorthand form, convert to full form\n let color = hexColor.substring(1).split(\"\");\n if (color.length === 3) {\n color = [color[0], color[0], color[1], color[1], color[2], color[2]];\n }\n\n // Convert to RGB values\n const r = parseInt(color[0] + color[1], 16);\n const g = parseInt(color[2] + color[3], 16);\n const b = parseInt(color[4] + color[5], 16);\n\n // Convert opacity to a decimal for CSS\n const alpha = opacity / 100;\n\n // Construct and return the RGBA color\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n","import React, { useCallback, useEffect, useRef } from \"react\";\nimport {\n collection,\n deleteDoc,\n doc,\n DocumentSnapshot,\n Firestore,\n getFirestore,\n onSnapshot,\n setDoc\n} from \"firebase/firestore\";\nimport { FirebaseApp } from \"firebase/app\";\nimport { Role, UserManagement, UserWithRoles } from \"../types\";\nimport { AuthController, PermissionsBuilder, User } from \"@firecms/core\";\nimport { resolveUserRolePermissions } from \"../utils\";\n\ntype UserWithRoleIds = User & { roles: string[] };\n\nexport interface UserManagementParams {\n /**\n * The Firebase app to use for the user management. The config will be saved in the Firestore\n * collection indicated by `configPath`.\n */\n firebaseApp?: FirebaseApp;\n /**\n * Path where the plugin users configuration is stored.\n * Default: __FIRECMS/config/users\n * You can specify a different path if you want to store the user management configuration in a different place.\n * Please keep in mind that the FireCMS users are not necessarily the same as the Firebase users (but they can be).\n * The path should be relative to the root of the Firestore database, and should always have an odd number of segments.\n */\n usersPath?: string;\n\n /**\n * Path where the plugin roles configuration is stored.\n * Default: __FIRECMS/config/roles\n */\n rolesPath?: string;\n\n usersLimit?: number;\n\n canEditRoles?: boolean;\n\n authController: AuthController;\n\n /**\n * If there are no roles in the database, provide a button to create the default roles.\n */\n allowDefaultRolesCreation?: boolean;\n\n /**\n * Include the collection config permissions in the user management system.\n */\n includeCollectionConfigPermissions?: boolean;\n\n}\n\n/**\n * This hook is used to build a user management object that can be used to\n * manage users and roles in a Firestore backend.\n * @param backendFirebaseApp\n * @param usersPath\n * @param rolesPath\n * @param usersLimit\n * @param canEditRoles\n */\nexport function useBuildFirestoreUserManagement({\n firebaseApp,\n usersPath = \"__FIRECMS/config/users\",\n rolesPath = \"__FIRECMS/config/roles\",\n usersLimit,\n canEditRoles = true,\n authController,\n allowDefaultRolesCreation,\n includeCollectionConfigPermissions\n }: UserManagementParams): UserManagement {\n\n const firestoreRef = useRef<Firestore>();\n\n const [rolesLoading, setRolesLoading] = React.useState<boolean>(true);\n const [usersLoading, setUsersLoading] = React.useState<boolean>(true);\n const [roles, setRoles] = React.useState<Role[]>([]);\n const [usersWithRoleIds, setUsersWithRoleIds] = React.useState<UserWithRoleIds[]>([]);\n\n const users = usersWithRoleIds.map(u => ({\n ...u,\n roles: roles.filter(r => u.roles?.includes(r.id))\n }) as UserWithRoles);\n\n const [rolesError, setRolesError] = React.useState<Error | undefined>();\n const [usersError, setUsersError] = React.useState<Error | undefined>();\n\n const loading = rolesLoading || usersLoading;\n\n const loggedInUser: UserWithRoles | undefined = users.find(u => u.email?.toLowerCase() === authController.user?.email?.toLowerCase());\n // console.log(\"authController\", authController);\n // if (!loading && !authController.authLoading) {\n // const user = authController.user;\n // if (user) {\n // loggedInUser = users.find(u => u.email?.toLowerCase() === user.email?.toLowerCase());\n // }\n // }\n\n useEffect(() => {\n if (!firebaseApp) return;\n firestoreRef.current = getFirestore(firebaseApp);\n }, [firebaseApp]);\n\n useEffect(() => {\n if (!firebaseApp || !rolesPath) return;\n const firestore = getFirestore(firebaseApp);\n\n return onSnapshot(collection(firestore, rolesPath),\n {\n next: (snapshot) => {\n setRolesError(undefined);\n try {\n const newRoles = docsToRoles(snapshot.docs);\n setRoles(newRoles);\n } catch (e) {\n // console.error(e);\n setRolesError(e as Error);\n }\n setRolesLoading(false);\n },\n error: (e) => {\n setRolesError(e);\n setRolesLoading(false);\n }\n }\n );\n }, [firebaseApp, rolesPath]);\n\n useEffect(() => {\n if (!firebaseApp || !usersPath) return;\n const firestore = getFirestore(firebaseApp);\n\n return onSnapshot(collection(firestore, usersPath),\n {\n next: (snapshot) => {\n setUsersError(undefined);\n try {\n const newUsers = docsToUsers(snapshot.docs);\n setUsersWithRoleIds(newUsers);\n } catch (e) {\n setUsersError(e as Error);\n }\n setUsersLoading(false);\n },\n error: (e) => {\n setUsersError(e);\n setUsersLoading(false);\n }\n }\n );\n }, [firebaseApp, usersPath]);\n\n const saveUser = useCallback(async (user: UserWithRoles): Promise<UserWithRoles> => {\n const firestore = firestoreRef.current;\n if (!firestore || !usersPath) throw Error(\"useFirestoreConfigurationPersistence Firestore not initialised\");\n console.debug(\"Persisting user\", user);\n const roleIds = user.roles.map(r => r.id);\n const {\n uid,\n ...userData\n } = user;\n return setDoc(doc(firestore, usersPath, uid), { ...userData, roles: roleIds }, { merge: true }).then(() => user);\n }, [usersPath]);\n\n const saveRole = useCallback((role: Role): Promise<void> => {\n const firestore = firestoreRef.current;\n if (!firestore || !rolesPath) throw Error(\"useFirestoreConfigurationPersistence Firestore not initialised\");\n console.debug(\"Persisting role\", role);\n const {\n id,\n ...roleData\n } = role;\n const ref = doc(firestore, rolesPath, id);\n return setDoc(ref, roleData, { merge: true });\n }, [rolesPath]);\n\n const deleteUser = useCallback(async (user: UserWithRoles): Promise<void> => {\n const firestore = firestoreRef.current;\n if (!firestore || !usersPath) throw Error(\"useFirestoreConfigurationPersistence Firestore not initialised\");\n console.debug(\"Deleting\", user);\n const { uid } = user;\n return deleteDoc(doc(firestore, usersPath, uid));\n }, [usersPath]);\n\n const deleteRole = useCallback((role: Role): Promise<void> => {\n const firestore = firestoreRef.current;\n if (!firestore || !rolesPath) throw Error(\"useFirestoreConfigurationPersistence Firestore not initialised\");\n console.debug(\"Deleting\", role);\n const { id } = role;\n const ref = doc(firestore, rolesPath, id);\n return deleteDoc(ref);\n }, [rolesPath]);\n\n const collectionPermissions: PermissionsBuilder = useCallback(({\n collection,\n }) => resolveUserRolePermissions({\n collection,\n user: loggedInUser ?? null\n }), [loggedInUser?.uid]);\n\n return {\n loading,\n loggedInUser,\n roles,\n users,\n saveUser,\n saveRole,\n deleteUser,\n deleteRole,\n usersLimit,\n canEditRoles: canEditRoles === undefined ? true : canEditRoles,\n allowDefaultRolesCreation: allowDefaultRolesCreation === undefined ? true : allowDefaultRolesCreation,\n includeCollectionConfigPermissions: Boolean(includeCollectionConfigPermissions),\n collectionPermissions\n }\n}\n\nconst docsToUsers = (docs: DocumentSnapshot[]): (UserWithRoleIds)[] => {\n return docs.map((doc) => {\n const data = doc.data() as any;\n const newVar = {\n uid: doc.id,\n ...data,\n created_on: data?.created_on?.toDate(),\n updated_on: data?.updated_on?.toDate()\n };\n return newVar as (UserWithRoleIds);\n });\n}\n\nconst docsToRoles = (docs: DocumentSnapshot[]): Role[] => {\n return docs.map((doc) => ({\n id: doc.id,\n ...doc.data()\n } as Role));\n}\n","import React, { PropsWithChildren } from \"react\";\nimport { UserManagement, UserWithRoles } from \"./types\";\n\nexport const UserManagementContext = React.createContext<UserManagement<any>>({} as any);\n\nexport interface UserManagementProviderProps<U extends UserWithRoles = UserWithRoles> {\n userManagement: UserManagement<U>\n}\n\nexport function UserManagementProvider<U extends UserWithRoles = UserWithRoles>({\n children,\n userManagement\n }: PropsWithChildren<UserManagementProviderProps<U>>) {\n return (\n <UserManagementContext.Provider value={userManagement}>\n {children}\n </UserManagementContext.Provider>\n );\n};\n","import { useContext } from \"react\";\nimport { UserManagement } from \"../types/user_management\";\nimport { UserManagementContext } from \"../UserManagementProvider\";\n\nexport const useUserManagement = () => useContext<UserManagement>(UserManagementContext);\n","import { Chip, getColorSchemeForSeed } from \"@firecms/ui\";\nimport { Role } from \"../../types\";\n\nexport type RoleChipProps = {\n role: Role;\n}\n\nexport function RoleChip({ role }: RoleChipProps) {\n let colorScheme;\n if (role.isAdmin) {\n colorScheme = \"blueDarker\";\n } else if (role.id === \"editor\") {\n colorScheme = \"yellowLight\";\n } else if (role.id === \"viewer\") {\n colorScheme = \"grayLight\";\n } else {\n colorScheme = getColorSchemeForSeed(role.id);\n }\n\n return (\n <Chip\n colorScheme={colorScheme}\n key={role.id}>\n {role.name}\n </Chip>\n );\n\n}\n","import React, { useCallback, useState } from \"react\";\nimport * as Yup from \"yup\";\n\nimport { EntityCollection, FieldCaption, toSnakeCase, } from \"@firecms/core\";\nimport {\n Button,\n Checkbox,\n Dialog,\n DialogActions,\n DialogContent,\n DoneIcon,\n LoadingButton,\n Paper,\n Select,\n SelectItem,\n Table,\n TableBody,\n TableCell,\n TableHeader,\n TableRow,\n TextField,\n Tooltip,\n Typography\n} from \"@firecms/ui\";\nimport { useUserManagement } from \"../../hooks\";\nimport { Formex, getIn, useCreateFormex } from \"@firecms/formex\";\nimport { Role } from \"../../types\";\n\nexport const RoleYupSchema = Yup.object().shape({\n id: Yup.string().required(\"Required\"),\n name: Yup.string().required(\"Required\")\n});\n\nexport function RolesDetailsForm({\n open,\n role,\n editable,\n handleClose,\n collections\n }: {\n open: boolean,\n editable?: boolean,\n role?: Role,\n handleClose: () => void,\n collections?: EntityCollection[]\n}) {\n\n const { saveRole } = useUserManagement();\n const isNewRole = !role;\n\n const [savingError, setSavingError] = useState<Error | undefined>();\n\n const onRoleUpdated = useCallback((role: Role) => {\n setSavingError(undefined);\n return saveRole(role);\n }, [saveRole]);\n\n const formex = useCreateFormex({\n initialValues: role ?? {\n name: \"\"\n } as Role,\n onSubmit: (role: Role, formexController) => {\n return onRoleUpdated(role)\n .then(() => {\n formexController.resetForm({\n values: role\n });\n handleClose();\n })\n .catch(e => setSavingError(e));\n },\n validation: (values) => {\n return RoleYupSchema.validate(values, { abortEarly: false })\n .then(() => ({}))\n .catch((e) => {\n const errors: Record<string, string> = {};\n e.inner.forEach((error: any) => {\n errors[error.path] = error.message;\n });\n return errors;\n });\n }\n\n });\n\n const {\n isSubmitting,\n touched,\n values,\n errors,\n handleChange,\n setFieldValue,\n dirty,\n setFieldTouched\n } = formex;\n\n const isAdmin = values.isAdmin ?? false;\n const defaultCreate = values.defaultPermissions?.create ?? false;\n const defaultRead = values.defaultPermissions?.read ?? false;\n const defaultEdit = values.defaultPermissions?.edit ?? false;\n const defaultDelete = values.defaultPermissions?.delete ?? false;\n\n React.useEffect(() => {\n const idTouched = getIn(touched, \"id\");\n if (!idTouched && values.name) {\n setFieldValue(\"id\", toSnakeCase(values.name))\n }\n }, [touched, values.name]);\n\n return (\n <Dialog\n open={open}\n maxWidth={\"4xl\"}\n >\n <Formex value={formex}>\n <form noValidate\n autoComplete={\"off\"}\n onSubmit={formex.handleSubmit}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n position: \"relative\",\n height: \"100%\"\n }}>\n <DialogContent className=\"flex-grow\">\n <div\n className=\"flex flex-row pt-12 pb-8\">\n <Typography variant={\"h4\"}\n className=\"flex-grow\">\n Role\n </Typography>\n </div>\n\n <div className={\"grid grid-cols-12 gap-8\"}>\n\n <div className={\"col-span-12 md:col-span-8\"}>\n <TextField\n name=\"name\"\n required\n error={touched.name && Boolean(errors.name)}\n value={values.name}\n disabled={isAdmin || !editable}\n onChange={handleChange}\n aria-describedby=\"name-helper-text\"\n label=\"Name\"\n />\n <FieldCaption>\n {touched.name && Boolean(errors.name) ? errors.name : \"Name of this role\"}\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12 md:col-span-4\"}>\n <TextField\n name=\"id\"\n required\n error={touched.id && Boolean(errors.id)}\n value={values.id}\n disabled={!isNewRole || !editable}\n onChange={(e) => {\n handleChange(e);\n setFieldTouched(\"id\", true)\n }}\n aria-describedby=\"id-helper-text\"\n label=\"ID\"\n />\n <FieldCaption>\n {touched.id && Boolean(errors.id) ? errors.id : \"ID of this role\"}\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12\"}>\n <Paper\n\n className=\"bg-inherit\">\n <Table>\n <TableHeader>\n <TableCell></TableCell>\n <TableCell\n align=\"center\">Create\n entities\n </TableCell>\n <TableCell\n align=\"center\">Read\n entities\n </TableCell>\n <TableCell\n align=\"center\">Update\n entities\n </TableCell>\n <TableCell\n align=\"center\">Delete\n entities\n </TableCell>\n </TableHeader>\n\n <TableBody>\n <TableRow>\n <TableCell\n scope=\"row\">\n <strong>All\n collections</strong>\n </TableCell>\n <TableCell\n align=\"center\">\n <Tooltip\n title=\"Create entities in collections\">\n <Checkbox\n disabled={isAdmin || !editable}\n checked={(isAdmin || defaultCreate) ?? false}\n onCheckedChange={(checked) => setFieldValue(\"defaultPermissions.create\", checked)}\n />\n </Tooltip>\n </TableCell>\n\n <TableCell\n align=\"center\">\n <Tooltip\n title=\"Access all data in every collection\">\n <Checkbox\n disabled={isAdmin || !editable}\n checked={(isAdmin || defaultRead) ?? false}\n onCheckedChange={(checked) => setFieldValue(\"defaultPermissions.read\", checked)}\n />\n </Tooltip>\n </TableCell>\n <TableCell\n align=\"center\">\n <Tooltip\n title=\"Update data in any collection\">\n <Checkbox\n disabled={isAdmin || !editable}\n checked={(isAdmin || defaultEdit) ?? false}\n onCheckedChange={(checked) => setFieldValue(\"defaultPermissions.edit\", checked)}\n />\n </Tooltip>\n </TableCell>\n <TableCell\n align=\"center\">\n <Tooltip\n title=\"Delete data in any collection\">\n <Checkbox\n disabled={isAdmin || !editable}\n checked={(isAdmin || defaultDelete) ?? false}\n onCheckedChange={(checked) => setFieldValue(\"defaultPermissions.delete\", checked)}\n />\n\n </Tooltip>\n </TableCell>\n </TableRow>\n {collections && collections.map((col) => (\n <TableRow key={col.name}>\n <TableCell\n scope=\"row\">\n {col.name}\n </TableCell>\n <TableCell\n align=\"center\">\n <Checkbox\n disabled={isAdmin || defaultCreate || !editable}\n checked={(isAdmin || defaultCreate || getIn(values, `collectionPermissions.${col.path}.create`)) ?? false}\n onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.create`, checked)}/>\n </TableCell>\n <TableCell\n align=\"center\">\n <Checkbox\n disabled={isAdmin || defaultRead || !editable}\n checked={(isAdmin || defaultRead || getIn(values, `collectionPermissions.${col.path}.read`)) ?? false}\n onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.read`, checked)}/>\n </TableCell>\n <TableCell\n align=\"center\">\n <Checkbox\n disabled={isAdmin || defaultEdit || !editable}\n checked={(isAdmin || defaultEdit || getIn(values, `collectionPermissions.${col.path}.edit`)) ?? false}\n onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.edit`, checked)}/>\n </TableCell>\n <TableCell\n align=\"center\">\n <Checkbox\n disabled={isAdmin || defaultDelete || !editable}\n checked={(isAdmin || defaultDelete || getIn(values, `collectionPermissions.${col.path}.delete`)) ?? false}\n onCheckedChange={(checked) => setFieldValue(`collectionPermissions.${col.path}.delete`, checked)}/>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </Paper>\n <FieldCaption>\n You can customise the permissions\n that the users related to this\n role can perform in the entities\n of each collection\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12 md:col-span-4\"}>\n <Select\n error={touched.config && Boolean(errors.config)}\n id=\"createCollections\"\n name=\"createCollections\"\n label=\"Create collections\"\n position={\"item-aligned\"}\n disabled={isAdmin || !editable}\n onChange={(event) => setFieldValue(\"config.createCollections\", event.target.value === \"true\")}\n value={isAdmin || values.config?.createCollections ? \"true\" : \"false\"}\n renderValue={(value: any) => value === \"true\" ? \"Yes\" : \"No\"}\n >\n <SelectItem\n value={\"true\"}> Yes </SelectItem>\n <SelectItem\n value={\"false\"}> No </SelectItem>\n </Select>\n\n <FieldCaption>\n {touched.config && Boolean(errors.config) ? errors.config : \"Can the user create collections\"}\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12 md:col-span-4\"}>\n <Select\n error={touched.config && Boolean(errors.config)}\n id=\"editCollections\"\n name=\"editCollections\"\n label=\"Edit collections\"\n disabled={isAdmin || !editable}\n position={\"item-aligned\"}\n onChange={(event) => setFieldValue(\"config.editCollections\", event.target.value === \"own\" ? \"own\" : event.target.value === \"true\")}\n value={isAdmin ? \"true\" : (values.config?.editCollections === \"own\" ? \"own\" : (values.config?.editCollections ? \"true\" : \"false\"))}\n renderValue={(value: any) => value === \"own\" ? \"Own\" : (value === \"true\" ? \"Yes\" : \"No\")}\n >\n <SelectItem\n value={\"true\"}> Yes </SelectItem>\n <SelectItem\n value={\"false\"}> No </SelectItem>\n <SelectItem\n value={\"own\"}> Only\n his/her own </SelectItem>\n </Select>\n\n <FieldCaption>\n {touched.config && Boolean(errors.config) ? errors.config : \"Can the user edit collections\"}\n </FieldCaption>\n </div>\n\n <div className={\"col-span-12 md:col-span-4\"}>\n <Select\n error={touched.config && Boolean(errors.config)}\n id=\"deleteCollections\"\n name=\"deleteCollections\"\n label=\"Delete collections\"\n disabled={isAdmin || !editable}\n position={\"item-aligned\"}\n onChange={(event) => setFieldValue(\"config.deleteCollections\", event.target.value === \"own\" ? \"own\" : event.target.value === \"true\")}\n value={isAdmin ? \"true\" : (values.config?.deleteCollections === \"own\" ? \"own\" : (values.config?.deleteCollections ? \"true\" : \"false\"))}\n renderValue={(value: any) => value === \"own\" ? \"Own\" : (value === \"true\" ? \"Yes\" : \"No\")}\n >\n <SelectItem\n value={\"true\"}> Yes </SelectItem>\n <SelectItem\n value={\"false\"}> No </SelectItem>\n <SelectItem\n value={\"own\"}> Only\n his/her own </SelectItem>\n </Select>\n\n <FieldCaption>\n {touched.config && Boolean(errors.config) ? errors.config : \"Can the user delete collections\"}\n </FieldCaption>\n\n </div>\n\n </div>\n </DialogContent>\n\n <DialogActions position={\"sticky\"}>\n {savingError && <Typography className={\"text-red-500\"}>\n There was an error saving this role\n </Typography>}\n <Button variant={\"text\"}\n onClick={() => {\n handleClose();\n }}>\n Cancel\n </Button>\n <LoadingButton\n variant=\"filled\"\n color=\"primary\"\n type=\"submit\"\n disabled={!dirty}\n loading={isSubmitting}\n startIcon={<DoneIcon/>}\n >\n {isNewRole ? \"Create role\" : \"Update\"}\n </LoadingButton>\n </DialogActions>\n </form>\n\n </Formex>\n </Dialog>\n );\n}\n","import { Role } from \"../../types\";\n\nexport const DEFAULT_ROLES: Role[] = [\n {\n id: \"admin\",\n name: \"Admin\",\n isAdmin: true\n },\n {\n id: \"editor\",\n name: \"Editor\",\n isAdmin: false,\n defaultPermissions: {\n read: true,\n create: true,\n edit: true,\n delete: true\n },\n config: {\n createCollections: true,\n editCollections: \"own\",\n deleteCollections: \"own\"\n }\n },\n {\n id: \"viewer\",\n name: \"Viewer\",\n isAdmin: false,\n defaultPermissions: {\n read: true,\n create: false,\n edit: false,\n delete: false\n }\n }\n];\n","import { useState } from \"react\";\nimport {\n Button,\n CenteredView,\n Checkbox,\n DeleteIcon,\n IconButton,\n Table,\n TableBody,\n TableCell,\n TableHeader,\n TableRow,\n Tooltip,\n Typography\n} from \"@firecms/ui\";\nimport { DeleteConfirmationDialog } from \"@firecms/core\";\nimport { useUserManagement } from \"../../hooks\";\nimport { Role } from \"../../types\";\nimport { RoleChip } from \"./RoleChip\";\nimport { DEFAULT_ROLES } from \"./default_roles\";\n\nexport function RolesTable({\n onRoleClicked,\n editable\n }: {\n onRoleClicked: (role: Role) => void;\n editable: boolean;\n}) {\n\n const {\n roles,\n saveRole,\n deleteRole,\n allowDefaultRolesCreation\n } = useUserManagement();\n\n const [roleToBeDeleted, setRoleToBeDeleted] = useState<Role | undefined>(undefined);\n const [deleteInProgress, setDeleteInProgress] = useState<boolean>(false);\n\n return <div\n className=\"w-full overflow-auto\">\n <Table>\n <TableHeader>\n <TableCell header={true} className=\"w-16\"></TableCell>\n <TableCell header={true}>Role</TableCell>\n <TableCell header={true} className={\"items-center\"}>Is Admin</TableCell>\n <TableCell header={true}>Default permissions</TableCell>\n </TableHeader>\n\n <TableBody>\n {roles && roles.map((role) => {\n const canCreateAll = role.isAdmin || role.defaultPermissions?.create;\n const canReadAll = role.isAdmin || role.defaultPermissions?.read;\n const canUpdateAll = role.isAdmin || role.defaultPermissions?.edit;\n const canDeleteAll = role.isAdmin || role.defaultPermissions?.delete;\n return (\n <TableRow\n key={role.name}\n onClick={() => {\n onRoleClicked(role);\n }}\n >\n <TableCell style={{ width: \"64px\" }}>\n {!role.isAdmin &&\n <Tooltip title={\"Delete this role\"}>\n <IconButton\n size={\"small\"}\n disabled={!editable}\n onClick={(event) => {\n event.stopPropagation();\n return setRoleToBeDeleted(role);\n }}>\n <DeleteIcon/>\n </IconButton>\n </Tooltip>}\n </TableCell>\n <TableCell>\n <RoleChip role={role}/>\n </TableCell>\n <TableCell className={\"items-center\"}>\n <Checkbox checked={role.isAdmin ?? false}/>\n </TableCell>\n <TableCell>\n <ul>\n {canCreateAll && <li>Create</li>}\n {canReadAll && <li>Read</li>}\n {canUpdateAll && <li>Update</li>}\n {canDeleteAll && <li>Delete</li>}\n </ul>\n </TableCell>\n </TableRow>\n );\n })}\n\n {(!roles || roles.length === 0) && <TableRow>\n <TableCell colspan={4}>\n <CenteredView className={\"flex flex-col gap-4 my-8 items-center\"}>\n <Typography variant={\"label\"}>\n You don&apos;t have any roles yet.\n </Typography>\n {allowDefaultRolesCreation && <Button variant={\"outlined\"}\n onClick={() => {\n DEFAULT_ROLES.forEach((role) => {\n saveRole(role);\n });\n }}>\n Create default roles\n </Button>}\n </CenteredView>\n </TableCell>\n </TableRow>}\n\n </TableBody>\n\n </Table>\n\n <DeleteConfirmationDialog\n open={Boolean(roleToBeDeleted)}\n loading={deleteInProgress}\n onAccept={() => {\n if (roleToBeDeleted) {\n setDeleteInProgress(true);\n deleteRole(roleToBeDeleted)\n .then(() => {\n setRoleToBeDeleted(undefined);\n })\n .finally(() => {\n setDeleteInProgress(false);\n })\n }\n }}\n onCancel={() => {\n setRoleToBeDeleted(undefined);\n }}\n title={<>Delete?</>}\n body={<>Are you sure you want to delete this role?</>}/>\n\n </div>;\n}\n","import React, { useCallback, useState } from \"react\";\n\nimport { useNavigationController } from \"@firecms/core\";\nimport { AddIcon, Button, Container, Tooltip, Typography } from \"@firecms/ui\";\nimport { RolesTable } from \"./RolesTable\";\nimport { RolesDetailsForm } from \"./RolesDetailsForm\";\nimport { useUserManagement } from \"../../hooks\";\nimport { Role } from \"../../types\";\n\nexport const RolesView = React.memo(\n function RolesView({ children }: { children?: React.ReactNode }) {\n\n const { collections } = useNavigationController();\n const [dialogOpen, setDialogOpen] = useState(false);\n const [selectedRole, setSelectedRole] = useState<Role | undefined>();\n\n const { canEditRoles } = useUserManagement();\n\n const onRoleClicked = useCallback((user: Role) => {\n setDialogOpen(true);\n setSelectedRole(user);\n }, []);\n\n const handleClose = () => {\n setSelectedRole(undefined);\n setDialogOpen(false);\n };\n\n return (\n <Container className=\"w-full flex flex-col py-4 gap-4\" maxWidth={\"6xl\"}>\n\n {children}\n\n <div className=\"flex items-center mt-12\">\n <Typography gutterBottom variant=\"h4\"\n className=\"flex-grow\"\n component=\"h4\">\n Roles\n </Typography>\n <Tooltip title={!canEditRoles ? \"Update plans to customise roles\" : undefined}>\n <Button\n size={\"large\"}\n disabled={!canEditRoles}\n startIcon={<AddIcon/>}\n onClick={() => setDialogOpen(true)}>\n Add role\n </Button>\n </Tooltip>\n </div>\n\n <RolesTable onRoleClicked={onRoleClicked} editable={Boolean(canEditRoles)}/>\n\n <RolesDetailsForm\n key={selectedRole?.id ?? \"new\"}\n open={dialogOpen}\n role={selectedRole}\n editable={canEditRoles}\n collections={collections}\n handleClose={handleClose}/>\n\n </Container>\n )\n });\n","import React, { useCallback } from \"react\";\nimport * as Yup from \"yup\";\nimport {\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DoneIcon,\n LoadingButton,\n MultiSelect,\n MultiSelectItem,\n TextField,\n Typography,\n} from \"@firecms/ui\";\nimport { FieldCaption, useSnackbarController } from \"@firecms/core\";\nimport { Formex, useCreateFormex } from \"@firecms/formex\";\n\nimport { Role, UserWithRoles } from \"../../types\";\nimport { areRolesEqual } from \"../../utils\";\nimport { useUserManagement } from \"../../hooks\";\nimport { RoleChip } from \"../roles\";\n\nexport const UserYupSchema = Yup.object().shape({\n displayName: Yup.string().required(\"Required\"),\n email: Yup.string().email().required(\"Required\"),\n roles: Yup.array().min(1)\n});\n\nfunction canUserBeEdited(loggedUser: UserWithRoles, user: UserWithRoles, users: UserWithRoles[], roles: Role[], prevUser?: UserWithRoles) {\n const admins = users.filter(u => u.roles.map(r => r.id).includes(\"admin\"));\n const loggedUserIsAdmin = loggedUser.roles.map(r => r.id).includes(\"admin\");\n const didRolesChange = !prevUser || !areRolesEqual(prevUser.roles, user.roles);\n\n if (didRolesChange && !loggedUserIsAdmin) {\n throw new Error(\"Only admins can change roles\");\n }\n\n // was the admin role removed\n const adminRoleRemoved = prevUser && prevUser.roles.map(r => r.id).includes(\"admin\") && !user.roles.map(r => r.id).includes(\"admin\");\n\n // avoid removing the last admin\n if (adminRoleRemoved && admins.length === 1) {\n throw new Error(\"There must be at least one admin\");\n }\n return true;\n}\n\nexport function UserDetailsForm({\n open,\n user: userProp,\n handleClose\n }: {\n open: boolean,\n user?: UserWithRoles,\n handleClose: () => void\n}) {\n\n const snackbarController = useSnackbarController();\n const {\n loggedInUser,\n saveUser,\n users,\n roles,\n } = useUserManagement();\n const isNewUser = !userProp;\n\n const onUserUpdated = useCallback((savedUser: UserWithRoles): Promise<UserWithRoles> => {\n if (!loggedInUser) {\n throw new Error(\"Logged user not found\");\n }\n try {\n canUserBeEdited(loggedInUser, savedUser, users, roles, userProp);\n return saveUser(savedUser);\n } catch (e: any) {\n return Promise.reject(e);\n }\n }, [roles, saveUser, userProp, users, loggedInUser]);\n\n const formex = useCreateFormex({\n initialValues: userProp ?? {\n displayName: \"\",\n email: \"\",\n roles: roles.filter(r => r.id === \"editor\")\n } as UserWithRoles,\n validation: (values) => {\n return UserYupSchema.validate(values, { abortEarly: false })\n .then(() => {\n return {};\n }).catch((e) => {\n return e.inner.reduce((acc: any, error: any) => {\n acc[error.path] = error.message;\n return acc;\n }, {});\n });\n },\n onSubmit: (user: UserWithRoles, formexController) => {\n\n return onUserUpdated(user)\n .then(() => {\n handleClose();\n formexController.resetForm({\n values: user\n });\n }).catch((e) => {\n snackbarController.open({\n type: \"error\",\n message: e.message\n });\n });\n }\n });\n\n const {\n isSubmitting,\n touched,\n handleChange,\n values,\n errors,\n setFieldValue,\n dirty,\n handleSubmit,\n submitCount\n } = formex;\n\n return (\n <Dialog\n open={open}\n onOpenChange={(open) => !open ? handleClose() : undefined}\n maxWidth={\"4xl\"}\n >\n <Formex value={formex}>\n <form\n onSubmit={handleSubmit}\n autoComplete={\"off\"}\n noValidate\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n position: \"relative\",\n height: \"100%\"\n }}>\n <DialogContent className=\"h-full flex-grow\">\n <div\n className=\"flex flex-row pt-4 pb-4\">\n <Typography variant={\"h4\"}\n className=\"flex-grow\">\n User\n </Typography>\n </div>\n\n <div className={\"grid grid-cols-12 gap-8\"}>\n\n <div className={\"col-span-12\"}>\n <TextField\n name=\"displayName\"\n required\n error={submitCount > 0 && Boolean(errors.displayName)}\n value={values.displayName ?? \"\"}\n onChange={handleChange}\n aria-describedby=\"name-helper-text\"\n label=\"Name\"\n />\n <FieldCaption>\n {submitCount > 0 && Boolean(errors.displayName) ? errors.displayName : \"Name of this user\"}\n </FieldCaption>\n </div>\n <div className={\"col-span-12\"}>\n <TextField\n required\n error={submitCount > 0 && Boolean(errors.email)}\n name=\"email\"\n value={values.email ?? \"\"}\n onChange={handleChange}\n aria-describedby=\"email-helper-text\"\n label=\"Email\"\n />\n <FieldCaption>\n {submitCount > 0 && Boolean(errors.email) ? errors.email : \"Email of this user\"}\n </FieldCaption>\n </div>\n <div className={\"col-span-12\"}>\n <MultiSelect\n label=\"Roles\"\n value={values.roles.map(r => r.id) ?? []}\n onMultiValueChange={(value: string[]) => setFieldValue(\"roles\", value.map(id => roles.find(r => r.id === id) as Role))}\n renderValue={(value: string) => {\n const userRole = roles\n .find((role) => role.id === value);\n if (!userRole) return null;\n return <div className=\"flex flex-wrap space-x-2 space-y-2\">\n <RoleChip key={userRole?.id} role={userRole}/>\n </div>;\n }}>\n {roles.map(userRole => <MultiSelectItem key={userRole.id}\n value={userRole.id}>\n <RoleChip key={userRole?.id} role={userRole}/>\n </MultiSelectItem>)}\n </MultiSelect>\n </div>\n\n </div>\n\n </DialogContent>\n\n <DialogActions>\n\n <Button variant={\"text\"}\n onClick={() => {\n handleClose();\n }}>\n Cancel\n </Button>\n\n <LoadingButton\n variant=\"filled\"\n color=\"primary\"\n type=\"submit\"\n disabled={!dirty}\n loading={isSubmitting}\n startIcon={<DoneIcon/>}\n >\n {isNewUser ? \"Create user\" : \"Update\"}\n </LoadingButton>\n </DialogActions>\n </form>\n </Formex>\n\n </Dialog>\n );\n}\n","import { useState } from \"react\";\n\nimport { format } from \"date-fns\";\nimport * as locales from \"date-fns/locale\";\n\nimport {\n defaultDateFormat,\n DeleteConfirmationDialog,\n useAuthController,\n useCustomizationController,\n useSnackbarController\n} from \"@firecms/core\";\nimport {\n Button,\n CenteredView,\n DeleteIcon,\n IconButton,\n Table,\n TableBody,\n TableCell,\n TableHeader,\n TableRow,\n Tooltip,\n Typography,\n} from \"@firecms/ui\";\nimport { Role, UserWithRoles } from \"../../types\";\nimport { useUserManagement } from \"../../hooks\";\nimport { RoleChip } from \"../roles\";\n\nexport function UsersTable({ onUserClicked }: {\n onUserClicked: (user: UserWithRoles) => void;\n}) {\n\n const {\n users,\n saveUser,\n deleteUser\n } = useUserManagement();\n\n const authController = useAuthController();\n const snackbarController = useSnackbarController();\n\n const customizationController = useCustomizationController();\n const dateUtilsLocale = customizationController?.locale ? locales[customizationController?.locale as keyof typeof locales] : undefined;\n const dateFormat: string = customizationController?.dateTimeFormat ?? defaultDateFormat;\n\n const [userToBeDeleted, setUserToBeDeleted] = useState<UserWithRoles | undefined>(undefined);\n const [deleteInProgress, setDeleteInProgress] = useState<boolean>(false);\n\n return (\n <div className=\"overflow-auto\">\n\n <Table>\n\n <TableHeader>\n <TableCell className=\"truncate w-16\"></TableCell>\n <TableCell>ID</TableCell>\n <TableCell>Email</TableCell>\n <TableCell>Name</TableCell>\n <TableCell>Roles</TableCell>\n <TableCell>Created on</TableCell>\n </TableHeader>\n <TableBody>\n {users && users.map((user) => {\n\n const userRoles: Role[] | undefined = user.roles;\n\n const formattedDate = user.created_on ? format(user.created_on, dateFormat, { locale: dateUtilsLocale }) : \"\";\n\n return (\n <TableRow\n key={\"row_\" + user.uid}\n onClick={() => {\n onUserClicked(user);\n }}\n >\n <TableCell className={\"w-10\"}>\n <Tooltip title={\"Delete this user\"}>\n <IconButton\n size={\"small\"}\n onClick={(event) => {\n event.stopPropagation();\n return setUserToBeDeleted(user);\n }}>\n <DeleteIcon/>\n </IconButton>\n </Tooltip>\n </TableCell>\n <TableCell>{user.uid}</TableCell>\n <TableCell>{user.email}</TableCell>\n <TableCell className={\"font-medium align-left\"}>{user.displayName}</TableCell>\n <TableCell className=\"align-left\">\n {userRoles\n ? <div className=\"flex flex-wrap gap-2\">\n {userRoles.map(userRole =>\n <RoleChip key={userRole?.id} role={userRole}/>\n )}\n </div>\n : null}\n </TableCell>\n <TableCell>{formattedDate}</TableCell>\n </TableRow>\n );\n })}\n\n {(!users || users.length === 0) && <TableRow>\n <TableCell colspan={6}>\n <CenteredView className={\"flex flex-col gap-4 my-8 items-center\"}>\n <Typography variant={\"label\"}>\n There are no users yet\n </Typography>\n <Button variant={\"outlined\"}\n onClick={() => {\n if (!authController.user?.uid) {\n throw Error(\"UsersTable, authController misconfiguration\");\n }\n saveUser({\n uid: authController.user?.uid,\n email: authController.user?.email,\n displayName: authController.user?.displayName,\n photoURL: authController.user?.photoURL,\n providerId: authController.user?.providerId,\n isAnonymous: authController.user?.isAnonymous,\n roles: [{ id: \"admin\", name: \"Admin\" }],\n created_on: new Date()\n })\n .then(() => {\n snackbarController.open({\n type: \"success\",\n message: \"User added successfully\"\n })\n })\n .catch((error) => {\n snackbarController.open({\n type: \"error\",\n message: \"Error adding user: \" + error.message,\n })\n });\n }}>\n\n Add the logged user as an admin\n </Button>\n </CenteredView>\n </TableCell>\n </TableRow>}\n\n </TableBody>\n </Table>\n\n <DeleteConfirmationDialog\n open={Boolean(userToBeDeleted)}\n loading={deleteInProgress}\n onAccept={() => {\n if (userToBeDeleted) {\n setDeleteInProgress(true);\n deleteUser(userToBeDeleted)\n .then(() => {\n setUserToBeDeleted(undefined);\n })\n .catch((error) => {\n snackbarController.open({\n type: \"error\",\n message: \"Error deleting user: \" + error.message,\n })\n })\n .finally(() => {\n setDeleteInProgress(false);\n })\n }\n }}\n onCancel={() => {\n setUserToBeDeleted(undefined);\n }}\n title={<>Delete?</>}\n body={<>Are you sure you want to delete this user?</>}/>\n </div>);\n}\n","import { AddIcon, Button, Container, Typography } from \"@firecms/ui\";\n\nimport { UsersTable } from \"./UsersTable\";\nimport { UserDetailsForm } from \"./UserDetailsForm\";\nimport React, { useCallback, useState } from \"react\";\nimport { UserWithRoles } from \"../../types\";\nimport { useUserManagement } from \"../../hooks/useUserManagement\";\n\nexport const UsersView = function UsersView({ children }: { children?: React.ReactNode }) {\n\n const [dialogOpen, setDialogOpen] = useState<boolean>();\n const [selectedUser, setSelectedUser] = useState<UserWithRoles | undefined>();\n\n const { users, usersLimit } = useUserManagement();\n\n const reachedUsersLimit = usersLimit !== undefined && (users && users.length >= usersLimit);\n\n const onUserClicked = useCallback((user: UserWithRoles) => {\n setSelectedUser(user);\n setDialogOpen(true);\n }, []);\n\n const handleClose = useCallback(() => {\n setDialogOpen(false);\n setSelectedUser(undefined);\n }, []);\n\n return (\n <Container className=\"w-full flex flex-col py-4 gap-4\" maxWidth={\"6xl\"}>\n\n {children}\n\n <div\n className=\"flex items-center mt-12\">\n <Typography gutterBottom variant=\"h4\"\n className=\"flex-grow\"\n component=\"h4\">\n Users\n </Typography>\n <Button\n size={\"large\"}\n disabled={reachedUsersLimit}\n startIcon={<AddIcon/>}\n onClick={() => setDialogOpen(true)}>\n Add user\n </Button>\n </div>\n\n <UsersTable onUserClicked={onUserClicked}/>\n\n <UserDetailsForm\n key={selectedUser?.uid ?? \"new\"}\n open={dialogOpen ?? false}\n user={selectedUser}\n handleClose={handleClose}/>\n\n </Container>\n )\n};\n","import { AuthController, FireCMSPlugin } from \"@firecms/core\";\nimport { UserManagementProvider } from \"./UserManagementProvider\";\nimport { UserManagement } from \"./types\";\n\nexport function useUserManagementPlugin({ userManagement }: {\n userManagement: UserManagement,\n}): FireCMSPlugin {\n return {\n name: \"User management plugin\",\n loading: userManagement.loading,\n provider: {\n Component: UserManagementProvider,\n props: {\n userManagement\n }\n }\n }\n}\n","import { CMSView } from \"@firecms/core\";\nimport { RolesView, UsersView } from \"./components\";\n\nexport const userManagementAdminViews: CMSView[] = [\n {\n path: \"users\",\n name: \"CMS Users\",\n group: \"Admin\",\n icon: \"face\",\n view: <UsersView/>\n },\n {\n path: \"roles\",\n name: \"Roles\",\n group: \"Admin\",\n icon: \"gpp_good\",\n view: <RolesView/>\n }\n]\n"],"names":["RESERVED_GROUPS","DEFAULT_PERMISSIONS","resolveUserRolePermissions","collection","user","roles","basePermissions","role","resolveCollectionRole","mergePermissions","id","permA","permB","getUserRoles","fireCMSUser","r","areRolesEqual","rolesA","rolesB","rolesAIds","rolesBIds","cacheDelegatedLoginToken","projectId","delegatedToken","data","parseJwt","expiry","getDelegatedLoginTokenFromCache","entry","clearDelegatedLoginTokensCache","i","key","token","base64","jsonPayload","c","darkenColor","hexColor","darkenBy","color","g","b","hexToRgbaWithOpacity","opacity","alpha","useBuildFirestoreUserManagement","firebaseApp","usersPath","rolesPath","usersLimit","canEditRoles","authController","allowDefaultRolesCreation","includeCollectionConfigPermissions","firestoreRef","useRef","rolesLoading","setRolesLoading","React","usersLoading","setUsersLoading","setRoles","usersWithRoleIds","setUsersWithRoleIds","users","u","rolesError","setRolesError","usersError","setUsersError","loading","loggedInUser","useEffect","getFirestore","firestore","onSnapshot","snapshot","newRoles","docsToRoles","e","newUsers","docsToUsers","saveUser","useCallback","roleIds","uid","userData","setDoc","doc","saveRole","roleData","ref","deleteUser","deleteDoc","deleteRole","collectionPermissions","docs","UserManagementContext","UserManagementProvider","children","userManagement","useUserManagement","useContext","RoleChip","colorScheme","getColorSchemeForSeed","jsx","Chip","RoleYupSchema","Yup","RolesDetailsForm","open","editable","handleClose","collections","isNewRole","savingError","setSavingError","useState","onRoleUpdated","formex","useCreateFormex","formexController","values","errors","error","isSubmitting","touched","handleChange","setFieldValue","dirty","setFieldTouched","isAdmin","defaultCreate","defaultRead","defaultEdit","defaultDelete","getIn","toSnakeCase","Dialog","Formex","jsxs","DialogContent","Typography","TextField","FieldCaption","Paper","Table","TableHeader","TableCell","TableBody","TableRow","Tooltip","Checkbox","checked","col","Select","event","value","SelectItem","DialogActions","Button","LoadingButton","DoneIcon","DEFAULT_ROLES","RolesTable","onRoleClicked","roleToBeDeleted","setRoleToBeDeleted","deleteInProgress","setDeleteInProgress","canCreateAll","canReadAll","canUpdateAll","canDeleteAll","IconButton","DeleteIcon","CenteredView","DeleteConfirmationDialog","RolesView","useNavigationController","dialogOpen","setDialogOpen","selectedRole","setSelectedRole","Container","AddIcon","UserYupSchema","canUserBeEdited","loggedUser","prevUser","admins","loggedUserIsAdmin","UserDetailsForm","userProp","snackbarController","useSnackbarController","isNewUser","onUserUpdated","savedUser","acc","handleSubmit","submitCount","MultiSelect","userRole","MultiSelectItem","UsersTable","onUserClicked","useAuthController","customizationController","useCustomizationController","dateUtilsLocale","locales","dateFormat","defaultDateFormat","userToBeDeleted","setUserToBeDeleted","userRoles","formattedDate","format","UsersView","selectedUser","setSelectedUser","reachedUsersLimit","useUserManagementPlugin","userManagementAdminViews"],"mappings":"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"}
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.pre.1",
4
+ "version": "3.0.0-canary.8",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -31,9 +31,10 @@
31
31
  "types": "dist/index.d.ts",
32
32
  "source": "src/index.ts",
33
33
  "dependencies": {
34
- "@firecms/core": "^3.0.0-beta.4.pre.1",
35
- "@firecms/formex": "^3.0.0-beta.4.pre.1",
36
- "@firecms/ui": "^3.0.0-beta.4.pre.1"
34
+ "@firecms/core": "^3.0.0-canary.8",
35
+ "@firecms/formex": "^3.0.0-canary.8",
36
+ "@firecms/ui": "^3.0.0-canary.8",
37
+ "date-fns": "^3.6.0"
37
38
  },
38
39
  "peerDependencies": {
39
40
  "firebase": "^10.7.1",
@@ -72,5 +73,5 @@
72
73
  "react-app/jest"
73
74
  ]
74
75
  },
75
- "gitHead": "a197c6698a64aeb8f9608e6a177a7ecd149920de"
76
+ "gitHead": "6d3cbe74b9d5ac0fbd7ee9110a92d0188a252f02"
76
77
  }
@@ -1,5 +1,4 @@
1
1
  import { useState } from "react";
2
- import { User as FirebaseUser } from "firebase/auth";
3
2
 
4
3
  import { format } from "date-fns";
5
4
  import * as locales from "date-fns/locale";
@@ -25,8 +24,8 @@ import {
25
24
  Typography,
26
25
  } from "@firecms/ui";
27
26
  import { Role, UserWithRoles } from "../../types";
28
- import { useUserManagement } from "../../hooks/useUserManagement";
29
- import { RoleChip } from "../roles/RoleChip";
27
+ import { useUserManagement } from "../../hooks";
28
+ import { RoleChip } from "../roles";
30
29
 
31
30
  export function UsersTable({ onUserClicked }: {
32
31
  onUserClicked: (user: UserWithRoles) => void;
@@ -38,7 +37,7 @@ export function UsersTable({ onUserClicked }: {
38
37
  deleteUser
39
38
  } = useUserManagement();
40
39
 
41
- const authController = useAuthController<FirebaseUser>();
40
+ const authController = useAuthController();
42
41
  const snackbarController = useSnackbarController();
43
42
 
44
43
  const customizationController = useCustomizationController();