From 81b46581ab79f8f5e9e132e00e5d1b8e9182dd46 Mon Sep 17 00:00:00 2001
From: eug-vs <eug-vs@keemail.me>
Date: Sun, 15 Nov 2020 04:07:33 +0300
Subject: feat: implement authentication

---
 src/hooks/useAuth.tsx | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)
 create mode 100644 src/hooks/useAuth.tsx

(limited to 'src/hooks/useAuth.tsx')

diff --git a/src/hooks/useAuth.tsx b/src/hooks/useAuth.tsx
new file mode 100644
index 0000000..39351ae
--- /dev/null
+++ b/src/hooks/useAuth.tsx
@@ -0,0 +1,70 @@
+import React, {
+  useEffect, useCallback, useMemo, useContext, createContext
+} from 'react';
+import { User } from '../types';
+import { post } from '../requests';
+import { useUser } from './APIClient';
+import useLocalStorage from './useLocalStorage';
+
+
+interface ContextType {
+  user: User | undefined,
+  login: (username: string, password: string, remember?: boolean) => Promise<boolean>;
+  logout: () => void;
+  isAuthenticated: boolean;
+}
+
+const authContext = createContext<ContextType>({
+  user: undefined,
+  login: async () => false,
+  logout: () => {},
+  isAuthenticated: false
+});
+
+const useProvideAuth = () => {
+  const [remember, setRemember] = useLocalStorage('remember');
+  const [username, setUsername] = useLocalStorage('username');
+  const [token, setToken] = useLocalStorage('token');
+  const { data: user } = useUser(username);
+
+  const isAuthenticated = useMemo(() => Boolean(username), [username]);
+
+  const logout = useCallback(() => {
+    setToken(null);
+    setUsername(null);
+  }, [setToken, setUsername]);
+
+  useEffect(() => {
+    // If should not remember, logout
+    if (!remember) logout();
+  }, [remember, logout]);
+
+
+  const login: ContextType['login'] = (name, password, shouldRemember = true) => {
+    return post('/authentication', {
+      strategy: 'local',
+      username: name,
+      password
+    }).then(response => {
+      setToken(response.data.accessToken);
+      setUsername(name);
+      setRemember(shouldRemember ? 'true' : null);
+      return true;
+    }).catch(() => false);
+  };
+
+  return {
+    user, login, logout, token, isAuthenticated
+  };
+};
+
+export const AuthProvider: React.FC = ({ children }) => {
+  const auth = useProvideAuth();
+  const { Provider } = authContext;
+  return <Provider value={auth}>{children}</Provider>;
+};
+
+export const useAuth = (): ContextType => {
+  return useContext(authContext);
+};
+
-- 
cgit v1.2.3

