Аутентификация
Логика авторизации и регистрации с помощью supabase
This commit is contained in:
parent
18877a2da2
commit
c760b48719
@ -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>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user