mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-13 07:40:59 +00:00
fix(airtrail): a new host does not inherit the stored API key
Saving the AirTrail settings with a different URL and the key field left masked or blank kept the stored key, so the next sync sent the old instance's key to the new host. The key now goes with the host, as it already did for the connection test and for Dawarich: a new origin without a new key clears it, a path edit on the same origin keeps it. The key is cleared before the new address is written.
This commit is contained in:
@@ -115,7 +115,6 @@ async function fetchServerFeatures(): Promise<{ minNativeShellApi?: unknown }> {
|
||||
return (await res.json()) as { minNativeShellApi?: unknown };
|
||||
}
|
||||
|
||||
/** The scrolled list in the middle of the screen, else the page, back to its top. */
|
||||
/** The launch link this web view has already followed, so a reload does not follow it again. */
|
||||
const LAUNCH_LINK_KEY = 'trek_launch_link_done';
|
||||
|
||||
@@ -139,6 +138,7 @@ async function openLaunchLink(): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
/** The scrolled list in the middle of the screen, else the page, back to its top. */
|
||||
export function scrollToTop(): void {
|
||||
let el = document.elementFromPoint(window.innerWidth / 2, window.innerHeight / 2) as HTMLElement | null;
|
||||
while (el && el !== document.body) {
|
||||
|
||||
@@ -119,6 +119,17 @@ export class AirtrailService {
|
||||
const provided = (apiKey || '').trim();
|
||||
const newKey = provided && provided !== KEY_MASK ? maybe_encrypt_api_key(provided) : undefined;
|
||||
|
||||
// A key belongs to the instance it was issued on, as in testConnection. A
|
||||
// new host with the key field left masked or blank would otherwise send the
|
||||
// old instance's key to the new one on the next sync, so the key goes with
|
||||
// the host. A path edit on the same origin keeps it. The key is cleared
|
||||
// before the new address is written, so no moment stores the new address
|
||||
// beside the old key.
|
||||
if (newKey === undefined) {
|
||||
const previousUrl = (await this.readRow(userId))?.airtrail_url ?? null;
|
||||
if (movedHost(previousUrl, trimmedUrl)) await this.airtrailRepo.clearAirtrailApiKey(userId);
|
||||
}
|
||||
|
||||
if (newKey !== undefined) {
|
||||
await this.airtrailRepo.setAirtrailSettingsWithKey(
|
||||
userId,
|
||||
|
||||
@@ -89,3 +89,39 @@ describe('AirtrailService — at-rest encryption (3h L3)', () => {
|
||||
expect((await svc.getAirtrailCredentials(user.id))?.apiKey).toBe('second-key');
|
||||
});
|
||||
});
|
||||
|
||||
describe('AirtrailService — the stored key stays with its host (GHSA-mwf5-5px8-c9h5)', () => {
|
||||
const MASK = '••••••••';
|
||||
|
||||
it('AIRTRAIL-SVC-HOST-001: a new host saved with the key masked or blank drops the stored key', async () => {
|
||||
for (const keyField of [MASK, '', undefined]) {
|
||||
const { user } = createUser(testDb);
|
||||
await svc.saveSettings(user.id, 'https://airtrail-a.example.test', 'key-for-a', false, false, null);
|
||||
|
||||
await svc.saveSettings(user.id, 'https://other-host.example.test', keyField, false, false, null);
|
||||
|
||||
expect(await rawAirtrailKey(user.id)).toBeNull();
|
||||
expect(await svc.getAirtrailCredentials(user.id)).toBeNull();
|
||||
expect((await readUser(t, user.id)).airtrail_url).toBe('https://other-host.example.test');
|
||||
}
|
||||
});
|
||||
|
||||
it('AIRTRAIL-SVC-HOST-002: a path edit on the same origin keeps the stored key', async () => {
|
||||
const { user } = createUser(testDb);
|
||||
await svc.saveSettings(user.id, 'https://airtrail-a.example.test', 'key-for-a', false, false, null);
|
||||
|
||||
await svc.saveSettings(user.id, 'https://airtrail-a.example.test/api', MASK, false, false, null);
|
||||
|
||||
expect((await svc.getAirtrailCredentials(user.id))?.apiKey).toBe('key-for-a');
|
||||
});
|
||||
|
||||
it('AIRTRAIL-SVC-HOST-003: a new host saved with a new key stores that key', async () => {
|
||||
const { user } = createUser(testDb);
|
||||
await svc.saveSettings(user.id, 'https://airtrail-a.example.test', 'key-for-a', false, false, null);
|
||||
|
||||
await svc.saveSettings(user.id, 'https://other-host.example.test', 'key-for-b', false, false, null);
|
||||
|
||||
const creds = await svc.getAirtrailCredentials(user.id);
|
||||
expect(creds).toMatchObject({ baseUrl: 'https://other-host.example.test', apiKey: 'key-for-b' });
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user