2026-04-19 01:47:06 +00:00
|
|
|
import { assert, assertEquals } from '@std/assert';
|
|
|
|
|
|
|
|
|
|
import { SecretSettingsManager } from '../ts/database/secret-settings.ts';
|
|
|
|
|
|
|
|
|
|
class FakeAuthRepository {
|
|
|
|
|
public settings = new Map<string, string>();
|
|
|
|
|
public secretSettings = new Map<string, string>();
|
|
|
|
|
|
|
|
|
|
getSetting(key: string): string | null {
|
|
|
|
|
return this.settings.get(key) ?? null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setSetting(key: string, value: string): void {
|
|
|
|
|
this.settings.set(key, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
deleteSetting(key: string): void {
|
|
|
|
|
this.settings.delete(key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getSecretSetting(key: string): string | null {
|
|
|
|
|
return this.secretSettings.get(key) ?? null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setSecretSetting(key: string, value: string): void {
|
|
|
|
|
this.secretSettings.set(key, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
deleteSecretSetting(key: string): void {
|
|
|
|
|
this.secretSettings.delete(key);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Deno.test('secret settings migrate legacy plaintext aliases into encrypted storage', async () => {
|
|
|
|
|
const authRepo = new FakeAuthRepository();
|
|
|
|
|
authRepo.setSetting('cloudflareAPIKey', 'cf-secret-token');
|
|
|
|
|
|
|
|
|
|
const secretSettings = new SecretSettingsManager(authRepo as any);
|
|
|
|
|
const token = await secretSettings.get('cloudflareToken');
|
|
|
|
|
|
|
|
|
|
assertEquals(token, 'cf-secret-token');
|
|
|
|
|
assertEquals(authRepo.getSetting('cloudflareAPIKey'), null);
|
|
|
|
|
assertEquals(authRepo.getSetting('cloudflareToken'), null);
|
|
|
|
|
|
|
|
|
|
const storedSecret = authRepo.getSecretSetting('cloudflareToken');
|
|
|
|
|
assert(storedSecret?.startsWith('enc:v1:'));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Deno.test('secret settings canonicalize aliases and clear old secret entries', async () => {
|
|
|
|
|
const authRepo = new FakeAuthRepository();
|
|
|
|
|
const secretSettings = new SecretSettingsManager(authRepo as any);
|
|
|
|
|
|
|
|
|
|
await secretSettings.set('backup_encryption_password', 'backup-passphrase');
|
|
|
|
|
|
|
|
|
|
assertEquals(await secretSettings.get('backupPassword'), 'backup-passphrase');
|
|
|
|
|
assert(authRepo.getSecretSetting('backupPassword')?.startsWith('enc:v1:'));
|
|
|
|
|
assertEquals(authRepo.getSecretSetting('backup_encryption_password'), null);
|
|
|
|
|
|
|
|
|
|
secretSettings.clear('backupPassword');
|
|
|
|
|
assertEquals(await secretSettings.get('backupPassword'), null);
|
|
|
|
|
});
|
2026-04-29 15:24:25 +00:00
|
|
|
|
|
|
|
|
Deno.test('secret settings treat dcrouter gateway token as encrypted secret', async () => {
|
|
|
|
|
const authRepo = new FakeAuthRepository();
|
|
|
|
|
authRepo.setSetting('externalGatewayApiToken', 'dcr-secret-token');
|
|
|
|
|
|
|
|
|
|
const secretSettings = new SecretSettingsManager(authRepo as any);
|
|
|
|
|
const token = await secretSettings.get('dcrouterGatewayApiToken');
|
|
|
|
|
|
|
|
|
|
assertEquals(token, 'dcr-secret-token');
|
|
|
|
|
assertEquals(authRepo.getSetting('externalGatewayApiToken'), null);
|
|
|
|
|
assert(authRepo.getSecretSetting('dcrouterGatewayApiToken')?.startsWith('enc:v1:'));
|
|
|
|
|
});
|