Аутентификация

Логика авторизации и регистрации с помощью supabase
This commit is contained in:
degradin 2025-05-07 13:33:37 +03:00
parent 18877a2da2
commit c760b48719

View File

@ -1,9 +1,8 @@
import { import React, {
createContext, createContext,
useContext, useContext,
useState, useState,
useEffect, useEffect,
useCallback,
} from "react"; } from "react";
import { import {
supabase, supabase,
@ -16,126 +15,145 @@ import {
const AuthContext = createContext(); const AuthContext = createContext();
export function useAuth() { export const useAuth = () => {
const context = useContext(AuthContext); const context = useContext(AuthContext);
if (!context) { if (!context) {
throw new Error("useAuth must be used within an AuthProvider"); throw new Error("useAuth must be used within an AuthProvider");
} }
return context; return context;
} };
export function AuthProvider({ children }) { export const AuthProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState(null); const [currentUser, setCurrentUser] = useState(null);
const [userProfile, setUserProfile] = useState(null); const [userProfile, setUserProfile] = useState(null);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState(null); const [error, setError] = useState(null);
const signup = useCallback(async (email, password, username) => {
try {
setError(null);
const result = await supabaseSignUp(email, password, username);
return result;
} catch (error) {
const errorMessage = error.message || "Failed to sign up";
setError(errorMessage);
throw error;
}
}, []);
const login = useCallback(async (email, password) => {
try {
setError(null);
const result = await supabaseSignIn(email, password);
return result;
} catch (error) {
const errorMessage = error.message || "Failed to log in";
setError(errorMessage);
throw error;
}
}, []);
const logout = useCallback(async () => {
try {
setError(null);
await supabaseSignOut();
setCurrentUser(null);
setUserProfile(null);
} catch (error) {
const errorMessage = error.message || "Failed to log out";
setError(errorMessage);
throw error;
}
}, []);
const fetchUserProfile = useCallback(async (uid) => {
if (!uid) return null;
try {
setError(null);
return await getUserProfile(uid);
} catch (error) {
const errorMessage = error.message || "Failed to fetch user profile";
setError(errorMessage);
return null;
}
}, []);
useEffect(() => { useEffect(() => {
let authSubscription; // Проверяем текущую сессию при загрузке
const checkSession = async () => {
const initializeAuth = async () => {
try { try {
setError(null); const { data: { session }, error: sessionError } = await supabase.auth.getSession();
const user = await getCurrentUser(); if (sessionError) throw sessionError;
if (user) {
setCurrentUser(user); if (session?.user) {
const profile = await fetchUserProfile(user.id); setCurrentUser(session.user);
// Загружаем профиль пользователя
const { data: profile, error: profileError } = await supabase
.from('users')
.select('*')
.eq('id', session.user.id)
.single();
if (profileError) throw profileError;
setUserProfile(profile); setUserProfile(profile);
} }
} catch (err) {
const { console.error('Error checking session:', err);
data: { subscription }, setError('Ошибка проверки сессии');
} = supabase.auth.onAuthStateChange(async (event, session) => {
if (session?.user) {
setCurrentUser(session.user);
const profile = await fetchUserProfile(session.user.id);
setUserProfile(profile);
} else {
setCurrentUser(null);
setUserProfile(null);
}
});
authSubscription = subscription;
} catch (error) {
const errorMessage = error.message || "Failed to initialize auth";
setError(errorMessage);
} finally { } finally {
setLoading(false); setLoading(false);
} }
}; };
initializeAuth(); checkSession();
// Подписываемся на изменения состояния авторизации
const { data: { subscription } } = supabase.auth.onAuthStateChange(async (event, session) => {
if (event === 'SIGNED_IN' && session?.user) {
setCurrentUser(session.user);
try {
const { data: profile, error: profileError } = await supabase
.from('users')
.select('*')
.eq('id', session.user.id)
.single();
if (profileError) throw profileError;
setUserProfile(profile);
} catch (err) {
console.error('Error loading user profile:', err);
setError('Ошибка загрузки профиля');
}
} else if (event === 'SIGNED_OUT') {
setCurrentUser(null);
setUserProfile(null);
}
});
return () => { return () => {
if (authSubscription) { subscription.unsubscribe();
authSubscription.unsubscribe();
}
}; };
}, [fetchUserProfile]); }, []);
const signIn = async (email, password) => {
try {
setError(null);
const { data, error } = await supabase.auth.signInWithPassword({
email,
password
});
if (error) throw error;
return data;
} catch (err) {
console.error('Error signing in:', err);
setError(err.message || 'Ошибка входа');
throw err;
}
};
const signUp = async (email, password, username) => {
try {
setError(null);
const { data, error } = await supabase.auth.signUp({
email,
password,
options: {
data: { username }
}
});
if (error) throw error;
return data;
} catch (err) {
console.error('Error signing up:', err);
setError(err.message || 'Ошибка регистрации');
throw err;
}
};
const signOut = async () => {
try {
setError(null);
const { error } = await supabase.auth.signOut();
if (error) throw error;
setCurrentUser(null);
setUserProfile(null);
} catch (err) {
console.error('Error signing out:', err);
setError('Ошибка при выходе');
throw err;
}
};
const value = { const value = {
currentUser, currentUser,
userProfile, userProfile,
signup,
login,
logout,
loading, loading,
error, error,
updateProfile: fetchUserProfile, signIn,
signUp,
signOut
}; };
if (loading) {
return <div className="flex justify-center items-center h-screen">Загрузка...</div>;
}
return ( return (
<AuthContext.Provider value={value}> <AuthContext.Provider value={value}>
{!loading && children} {children}
</AuthContext.Provider> </AuthContext.Provider>
); );
} };