Add Optional 2FA Support (#61)

* Add TOTP MFA Support

* Add Passkey MFA Support

It's not impossible I missed some minor cleanup, but most things make sense and there isn't a lot of obvious duplication anymore.

---------

Co-authored-by: Bruno Bernardino <me@brunobernardino.com>
This commit is contained in:
0xGingi
2025-05-29 12:30:28 -04:00
committed by GitHub
parent 2a77915630
commit 455a7201e9
28 changed files with 2361 additions and 40 deletions

View File

@@ -1,6 +1,6 @@
import { Handlers, PageProps } from 'fresh/server.ts';
import { currencyMap, FreshContextState, SupportedCurrencySymbol } from '/lib/types.ts';
import { currencyMap, FreshContextState, SupportedCurrencySymbol, User } from '/lib/types.ts';
import { PASSWORD_SALT } from '/lib/auth.ts';
import { UserModel, VerificationCodeModel } from '/lib/models/user.ts';
import { convertFormDataToObject, generateHash, validateEmail } from '/lib/utils/misc.ts';
@@ -21,7 +21,11 @@ interface Data {
formData: Record<string, any>;
currency?: SupportedCurrencySymbol;
isExpensesAppEnabled: boolean;
isMultiFactorAuthEnabled: boolean;
helpEmail: string;
user: {
extra: Pick<User['extra'], 'multi_factor_auth_methods'>;
};
}
export const handler: Handlers<Data, FreshContextState> = {
@@ -32,12 +36,15 @@ export const handler: Handlers<Data, FreshContextState> = {
const isExpensesAppEnabled = await AppConfig.isAppEnabled('expenses');
const helpEmail = (await AppConfig.getConfig()).visuals.helpEmail;
const isMultiFactorAuthEnabled = await AppConfig.isMultiFactorAuthEnabled();
return await context.render({
formData: {},
currency: context.state.user.extra.expenses_currency,
isExpensesAppEnabled,
helpEmail,
isMultiFactorAuthEnabled,
user: context.state.user,
});
},
async POST(request, context) {
@@ -47,6 +54,7 @@ export const handler: Handlers<Data, FreshContextState> = {
const isExpensesAppEnabled = await AppConfig.isAppEnabled('expenses');
const helpEmail = (await AppConfig.getConfig()).visuals.helpEmail;
const isMultiFactorAuthEnabled = await AppConfig.isMultiFactorAuthEnabled();
let action: Action = 'change-email';
let errorTitle = '';
@@ -190,6 +198,8 @@ export const handler: Handlers<Data, FreshContextState> = {
currency: user.extra.expenses_currency,
isExpensesAppEnabled,
helpEmail,
isMultiFactorAuthEnabled,
user: user,
});
} catch (error) {
console.error(error);
@@ -202,6 +212,8 @@ export const handler: Handlers<Data, FreshContextState> = {
currency: user.extra.expenses_currency,
isExpensesAppEnabled,
helpEmail,
isMultiFactorAuthEnabled,
user: user,
});
}
},
@@ -216,7 +228,9 @@ export default function SettingsPage({ data }: PageProps<Data, FreshContextState
notice={data?.notice}
currency={data?.currency}
isExpensesAppEnabled={data?.isExpensesAppEnabled}
isMultiFactorAuthEnabled={data?.isMultiFactorAuthEnabled}
helpEmail={data?.helpEmail}
user={data?.user}
/>
</main>
);