UNPKG

@vaadin/hilla-react-auth

Version:

Hilla auth utils for React

147 lines 3.68 kB
import { login as _login, logout as _logout, UnauthorizedResponseError } from "@vaadin/hilla-frontend"; import { createContext, useContext, useEffect, useReducer } from "react"; import { jsx as _jsx } from "react/jsx-runtime"; const LOGIN_FETCH = "LOGIN_FETCH"; const LOGIN_SUCCESS = "LOGIN_SUCCESS"; const LOGIN_FAILURE = "LOGIN_FAILURE"; const LOGOUT = "LOGOUT"; function createAuthenticateThunk(dispatch, getAuthenticatedUser) { async function authenticate() { dispatch({ type: LOGIN_FETCH }); const user = await getAuthenticatedUser().catch((error) => { if (error instanceof UnauthorizedResponseError) { return undefined; } throw error; }); if (user) { dispatch({ user, type: LOGIN_SUCCESS }); } else { dispatch({ error: "Not authenticated", type: LOGIN_FAILURE }); } } return authenticate; } function createUnauthenticateThunk(dispatch) { return () => { dispatch({ type: LOGOUT }); }; } const initialState = { initializing: true, loading: false }; function reducer(state, action) { switch (action.type) { case LOGIN_FETCH: return { initializing: false, loading: true }; case LOGIN_SUCCESS: return { initializing: false, loading: false, user: action.user }; case LOGIN_FAILURE: return { initializing: false, loading: false, error: action.error }; case LOGOUT: return { initializing: false, loading: false }; default: return state; } } /** * The hook that can be used to get the authentication state. * It returns the state of the authentication. */ export const AuthContext = createContext({ state: initialState, login() { throw new Error("AuthContext not initialized"); }, logout() { throw new Error("AuthContext not initialized"); }, hasAccess() { throw new Error("AuthContext not initialized"); } }); const getDefaultRoles = (user) => { const userWithRoles = user; return Array.isArray(userWithRoles.roles) ? userWithRoles.roles : []; }; function AuthProvider({ children, getAuthenticatedUser, config }) { const [state, dispatch] = useReducer(reducer, initialState); const authenticate = createAuthenticateThunk(dispatch, getAuthenticatedUser); const unauthenticate = createUnauthenticateThunk(dispatch); async function login(username, password, options) { const result = await _login(username, password, options); if (!result.error) { await authenticate(); } return result; } async function logout(options) { await _logout(options); unauthenticate(); } function hasAccess({ loginRequired, requiresLogin, rolesAllowed }) { const requiresAuth = loginRequired ?? requiresLogin ?? rolesAllowed; if (!requiresAuth) { return true; } if (!state.user) { return false; } if (rolesAllowed) { const userRoles = config?.getRoles ? config.getRoles(state.user) : getDefaultRoles(state.user); return rolesAllowed.some((allowedRole) => userRoles.includes(allowedRole)); } return true; } useEffect(() => { authenticate().catch(() => {}); }, []); const auth = { state, login, logout, hasAccess }; return _jsx(AuthContext.Provider, { value: auth, children }); } /** * The hook that can be used to authenticate the user. * It returns the state of the authentication and the functions * to authenticate and unauthenticate the user. */ function useAuth() { return useContext(AuthContext); } export function configureAuth(getAuthenticatedUser, config) { function PreconfiguredAuthProvider({ children }) { return _jsx(AuthProvider, { getAuthenticatedUser, config, children }); } return { AuthProvider: PreconfiguredAuthProvider, useAuth }; } //# sourceMappingURL=./useAuth.js.map