Files
tessera-ctl/apps/web/src/lib/settings-api.ts
T
schalli 01ff137f43
Tessera CI/CD / Lint & Type Check (push) Waiting to run
Tessera CI/CD / Tests (push) Blocked by required conditions
Tessera CI/CD / Build & Deploy (push) Blocked by required conditions
fix(07): UAT fixes — SMTP test email, DKV routing, Exchange domain field
- SMTP: add test-to field, send real email via sendMail() instead of verify()
- SMTP: fix no_auth warning shown as error for open-relay servers
- DKV: register dkv-fleet in MODULE_REGISTRY (fixes "Modul nicht gefunden")
- DKV: add dynamic [category]/[moduleSlug]/settings + vehicles sub-routes
- DKV: settings/vehicles links use useParams for consistent URLs
- DKV: add gear icon settings link to module main page
- DKV: rename module to "DKV-Rechnung" in seed + translations
- DKV: add optional domain field for Exchange (WebCredentials 3rd arg)
- DKV: hide IMAP-only fields (Port/Verschlüsselung/Ordner) when Exchange selected
- DKV: hide Exchange-only field (Domain) when IMAP selected
- Prisma: add domain column to DkvModuleConfig

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 21:58:26 +02:00

92 lines
2.7 KiB
TypeScript

/**
* Settings API client — SMTP configuration.
* Consumes the SettingsController built in 07-03.
* All calls use credentials: 'include' for cookie-based auth.
*
* T-07-17: SmtpConfig exposes only hasPassword, never the secret.
* The password field is never pre-filled from server data.
*/
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001';
// --- Types mirroring the 07-03 backend contract ---
/**
* SMTP configuration as returned by GET /settings/smtp.
* encryptedPassword is NEVER returned (T-07-17).
*/
export interface SmtpConfig {
host: string;
port: number;
encryption: 'none' | 'starttls' | 'ssl-tls';
username?: string;
fromAddress: string;
/** True when an encrypted password is stored; the password value is never exposed. */
hasPassword: boolean;
}
/**
* Payload for PUT /settings/smtp and POST /settings/smtp/test.
* password is optional — omit to preserve the existing stored password.
*/
export interface SaveSmtpPayload {
host: string;
port: number;
encryption: 'none' | 'starttls' | 'ssl-tls';
username?: string;
/** Only include when the user has typed a new password. */
password?: string;
fromAddress: string;
/** If set, backend sends a real test email to this address instead of just verify(). */
testTo?: string;
}
// --- API functions ---
/**
* Fetch the SMTP configuration for the current tenant.
* GET /settings/smtp
* Returns null when no configuration has been saved yet (404).
*/
export async function fetchSmtp(): Promise<SmtpConfig | null> {
const res = await fetch(`${API_URL}/settings/smtp`, {
credentials: 'include',
});
if (res.status === 404) return null;
if (!res.ok) throw new Error('Failed to fetch SMTP config');
return res.json();
}
/**
* Save the SMTP configuration.
* PUT /settings/smtp
*/
export async function saveSmtp(payload: SaveSmtpPayload): Promise<SmtpConfig> {
const res = await fetch(`${API_URL}/settings/smtp`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify(payload),
});
if (!res.ok) throw new Error('Failed to save SMTP config');
return res.json();
}
/**
* Test the SMTP connection with the given settings.
* POST /settings/smtp/test
* Returns { success: boolean } — backend runs nodemailer.verify().
*/
export async function testSmtp(
payload: SaveSmtpPayload,
): Promise<{ success: boolean; warning?: string }> {
const res = await fetch(`${API_URL}/settings/smtp/test`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify(payload),
});
if (!res.ok) throw new Error('Failed to test SMTP config');
return res.json();
}