blob: 83f731fc531998659b938d659abcbe2d954c9083 [file] [log] [blame]
Adrien Béraud6ecaa402021-04-06 17:37:25 -04001/*
2 * Copyright (c) 2017-2021 Savoir-faire Linux Inc.
3 *
4 * Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
Adrien Béraud6ecaa402021-04-06 17:37:25 -040020class AuthManager {
21 constructor() {
22 console.log("AuthManager()")
Adrien Béraud6ecaa402021-04-06 17:37:25 -040023 this.authenticating = false
Adrien Béraude74741b2021-04-19 13:22:54 -040024
25 this.state = {
26 initialized: false,
27 authenticated: true,
28 setupComplete: true,
29 error: false
30 }
31
Adrien Béraud6ecaa402021-04-06 17:37:25 -040032 this.tasks = []
33 this.onAuthChanged = undefined
Adrien Béraude5cad982021-06-07 10:05:50 -040034
35 if (initData) {
36 console.log("Using static initData")
37 this.setInitData(initData)
38 return
39 }
Adrien Béraud6ecaa402021-04-06 17:37:25 -040040 }
Adrien Béraud6ecaa402021-04-06 17:37:25 -040041
42 isAuthenticated() {
Adrien Béraude74741b2021-04-19 13:22:54 -040043 return this.state.authenticated
Adrien Béraud6ecaa402021-04-06 17:37:25 -040044 }
45
Adrien Béraude74741b2021-04-19 13:22:54 -040046 getState() {
47 return this.state
48 }
49
Adrien Béraude5cad982021-06-07 10:05:50 -040050 setInitData(data) {
51 this.authenticating = false
52 this.state.initialized = true
53 if (data.username) {
54 Object.assign(this.state, {
55 authenticated: true,
56 setupComplete: true,
57 error: false,
58 user: { username: data.username, type: data.type }
59 })
60 } else {
61 Object.assign(this.state, {
62 authenticated: false,
63 setupComplete: 'setupComplete' in data ? data.setupComplete : true,
64 error: false
65 })
66 }
67 console.log("Init ended")
68 /*if (this.onAuthChanged)
69 this.onAuthChanged(this.state)*/
70 }
71
Adrien Béraude74741b2021-04-19 13:22:54 -040072 init(cb) {
73 this.onAuthChanged = cb
74 if (this.state.initialized || this.authenticating)
75 return
Adrien Béraude5cad982021-06-07 10:05:50 -040076 /*if (initData) {
77 console.log("Using static initData")
78 this.setInitData(initData)
79 return
80 }*/
Adrien Béraude74741b2021-04-19 13:22:54 -040081 this.authenticating = true
82 fetch('/auth')
83 .then(async (response) => {
84 this.authenticating = false
85 this.state.initialized = true
Adrien Béraude74741b2021-04-19 13:22:54 -040086 if (response.status === 200) {
Adrien Béraude5cad982021-06-07 10:05:50 -040087 this.setInitData(await response.json())
Adrien Béraude74741b2021-04-19 13:22:54 -040088 } else if (response.status === 401) {
Adrien Béraude5cad982021-06-07 10:05:50 -040089 this.setInitData(await response.json())
Adrien Béraude74741b2021-04-19 13:22:54 -040090 } else {
91 this.state.error = true
Adrien Béraude5cad982021-06-07 10:05:50 -040092 if (this.onAuthChanged)
93 this.onAuthChanged(this.state)
Adrien Béraude74741b2021-04-19 13:22:54 -040094 }
Adrien Béraud88a52442021-04-26 12:11:41 -040095 }).catch(e => {
96 this.authenticating = false
97 console.log(e)
Adrien Béraude74741b2021-04-19 13:22:54 -040098 })
99 }
100
101 deinit() {
102 console.log("Deinit")
103 this.onAuthChanged = undefined
104 }
105
106 async setup(password) {
107 if (this.authenticating || this.state.setupComplete)
108 return
109 console.log("Starting setup")
110 this.authenticating = true
111 const response = await fetch(`/setup`, {
112 method: 'POST',
113 headers: {
114 'Accept': 'application/json',
115 'Content-Type': 'application/json'
116 },
117 body: JSON.stringify({ password })
118 })
119 console.log(response)
120 if (response.ok) {
121 console.log("Success, going home")
122 //history.replace('/')
123 } else {
124 }
125 this.authenticating = false
126 this.state.setupComplete = true
127 if (this.onAuthChanged)
128 this.onAuthChanged(this.state)
129 return response.ok
130 }
131
132 authenticate(username, password) {
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400133 if (this.authenticating)
134 return
135 console.log("Starting authentication")
136 this.authenticating = true
Adrien Béraude74741b2021-04-19 13:22:54 -0400137 fetch(`/auth/local?username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`, { method:"POST" })
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400138 .then(response => {
139 console.log(response)
140 this.authenticating = false
Adrien Béraude74741b2021-04-19 13:22:54 -0400141 this.state.authenticated = response.ok && response.status === 200
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400142 if (this.onAuthChanged)
Adrien Béraude74741b2021-04-19 13:22:54 -0400143 this.onAuthChanged(this.state)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400144 while (this.tasks.length !== 0) {
145 const task = this.tasks.shift()
Adrien Béraude74741b2021-04-19 13:22:54 -0400146 if (this.state.authenticated)
Adrien Béraude5cad982021-06-07 10:05:50 -0400147 fetch(task.url, task.init)
148 .then(res => task.resolve(res))
149 .catch(e => console.log("Error executing pending task: " + e))
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400150 else
151 task.reject(new Error("Authentication failed"))
152 }
Adrien Béraud88a52442021-04-26 12:11:41 -0400153 }).catch(e => {
154 this.authenticating = false
155 console.log(e)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400156 })
157 }
158
159 disconnect() {
160 console.log("Disconnect")
Adrien Béraude74741b2021-04-19 13:22:54 -0400161 this.state.authenticated = false
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400162 if (this.onAuthChanged)
Adrien Béraude74741b2021-04-19 13:22:54 -0400163 this.onAuthChanged(this.state)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400164 }
165
166 fetch(url, init) {
Adrien Béraud150b4782021-04-21 19:40:59 -0400167 console.log(`fetch ${url}`)
Adrien Béraude74741b2021-04-19 13:22:54 -0400168 if (!this.state.authenticated) {
Adrien Béraud4e287b92021-04-24 16:15:56 -0400169 if (!init || !init.method || init.method === 'GET') {
170 return new Promise((resolve, reject) => this.tasks.push({url, init, resolve, reject}))
171 } else {
172 return new Promise((resolve, reject) => reject("Not authenticated"))
173 }
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400174 }
175 return fetch(url, init)
176 .then(response => {
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400177 if (response.status === 401) {
178 this.disconnect()
179 return this.fetch(url, init)
180 }
181 return response
182 })
183 }
184}
185
186export default new AuthManager()