/
auth.js
121 lines (111 loc) · 3.02 KB
/
auth.js
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import React from 'react';
import AsyncStorage from '@react-native-community/async-storage';
import {STORAGE_KEYS} from '../constants';
export const AuthContext = React.createContext();
export const AuthProvider = ({children}) => {
const [auth, setAuth] = React.useState();
const [username, setUsername] = React.useState();
const [secret, setSecret] = React.useState();
const [ready, setReady] = React.useState(false);
React.useEffect(() => {
(async () => {
// For debugging
// const storage = await AsyncStorage.multiGet(
// await AsyncStorage.getAllKeys(),
// )
// console.log(JSON.stringify(storage, null, 2))
const [
[, _auth],
[, _username],
[, _secret],
] = await AsyncStorage.multiGet([
STORAGE_KEYS.auth,
STORAGE_KEYS.username,
STORAGE_KEYS.secret,
]);
// console.log(_auth, _username, _secret)
setAuth(_auth);
setUsername(_username);
setSecret(_secret);
setReady(true);
})();
}, []);
const fetchWithAuth = React.useCallback(
async (url, opts = {}) => {
if (auth) {
opts.headers = opts.headers || {};
opts.headers.Cookie = `auth=${auth}`;
}
const res = await fetch('https://echojs.com/api' + url, opts);
const json = await res.json();
if (json.status === 'err') {
throw new Error(json.error);
}
return json;
},
[auth],
);
const login = React.useCallback(
async (_username, password) => {
const json = await fetchWithAuth(
`/login?username=${_username}&password=${password}`,
);
await AsyncStorage.multiSet([
[STORAGE_KEYS.auth, json.auth],
[STORAGE_KEYS.username, _username],
[STORAGE_KEYS.secret, json.apisecret],
]);
setAuth(json.auth);
setUsername(_username);
setSecret(json.apisecret);
},
[fetchWithAuth],
);
const createAccount = React.useCallback(
async (_username, password) => {
await fetchWithAuth(
`/create_account?username=${_username}&password=${password}`,
{method: 'POST'},
);
// Seems EchoJS's create account API does not return secret
// So don't use any data from this API
// Just create account and call login API again to login
},
[fetchWithAuth],
);
const logout = React.useCallback(async () => {
try {
await fetchWithAuth(`/logout?apisecret=${secret}`, {
method: 'POST',
});
} catch (err) {
} finally {
await AsyncStorage.multiRemove([
STORAGE_KEYS.auth,
STORAGE_KEYS.username,
STORAGE_KEYS.secret,
]);
setAuth(null);
setUsername(null);
setSecret(null);
}
}, [fetchWithAuth, secret]);
if (!ready) {
return null;
}
return (
<AuthContext.Provider
value={{
auth,
username,
secret,
ready,
login,
createAccount,
logout,
fetchWithAuth,
}}>
{children}
</AuthContext.Provider>
);
};