This commit is contained in:
Debian
2026-03-30 07:16:50 +00:00
parent 75f48591e9
commit 42b50b78cc
6 changed files with 56 additions and 283 deletions
+10 -25
View File
@@ -9,11 +9,7 @@ import type {
} from "@internal-mail/shared";
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL ?? "";
let csrfToken: string | null = null;
type RequestOptions = RequestInit & {
includeCsrf?: boolean;
};
let activeEmail: string | null = null;
const parseResponse = async <T>(response: Response): Promise<T> => {
if (response.status === 204) {
@@ -31,20 +27,19 @@ const parseResponse = async <T>(response: Response): Promise<T> => {
return payload as T;
};
const request = async <T>(path: string, options?: RequestOptions): Promise<T> => {
const request = async <T>(path: string, options?: RequestInit): Promise<T> => {
const headers = new Headers(options?.headers);
const isFormData = options?.body instanceof FormData;
if (!isFormData && options?.body && !headers.has("Content-Type")) {
headers.set("Content-Type", "application/json");
}
if (options?.includeCsrf && csrfToken) {
headers.set("X-CSRF-Token", csrfToken);
if (activeEmail && !headers.has("X-User-Email")) {
headers.set("X-User-Email", activeEmail);
}
const response = await fetch(`${apiBaseUrl}${path}`, {
...options,
credentials: "include",
headers
});
@@ -52,13 +47,12 @@ const request = async <T>(path: string, options?: RequestOptions): Promise<T> =>
};
export const apiClient = {
setCsrfToken(value: string | null) {
csrfToken = value;
setActiveEmail(value: string | null) {
activeEmail = value;
},
async getSession(): Promise<SessionView> {
const payload = await request<{ session: SessionView }>("/api/auth/session");
csrfToken = payload.session.csrfToken;
return payload.session;
},
@@ -68,16 +62,15 @@ export const apiClient = {
body: JSON.stringify({ email, password, totpCode })
});
csrfToken = payload.session.csrfToken;
activeEmail = payload.session.user?.email ?? email;
return payload.session;
},
async logout(): Promise<void> {
await request("/api/auth/logout", {
method: "POST",
includeCsrf: true
method: "POST"
});
csrfToken = null;
activeEmail = null;
},
async getMessages(): Promise<MailMessageSummary[]> {
@@ -92,7 +85,6 @@ export const apiClient = {
async sendMessage(to: string[], subject: string, textBody: string): Promise<void> {
await request("/api/mail/send", {
method: "POST",
includeCsrf: true,
body: JSON.stringify({ to, subject, textBody })
});
},
@@ -104,7 +96,6 @@ export const apiClient = {
async updateProfile(displayName: string): Promise<ProfileSettings> {
return request<ProfileSettings>("/api/settings/profile", {
method: "PATCH",
includeCsrf: true,
body: JSON.stringify({ displayName })
});
},
@@ -114,7 +105,6 @@ export const apiClient = {
formData.set("avatar", file);
return request<ProfileSettings>("/api/settings/avatar", {
method: "POST",
includeCsrf: true,
body: formData
});
},
@@ -126,22 +116,19 @@ export const apiClient = {
async updateForwarding(enabled: boolean, target: string | null): Promise<ForwardingRule> {
return request<ForwardingRule>("/api/settings/forwarding", {
method: "PUT",
includeCsrf: true,
body: JSON.stringify({ enabled, target })
});
},
async setupTotp(): Promise<TotpSetupResponse> {
return request<TotpSetupResponse>("/api/auth/totp/setup", {
method: "POST",
includeCsrf: true
method: "POST"
});
},
async enableTotp(code: string): Promise<void> {
await request("/api/auth/totp/enable", {
method: "POST",
includeCsrf: true,
body: JSON.stringify({ code })
});
},
@@ -149,9 +136,7 @@ export const apiClient = {
async disableTotp(code: string): Promise<void> {
await request("/api/auth/totp/disable", {
method: "POST",
includeCsrf: true,
body: JSON.stringify({ code })
});
}
};