auth-api.ts178 lines · main
1/**
2 * Server helpers for yellow Authentication pages → briven-engine API.
3 * Forwards session cookies via apiFetch.
4 */
5
6import { apiFetch } from '@/lib/api';
7
8export type AuthCoreInfo = {
9 ok?: boolean;
10 engine?: string;
11 engineVersion?: string;
12 storage?: string;
13 database?: string;
14 message?: string;
15 hello?: string | null;
16 schemaReady?: boolean;
17 poolReady?: boolean;
18 appLoginReady?: boolean;
19 loginMethods?: string[];
20 productStatus?: string;
21 notice?: string;
22 buildSha?: string;
23 buildAt?: string;
24};
25
26export type AuthDashboard = {
27 engine: string;
28 storage: string;
29 database: string;
30 ok: boolean;
31 message: string;
32 counts: {
33 users: number;
34 sessions: number;
35 tenants: number;
36 thirdPartyLinks: number;
37 passwordlessCodesActive: number;
38 };
39 methods: {
40 emailPassword: boolean;
41 passwordlessEmail: boolean;
42 passwordlessSms: boolean;
43 google: boolean;
44 github: boolean;
45 webauthn: boolean;
46 mfa: boolean;
47 };
48 recentUsers: Array<{
49 id: string;
50 emails: string[];
51 phoneNumbers: string[];
52 timeJoined: number;
53 }>;
54 recipesLoaded: string[];
55};
56
57export async function fetchAuthCoreInfo(): Promise<AuthCoreInfo | null> {
58 try {
59 const res = await apiFetch('/v1/auth-core/info');
60 if (!res.ok) return null;
61 return (await res.json()) as AuthCoreInfo;
62 } catch {
63 return null;
64 }
65}
66
67export async function fetchAuthDashboard(
68 projectId?: string,
69): Promise<
70 | { ok: true; data: AuthDashboard }
71 | { ok: false; status: number; message: string }
72> {
73 try {
74 const q = projectId
75 ? `?projectId=${encodeURIComponent(projectId)}`
76 : '';
77 const res = await apiFetch(`/v1/auth-core/dashboard${q}`);
78 if (res.status === 401) {
79 return { ok: false, status: 401, message: 'sign in to briven.tech required' };
80 }
81 if (!res.ok) {
82 const t = await res.text().catch(() => '');
83 return { ok: false, status: res.status, message: t || res.statusText };
84 }
85 return { ok: true, data: (await res.json()) as AuthDashboard };
86 } catch (err) {
87 return {
88 ok: false,
89 status: 0,
90 message: err instanceof Error ? err.message : String(err),
91 };
92 }
93}
94
95export async function fetchAuthUsers(
96 limit = 50,
97 projectId?: string,
98): Promise<
99 | {
100 ok: true;
101 users: Array<{
102 id: string;
103 emails: string[];
104 phoneNumbers: string[];
105 tenantId?: string;
106 timeJoined: number;
107 storage?: string;
108 }>;
109 storage?: string;
110 }
111 | { ok: false; status: number; message: string }
112> {
113 try {
114 const params = new URLSearchParams({ limit: String(limit) });
115 if (projectId) params.set('projectId', projectId);
116 const res = await apiFetch(`/v1/auth-core/users?${params}`);
117 if (res.status === 401) {
118 return { ok: false, status: 401, message: 'sign in to briven.tech required' };
119 }
120 if (!res.ok) {
121 const t = await res.text().catch(() => '');
122 return { ok: false, status: res.status, message: t || res.statusText };
123 }
124 const body = (await res.json()) as {
125 users?: Array<{
126 id: string;
127 emails: string[];
128 phoneNumbers: string[];
129 tenantId?: string;
130 timeJoined: number;
131 storage?: string;
132 }>;
133 storage?: string;
134 };
135 return {
136 ok: true,
137 users: body.users ?? [],
138 storage: body.storage ?? 'doltgres',
139 };
140 } catch (err) {
141 return {
142 ok: false,
143 status: 0,
144 message: err instanceof Error ? err.message : String(err),
145 };
146 }
147}
148
149export async function fetchAuthRecipes(): Promise<{
150 loaded: string[];
151 catalog: Array<{
152 id: string;
153 title: string;
154 phase: number;
155 loaded: boolean;
156 sms: boolean;
157 }>;
158 smsIncluded?: boolean;
159 storage?: string;
160} | null> {
161 try {
162 const res = await apiFetch('/v1/auth-core/recipes');
163 if (!res.ok) return null;
164 return (await res.json()) as {
165 loaded: string[];
166 catalog: Array<{
167 id: string;
168 title: string;
169 phase: number;
170 loaded: boolean;
171 sms: boolean;
172 }>;
173 smsIncluded?: boolean;
174 };
175 } catch {
176 return null;
177 }
178}