import React from 'react' import { FormField, GenericError, LoginFlow, LoginFlowMethodConfig, RecoveryFlow, RecoveryFlowMethodConfig, RegistrationFlow, RegistrationFlowMethodConfig, SettingsFlow, SettingsFlowMethodConfig, VerificationFlow, VerificationFlowMethodConfig } from '@oryd/kratos-client' import { AxiosError } from 'axios' import { getPosition } from '../translations' import { showMessage } from 'react-native-flash-message' export function camelize(str: string) { return str.replace(/_([a-z])/g, (g) => g[1].toUpperCase()) as keyof T } export function getFieldValue( key: string, fields: Array, fallback: T ): T { const field = fields.find(({ name }) => name == key) if (field) { return (field.value as unknown) as T } return fallback } export const fieldsToKeyMap = (fields: Array) => { const proto: { [key: string]: any } = {} fields.forEach((field) => { proto[field.name] = field.value as any }) return proto } export function handleFlowInitError(err: AxiosError) { return } export function handleFormSubmitError( setConfig: (p: T) => void, initialize: () => void, logout?: () => void ) { return (err: AxiosError) => { if (err.response) { switch (err.response.status) { case 400: if (typeof err.response.data.error === 'object') { console.warn(err.response.data) const ge: GenericError = err.response.data showMessage({ message: `${ge.error?.message}: ${ge.error?.reason}`, type: 'danger' }) return Promise.resolve() } console.warn('Form validation failed:', err.response.data) setConfig(err.response.data) return Promise.resolve() case 404: case 410: // This happens when the flow is, for example, expired or was deleted. // We simply re-initialize the flow if that happens! console.warn('Flow could not be found, reloading page.') initialize() return Promise.resolve() case 403: case 401: if (!logout) { console.error( `Received unexpected 401/403 status code: `, err, err.response.data ) return Promise.resolve() } // This happens when the privileged session is expired but the user tried // to modify a privileged field (e.g. change the password). console.warn( 'The server indicated that this action is not allowed for you. The most likely cause of that is that you modified a privileged field (e.g. your password) but your ORY Kratos Login Session is too old.' ) showMessage({ message: 'Please re-authenticate before making these changes.', type: 'warning' }) logout() return Promise.resolve() } } console.error(err, err.response?.data) return Promise.resolve() } } // This helper returns a flow method config (e.g. for the password flow). // If active is set and not the given flow method key, it wil be omitted. // This prevents the user from e.g. signing up with email but still seeing // other sign up form elements when an input is incorrect. // // It also sorts the form fields so that e.g. the email address is first. export const methodConfig = ( flow: | LoginFlow | RegistrationFlow | RecoveryFlow | SettingsFlow | VerificationFlow, key: string ): | LoginFlowMethodConfig | RegistrationFlowMethodConfig | RecoveryFlowMethodConfig | SettingsFlowMethodConfig | VerificationFlowMethodConfig | undefined => { if (!flow.methods[key]) { // The flow method is apparently not configured -> return empty return } const config = flow.methods[key].config // We want the form fields to be sorted so that the email address is first, the // password second, and so on. config?.fields.sort( (first: FormField, second: FormField) => getPosition(first) - getPosition(second) ) return config }