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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
| import { useState, useEffect, useCallback } from 'react';
import { api, type User } from '../api/client';
import {
saveToken,
loadToken,
clearAll,
saveUser,
loadUser,
saveHost,
loadHost,
} from '../store/auth';
import { setBaseUrl } from '../api/client';
export interface AuthState {
user: User | null;
token: string | null;
loading: boolean;
error: string | null;
}
export function useAuth() {
const [state, setState] = useState<AuthState>({
user: null,
token: null,
loading: true,
error: null,
});
useEffect(() => {
(async () => {
try {
const [token, user, host] = await Promise.all([
loadToken(),
loadUser(),
loadHost(),
]);
if (host) {
setBaseUrl(host);
}
if (token && user) {
setState({ user, token, loading: false, error: null });
} else {
setState({ user: null, token: null, loading: false, error: null });
}
} catch {
setState({ user: null, token: null, loading: false, error: null });
}
})();
}, []);
const login = useCallback(async (usernameOrToken: string, passwordOrEmpty?: string, host?: string) => {
setState((s) => ({ ...s, loading: true, error: null }));
try {
if (host) {
setBaseUrl(host);
await saveHost(host);
}
let token: string;
let user: User;
if (!passwordOrEmpty) {
token = usernameOrToken;
api.setToken(token);
user = await api.getMe();
} else {
const res = await api.login(usernameOrToken, passwordOrEmpty);
token = res.token;
api.setToken(token);
user = await api.getMe();
}
await Promise.all([saveToken(token), saveUser(user)]);
setState({ user, token, loading: false, error: null });
} catch (err: unknown) {
const msg = err instanceof Error ? err.message : 'Login failed';
setState((s) => ({ ...s, loading: false, error: msg }));
throw err;
}
}, []);
const logout = useCallback(async () => {
await clearAll();
setState({ user: null, token: null, loading: false, error: null });
}, []);
const clearError = useCallback(() => {
setState((s) => ({ ...s, error: null }));
}, []);
return {
...state,
isAuthenticated: !!state.token && !!state.user,
login,
logout,
clearError,
};
}
|