Skip to content

Commit

Permalink
restructured project config for using in react package
Browse files Browse the repository at this point in the history
  • Loading branch information
Aby-JS committed Feb 3, 2024
1 parent a27ae18 commit ce9dfe2
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 36 deletions.
9 changes: 5 additions & 4 deletions packages/react/src/contexts/FlowHandlerContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import type {
UserState,
VerificationMethods,
} from '@corbado/shared-ui';
import { ScreenNames } from '@corbado/shared-ui';
import type { ProjectConfig } from '@corbado/types';
import { ScreenNames } from '@corbado/shared-ui'
import { createContext } from 'react';

export interface FlowHandlerContextProps {
Expand All @@ -17,7 +16,8 @@ export interface FlowHandlerContextProps {
currentUserState: UserState;
currentVerificationMethod: VerificationMethods | undefined;
initialized: boolean;
projectConfig: ProjectConfig | undefined;
userNameRequired: boolean;
allowUserRegistration: boolean;
navigateBack: () => ScreenNames;
emitEvent: (event?: FlowHandlerEvents, eventOptions?: FlowHandlerEventOptions) => Promise<void> | undefined;
changeFlow: () => void;
Expand All @@ -30,7 +30,8 @@ export const initialContext: FlowHandlerContextProps = {
currentUserState: {},
currentVerificationMethod: undefined,
initialized: false,
projectConfig: undefined,
userNameRequired: true,
allowUserRegistration: true,
navigateBack: () => ScreenNames.Start,
emitEvent: () => Promise.reject(),
changeFlow: () => void 0,
Expand Down
14 changes: 8 additions & 6 deletions packages/react/src/contexts/FlowHandlerProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import type {
VerificationMethods,
} from '@corbado/shared-ui';
import { FlowHandler, FlowHandlerEvents, ScreenNames } from '@corbado/shared-ui';
import type { ProjectConfig } from '@corbado/types';
import i18n from 'i18next';
import type { FC, PropsWithChildren } from 'react';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
Expand All @@ -34,7 +33,8 @@ export const FlowHandlerProvider: FC<PropsWithChildren<Props>> = ({
const [currentUserState, setCurrentUserState] = useState<UserState>({});
const [currentFlow, setCurrentFlow] = useState<FlowNames>();
const [initialized, setInitialized] = useState(false);
const [projectConfig, setProjectConfig] = useState<ProjectConfig | undefined>(undefined);
const [userNameRequired, setUserNameRequired] = useState(true);
const [allowUserRegistration, setAllowUserRegistration] = useState(true);
const currentFlowType = useRef<FlowTypeText>();
const verificationMethod = useRef<VerificationMethods>();
const onFlowChangeCbId = useRef<number>(0);
Expand All @@ -53,7 +53,7 @@ export const FlowHandlerProvider: FC<PropsWithChildren<Props>> = ({
}

const projectConfig = projectConfigResult.val;
const flowHandler = new FlowHandler(projectConfig, onLoggedIn, initialFlowType);
const flowHandler = new FlowHandler(corbadoApp, projectConfig, onLoggedIn, initialFlowType);

onFlowChangeCbId.current = flowHandler.onFlowChange(updates => {
updates.flowName && setCurrentFlow(updates.flowName);
Expand All @@ -72,10 +72,11 @@ export const FlowHandlerProvider: FC<PropsWithChildren<Props>> = ({
setCurrentUserState(value);
});

await flowHandler.init(corbadoApp, i18n);
await flowHandler.init(i18n);

setProjectConfig(projectConfig);
setFlowHandler(flowHandler);
setUserNameRequired(flowHandler.userNameRequired);
setAllowUserRegistration(flowHandler.allowUserRegistration);
setInitialized(true);
})();

Expand Down Expand Up @@ -112,7 +113,8 @@ export const FlowHandlerProvider: FC<PropsWithChildren<Props>> = ({
currentUserState,
currentVerificationMethod: verificationMethod.current,
initialized,
projectConfig,
userNameRequired,
allowUserRegistration,
changeFlow,
navigateBack,
emitEvent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { AuthFormScreen, FormInput } from '../../../../components';
import useFlowHandler from '../../../../hooks/useFlowHandler';

export const Start = () => {
const { emitEvent, currentUserState, projectConfig } = useFlowHandler();
const { emitEvent, currentUserState, allowUserRegistration } = useFlowHandler();
const { t } = useTranslation('translation', { keyPrefix: `authentication.login.start` });
const [loading, setLoading] = useState(false);
const initialized = useRef(false);
Expand All @@ -29,7 +29,7 @@ export const Start = () => {
const headerText = useMemo(() => t('header'), [t]);
const subHeaderText = useMemo(() => t('subheader'), [t]);
const flowChangeButtonText = useMemo(
() => (projectConfig?.allowUserRegistration ? t('button_signup') : undefined),
() => (allowUserRegistration ? t('button_signup') : undefined),
[t],
);
const emailFieldLabel = useMemo(() => t('textField_email'), [t]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { AuthFormScreen, FormInput } from '../../../../components';
import useFlowHandler from '../../../../hooks/useFlowHandler';

export const Start = () => {
const { currentUserState, projectConfig, emitEvent } = useFlowHandler();
const { currentUserState, userNameRequired, emitEvent } = useFlowHandler();
const { t } = useTranslation('translation', { keyPrefix: `authentication.signup.start` });
const [emailError, setEmailError] = useState<RecoverableError | null>(null);
const [userNameError, setUserNameError] = useState<RecoverableError | null>(null);
Expand All @@ -31,7 +31,7 @@ export const Start = () => {
const handleSubmit = useCallback(() => {
setLoading(true);

const fullName = projectConfig?.userFullNameRequired ? fullNameRef.current?.value : emailRef.current?.value;
const fullName = userNameRequired ? fullNameRef.current?.value : emailRef.current?.value;

void emitEvent(FlowHandlerEvents.PrimaryButton, {
userStateUpdate: { email: emailRef.current?.value, fullName },
Expand All @@ -48,7 +48,7 @@ export const Start = () => {
submitButtonText={submitButtonText}
loading={loading}
>
{projectConfig?.userFullNameRequired && (
{userNameRequired && (
<FormInput
name='fullName'
label={nameFieldLabel}
Expand Down
9 changes: 0 additions & 9 deletions packages/react/src/screens/core/SignUp.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
import { NonRecoverableError, useCorbado } from '@corbado/react-sdk';
import { FlowType } from '@corbado/shared-ui';
import type { CorbadoSignUpConfig } from '@corbado/types';
import type { FC } from 'react';
import React from 'react';

import { AuthFlow } from '../../components';
import FlowHandlerProvider from '../../contexts/FlowHandlerProvider';
import useFlowHandler from '../../hooks/useFlowHandler';

const SignUp: FC<CorbadoSignUpConfig> = ({ onSignedUp, navigateToLogin }) => {
const { projectConfig } = useFlowHandler();
const { setGlobalError } = useCorbado();

if (!projectConfig?.allowUserRegistration) {
setGlobalError(NonRecoverableError.userRegistrationNotAllowed());
}

return (
<div className='cb-container'>
<FlowHandlerProvider
Expand Down
38 changes: 27 additions & 11 deletions packages/shared-ui/src/flowHandler/flowHandler.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ProjectConfig, SessionUser } from '@corbado/types';
import type { CorbadoApp } from '@corbado/web-core';
import { type CorbadoApp,NonRecoverableError } from '@corbado/web-core';
import type { i18n } from 'i18next';

import { canUsePasskeys } from '../utils';
Expand All @@ -26,6 +26,7 @@ export class FlowHandler {
#screenHistory: ScreenNames[];
#config: FlowHandlerConfig;
#state: FlowHandlerState | undefined;
#corbadoApp: CorbadoApp;

#onFlowUpdateCallbacks: Array<(updates: FlowHandlerUpdates) => void> = [];
#onUserStateChangeCallbacks: Array<(v: UserState) => void> = [];
Expand All @@ -34,12 +35,23 @@ export class FlowHandler {
* The constructor initializes the FlowHandler with a flow name, a project configuration, and a flow handler configuration.
* It sets the current flow to the specified flow, the current screen to the Start screen, and initializes the screen history as an empty array.
*/
constructor(projectConfig: ProjectConfig, onLoggedIn: () => void, initialFlowType: FlowType = FlowType.SignUp) {
if (!projectConfig.allowUserRegistration) {
initialFlowType = FlowType.Login;
constructor(corbadoApp: CorbadoApp | undefined, projectConfig: ProjectConfig, onLoggedIn: () => void, initialFlowType?: FlowType) {
if (!corbadoApp) {
throw new Error('corbadoApp is undefined. This should not happen.');
}

this.#config = new FlowHandlerConfig(onLoggedIn, projectConfig, initialFlowType);
let flowType = initialFlowType;

if (projectConfig.allowUserRegistration === false) {
if (initialFlowType === FlowType.SignUp) {
corbadoApp.globalErrors.next(NonRecoverableError.userRegistrationNotAllowed())
} else {
flowType = FlowType.Login;
}
}

this.#corbadoApp = corbadoApp;
this.#config = new FlowHandlerConfig(onLoggedIn, projectConfig, flowType);
this.#screenHistory = [];
this.#currentScreen = this.#config.initialScreenName;
}
Expand All @@ -48,11 +60,7 @@ export class FlowHandler {
* Initializes the FlowHandler.
* Call this function after registering all callbacks.
*/
async init(corbadoApp: CorbadoApp | undefined, i18next: i18n) {
if (!corbadoApp) {
throw new Error('corbadoApp is undefined. This should not happen.');
}

async init(i18next: i18n) {
const passkeysSupported = await canUsePasskeys();

this.#state = new FlowHandlerState(
Expand All @@ -63,7 +71,7 @@ export class FlowHandler {
emailError: undefined,
},
passkeysSupported,
corbadoApp,
this.#corbadoApp,
i18next,
);

Expand All @@ -86,6 +94,14 @@ export class FlowHandler {
return this.#config.verificationMethod;
}

get userNameRequired() {
return this.#config.userNameRequired;
}

get allowUserRegistration() {
return this.#config.allowUserRegistration;
}

/**
* Method to add a callback function to be called when the current flow changes.
* @param cb The callback function to be called when the current flow changes.
Expand Down
10 changes: 10 additions & 0 deletions packages/shared-ui/src/flowHandler/flowHandlerConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ export class FlowHandlerConfig {
readonly #onLoggedIn: () => void;
readonly #initialScreenName: ScreenNames;
readonly #flowDetails: FlowDetails;
readonly #projectConfig: ProjectConfig;
#flowType: FlowType;

constructor(onLoggedIn: () => void, projectConfig: ProjectConfig, initialFlowType: FlowType = FlowType.SignUp) {
this.#onLoggedIn = onLoggedIn;
this.#flowType = initialFlowType;
this.#projectConfig = projectConfig;
this.#flowDetails = this.#getFlowDetails(projectConfig);
this.#initialScreenName = this.#getInitialScreenName();
}
Expand Down Expand Up @@ -47,6 +49,14 @@ export class FlowHandlerConfig {
return this.#flowDetails[this.#flowType].options.verificationMethod ?? 'emailOtp';
}

get userNameRequired() {
return this.#projectConfig.userFullNameRequired;
}

get allowUserRegistration() {
return this.#projectConfig.allowUserRegistration;
}

// The update method allows the type of flow to be changed,
// and updates the flow name and options accordingly.
update(flowType: FlowType) {
Expand Down
2 changes: 1 addition & 1 deletion playground/react/.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Flow: PasskeySignupWithEmailOTPFallback
REACT_APP_CORBADO_PROJECT_ID=pro-8793272752372175738
REACT_APP_CORBADO_PROJECT_ID=pro-503401103218055321

# Flow: PasskeySignupWithEmailOTPFallback + Email Link verification method
# REACT_APP_CORBADO_PROJECT_ID=pro-423122463392265807

0 comments on commit ce9dfe2

Please sign in to comment.