181 lines
4.5 KiB
JavaScript
181 lines
4.5 KiB
JavaScript
import React, { createContext, useContext, useState, useEffect } from "react";
|
|
import { supabase } from "@/config/supabase";
|
|
import { message } from "antd";
|
|
import { useNavigate, useSearchParams, useLocation } from "react-router-dom";
|
|
|
|
const AuthContext = createContext({});
|
|
|
|
export const AuthProvider = ({ children }) => {
|
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
const navigate = useNavigate();
|
|
const location = useLocation();
|
|
const [user, setUser] = useState(null);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
//处理google登录
|
|
const hash = window.location.hash.substring(1);
|
|
const hashParams = new URLSearchParams(hash);
|
|
const accessToken = hashParams.get("access_token");
|
|
const refreshToken = hashParams.get("refresh_token");
|
|
if (accessToken && refreshToken) {
|
|
(async () => {
|
|
const { data, error } = await supabase.auth.setSession({
|
|
access_token: accessToken,
|
|
refresh_token: refreshToken,
|
|
});
|
|
})();
|
|
}
|
|
}, [navigate]);
|
|
|
|
// 监听认证状态变化
|
|
useEffect(() => {
|
|
// 获取初始会话状态
|
|
const initSession = async () => {
|
|
try {
|
|
const {
|
|
data: { session },
|
|
error,
|
|
} = await supabase.auth.getSession();
|
|
setUser(session?.user ?? null);
|
|
} catch (error) {
|
|
console.error("Error getting session:", error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
initSession();
|
|
|
|
// 订阅认证状态变化
|
|
const {
|
|
data: { subscription },
|
|
} = supabase.auth.onAuthStateChange((_event, session) => {
|
|
setUser(session?.user ?? null);
|
|
});
|
|
|
|
return () => {
|
|
subscription?.unsubscribe();
|
|
};
|
|
}, []);
|
|
|
|
// useEffect(() => {
|
|
// const redirectTo = searchParams.get("redirectTo");
|
|
// if (redirectTo) {
|
|
// navigate(redirectTo);
|
|
// }
|
|
// }, [location.pathname]);
|
|
|
|
// 邮箱密码登录
|
|
const login = async (email, password) => {
|
|
try {
|
|
setLoading(true);
|
|
const { data, error } = await supabase.auth.signInWithPassword({
|
|
email,
|
|
password,
|
|
});
|
|
|
|
if (error) {
|
|
message.error(error.message || "登录失败,请稍后重试");
|
|
return;
|
|
}
|
|
|
|
setUser(data.user);
|
|
return data;
|
|
} catch (error) {
|
|
message.error(error.message || "登录失败,请稍后重试");
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
// Google 登录
|
|
const signInWithGoogle = async () => {
|
|
try {
|
|
setLoading(true);
|
|
const redirectTo = searchParams.get("redirectTo");
|
|
const { data, error } = await supabase.auth.signInWithOAuth({
|
|
provider: "google",
|
|
options: {
|
|
redirectTo: `${window.location.origin}/login?redirectTo=${
|
|
redirectTo ?? ""
|
|
}`,
|
|
},
|
|
});
|
|
|
|
if (error) {
|
|
message.error(error.message || "Google 登录失败,请稍后重试");
|
|
return;
|
|
}
|
|
|
|
return data;
|
|
} catch (error) {
|
|
message.error(error.message || "Google 登录失败,请稍后重试");
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
// 注册
|
|
const register = async (email, password) => {
|
|
try {
|
|
setLoading(true);
|
|
const { data, error } = await supabase.auth.signUp({
|
|
email,
|
|
password,
|
|
options: {
|
|
emailRedirectTo: `${window.location.origin}/auth/callback`,
|
|
},
|
|
});
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
message.success("注册成功!请查收验证邮件。");
|
|
return data;
|
|
} catch (error) {
|
|
message.error(error.message || "注册失败");
|
|
throw error;
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
// 登出
|
|
const logout = async () => {
|
|
try {
|
|
setLoading(true);
|
|
const { error } = await supabase.auth.signOut({
|
|
scope: "local",
|
|
});
|
|
if (error) {
|
|
message.error(error.message || "登出失败,请稍后重试");
|
|
return;
|
|
}
|
|
setUser(null);
|
|
message.success("已成功登出");
|
|
navigate(`/login?redirectTo=${location.pathname}`, { replace: true });
|
|
} catch (error) {
|
|
message.error(error.message || "登出失败,请稍后重试");
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
const value = {
|
|
user,
|
|
loading,
|
|
login,
|
|
logout,
|
|
register,
|
|
signInWithGoogle,
|
|
};
|
|
|
|
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
|
};
|
|
|
|
export const useAuth = () => {
|
|
const context = useContext(AuthContext);
|
|
return context;
|
|
};
|