feat(domains): add allowed-domain repository and whitelist check

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-17 15:09:31 +02:00
parent 11b6b8fff1
commit 4c8f4da46c
3 changed files with 84 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
import type Database from 'better-sqlite3';
import type { AllowedDomain } from '$lib/types';
export function normalizeDomain(raw: string): string {
return raw.trim().toLowerCase().replace(/^www\./, '');
}
export function listDomains(db: Database.Database): AllowedDomain[] {
return db
.prepare('SELECT id, domain, display_name FROM allowed_domain ORDER BY domain')
.all() as AllowedDomain[];
}
export function addDomain(
db: Database.Database,
domain: string,
displayName: string | null = null,
addedByProfileId: number | null = null
): AllowedDomain {
const normalized = normalizeDomain(domain);
const row = db
.prepare(
`INSERT INTO allowed_domain(domain, display_name, added_by_profile_id)
VALUES (?, ?, ?)
RETURNING id, domain, display_name`
)
.get(normalized, displayName, addedByProfileId) as AllowedDomain;
return row;
}
export function removeDomain(db: Database.Database, id: number): void {
db.prepare('DELETE FROM allowed_domain WHERE id = ?').run(id);
}

View File

@@ -0,0 +1,16 @@
import type Database from 'better-sqlite3';
import { normalizeDomain } from './repository';
export function isDomainAllowed(db: Database.Database, urlString: string): boolean {
let host: string;
try {
host = new URL(urlString).hostname;
} catch {
return false;
}
const normalized = normalizeDomain(host);
const row = db
.prepare('SELECT 1 AS ok FROM allowed_domain WHERE domain = ? LIMIT 1')
.get(normalized);
return row !== undefined;
}