blob: ea55c3a29b107c56aceeba2cfe138999a169b661 [file] [log] [blame]
simon80b7b3b2022-09-28 17:50:10 -04001/* eslint-disable no-undef */
2// TODO: This hides eslint errors for this file. This should be removed once this file is cleaned up.
3
Adrien Béraud6ecaa402021-04-06 17:37:25 -04004/*
5 * Copyright (c) 2017-2021 Savoir-faire Linux Inc.
6 *
7 * Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
Adrien Béraud6ecaa402021-04-06 17:37:25 -040023class AuthManager {
simond47ef9e2022-09-28 22:24:28 -040024 constructor() {
25 console.log('AuthManager()');
26 this.authenticating = false;
Adrien Béraude74741b2021-04-19 13:22:54 -040027
simond47ef9e2022-09-28 22:24:28 -040028 this.state = {
29 initialized: false,
30 authenticated: true,
31 setupComplete: true,
32 error: false,
33 };
Adrien Béraude74741b2021-04-19 13:22:54 -040034
simond47ef9e2022-09-28 22:24:28 -040035 this.tasks = [];
36 this.onAuthChanged = undefined;
Adrien Béraude5cad982021-06-07 10:05:50 -040037
simond47ef9e2022-09-28 22:24:28 -040038 if (initData) {
39 console.log('Using static initData');
40 this.setInitData(initData);
41 return;
Adrien Béraud6ecaa402021-04-06 17:37:25 -040042 }
simond47ef9e2022-09-28 22:24:28 -040043 }
Adrien Béraud6ecaa402021-04-06 17:37:25 -040044
simond47ef9e2022-09-28 22:24:28 -040045 isAuthenticated() {
46 return this.state.authenticated;
47 }
48
49 getState() {
50 return this.state;
51 }
52
53 setInitData(data) {
54 this.authenticating = false;
55 this.state.initialized = true;
56 if (data.username) {
57 Object.assign(this.state, {
58 authenticated: true,
59 setupComplete: true,
60 error: false,
61 user: { username: data.username, type: data.type },
62 });
63 } else {
64 Object.assign(this.state, {
65 authenticated: false,
66 setupComplete: 'setupComplete' in data ? data.setupComplete : true,
67 error: false,
68 });
Adrien Béraud6ecaa402021-04-06 17:37:25 -040069 }
simond47ef9e2022-09-28 22:24:28 -040070 console.log('Init ended');
71 /*if (this.onAuthChanged)
Adrien Béraude5cad982021-06-07 10:05:50 -040072 this.onAuthChanged(this.state)*/
simond47ef9e2022-09-28 22:24:28 -040073 }
Adrien Béraude5cad982021-06-07 10:05:50 -040074
simond47ef9e2022-09-28 22:24:28 -040075 init(cb) {
76 this.onAuthChanged = cb;
77 if (this.state.initialized || this.authenticating) return;
78 /*if (initData) {
Adrien Béraude5cad982021-06-07 10:05:50 -040079 console.log("Using static initData")
80 this.setInitData(initData)
81 return
82 }*/
simond47ef9e2022-09-28 22:24:28 -040083 this.authenticating = true;
84 fetch('/auth')
85 .then(async (response) => {
86 this.authenticating = false;
87 this.state.initialized = true;
88 if (response.status === 200) {
89 this.setInitData(await response.json());
90 } else if (response.status === 401) {
91 this.setInitData(await response.json());
Adrien Béraude74741b2021-04-19 13:22:54 -040092 } else {
simond47ef9e2022-09-28 22:24:28 -040093 this.state.error = true;
94 if (this.onAuthChanged) this.onAuthChanged(this.state);
Adrien Béraude74741b2021-04-19 13:22:54 -040095 }
simond47ef9e2022-09-28 22:24:28 -040096 })
97 .catch((e) => {
98 this.authenticating = false;
99 console.log(e);
100 });
101 }
Adrien Béraude74741b2021-04-19 13:22:54 -0400102
simond47ef9e2022-09-28 22:24:28 -0400103 deinit() {
104 console.log('Deinit');
105 this.onAuthChanged = undefined;
106 }
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400107
simond47ef9e2022-09-28 22:24:28 -0400108 async setup(password) {
109 if (this.authenticating || this.state.setupComplete) return;
110 console.log('Starting setup');
111 this.authenticating = true;
112 const response = await fetch(`/setup`, {
113 method: 'POST',
114 headers: {
115 Accept: 'application/json',
116 'Content-Type': 'application/json',
117 },
118 body: JSON.stringify({ password }),
119 });
120 console.log(response);
121 if (response.ok) {
122 console.log('Success, going home');
123 //navigate('/')
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400124 }
simon80b7b3b2022-09-28 17:50:10 -0400125
simond47ef9e2022-09-28 22:24:28 -0400126 this.authenticating = false;
127 this.state.setupComplete = true;
128 if (this.onAuthChanged) this.onAuthChanged(this.state);
129 return response.ok;
130 }
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400131
simond47ef9e2022-09-28 22:24:28 -0400132 authenticate(username, password) {
133 if (this.authenticating) return;
134 console.log('Starting authentication');
135 this.authenticating = true;
136 fetch(`/auth/local?username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`, {
137 method: 'POST',
138 })
139 .then((response) => {
140 console.log(response);
141 this.authenticating = false;
142 this.state.authenticated = response.ok && response.status === 200;
143 if (this.onAuthChanged) this.onAuthChanged(this.state);
144 while (this.tasks.length !== 0) {
145 const task = this.tasks.shift();
146 if (this.state.authenticated)
147 fetch(task.url, task.init)
148 .then((res) => task.resolve(res))
149 .catch((e) => console.log('Error executing pending task: ' + e));
150 else task.reject(new Error('Authentication failed'));
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400151 }
simond47ef9e2022-09-28 22:24:28 -0400152 })
153 .catch((e) => {
154 this.authenticating = false;
155 console.log(e);
156 });
157 }
158
159 disconnect() {
160 console.log('Disconnect');
161 this.state.authenticated = false;
162 if (this.onAuthChanged) this.onAuthChanged(this.state);
163 }
164
165 fetch(url, init) {
166 console.log(`fetch ${url}`);
167 if (!this.state.authenticated) {
168 if (!init || !init.method || init.method === 'GET') {
169 return new Promise((resolve, reject) => this.tasks.push({ url, init, resolve, reject }));
170 } else {
171 return new Promise((resolve, reject) => reject('Not authenticated'));
172 }
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400173 }
simond47ef9e2022-09-28 22:24:28 -0400174 return fetch(url, init).then((response) => {
175 if (response.status === 401) {
176 this.disconnect();
177 return this.fetch(url, init);
178 }
179 return response;
180 });
181 }
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400182}
183
simond47ef9e2022-09-28 22:24:28 -0400184export default new AuthManager();