mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-02 16:15:39 +00:00
50 lines
2.6 KiB
TypeScript
50 lines
2.6 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
import { dispatchApiCall } from '@/lib/plugin-sandbox/host-api';
|
|
import type { InstalledPlugin } from '@/lib/plugin-types';
|
|
|
|
// api.admin.getConfig asked the config route without ?public=1. The route
|
|
// hands an admin session every field, secrets included, so a plugin running
|
|
// for a user who was also signed in to the admin console got its own API
|
|
// keys (the Safe Browsing key of the link check). Secrets are for the server
|
|
// proxy only.
|
|
|
|
const plugin = {
|
|
id: 'external-link-warning', name: 'Link check', version: '2.0.0', author: '', description: '', type: 'hook',
|
|
permissions: ['admin:config'], grantedPermissions: ['admin:config'], managed: true, entrypoint: 'index.js',
|
|
enabled: true, status: 'running', settings: {},
|
|
} as unknown as InstalledPlugin;
|
|
|
|
afterEach(() => vi.unstubAllGlobals());
|
|
|
|
describe('api.admin config reads', () => {
|
|
it('ask for the fields without secrets', async () => {
|
|
const urls: string[] = [];
|
|
vi.stubGlobal('fetch', vi.fn(async (url: RequestInfo | URL) => {
|
|
urls.push(String(url));
|
|
return new Response(JSON.stringify({ trustedDomains: 'example.com' }), { headers: { 'content-type': 'application/json' } });
|
|
}));
|
|
expect(await dispatchApiCall(plugin, 'admin.getAllConfig', [])).toEqual({ trustedDomains: 'example.com' });
|
|
expect(await dispatchApiCall(plugin, 'admin.getConfig', ['trustedDomains'])).toBe('example.com');
|
|
expect(urls).toHaveLength(2);
|
|
for (const url of urls) expect(url).toMatch(/\/api\/admin\/plugins\/external-link-warning\/config\?public=1$/);
|
|
});
|
|
});
|
|
|
|
// The server a plugin's credential reaches (originKey) is what stays
|
|
// reachable with no third-party traffic: the plugin may not write it.
|
|
describe('api.admin config writes', () => {
|
|
it("refuse the plugin's own server address fields", async () => {
|
|
const fetchSpy = vi.fn(async () => new Response('{}'));
|
|
vi.stubGlobal('fetch', fetchSpy);
|
|
const withServer = {
|
|
...plugin,
|
|
credentials: { linkcheck: { label: 'x', scope: 'admin', inject: { type: 'bearer' }, secretKey: 'endpointToken', originKey: 'endpointUrl' } },
|
|
} as unknown as InstalledPlugin;
|
|
await expect(dispatchApiCall(withServer, 'admin.setConfig', ['endpointUrl', 'https://collector.example/'])).rejects.toThrow(/only an administrator/);
|
|
await expect(dispatchApiCall(withServer, 'admin.deleteConfig', ['endpointUrl'])).rejects.toThrow(/only an administrator/);
|
|
expect(fetchSpy).not.toHaveBeenCalled();
|
|
await dispatchApiCall(withServer, 'admin.setConfig', ['trustedDomains', 'example.com']);
|
|
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|