fix(auth): map logto string ID to supabase UUID via email to prevent 400 bad request
This commit is contained in:
+50
-15
@@ -21,20 +21,49 @@ import {
|
|||||||
requestPasswordReset,
|
requestPasswordReset,
|
||||||
} from '@/lib/logto/client';
|
} from '@/lib/logto/client';
|
||||||
|
|
||||||
// Sincroniza user Logto com profiles Supabase
|
// Sincroniza user Logto com profiles Supabase e retorna o UUID real do Supabase
|
||||||
async function syncUserToProfile(user: LogtoUser): Promise<void> {
|
async function syncUserToProfile(user: LogtoUser): Promise<string> {
|
||||||
if (!user?.sub) return;
|
if (!user?.sub) return user.sub;
|
||||||
|
const email = user.email || `${user.username || 'user'}@logto.local`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await supabase.from('profiles').upsert(
|
// 1. Tenta buscar o perfil existente pelo email
|
||||||
{
|
const { data: existing } = await supabase
|
||||||
id: user.sub,
|
.from('profiles')
|
||||||
full_name: user.name || user.email || user.username || 'Usuário',
|
.select('id')
|
||||||
email: user.email || null,
|
.eq('email', email)
|
||||||
},
|
.maybeSingle();
|
||||||
{ onConflict: 'id', ignoreDuplicates: false }
|
|
||||||
);
|
let profileId = existing?.id;
|
||||||
|
|
||||||
|
// 2. Se existe, atualizamos o nome e retornamos o UUID
|
||||||
|
if (profileId) {
|
||||||
|
const name = user.name || user.username;
|
||||||
|
if (name) {
|
||||||
|
await supabase.from('profiles').update({
|
||||||
|
full_name: name,
|
||||||
|
}).eq('id', profileId);
|
||||||
|
}
|
||||||
|
return profileId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Se não existir, criamos um novo com um UUID gerado
|
||||||
|
profileId = crypto.randomUUID();
|
||||||
|
const { error: insertError } = await supabase.from('profiles').insert({
|
||||||
|
id: profileId,
|
||||||
|
email: email,
|
||||||
|
full_name: user.name || user.username || 'Usuário Logto',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (insertError) {
|
||||||
|
console.warn('Erro ao inserir novo profile no Supabase:', insertError);
|
||||||
|
return user.sub;
|
||||||
|
}
|
||||||
|
|
||||||
|
return profileId;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn('Erro ao sincronizar profile Supabase:', err);
|
console.warn('Erro ao sincronizar profile Supabase:', err);
|
||||||
|
return user.sub;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,9 +98,12 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
handleCallback().then((ok) => {
|
handleCallback().then((ok) => {
|
||||||
if (ok) {
|
if (ok) {
|
||||||
logtoGetUser().then((u) => {
|
logtoGetUser().then(async (u) => {
|
||||||
|
if (u) {
|
||||||
|
const profileId = await syncUserToProfile(u);
|
||||||
|
u.id = profileId;
|
||||||
|
}
|
||||||
setUser(u);
|
setUser(u);
|
||||||
if (u) syncUserToProfile(u);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
setAuthInitialized(true);
|
setAuthInitialized(true);
|
||||||
@@ -80,9 +112,12 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
|||||||
} else {
|
} else {
|
||||||
setAuthInitialized(true);
|
setAuthInitialized(true);
|
||||||
if (isAuthenticated()) {
|
if (isAuthenticated()) {
|
||||||
logtoGetUser().then((u) => {
|
logtoGetUser().then(async (u) => {
|
||||||
|
if (u) {
|
||||||
|
const profileId = await syncUserToProfile(u);
|
||||||
|
u.id = profileId;
|
||||||
|
}
|
||||||
setUser(u);
|
setUser(u);
|
||||||
if (u) syncUserToProfile(u);
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user