forked from Acode-Foundation/Acode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauth.js
More file actions
161 lines (143 loc) · 3.59 KB
/
Copy pathauth.js
File metadata and controls
161 lines (143 loc) · 3.59 KB
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import config from "./config";
/**
* @typedef {object} User
* @property {number} id
* @property {string} name
* @property {string} role
* @property {string} email
* @property {string} github
* @property {string} website
* @property {number} verified
* @property {number} threshold
* @property {number} acode_pro
* @property {number} github_id
* @property {number} google_id
* @property {string} avatar_url
* @property {string} pro_purchased_at
* @property {string} created_at
* @property {string} updated_at
* @property {boolean} isAdmin
*/
/**@type {User|null} */
let loggedInUser = null;
/**@type {number} */
let cacheTimeout = null;
const CACHE_USER_KEY = "cached-logged-in-user";
const LOGIN_RESUME_TIMEOUT_MS = 60_000;
const loginEvents = {
listeners: new Set(),
emit(data) {
for (const listener of this.listeners) {
listener(data);
}
},
addListener(callback) {
this.listeners.add(callback);
},
removeListener(callback) {
this.listeners.delete(callback);
},
};
class AuthService {
#loginCallbacks = new Set();
#loginTimeout = null;
constructor() {
loginEvents.addListener(() => {
clearTimeout(this.#loginTimeout);
for (const callback of this.#loginCallbacks) {
callback.resolve();
}
this.#loginCallbacks.clear();
});
document.addEventListener("resume", () => {
clearTimeout(this.#loginTimeout);
this.#loginTimeout = setTimeout(() => {
for (const callback of this.#loginCallbacks) {
callback.reject("Login timed out");
}
this.#loginCallbacks.clear();
}, LOGIN_RESUME_TIMEOUT_MS);
});
}
/**
* Helper to wrap cordova.exec in a Promise
*/
#exec(action, args = []) {
return new Promise((resolve, reject) => {
cordova.exec(resolve, reject, "Authenticator", action, args);
});
}
async logout() {
try {
const res = await fetch(`${config.API_BASE}/login`, {
method: "DELETE",
});
if (!res.ok) {
throw new Error("Unable to logout.");
}
} catch (error) {
console.error("Error during logout:", error);
}
loggedInUser = null;
localStorage.removeItem(CACHE_USER_KEY);
try {
await this.#exec("logout");
return true;
} catch (error) {
console.error("Failed to logout.", error);
return false;
}
}
/**
* @param {boolean} forceFetch
* @returns {Promise<User>}
*/
async getLoggedInUser(forceFetch = false) {
if (loggedInUser && !forceFetch) return loggedInUser;
try {
const res = await fetch(`${config.API_BASE}/login`);
if (res.ok) {
loggedInUser = await res.json();
localStorage.setItem(CACHE_USER_KEY, JSON.stringify(loggedInUser));
clearTimeout(cacheTimeout);
cacheTimeout = setTimeout(() => (loggedInUser = null), 600_000);
return loggedInUser;
}
if (res.status === 401) {
localStorage.removeItem(CACHE_USER_KEY);
return null;
}
throw new Error("Unable to fetch user Info");
} catch (error) {
if (CACHE_USER_KEY in localStorage) {
try {
return JSON.parse(localStorage.getItem(CACHE_USER_KEY));
} catch {}
}
console.error("Unable to fetch user info:", error);
throw error;
}
}
async login() {
return new Promise((resolve, reject) => {
const callback = { resolve, reject };
this.#loginCallbacks.add(callback);
this.#exec("login", [
{
baseUrl: config.BASE_URL,
appVersionCode: window.BuildInfo?.versionCode || 0,
},
])
.then(() => {
loginEvents.emit();
})
.catch((err) => {
console.error("Native login error", err);
this.#loginCallbacks.delete(callback);
reject("Failed to login");
});
});
}
}
export default new AuthService();
export { loginEvents };