fix/create-user

This commit is contained in:
João Gustavo 2025-10-17 00:23:28 -03:00
parent 26a20225f6
commit f95fb7d3ce
2 changed files with 31 additions and 21 deletions

View File

@ -1646,54 +1646,51 @@ export function gerarSenhaAleatoria(): string {
} }
export async function criarUsuario(input: CreateUserInput): Promise<CreateUserResponse> { export async function criarUsuario(input: CreateUserInput): Promise<CreateUserResponse> {
// Call the Edge Function directly (no proxy). The backend function is // Prefer calling the Functions path first in environments where /create-user
// responsible for role assignment and any service-role operations. // is not mapped at the API root (this avoids expected 404 noise). Keep the
// The OpenAPI for the new endpoint exposes POST /create-user at the // root /create-user as a fallback for deployments that expose it.
// API root (API_BASE). Call that endpoint directly from the client.
const url = `${API_BASE}/create-user`;
const functionsUrl = `${API_BASE}/functions/v1/create-user`; const functionsUrl = `${API_BASE}/functions/v1/create-user`;
const url = `${API_BASE}/create-user`;
// Network/fetch errors (including CORS preflight failures) throw before we get a Response.
// Catch them and provide a clearer, actionable error message for developers/operators.
let res: Response | null = null; let res: Response | null = null;
try { try {
res = await fetch(url, { res = await fetch(functionsUrl, {
method: 'POST', method: 'POST',
headers: { ...baseHeaders(), 'Content-Type': 'application/json' }, headers: { ...baseHeaders(), 'Content-Type': 'application/json' },
body: JSON.stringify(input), body: JSON.stringify(input),
}); });
} catch (err: any) { } catch (err: any) {
console.error('[criarUsuario] fetch error for', url, err); console.error('[criarUsuario] fetch error for', functionsUrl, err);
// Attempt functions fallback when primary endpoint can't be reached (network/CORS/route) // Attempt root /create-user fallback when functions path can't be reached
try { try {
console.warn('[criarUsuario] tentando fallback para', functionsUrl); console.warn('[criarUsuario] tentando fallback para', url);
const res2 = await fetch(functionsUrl, { const res2 = await fetch(url, {
method: 'POST', method: 'POST',
headers: { ...baseHeaders(), 'Content-Type': 'application/json' }, headers: { ...baseHeaders(), 'Content-Type': 'application/json' },
body: JSON.stringify(input), body: JSON.stringify(input),
}); });
return await parse<CreateUserResponse>(res2 as Response); return await parse<CreateUserResponse>(res2 as Response);
} catch (err2: any) { } catch (err2: any) {
console.error('[criarUsuario] fallback functions also failed', err2); console.error('[criarUsuario] fallback /create-user also failed', err2);
throw new Error( throw new Error(
'Falha ao contatar o endpoint /create-user e o fallback /functions/v1/create-user também falhou. Verifique disponibilidade e CORS. Detalhes: ' + 'Falha ao contatar o endpoint /functions/v1/create-user e o fallback /create-user também falhou. Verifique disponibilidade e CORS. Detalhes: ' +
(err?.message ?? String(err)) + ' | fallback: ' + (err2?.message ?? String(err2)) (err?.message ?? String(err)) + ' | fallback: ' + (err2?.message ?? String(err2))
); );
} }
} }
// If we got a response but it's 404 (route not found), try the functions path too // If we got a response but it's 404 (route not found), try the root path too
if (res && !res.ok && res.status === 404) { if (res && !res.ok && res.status === 404) {
try { try {
console.warn('[criarUsuario] /create-user returned 404; trying functions path', functionsUrl); console.warn('[criarUsuario] /functions/v1/create-user returned 404; trying root path', url);
const res2 = await fetch(functionsUrl, { const res2 = await fetch(url, {
method: 'POST', method: 'POST',
headers: { ...baseHeaders(), 'Content-Type': 'application/json' }, headers: { ...baseHeaders(), 'Content-Type': 'application/json' },
body: JSON.stringify(input), body: JSON.stringify(input),
}); });
return await parse<CreateUserResponse>(res2 as Response); return await parse<CreateUserResponse>(res2 as Response);
} catch (err2: any) { } catch (err2: any) {
console.error('[criarUsuario] fallback functions failed after 404', err2); console.error('[criarUsuario] fallback /create-user failed after 404', err2);
// Fall through to parse original response to provide friendly error // Fall through to parse original response to provide friendly error
} }
} }
@ -1798,7 +1795,11 @@ export async function criarUsuarioMedico(medico: { email: string; full_name: str
const redirectBase = 'https://mediconecta-app-liart.vercel.app'; const redirectBase = 'https://mediconecta-app-liart.vercel.app';
const emailRedirectTo = `${redirectBase.replace(/\/$/, '')}/profissional`; const emailRedirectTo = `${redirectBase.replace(/\/$/, '')}/profissional`;
const redirect_url = emailRedirectTo; const redirect_url = emailRedirectTo;
return await criarUsuario({ email: medico.email, password: '', full_name: medico.full_name, phone: medico.phone_mobile, role: 'medico' as any, emailRedirectTo, redirect_url, target: 'medico' }); // generate a secure-ish random password on the client so the caller can receive it
const password = gerarSenhaAleatoria();
const resp = await criarUsuario({ email: medico.email, password, full_name: medico.full_name, phone: medico.phone_mobile, role: 'medico' as any, emailRedirectTo, redirect_url, target: 'medico' });
// Return backend response plus the generated password so the UI can show/save it
return { ...(resp as any), password };
} }
// Criar usuário para PACIENTE no Supabase Auth (sistema de autenticação) // Criar usuário para PACIENTE no Supabase Auth (sistema de autenticação)
@ -1807,7 +1808,11 @@ export async function criarUsuarioPaciente(paciente: { email: string; full_name:
const redirectBase = 'https://mediconecta-app-liart.vercel.app'; const redirectBase = 'https://mediconecta-app-liart.vercel.app';
const emailRedirectTo = `${redirectBase.replace(/\/$/, '')}/paciente`; const emailRedirectTo = `${redirectBase.replace(/\/$/, '')}/paciente`;
const redirect_url = emailRedirectTo; const redirect_url = emailRedirectTo;
return await criarUsuario({ email: paciente.email, password: '', full_name: paciente.full_name, phone: paciente.phone_mobile, role: 'paciente' as any, emailRedirectTo, redirect_url, target: 'paciente' }); // generate a secure-ish random password on the client so the caller can receive it
const password = gerarSenhaAleatoria();
const resp = await criarUsuario({ email: paciente.email, password, full_name: paciente.full_name, phone: paciente.phone_mobile, role: 'paciente' as any, emailRedirectTo, redirect_url, target: 'paciente' });
// Return backend response plus the generated password so the UI can show/save it
return { ...(resp as any), password };
} }

View File

@ -66,11 +66,16 @@ async function processResponse<T>(response: Response): Promise<T> {
if (!response.ok) { if (!response.ok) {
const errorMessage = data?.message || data?.error || response.statusText || 'Erro na autenticação'; const errorMessage = data?.message || data?.error || response.statusText || 'Erro na autenticação';
const errorCode = data?.code || String(response.status); const errorCode = data?.code || String(response.status);
// Log raw text as well to help debug cases where JSON is empty or {}
let rawText = '';
try { rawText = await response.clone().text(); } catch (_) { rawText = '<unable to read raw text>'; }
console.error('[AUTH ERROR]', { console.error('[AUTH ERROR]', {
url: response.url, url: response.url,
status: response.status, status: response.status,
data, data,
rawText,
}); });
throw new AuthenticationError(errorMessage, errorCode, data); throw new AuthenticationError(errorMessage, errorCode, data);