Implement a more robust Config (#60)

* Implement a more robust Config

This moves the configuration variables from the `.env` file to a new `bewcloud.config.ts` file. Note that DB connection and secrets are still in the `.env` file.

This will allow for more reliable and easier personalized configurations, and was a requirement to start working on adding SSO (#13).

For now, `.env`-based config will still be allowed and respected (overriden by `bewcloud.config.ts`), but in the future I'll probably remove it (some major upgrade).

* Update deploy script to also copy the new config file
This commit is contained in:
Bruno Bernardino
2025-05-25 15:48:53 +01:00
committed by GitHub
parent 69142973d8
commit e337859a22
30 changed files with 443 additions and 198 deletions

View File

@@ -6,7 +6,7 @@ import { UserModel, VerificationCodeModel } from '/lib/models/user.ts';
import { convertFormDataToObject, generateHash, validateEmail } from '/lib/utils/misc.ts';
import { getFormDataField } from '/lib/form-utils.tsx';
import { sendVerifyEmailEmail } from '/lib/providers/brevo.ts';
import { isEmailEnabled } from '/lib/config.ts';
import { AppConfig } from '/lib/config.ts';
import Settings, { Action, actionWords } from '/islands/Settings.tsx';
interface Data {
@@ -20,6 +20,8 @@ interface Data {
};
formData: Record<string, any>;
currency?: SupportedCurrencySymbol;
isExpensesAppEnabled: boolean;
helpEmail: string;
}
export const handler: Handlers<Data, FreshContextState> = {
@@ -28,9 +30,14 @@ export const handler: Handlers<Data, FreshContextState> = {
return new Response('Redirect', { status: 303, headers: { 'Location': `/login` } });
}
const isExpensesAppEnabled = await AppConfig.isAppEnabled('expenses');
const helpEmail = (await AppConfig.getConfig()).visuals.helpEmail;
return await context.render({
formData: {},
currency: context.state.user.extra.expenses_currency,
isExpensesAppEnabled,
helpEmail,
});
},
async POST(request, context) {
@@ -38,6 +45,9 @@ export const handler: Handlers<Data, FreshContextState> = {
return new Response('Redirect', { status: 303, headers: { 'Location': `/login` } });
}
const isExpensesAppEnabled = await AppConfig.isAppEnabled('expenses');
const helpEmail = (await AppConfig.getConfig()).visuals.helpEmail;
let action: Action = 'change-email';
let errorTitle = '';
let errorMessage = '';
@@ -72,7 +82,7 @@ export const handler: Handlers<Data, FreshContextState> = {
throw new Error('Email is already in use.');
}
if (action === 'change-email' && isEmailEnabled()) {
if (action === 'change-email' && (await AppConfig.isEmailVerificationEnabled())) {
const verificationCode = await VerificationCodeModel.create(user, email, 'email');
await sendVerifyEmailEmail(email, verificationCode);
@@ -80,7 +90,7 @@ export const handler: Handlers<Data, FreshContextState> = {
successTitle = 'Verify your email!';
successMessage = 'You have received a code in your new email. Use it to verify it here.';
} else {
if (isEmailEnabled()) {
if (await AppConfig.isEmailVerificationEnabled()) {
const code = getFormDataField(formData, 'verification-code');
await VerificationCodeModel.validate(user, email, code, 'email');
@@ -178,6 +188,8 @@ export const handler: Handlers<Data, FreshContextState> = {
notice,
formData: convertFormDataToObject(formData),
currency: user.extra.expenses_currency,
isExpensesAppEnabled,
helpEmail,
});
} catch (error) {
console.error(error);
@@ -188,6 +200,8 @@ export const handler: Handlers<Data, FreshContextState> = {
error: { title: errorTitle, message: errorMessage },
formData: convertFormDataToObject(formData),
currency: user.extra.expenses_currency,
isExpensesAppEnabled,
helpEmail,
});
}
},
@@ -196,7 +210,14 @@ export const handler: Handlers<Data, FreshContextState> = {
export default function SettingsPage({ data }: PageProps<Data, FreshContextState>) {
return (
<main>
<Settings formData={data?.formData} error={data?.error} notice={data?.notice} currency={data?.currency} />
<Settings
formData={data?.formData}
error={data?.error}
notice={data?.notice}
currency={data?.currency}
isExpensesAppEnabled={data?.isExpensesAppEnabled}
helpEmail={data?.helpEmail}
/>
</main>
);
}