a1d2c6e6c2
Returning members can now sign in with just their phone number. The bot DMs them a 6-digit OTP; on verify a 30-day session cookie is set. First-time users are directed to their invite link from the login page. - Make OtpChallenge.groupId optional (migration) for re-login challenges - Add memberLogin / memberVerify service methods - Add POST /public/auth/member-login and /member-verify controller endpoints - Add /api/my/login BFF route (sets tower_member_token cookie) - Add /my/login page (phone → OTP two-step form) - /my/* now redirects to /my/login instead of /onboard on no session Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
26 lines
987 B
TypeScript
26 lines
987 B
TypeScript
import { buildMemberCookie, getApiBaseUrl, jsonResponse } from '../../../_lib/api';
|
|
|
|
export const dynamic = 'force-dynamic';
|
|
|
|
export async function POST(req: Request): Promise<Response> {
|
|
const body = await req.json().catch(() => ({}));
|
|
const upstream = await fetch(`${getApiBaseUrl()}/public/auth/member-verify`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
|
body: JSON.stringify(body),
|
|
cache: 'no-store',
|
|
});
|
|
const payload = (await upstream.json().catch(() => ({}))) as {
|
|
memberToken?: string;
|
|
user?: { id: string; tenantId: string; jid: string; displayName: string | null };
|
|
message?: string;
|
|
};
|
|
if (!upstream.ok) return jsonResponse(payload, upstream.status);
|
|
if (!payload.memberToken) return jsonResponse({ message: 'Missing token in upstream response' }, 502);
|
|
return jsonResponse(
|
|
{ user: payload.user },
|
|
200,
|
|
{ 'Set-Cookie': buildMemberCookie(payload.memberToken) },
|
|
);
|
|
}
|