feat: Seaca mobile API, enrollment, FCM push and admin UI (0.9.0)

Adds mobile device registration by admin codes, refresh tokens, push channel
in notification policy, and Settings section for managing Seaca clients.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-10 13:19:14 +10:00
parent 86c602cf07
commit 563b836acc
32 changed files with 1916 additions and 45 deletions
+91
View File
@@ -289,6 +289,97 @@ export interface TopTypeItem {
count: number;
}
export interface MobileSettings {
devices_allowed: boolean;
max_devices_per_user: number;
min_app_version: string | null;
fcm_enabled: boolean;
fcm_configured: boolean;
source: string;
}
export interface MobileEnrollmentCode {
id: number;
label: string;
code_prefix: string;
target_user_id: number | null;
target_username: string | null;
login_mode: string;
max_uses: number;
use_count: number;
expires_at: string;
revoked_at: string | null;
created_at: string;
is_active: boolean;
}
export interface MobileEnrollmentCodeCreated extends MobileEnrollmentCode {
enrollment_code: string;
}
export interface MobileDevice {
id: number;
user_id: number;
username: string;
device_uuid: string;
display_name: string;
platform: string;
app_version: string | null;
has_fcm_token: boolean;
enrolled_at: string;
last_seen_at: string | null;
revoked_at: string | null;
is_active: boolean;
}
export function fetchMobileSettings(): Promise<MobileSettings> {
return apiFetch<MobileSettings>("/api/v1/mobile/settings");
}
export function updateMobileSettings(payload: {
devices_allowed: boolean;
max_devices_per_user: number;
min_app_version?: string | null;
}): Promise<MobileSettings> {
return apiFetch<MobileSettings>("/api/v1/mobile/settings", {
method: "PUT",
body: JSON.stringify(payload),
});
}
export function fetchMobileEnrollmentCodes(): Promise<MobileEnrollmentCode[]> {
return apiFetch<MobileEnrollmentCode[]>("/api/v1/mobile/enrollment-codes");
}
export function createMobileEnrollmentCode(payload: {
label?: string;
target_user_id?: number | null;
login_mode?: string;
max_uses?: number;
expires_in_hours?: number;
}): Promise<MobileEnrollmentCodeCreated> {
return apiFetch<MobileEnrollmentCodeCreated>("/api/v1/mobile/enrollment-codes", {
method: "POST",
body: JSON.stringify(payload),
});
}
export function revokeMobileEnrollmentCode(codeId: number): Promise<void> {
return apiFetch<void>(`/api/v1/mobile/enrollment-codes/${codeId}`, { method: "DELETE" });
}
export function fetchMobileDevices(): Promise<MobileDevice[]> {
return apiFetch<MobileDevice[]>("/api/v1/mobile/devices");
}
export function revokeMobileDevice(deviceId: number): Promise<MobileDevice> {
return apiFetch<MobileDevice>(`/api/v1/mobile/devices/${deviceId}`, { method: "DELETE" });
}
export function testMobileDevicePush(deviceId: number): Promise<{ message: string }> {
return apiFetch(`/api/v1/mobile/devices/${deviceId}/test-push`, { method: "POST" });
}
export interface DashboardSummary {
events_last_24h: number;
hosts_total: number;