@vaadin/hilla-react-auth
Version:
Hilla auth utils for React
147 lines • 3.68 kB
JavaScript
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