server/controllers/demo.ts
Rama main · réplica de lectura del repositorio original.
import type express from 'express';
import { translate as $t, assert, asyncErr, KError } from '../helpers';
import { getTranslator } from '../lib/translator';
import { Access, Budget, Category, Setting } from '../models';
import DefaultCategories from '../shared/default-categories.json';
import { DEMO_MODE } from '../shared/settings';
import {
type CreateAndRetrieveDataResult,
createAndRetrieveData as createAndRetrieveAccessData,
destroyWithData as destroyAccessWithData,
} from './accesses';
import { isDemoEnabled, isDemoForced } from './instance';
import type { IdentifiedRequest } from './routes';
export async function setupDemoMode(userId: number): Promise<CreateAndRetrieveDataResult> {
const i18n = await getTranslator(userId);
// Create default categories, unless they already existed.
const existingCategories = new Set((await Category.all(userId)).map(cat => cat.label));
for (const category of DefaultCategories) {
if (existingCategories.has($t(i18n, category.label))) {
continue;
}
await Category.create(userId, {
label: $t(i18n, category.label),
color: category.color,
});
}
const response = await createAndRetrieveAccessData(userId, {
vendorId: 'demo',
fields: [
{ name: 'login', value: 'mylogin' },
{ name: 'password', value: 'couldnotcareless' },
],
customLabel: 'Demo bank',
});
assert(response.kind === 'value', "demo account shouldn't require a user action");
const data = response.value;
// Set the demo mode to true only if other actions succeeded.
const isEnabled = await Setting.findOrCreateByKey(userId, DEMO_MODE, 'true');
if (isEnabled.value !== 'true') {
// The setting already existed and has the wrong value.
await Setting.updateByKey(userId, DEMO_MODE, 'true');
}
return data;
}
export async function enable(req: IdentifiedRequest<any>, res: express.Response) {
try {
const { id: userId } = req.user;
const isEnabled = await isDemoEnabled(userId);
if (isEnabled) {
throw new KError('Demo mode is already enabled, not enabling it.', 400);
}
const accesses = await Access.all(userId);
if (accesses.length > 0) {
throw new KError('Demo mode cannot be enabled if there already are accesses', 400);
}
const data = await setupDemoMode(userId);
res.status(201).json(data);
} catch (err) {
asyncErr(res, err, 'when enabling demo mode');
}
}
export async function disable(req: IdentifiedRequest<any>, res: express.Response) {
try {
const { id: userId } = req.user;
if (isDemoForced()) {
throw new KError('Demo mode is forced at the server level, not disabling it.', 400);
}
const isEnabled = await isDemoEnabled(userId);
if (!isEnabled) {
throw new KError('Demo mode was not enabled, not disabling it.', 400);
}
const accesses = await Access.all(userId);
for (const acc of accesses) {
await destroyAccessWithData(userId, acc);
}
// Keep the categories (and rules), in case the user created
// interesting ones. Delete all the budgets, though.
await Budget.destroyAll(userId);
// Only reset the setting value if all the destroy actions succeeded.
await Setting.updateByKey(userId, DEMO_MODE, 'false');
res.status(200).end();
} catch (err) {
asyncErr(res, err, 'when disabling demo mode');
}
}