Add Google and Github auth providers (#350)
This commit is contained in:
parent
f4ccecdd09
commit
25228fba25
|
@ -1,13 +1,19 @@
|
|||
import { useState } from 'react';
|
||||
import {
|
||||
useCallback,
|
||||
useState,
|
||||
} from 'react';
|
||||
import {
|
||||
Form,
|
||||
Input,
|
||||
Button,
|
||||
Divider,
|
||||
Space,
|
||||
} from 'antd';
|
||||
import {
|
||||
MailOutlined,
|
||||
LockOutlined,
|
||||
GoogleOutlined,
|
||||
GithubOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import {
|
||||
Link,
|
||||
|
@ -27,12 +33,39 @@ const { Item } = Form;
|
|||
|
||||
const Login = () => {
|
||||
const [form] = Form.useForm();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { login } = useAuth();
|
||||
const [isEmailLoading, setIsEmailLoading] = useState(false);
|
||||
const [isGoogleLoading, setIsGoogleLoading] = useState(false);
|
||||
const [isGithubLoading, setIsGithubLoading] = useState(false);
|
||||
const { login, googleAuth, githubAuth } = useAuth();
|
||||
const history = useHistory();
|
||||
const isAnythingLoading = isEmailLoading || isGoogleLoading || isGithubLoading;
|
||||
|
||||
const onFinish = async ({ email, password }: { form: any, email: string, password: string }) => {
|
||||
setIsLoading(true);
|
||||
const googleLogin = useCallback(async () => {
|
||||
setIsGoogleLoading(true);
|
||||
try {
|
||||
await googleAuth();
|
||||
logInSuccessful();
|
||||
history.push(Routes.ROOT);
|
||||
} catch (error) {
|
||||
logInFailed(error as Error);
|
||||
setIsGoogleLoading(false);
|
||||
}
|
||||
}, [googleAuth, history]);
|
||||
|
||||
const githubLogin = useCallback(async () => {
|
||||
setIsGithubLoading(true);
|
||||
try {
|
||||
await githubAuth();
|
||||
logInSuccessful();
|
||||
history.push(Routes.ROOT);
|
||||
} catch (error) {
|
||||
logInFailed(error as Error);
|
||||
setIsGithubLoading(false);
|
||||
}
|
||||
}, [githubAuth, history]);
|
||||
|
||||
const emailLogin = async ({ email, password }: { form: any, email: string, password: string }) => {
|
||||
setIsEmailLoading(true);
|
||||
try {
|
||||
const userCredentials = await login(email, password);
|
||||
logInSuccessful();
|
||||
|
@ -46,16 +79,16 @@ const Login = () => {
|
|||
form.resetFields();
|
||||
console.warn(error);
|
||||
logInFailed(error as Error);
|
||||
setIsLoading(false);
|
||||
setIsEmailLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={containerStyle}>
|
||||
<Divider>Log In</Divider>
|
||||
<Divider>Log In using email</Divider>
|
||||
<Form
|
||||
initialValues={{ remember: true }}
|
||||
onFinish={onFinish}
|
||||
onFinish={emailLogin}
|
||||
validateMessages={validateMessages}
|
||||
autoComplete="off"
|
||||
form={form}
|
||||
|
@ -68,6 +101,7 @@ const Login = () => {
|
|||
<Input
|
||||
prefix={<MailOutlined />}
|
||||
placeholder="Email"
|
||||
disabled={isAnythingLoading}
|
||||
/>
|
||||
</Item>
|
||||
<Item
|
||||
|
@ -78,6 +112,7 @@ const Login = () => {
|
|||
<Input.Password
|
||||
placeholder="Password"
|
||||
prefix={<LockOutlined />}
|
||||
disabled={isAnythingLoading}
|
||||
/>
|
||||
</Item>
|
||||
<Item>
|
||||
|
@ -85,16 +120,41 @@ const Login = () => {
|
|||
type="primary"
|
||||
htmlType="submit"
|
||||
style={{ width: '100%' }}
|
||||
loading={isLoading}
|
||||
loading={isEmailLoading}
|
||||
disabled={isAnythingLoading}
|
||||
>
|
||||
Log In
|
||||
</Button>
|
||||
</Item>
|
||||
<Link to={Routes.SIGN_UP}>Sign Up now</Link>
|
||||
<Link to={Routes.RESET_PASSWORD} style={{ float: 'right' }}>
|
||||
</Form>
|
||||
<Space direction="horizontal" style={{ width: '100%', justifyContent: 'center' }}>
|
||||
<Item>
|
||||
<Button
|
||||
loading={isGoogleLoading}
|
||||
onClick={googleLogin}
|
||||
disabled={isAnythingLoading}
|
||||
>
|
||||
<GoogleOutlined />Google
|
||||
</Button>
|
||||
</Item>
|
||||
<Item>
|
||||
<Button
|
||||
loading={isGithubLoading}
|
||||
onClick={githubLogin}
|
||||
disabled={isAnythingLoading}
|
||||
>
|
||||
<GithubOutlined />GitHub
|
||||
</Button>
|
||||
</Item>
|
||||
</Space>
|
||||
<Button type="link">
|
||||
<Link to={Routes.SIGN_UP}>Sign Up</Link>
|
||||
</Button>
|
||||
<Button type="link" style={{ float: 'right' }}>
|
||||
<Link to={Routes.RESET_PASSWORD}>
|
||||
Forgot password?
|
||||
</Link>
|
||||
</Form>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -27,7 +27,7 @@ const ResetPassword = () => {
|
|||
const { resetPassword } = useAuth();
|
||||
const history = useHistory();
|
||||
|
||||
const onFinish = async ({ email, password }: { form: any, email: string, password: string }) => {
|
||||
const onFinish = async ({ email }: { form: any, email: string }) => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
await resetPassword(email);
|
||||
|
@ -71,7 +71,7 @@ const ResetPassword = () => {
|
|||
Reset password
|
||||
</Button>
|
||||
</Item>
|
||||
<Link to={Routes.SIGN_UP}>Sign Up now</Link>
|
||||
<Link to={Routes.SIGN_UP}>Sign Up</Link>
|
||||
<Link to={Routes.LOGIN} style={{ float: 'right' }}>
|
||||
Log In
|
||||
</Link>
|
||||
|
|
|
@ -112,8 +112,10 @@ const SignUp = () => {
|
|||
Sign Up
|
||||
</Button>
|
||||
</Item>
|
||||
Or <Link to={Routes.LOGIN}>login</Link> if you already have an account!
|
||||
</Form>
|
||||
<Link to={Routes.LOGIN} style={{ float: 'right' }}>
|
||||
Log In
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -97,6 +97,7 @@ const TopBar = () => {
|
|||
</Menu.Item>
|
||||
</>
|
||||
)}
|
||||
<Menu.Divider />
|
||||
<Menu.Item key="gh" icon={<GithubOutlined />}>
|
||||
<a
|
||||
href="https://github.com/speedy-tuner/speedy-tuner-cloud"
|
||||
|
@ -106,7 +107,6 @@ const TopBar = () => {
|
|||
GitHub
|
||||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item key="preferences" disabled icon={<SettingOutlined />}>
|
||||
Preferences
|
||||
</Menu.Item>
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
import { UserCredential } from 'firebase/auth';
|
||||
import {
|
||||
User,
|
||||
UserCredential,
|
||||
} from 'firebase/auth';
|
||||
import {
|
||||
createContext,
|
||||
ReactNode,
|
||||
|
@ -14,23 +17,28 @@ import {
|
|||
sendEmailVerification,
|
||||
signOut,
|
||||
sendPasswordResetEmail,
|
||||
GoogleAuthProvider,
|
||||
GithubAuthProvider,
|
||||
signInWithPopup,
|
||||
} from '../firebase';
|
||||
|
||||
const AuthContext = createContext<any>(null);
|
||||
|
||||
interface AuthValue {
|
||||
currentUser?: UserCredential,
|
||||
signUp: (email: string, password: string) => Promise<UserCredential>,
|
||||
currentUser: User | null,
|
||||
signUp: (email: string, password: string) => Promise<void>,
|
||||
login: (email: string, password: string) => Promise<UserCredential>,
|
||||
logout: () => Promise<void>,
|
||||
resetPassword: (email: string) => Promise<UserCredential>,
|
||||
resetPassword: (email: string) => Promise<void>,
|
||||
googleAuth: () => Promise<void>,
|
||||
githubAuth: () => Promise<void>,
|
||||
}
|
||||
|
||||
const useAuth = () => useContext<AuthValue>(AuthContext);
|
||||
const AuthContext = createContext<AuthValue | null>(null);
|
||||
|
||||
const useAuth = () => useContext<AuthValue>(AuthContext as any);
|
||||
|
||||
const AuthProvider = (props: { children: ReactNode }) => {
|
||||
const { children } = props;
|
||||
const [currentUser, setCurrentUser] = useState<any | null>(null);
|
||||
const [currentUser, setCurrentUser] = useState<User | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
const value = useMemo(() => ({
|
||||
|
@ -40,6 +48,16 @@ const AuthProvider = (props: { children: ReactNode }) => {
|
|||
login: (email: string, password: string) => signInWithEmailAndPassword(auth, email, password),
|
||||
logout: () => signOut(auth),
|
||||
resetPassword: (email: string) => sendPasswordResetEmail(auth, email),
|
||||
googleAuth: async () => {
|
||||
const provider = new GoogleAuthProvider().addScope('https://www.googleapis.com/auth/userinfo.email');
|
||||
const credentials = await signInWithPopup(auth, provider);
|
||||
setCurrentUser(credentials.user);
|
||||
},
|
||||
githubAuth: async () => {
|
||||
const provider = new GithubAuthProvider().addScope('user:email');
|
||||
const credentials = await signInWithPopup(auth, provider);
|
||||
setCurrentUser(credentials.user);
|
||||
},
|
||||
}), [currentUser]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -6,6 +6,9 @@ import {
|
|||
signOut,
|
||||
sendEmailVerification,
|
||||
sendPasswordResetEmail,
|
||||
GoogleAuthProvider,
|
||||
GithubAuthProvider,
|
||||
signInWithPopup,
|
||||
} from 'firebase/auth';
|
||||
import { getAnalytics } from 'firebase/analytics';
|
||||
|
||||
|
@ -31,4 +34,7 @@ export {
|
|||
sendEmailVerification,
|
||||
signOut,
|
||||
sendPasswordResetEmail,
|
||||
GoogleAuthProvider,
|
||||
GithubAuthProvider,
|
||||
signInWithPopup,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue