mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-03 16:16:59 +00:00
The admin pages save the whole policy from the draft they loaded. A save from a page opened before another tab's or another admin's save, or before a deleted plugin was dropped from the policy, used to put the older policy back. GET /api/admin/policy now sends the policy version as an ETag; the policy, organisation, plugins and themes pages send it back as If-Match, and a save based on an older version answers 409 and keeps the draft on the page. A PUT without If-Match replaces the policy as before. Deleting a plugin or theme changes only its id in the stored policy, and a policy import compares against what it replaces. Test mocks of the config manager gain getPolicyVersion and updatePolicy, which the route and the extension cleanup now call.
30 lines
1.2 KiB
TypeScript
30 lines
1.2 KiB
TypeScript
import { configManager } from './config-manager';
|
|
import { deletePluginConfig } from './plugin-config';
|
|
|
|
/**
|
|
* Drop a deleted plugin or theme from the policy lists that refer to it by
|
|
* id. Left behind, a later upload that reuses the id would start out forced
|
|
* on for everyone without the admin asking for it.
|
|
*/
|
|
export async function forgetExtensionInPolicy(kind: 'plugin' | 'theme', id: string): Promise<void> {
|
|
await configManager.ensureLoaded();
|
|
const key = kind === 'plugin' ? 'forceEnabledPlugins' : 'forceEnabledThemes';
|
|
// Against the stored policy, so a policy save landing at the same time
|
|
// keeps its changes.
|
|
await configManager.updatePolicy((policy) => {
|
|
const list = policy[key] ?? [];
|
|
if (!list.includes(id)) return undefined;
|
|
return { ...policy, [key]: list.filter((x) => x !== id) };
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Everything the server keeps about an admin plugin besides its registry
|
|
* entry: the forced flag and its config (which can hold secrets). A plugin
|
|
* installed later under the same id starts clean.
|
|
*/
|
|
export async function cleanUpDeletedPlugin(id: string): Promise<void> {
|
|
await forgetExtensionInPolicy('plugin', id);
|
|
await deletePluginConfig(id);
|
|
}
|