mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-04 16:14:07 +00:00
107 lines
4.8 KiB
TypeScript
107 lines
4.8 KiB
TypeScript
// Area c of the assistant's host APIs, host side (see README.md): answering
|
|
// invitations, deleting events with undo, filter rules, batches of
|
|
// messages, the out-of-office's forward and changing settings.
|
|
//
|
|
// Three existing calls are taken over here and keep their permission:
|
|
// calendar.deleteEvent now also returns an undo token, vacation.get also
|
|
// says whether the out-of-office forwards mail, and vacation.set refuses,
|
|
// for every plugin, to switch the reply on while it forwards mail or while
|
|
// that can't be read.
|
|
|
|
import type { InstalledPlugin, Permission, VacationView } from '../../plugin-types';
|
|
import { useAuthStore } from '@/stores/auth-store';
|
|
import { useVacationStore } from '@/stores/vacation-store';
|
|
import { doVacationGet, doVacationSet } from '../host-api-settings';
|
|
import { isPlainRecord, sessionClient } from '../host-api-input';
|
|
import { NOT_MINE } from './not-mine';
|
|
import { doCalendarDeleteWithUndo, doCalendarRespond, doCalendarUndoDelete } from './c.calendar';
|
|
import { doFiltersCreate, doFiltersList, doFiltersUndo } from './c.filters';
|
|
import { doEmailBatch, doEmailUndoBatch } from './c.batch';
|
|
import { doDescribeSettings, doSetSettings, doUndoSettings } from './c.settings';
|
|
import type { AreaHostFeaturesC, VacationForwardField } from './c.types';
|
|
|
|
/** Method → permission, joined into PERM_PER_METHOD. */
|
|
export const PERMS: Readonly<Record<string, Permission | null>> = {
|
|
'calendar.respond': 'calendar:respond',
|
|
'calendar.deleteEvent': 'calendar:write',
|
|
'calendar.undoDelete': 'calendar:write',
|
|
'filters.list': 'filters:read',
|
|
'filters.create': 'filters:write',
|
|
'filters.undo': 'filters:write',
|
|
'email.batch': 'email:write',
|
|
'email.undoBatch': 'email:write',
|
|
'vacation.get': 'vacation:read',
|
|
'vacation.set': 'vacation:write',
|
|
'app.describeSettings': 'settings:read',
|
|
'app.setSettings': 'settings:change',
|
|
'app.undoSettings': 'settings:change',
|
|
};
|
|
|
|
/**
|
|
* Whether the out-of-office forwards mail while it is on: true, false, or
|
|
* null when the account has filters but they couldn't be read.
|
|
*/
|
|
function forwardActive(): boolean | null {
|
|
const state = useVacationStore.getState();
|
|
if (state.forwardUnknown) return null;
|
|
return state.forward?.enabled === true;
|
|
}
|
|
|
|
/** vacation.get, plus whether the out-of-office forwards mail while it is on. */
|
|
async function doVacationGetWithForward(): Promise<VacationView & VacationForwardField> {
|
|
const view = await doVacationGet();
|
|
return { ...view, forwardActive: forwardActive() };
|
|
}
|
|
|
|
/**
|
|
* vacation.set as before, but no plugin may switch the reply on while the
|
|
* out-of-office forwards mail to another address (set in Settings > Out of
|
|
* office) or while that can't be read: switching it on would start sending
|
|
* the user's mail elsewhere.
|
|
*/
|
|
async function doVacationSetGuarded(input: unknown): Promise<VacationView | null> {
|
|
const method = 'vacation.set';
|
|
if (isPlainRecord(input) && input.isEnabled === true) {
|
|
const client = sessionClient(method);
|
|
await useVacationStore.getState().fetchVacationResponse(client);
|
|
const forward = forwardActive();
|
|
if (forward !== false) {
|
|
throw new Error(forward === null
|
|
? `${method}: whether the out-of-office forwards mail can't be read right now, so it can't be switched on here; use Settings > Out of office`
|
|
: `${method}: the out-of-office forwards mail to another address, so a plugin can't switch it on; use Settings > Out of office`);
|
|
}
|
|
}
|
|
return doVacationSet(input);
|
|
}
|
|
|
|
/** Runs a method of this area; NOT_MINE for any other. */
|
|
export async function dispatch(plugin: InstalledPlugin, method: string, args: unknown[]): Promise<unknown> {
|
|
switch (method) {
|
|
case 'calendar.respond': return doCalendarRespond(args[0], args[1]);
|
|
case 'calendar.deleteEvent': return doCalendarDeleteWithUndo(plugin.id, args[0]);
|
|
case 'calendar.undoDelete': return doCalendarUndoDelete(plugin.id, args[0]);
|
|
case 'filters.list': return doFiltersList();
|
|
case 'filters.create': return doFiltersCreate(plugin.id, args[0]);
|
|
case 'filters.undo': return doFiltersUndo(plugin.id, args[0]);
|
|
case 'email.batch': return doEmailBatch(plugin.id, args[0]);
|
|
case 'email.undoBatch': return doEmailUndoBatch(plugin.id, args[0]);
|
|
case 'vacation.get': return doVacationGetWithForward();
|
|
case 'vacation.set': return doVacationSetGuarded(args[0]);
|
|
case 'app.describeSettings': return doDescribeSettings(args[0]);
|
|
case 'app.setSettings': return doSetSettings(plugin.id, args[0]);
|
|
case 'app.undoSettings': return doUndoSettings(plugin.id, args[0]);
|
|
default: return NOT_MINE;
|
|
}
|
|
}
|
|
|
|
/** This area's flags in api.host.features, right now. */
|
|
export function features(): AreaHostFeaturesC {
|
|
const client = useAuthStore.getState().client;
|
|
return {
|
|
answerInvitation: true,
|
|
filterRules: client?.supportsSieve?.() === true,
|
|
batchMail: true,
|
|
changeSettings: true,
|
|
};
|
|
}
|