Files
inji-wallet/machines/auth.ts
2023-04-17 20:58:46 +05:30

214 lines
5.3 KiB
TypeScript

import { init } from 'mosip-inji-face-sdk';
import { assign, ContextFrom, EventFrom, send, StateFrom } from 'xstate';
import { createModel } from 'xstate/lib/model';
import { downloadModel } from '../shared/commonprops/commonProps';
import { AppServices } from '../shared/GlobalContext';
import { StoreEvents, StoreResponseEvent } from './store';
const model = createModel(
{
serviceRefs: {} as AppServices,
passcode: '',
biometrics: '',
canUseBiometrics: false,
selectLanguage: false,
},
{
events: {
SETUP_PASSCODE: (passcode: string) => ({ passcode }),
SETUP_BIOMETRICS: (biometrics: string) => ({ biometrics }),
LOGOUT: () => ({}),
LOGIN: () => ({}),
STORE_RESPONSE: (response?: unknown) => ({ response }),
SELECT: () => ({}),
NEXT: () => ({}),
},
}
);
export const AuthEvents = model.events;
type SetupBiometricsEvent = EventFrom<typeof model, 'SETUP_BIOMETRICS'>;
export const authMachine = model.createMachine(
{
predictableActionArguments: true,
preserveActionOrder: true,
tsTypes: {} as import('./auth.typegen').Typegen0,
schema: {
context: model.initialContext,
events: {} as EventFrom<typeof model>,
},
id: 'auth',
initial: 'init',
states: {
init: {
entry: ['requestStoredContext'],
on: {
STORE_RESPONSE: [
{
cond: 'hasData',
target: 'checkingAuth',
actions: ['setContext'],
},
{ target: 'savingDefaults' },
],
},
},
savingDefaults: {
entry: ['storeContext'],
on: {
STORE_RESPONSE: 'checkingAuth',
},
},
checkingAuth: {
always: [
{ cond: 'hasLanguageset', target: 'languagesetup' },
{ cond: 'hasPasscodeSet', target: 'unauthorized' },
{ cond: 'hasBiometricSet', target: 'unauthorized' },
{ target: 'settingUp' },
],
},
languagesetup: {
on: {
SELECT: {
target: 'introSlider',
},
},
},
introSlider: {
on: {
NEXT: {
target: 'settingUp',
},
},
},
settingUp: {
on: {
SETUP_PASSCODE: {
target: 'authorized',
actions: ['setPasscode', 'storeContext', 'setLanguage'],
},
SETUP_BIOMETRICS: {
// Note! dont authorized yet we need to setup passcode too as discuss
// target: 'authorized',
actions: ['setBiometrics', 'storeContext', 'setLanguage'],
},
},
},
unauthorized: {
on: {
LOGIN: 'authorized',
},
},
authorized: {
invoke: {
src: 'downloadFaceSdkModel',
onDone: {
actions: ['storeContext'],
},
},
on: {
LOGOUT: 'unauthorized',
SETUP_BIOMETRICS: {
actions: ['setBiometrics', 'storeContext'],
},
},
},
},
},
{
actions: {
requestStoredContext: send(StoreEvents.GET('auth'), {
to: (context) => context.serviceRefs.store,
}),
storeContext: send(
(context) => {
const { serviceRefs, ...data } = context;
return StoreEvents.SET('auth', data);
},
{ to: (context) => context.serviceRefs.store }
),
setContext: model.assign((_, event) => {
const { serviceRefs, ...data } = event.response as ContextFrom<
typeof model
>;
return data;
}),
setPasscode: model.assign({
passcode: (_, event) => event.passcode,
}),
setBiometrics: model.assign({
biometrics: (_, event: SetupBiometricsEvent) => event.biometrics,
}),
setLanguage: assign({
selectLanguage: (context) => !context.selectLanguage,
}),
},
services: {
downloadFaceSdkModel: () => () => {
downloadModel();
},
},
guards: {
hasData: (_, event: StoreResponseEvent) => event.response != null,
hasPasscodeSet: (context) => {
return context.passcode !== '';
},
hasBiometricSet: (context) => {
return context.biometrics !== '' && context.passcode !== '';
},
hasLanguageset: (context) => {
return !context.selectLanguage;
},
},
}
);
export function createAuthMachine(serviceRefs: AppServices) {
return authMachine.withContext({
...authMachine.context,
serviceRefs,
});
}
type State = StateFrom<typeof authMachine>;
export function selectPasscode(state: State) {
return state.context.passcode;
}
export function selectBiometrics(state: State) {
return state.context.biometrics;
}
export function selectCanUseBiometrics(state: State) {
return state.context.canUseBiometrics;
}
export function selectAuthorized(state: State) {
return state.matches('authorized');
}
export function selectUnauthorized(state: State) {
return state.matches('unauthorized');
}
export function selectSettingUp(state: State) {
return state.matches('settingUp');
}
export function selectLanguagesetup(state: State) {
return state.matches('languagesetup');
}
export function selectIntroSlider(state: State) {
return state.matches('introSlider');
}