dha-login
v3.5.1
Published
module that contains login/logout functionality for a React app
Downloads
75
Readme
dha-login
Getting Started
Install
Install from npm:
- npm i dha-login
Build
The package uses the Typescript compiler (TSC) & Vite to build the source code. To build the project run the following command:
- npm run build
Peer Dependencies
These are the peerDependencies for dha-login. Make sure your app has these installed as dependencies if you want to use dha-login.
"peerDependencies": {
"@reduxjs/toolkit": "^1.8.1",
"react": "^17.0.2",
"react-redux": "^7.2.8",
"react-router-dom": "^6.3.0"
}
Usage Overview
This module should be used if you want login functionality in your PWA. This functionality involves prompting a user to make an "account" by designating a 6-digit pin & two security questions. The pin will be used on every subsequent login to identify the user, and correctly answering the security questions can authorize the user to reset their pin for any reason.
There are a few pieces from this module that you will need to configure inside your app:
- accountReducer
- AccountState (type)
- initialAccountState
<LoginDatabaseProvider />
- wrapper containing access to user login info<AuthProvider />
- wrapper inside<LoginDatabaseProvider />
that handles authentication & provides access to AuthContext
Components (Routing)
<RequireAuth />
- wraps any routes you want only accessible by authenticated (logged-in) users, providing the screens necessary for user authentication.
{AuthContext}
- holds authenticated (logged-in) state boolean, a setter for that state (setAuthenticated), the username set by the current user, and the setter for setting the username variable.
If you plan on using this module in the pwa-starter, make sure to edit the starter's 'tailwind.config.cjs' file with the following code (to tell tailwind to scan dha-login for tailwind classes):
module.exports = { content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}', './node_modules/dha-login/**/*.js'], };
Redux State
Relevant exports:
- accountReducer
- AccountState (type)
- InitialAccountState
Details
accountReducer, AccountState (type), and initialAccountState will be utilized to ensure that a user's "account created?" state (either true or false) remains even after they close the app.
The accountReducer reducer controls a a boolean state-value "created" that indicates whether or not the user has made an "account."
accountReducer is created using createSlice() from Redux Toolkit. You will need to add accountReducer to your root reducer. Most likely this will be done by including it in your combineReducers() function, which combines multiple reducers into one rootReducer. for example:
Implementation
example rootReducer.ts:
import { combineReducers } from '@reduxjs/toolkit';
import { accountReducer, AccountState, initialAccountState } from 'dha-login'; // Redux elements
export type State = {
counterState: CounterState,
eulaState: EulaState,
accountState: AccountState, // AccountState type defines accountState prop of State type
};
export const initialState: State = {
counterState: initialCounterState,
eulaState: initialEulaState,
accountState: initialAccountState, // initialAccountState
};
export const rootReducer = combineReducers({
counterState: counterSlice,
eulaState: eulaSlice,
// key name for accountReducer MUST be "accountState"
accountState: accountReducer, // accountReducer is added to rootReducers
});
!! IMPORTANT NOTE !!: In the root reducer, the key for the accountReducer MUST be "accountState." This is because <RequireAuth />
accesses that bit of state by that exact key.
!! You will also need to whitelist accountState
in your redux-persist config (likely in your store.ts file, see example below) !!:
example store.ts:
const persistConfig = {
key: 'root',
storage,
whitelist: ['eulaState', 'endorsementState', 'androidViewState', 'accountState'],
};
const store = configureStore({
reducer: persistReducer(persistConfig, rootReducer),
preloadedState: initialState,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}),
});
The whitelist property controls which parts of your redux state actually get persisted across all sessions. See redux-persist documentation if you want more specific details.
Providers
Relevant Exports
<LoginDatabaseProvider />
<AuthProvider />
Details
<LoginDatabaseProvider />
and <AuthProvider />
should be wrapped somewhere around your <Routes />
.
<LoginDatabaseProvider />
should wrap around <AuthProvider />
in your app (AuthContext
depends on <LoginDatabaseProvider />
for authentication functionality).
<AuthProvider />
gives its children access to{AuthContext}
, and stores base64-encodedauthenticated
state from{AuthContext}
in Session Storage in order to persist authentication-state through page refresh.<LoginDatabaseProvider />
gives<AuthProvider />
necessary database access (user "account" information).
Implementation
Your nesting should look something like this: example App.tsx:
import { AuthProvider, LoginDatabaseProvider } from 'dha-login';
const App = () => {
return (
//<BrowserRouter > or some other Router...
<Provider store={store}>
<PersistGate persistor={persistor}>
<LoginDatabaseProvider>
<DialogProvider>
<AuthProvider>
<Layout>
<AppRoutes />
</Layout>
</AuthProvider>
</DialogProvider>
</LoginDatabaseProvider>
</PersistGate>
</Provider>
//</BrowserRouter>
);
};
Components
Relevant Exports
<RequireAuth />
Details
Use <RequireAuth />
to wrap any <Route />
that you want to only be accessible by a logged-in user.
You will use this component wherever you have set up routing for your app (using React Router).
Make a <Route />
for <RequireAuth />
, and use it to wrap any other <Route />
's you only want accessible by the authenticated user.
Implementation
example AppRoutes.tsx:
import { RequireAuth } from 'dha-login';
import Home from 'somewhere/Home.tsx';
<Routes>
<Route element={<RequireAuth />}>
<Route element={<Home />} path="/" />
<Route element={<Protected2 />} path="/protectedRoute2" />
</Route>
</Routes>;
Context
Relevant Exports
{AuthContext}
- contains:
username
- string given by user during initial account setupauthenticated
- boolean state value where true means the user is currently 'logged in'setAuthenticated(booleanValue)
- function you can use to log a user out by settingauthenticated
to falsesetUsername(string)
- function that allows username to be set, shouldn't be necessary but it's there if you need it
- contains:
Details
{AuthContext}
can be used via React.useContext()
to access the authenticated
state, and the setter for that state, setAuthenticated()
when authenticated
state is true, <RequireAuth />
allows its child (protected) routes to be accessed/rendered.
when authenticated
state is false, <RequireAuth />
prompts the user for their pin, or allows them to reset their PIN by answering two security questions set up during account creation.
you can use setAuthenticated(false)
to log the user out. A user will also be logged out automatically an hour after logging-in, and will have to re-log.
Implementation
import { useContext } from 'react';
import { AuthContext } from 'dha-login';
const exampleComponent = () => {
const { authenticated, setAuthenticated, username } = useContext(AuthContext);
// authenticated returns true or false
// setAuthenticated(false) sets authenticated to false, effectively logging a user out
// username is the string the user set as their username upon account creation
// ...
};
Theme
Relevant Exports
{themeProps}
{useUpdateTheme}
Details
You can update the theme of dha-login using {useUpdateTheme}
by passing in a {themeProps}
object.
You call this function in a useEffect wherever you have set up routing for your app (using React Router).
You must use tailwindcss in the {themeProps}
object to modify the theme.
Implementation
example AppRoutes.tsx:
import { useUpdateTheme } from 'dha-login';
import type { themeProps } from 'dha-login';
const updater = useUpdateTheme();
useEffect(() => {
const theme: themeProps = {
modalBackground: 'bg-gradient-to-b from-gradient-light to-gradient-dark',
cardColor: 'bg-white',
textColor: 'text-black',
secondaryTextColor: 'text-secondary-color',
buttonColor: 'bg-secondary-color',
buttonTextColor: 'text-theme-dark-grey',
buttonShadow: 'shadow-card',
dropDownBorder: 'border border-solid border-[#6b7280]',
};
updater(theme);
}, []);
themeProps
Properties you can modify to update the theme.
interface themeProps {
modalBackground?: string;
cardColor?: string;
textColor?: string;
secondaryTextColor?: string;
buttonColor?: string;
buttonTextColor?: string;
buttonShadow?: string;
dropDownBorder?: string;
}
Troubleshooting
Npm Install Issues
- Clearing the package-lock.json and node_modules folder can help ensure that an app or package starts in a clean state.
- rm -rf package-lock.json node_modules
Hook Errors
- Hook errors can be caused when a local package is installed into an application where the package devDependencies conflict with the application dependencies by having multiple instances of the same dependency.
- You must tell the local dha-login to use peerDependencies from the app you are including the dha-login into using npm link (the example below is for using the dha-login in the dha-login).
- Refer to "Link peerDependencies" section above.
- npm link ../dha-login/node_modules/@material-ui/core
- Refer to "Link peerDependencies" section above.
NPM
https://www.npmjs.com/package/dha-login
License
pending