aboutsummaryrefslogtreecommitdiff
path: root/src/hooks/useAuth.tsx
blob: 2f03a330aeea09465e81976381504ea1030b66dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import React, {
  useEffect, useCallback, useMemo, useContext, createContext
} from 'react';
import { User } from 'which-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);
};