refactor: integrate Better-Auth for authentication and remove Supabase dependencies
This commit is contained in:
@@ -1,14 +1,8 @@
|
||||
import { setApiAccessToken } from '@/lib/api-client';
|
||||
import { supabase } from '@/lib/supabase';
|
||||
import type { Session, User } from '@supabase/supabase-js';
|
||||
import {
|
||||
type PropsWithChildren,
|
||||
createContext,
|
||||
useContext,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { authClient } from '@/lib/api-client';
|
||||
import { type PropsWithChildren, createContext, useContext, useMemo } from 'react';
|
||||
|
||||
export type User = typeof authClient.$Infer.Session.user;
|
||||
export type Session = typeof authClient.$Infer.Session.session;
|
||||
|
||||
type SignInParams = {
|
||||
email: string;
|
||||
@@ -48,14 +42,7 @@ const AuthContext = createContext<AuthContextValue | null>(null);
|
||||
|
||||
function getDisplayName(user: User | null): string {
|
||||
if (!user) return 'Usuario';
|
||||
|
||||
const fromMetadata =
|
||||
user.user_metadata?.name ?? user.user_metadata?.full_name ?? user.user_metadata?.user_name;
|
||||
|
||||
if (typeof fromMetadata === 'string' && fromMetadata.trim().length > 0) {
|
||||
return fromMetadata.trim();
|
||||
}
|
||||
|
||||
if (user.name?.trim()) return user.name.trim();
|
||||
return user.email ?? 'Usuario';
|
||||
}
|
||||
|
||||
@@ -66,47 +53,14 @@ function getInitials(name: string): string {
|
||||
}
|
||||
|
||||
function getAvatarUrl(user: User | null): string | null {
|
||||
if (!user) return null;
|
||||
|
||||
const value = user.user_metadata?.avatar_url ?? user.user_metadata?.picture;
|
||||
return typeof value === 'string' && value.length > 0 ? value : null;
|
||||
return user?.image || null;
|
||||
}
|
||||
|
||||
export function AuthProvider({ children }: PropsWithChildren) {
|
||||
const [session, setSession] = useState<Session | null>(null);
|
||||
const [user, setUser] = useState<User | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const { data, isPending } = authClient.useSession();
|
||||
|
||||
useEffect(() => {
|
||||
let mounted = true;
|
||||
|
||||
const init = async () => {
|
||||
const { data } = await supabase.auth.getSession();
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
setSession(data.session);
|
||||
setUser(data.session?.user ?? null);
|
||||
setApiAccessToken(data.session?.access_token ?? null);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
void init();
|
||||
|
||||
const {
|
||||
data: { subscription },
|
||||
} = supabase.auth.onAuthStateChange((_event, nextSession) => {
|
||||
setSession(nextSession);
|
||||
setUser(nextSession?.user ?? null);
|
||||
setApiAccessToken(nextSession?.access_token ?? null);
|
||||
setLoading(false);
|
||||
});
|
||||
|
||||
return () => {
|
||||
mounted = false;
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
}, []);
|
||||
const user = data?.user ?? null;
|
||||
const session = data?.session ?? null;
|
||||
|
||||
const value = useMemo<AuthContextValue>(() => {
|
||||
const displayName = getDisplayName(user);
|
||||
@@ -116,13 +70,13 @@ export function AuthProvider({ children }: PropsWithChildren) {
|
||||
return {
|
||||
user,
|
||||
session,
|
||||
loading,
|
||||
loading: isPending,
|
||||
isAuthenticated: Boolean(user),
|
||||
displayName,
|
||||
initials,
|
||||
avatarUrl,
|
||||
signInWithPassword: async ({ email, password }) => {
|
||||
const { error } = await supabase.auth.signInWithPassword({
|
||||
const { error } = await authClient.signIn.email({
|
||||
email,
|
||||
password,
|
||||
});
|
||||
@@ -132,15 +86,10 @@ export function AuthProvider({ children }: PropsWithChildren) {
|
||||
}
|
||||
},
|
||||
signUp: async ({ email, password, fullName }) => {
|
||||
const { data, error } = await supabase.auth.signUp({
|
||||
const { data: signUpData, error } = await authClient.signUp.email({
|
||||
email,
|
||||
password,
|
||||
options: {
|
||||
data: {
|
||||
full_name: fullName,
|
||||
name: fullName,
|
||||
},
|
||||
},
|
||||
name: fullName,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
@@ -148,15 +97,12 @@ export function AuthProvider({ children }: PropsWithChildren) {
|
||||
}
|
||||
|
||||
return {
|
||||
requiresEmailConfirmation: !data.session,
|
||||
requiresEmailConfirmation: !signUpData?.session,
|
||||
};
|
||||
},
|
||||
updateProfile: async ({ fullName }) => {
|
||||
const { error } = await supabase.auth.updateUser({
|
||||
data: {
|
||||
full_name: fullName,
|
||||
name: fullName,
|
||||
},
|
||||
const { error } = await authClient.user.update({
|
||||
name: fullName,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
@@ -164,8 +110,10 @@ export function AuthProvider({ children }: PropsWithChildren) {
|
||||
}
|
||||
},
|
||||
updatePassword: async ({ password }) => {
|
||||
const { error } = await supabase.auth.updateUser({
|
||||
password,
|
||||
// Better Auth uses changePassword for authenticated users
|
||||
const { error } = await authClient.changePassword({
|
||||
newPassword: password,
|
||||
revokeOtherSessions: true,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
@@ -173,13 +121,13 @@ export function AuthProvider({ children }: PropsWithChildren) {
|
||||
}
|
||||
},
|
||||
signOut: async () => {
|
||||
const { error } = await supabase.auth.signOut();
|
||||
const { error } = await authClient.signOut();
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
};
|
||||
}, [loading, session, user]);
|
||||
}, [isPending, session, user]);
|
||||
|
||||
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user