From 378b16f07e4d5aa5cc0d724e1070311cea2b24cb Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Sun, 23 Aug 2020 22:54:39 +0200 Subject: [PATCH 1/2] Add user name and avatar on the top bar --- docs/Authentication.md | 56 +++++++++++- docs/img/identity.png | Bin 0 -> 52243 bytes examples/demo/src/authProvider.ts | 7 ++ examples/simple/src/authProvider.js | 28 ++++++ packages/ra-core/src/auth/AuthContext.tsx | 6 ++ packages/ra-core/src/auth/index.ts | 2 + packages/ra-core/src/auth/useGetIdentity.ts | 86 ++++++++++++++++++ packages/ra-core/src/types.ts | 9 +- .../ra-ui-materialui/src/layout/UserMenu.js | 57 +++++++++--- 9 files changed, 233 insertions(+), 18 deletions(-) create mode 100644 docs/img/identity.png create mode 100644 packages/ra-core/src/auth/useGetIdentity.ts diff --git a/docs/Authentication.md b/docs/Authentication.md index 22d4de01152..aa0d33b5a4c 100644 --- a/docs/Authentication.md +++ b/docs/Authentication.md @@ -5,9 +5,9 @@ title: "Authentication" # Authentication -![Logout button](./img/login.gif) +![Login](./img/login.gif) -React-admin lets you secure your admin app with the authentication strategy of your choice. Since there are many possible strategies (Basic Auth, JWT, OAuth, etc.), react-admin simply provides hooks to execute your own authentication code. +React-admin lets you secure your admin app with the authentication strategy of your choice. Since there are many possible strategies (Basic Auth, JWT, OAuth, etc.), react-admin delegates authentication logic to your `authProvider`, and provides hooks to execute your authentication code. ## The `authProvider` @@ -33,6 +33,7 @@ const authProvider = { checkAuth: params => Promise.resolve(), checkError: error => Promise.resolve(), getPermissions: params => Promise.resolve(), + getIdentity: () => Promise.resolve(), }; ``` @@ -66,8 +67,8 @@ const authProvider = { } return response.json(); }) - .then(({ token }) => { - localStorage.setItem('token', token); + .then(auth => { + localStorage.setItem('auth', JSON.stringify(auth)); }); }, // ... @@ -94,7 +95,7 @@ const httpClient = (url, options = {}) => { if (!options.headers) { options.headers = new Headers({ Accept: 'application/json' }); } - const token = localStorage.getItem('token'); + const { token } = JSON.parse(localStorage.getItem('auth')); options.headers.set('Authorization', `Bearer ${token}`); return fetchUtils.fetchJson(url, options); }; @@ -111,6 +112,47 @@ Now the admin is secured: The user can be authenticated and use their credential If you have a custom REST client, don't forget to add credentials yourself. +## User Identity + +React-admin displays the current user name and avatar on the top right side of the screen. To enable this feature, implement the `getIdentity` method in the `authProvider`: + +```js +// in src/authProvider.js +const authProvider = { + login: ({ username, password }) => { /* ... */ }, + getIdentity: () => { + const { id, fullName, avatar } = JSON.parse(localStorage.getItem('auth')); + return { id, fullName, avatar }; + } + // ... +}; + +export default authProvider; +``` + +React-admin uses the `fullName` and the `avatar` (an image source, or a data-uri) in the App Bar: + +![User identity](./img/identity.png) + +**Tip**: You can use the `id` field to identify the current user in your code, by calling the `useGetIdentity` hook: + +```jsx +import { useGetIdentity, useGetOne } from 'react-admin'; + +const PostDetail = ({ id }) => { + const { data: post, loading: postLoading } = useGetOne('posts', id); + const { identity, loading: identityLoading } = useGetIdentity(); + if (postLoading || identityLoading) return <>Loading...; + if (!post.lockedBy || post.lockedBy === identity.id) { + // post isn't locked, or is locked by me + return + } else { + // post is locked by someone else and cannot be edited + return + } +} +``` + ## Logout Configuration As soon as you provide an `authProvider` prop to ``, react-admin displays a logout button in the top bar (or in the menu on mobile). When the user clicks on the logout button, this calls the `authProvider.logout()` method, and removes potentially sensitive data from the Redux store. Then the user gets redirected to the login page. @@ -121,6 +163,7 @@ So it's the responsibility of the `authProvider` to clean up the current authent // in src/authProvider.js export default { login: ({ username, password }) => { /* ... */ }, + getIdentity: () => { /* ... */ }, logout: () => { localStorage.removeItem('token'); return Promise.resolve(); @@ -147,6 +190,7 @@ For instance, to redirect the user to the login page for both 401 and 403 codes: // in src/authProvider.js export default { login: ({ username, password }) => { /* ... */ }, + getIdentity: () => { /* ... */ }, logout: () => { /* ... */ }, checkError: (error) => { const status = error.status; @@ -174,6 +218,7 @@ For instance, to check for the existence of the token in local storage: // in src/authProvider.js export default { login: ({ username, password }) => { /* ... */ }, + getIdentity: () => { /* ... */ }, logout: () => { /* ... */ }, checkError: (error) => { /* ... */ }, checkAuth: () => localStorage.getItem('token') @@ -189,6 +234,7 @@ If the promise is rejected, react-admin redirects by default to the `/login` pag // in src/authProvider.js export default { login: ({ username, password }) => { /* ... */ }, + getIdentity: () => { /* ... */ }, logout: () => { /* ... */ }, checkError: (error) => { /* ... */ }, checkAuth: () => localStorage.getItem('token') diff --git a/docs/img/identity.png b/docs/img/identity.png new file mode 100644 index 0000000000000000000000000000000000000000..f2502ff2480d3c3fd001dbfaac5c0d00363ace1b GIT binary patch literal 52243 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 dc5Vb+q3^}uaG$91 localStorage.getItem('username') ? Promise.resolve() : Promise.reject(), getPermissions: () => Promise.reject('Unknown method'), + getIdentity: () => + Promise.resolve({ + id: 'user', + fullName: 'Jane Doe', + avatar: + 'data:image/jpeg;base64,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', + }), }; export default authProvider; diff --git a/examples/simple/src/authProvider.js b/examples/simple/src/authProvider.js index af2f0a993c8..50ca0660941 100644 --- a/examples/simple/src/authProvider.js +++ b/examples/simple/src/authProvider.js @@ -4,16 +4,34 @@ export default { if (username === 'login' && password === 'password') { localStorage.removeItem('not_authenticated'); localStorage.removeItem('role'); + localStorage.setItem('login', 'login'); + localStorage.setItem('user', 'John Doe'); + localStorage.setItem( + 'avatar', + 'data:image/jpeg;base64,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' + ); return Promise.resolve(); } if (username === 'user' && password === 'password') { localStorage.setItem('role', 'user'); localStorage.removeItem('not_authenticated'); + localStorage.setItem('login', 'user'); + localStorage.setItem('user', 'Jane Doe'); + localStorage.setItem( + 'avatar', + 'data:image/jpeg;base64,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' + ); return Promise.resolve(); } if (username === 'admin' && password === 'password') { localStorage.setItem('role', 'admin'); localStorage.removeItem('not_authenticated'); + localStorage.setItem('login', 'admin'); + localStorage.setItem('user', 'Dennis Nedry'); + localStorage.setItem( + 'avatar', + 'data:image/jpeg;base64,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' + ); return Promise.resolve(); } localStorage.setItem('not_authenticated', true); @@ -22,6 +40,9 @@ export default { logout: () => { localStorage.setItem('not_authenticated', true); localStorage.removeItem('role'); + localStorage.removeItem('login'); + localStorage.removeItem('user'); + localStorage.removeItem('avatar'); return Promise.resolve(); }, checkError: ({ status }) => { @@ -38,4 +59,11 @@ export default { const role = localStorage.getItem('role'); return Promise.resolve(role); }, + getIdentity: () => { + return { + id: localStorage.getItem('login'), + fullName: localStorage.getItem('user'), + avatar: localStorage.getItem('avatar'), + }; + }, }; diff --git a/packages/ra-core/src/auth/AuthContext.tsx b/packages/ra-core/src/auth/AuthContext.tsx index e06e7c9ed63..b3e013eed06 100644 --- a/packages/ra-core/src/auth/AuthContext.tsx +++ b/packages/ra-core/src/auth/AuthContext.tsx @@ -2,12 +2,18 @@ import { createContext } from 'react'; import { AuthProvider } from '../types'; +const defaultIdentity = { + id: null, + fullName: null, +}; + const defaultProvider: AuthProvider = { login: () => Promise.resolve(), logout: () => Promise.resolve(), checkAuth: () => Promise.resolve(), checkError: () => Promise.resolve(), getPermissions: () => Promise.resolve(), + getIdentity: () => Promise.resolve(defaultIdentity), }; const AuthContext = createContext(defaultProvider); diff --git a/packages/ra-core/src/auth/index.ts b/packages/ra-core/src/auth/index.ts index e3d49e33714..d4c414f38d2 100644 --- a/packages/ra-core/src/auth/index.ts +++ b/packages/ra-core/src/auth/index.ts @@ -8,6 +8,7 @@ import WithPermissions from './WithPermissions'; import useLogin from './useLogin'; import useLogout from './useLogout'; import useCheckAuth from './useCheckAuth'; +import useGetIdentity from './useGetIdentity'; import useGetPermissions from './useGetPermissions'; import useLogoutIfAccessDenied from './useLogoutIfAccessDenied'; import convertLegacyAuthProvider from './convertLegacyAuthProvider'; @@ -21,6 +22,7 @@ export { useLogin, useLogout, useCheckAuth, + useGetIdentity, useGetPermissions, // hooks with state management usePermissions, diff --git a/packages/ra-core/src/auth/useGetIdentity.ts b/packages/ra-core/src/auth/useGetIdentity.ts new file mode 100644 index 00000000000..36fec18a828 --- /dev/null +++ b/packages/ra-core/src/auth/useGetIdentity.ts @@ -0,0 +1,86 @@ +import { useEffect } from 'react'; +import useAuthProvider from './useAuthProvider'; +import { UserIdentity } from '../types'; +import { useSafeSetState } from '../util/hooks'; + +const defaultIdentity = { + id: null, + fullName: null, +}; + +/** + * Return the current user identity by calling authProvider.getIdentity() on mount + * + * The return value updates according to the call state: + * + * - mount: { loading: true, loaded: false } + * - success: { identity: Identity, loading: false, loaded: true } + * - error: { error: Error, loading: false, loaded: true } + * + * The implementation is left to the authProvider. + * + * @returns The current user identity. Destructure as { identity, error, loading, loaded }. + * + * @example + * + * import { useGetIdentity, useGetOne } from 'react-admin'; + * + * const PostDetail = ({ id }) => { + * const { data: post, loading: postLoading } = useGetOne('posts', id); + * const { identity, loading: identityLoading } = useGetIdentity(); + * if (postLoading || identityLoading) return <>Loading...; + * if (!post.lockedBy || post.lockedBy === identity.id) { + * // post isn't locked, or is locked by me + * return + * } else { + * // post is locked by someone else and cannot be edited + * return + * } + * } + */ +const useGetIdentity = () => { + const [state, setState] = useSafeSetState({ + loading: true, + loaded: false, + }); + const authProvider = useAuthProvider(); + useEffect(() => { + if (typeof authProvider.getIdentity === 'function') { + const callAuthProvider = async () => { + try { + const identity = await authProvider.getIdentity(); + setState({ + loading: false, + loaded: true, + identity, + }); + } catch (error) { + setState({ + loading: false, + loaded: true, + error, + }); + } + }; + callAuthProvider(); + } else { + // fallback for pre-3.9 authProviders, which had no getIdentity method + // FIXME to be removed for the next major + setState({ + loading: false, + loaded: true, + identity: defaultIdentity, + }); + } + }, [authProvider, setState]); + return state; +}; + +interface State { + loading: boolean; + loaded: boolean; + identity?: UserIdentity; + error?: any; +} + +export default useGetIdentity; diff --git a/packages/ra-core/src/types.ts b/packages/ra-core/src/types.ts index 5bbe0fec57e..d546269fdcb 100644 --- a/packages/ra-core/src/types.ts +++ b/packages/ra-core/src/types.ts @@ -53,16 +53,23 @@ export type I18nProvider = { [key: string]: any; }; +export interface UserIdentity { + id: Identifier; + fullName?: string; + avatar?: string; + [key: string]: any; +} + /** * authProvider types */ - export type AuthProvider = { login: (params: any) => Promise; logout: (params: any) => Promise; checkAuth: (params: any) => Promise; checkError: (error: any) => Promise; getPermissions: (params: any) => Promise; + getIdentity?: () => Promise; [key: string]: any; }; diff --git a/packages/ra-ui-materialui/src/layout/UserMenu.js b/packages/ra-ui-materialui/src/layout/UserMenu.js index 536eb7390f0..28164ef0c45 100644 --- a/packages/ra-ui-materialui/src/layout/UserMenu.js +++ b/packages/ra-ui-materialui/src/layout/UserMenu.js @@ -1,15 +1,26 @@ import * as React from 'react'; import { Children, cloneElement, isValidElement, useState } from 'react'; import PropTypes from 'prop-types'; -import { useTranslate } from 'ra-core'; -import Tooltip from '@material-ui/core/Tooltip'; -import IconButton from '@material-ui/core/IconButton'; -import Menu from '@material-ui/core/Menu'; +import { useTranslate, useGetIdentity } from 'ra-core'; +import { Tooltip, IconButton, Menu, Button, Avatar } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; import AccountCircle from '@material-ui/icons/AccountCircle'; +const useStyles = makeStyles(theme => ({ + userButton: { + textTransform: 'none', + }, + avatar: { + width: theme.spacing(4), + height: theme.spacing(4), + }, +})); + const UserMenu = props => { const [anchorEl, setAnchorEl] = useState(null); const translate = useTranslate(); + const { loaded, identity } = useGetIdentity(); + const classes = useStyles(props); const { children, label, icon, logout } = props; if (!logout && !children) return null; @@ -19,18 +30,40 @@ const UserMenu = props => { const handleClose = () => setAnchorEl(null); return ( -
- - + {loaded && identity.fullName ? ( + + ) : ( + + + {icon} + + + )} Date: Sun, 23 Aug 2020 22:58:14 +0200 Subject: [PATCH 2/2] Fix auth name in localStorage --- docs/Authentication.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/Authentication.md b/docs/Authentication.md index aa0d33b5a4c..a52702dddd2 100644 --- a/docs/Authentication.md +++ b/docs/Authentication.md @@ -165,7 +165,7 @@ export default { login: ({ username, password }) => { /* ... */ }, getIdentity: () => { /* ... */ }, logout: () => { - localStorage.removeItem('token'); + localStorage.removeItem('auth'); return Promise.resolve(); }, // ... @@ -195,7 +195,7 @@ export default { checkError: (error) => { const status = error.status; if (status === 401 || status === 403) { - localStorage.removeItem('token'); + localStorage.removeItem('auth'); return Promise.reject(); } return Promise.resolve(); @@ -212,7 +212,7 @@ Redirecting to the login page whenever a REST response uses a 401 status code is Fortunately, each time the user navigates, react-admin calls the `authProvider.checkAuth()` method, so it's the ideal place to validate the credentials. -For instance, to check for the existence of the token in local storage: +For instance, to check for the existence of the authentication data in local storage: ```js // in src/authProvider.js @@ -221,7 +221,7 @@ export default { getIdentity: () => { /* ... */ }, logout: () => { /* ... */ }, checkError: (error) => { /* ... */ }, - checkAuth: () => localStorage.getItem('token') + checkAuth: () => localStorage.getItem('auth') ? Promise.resolve() : Promise.reject(), // ... @@ -237,7 +237,7 @@ export default { getIdentity: () => { /* ... */ }, logout: () => { /* ... */ }, checkError: (error) => { /* ... */ }, - checkAuth: () => localStorage.getItem('token') + checkAuth: () => localStorage.getItem('auth') ? Promise.resolve() : Promise.reject({ redirectTo: '/no-access' }), // ...