blob: 4f504db002770e514a2d9c87b27fcaa004b8552b [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
34 }
Adrien Béraud6ecaa402021-04-06 17:37:25 -040035
36 isAuthenticated() {
Adrien Béraude74741b2021-04-19 13:22:54 -040037 return this.state.authenticated
Adrien Béraud6ecaa402021-04-06 17:37:25 -040038 }
39
Adrien Béraude74741b2021-04-19 13:22:54 -040040 getState() {
41 return this.state
42 }
43
44 init(cb) {
45 this.onAuthChanged = cb
46 if (this.state.initialized || this.authenticating)
47 return
48 console.log("Init")
49 this.authenticating = true
50 fetch('/auth')
51 .then(async (response) => {
52 this.authenticating = false
53 this.state.initialized = true
54 console.log("Init ended")
55 console.log(response)
56 if (response.status === 200) {
57 const jsonData = await response.json()
58 Object.assign(this.state, {
59 authenticated: true,
60 setupComplete: true,
61 error: false,
62 user: { username: jsonData.username, type: jsonData.type }
63 })
64 } else if (response.status === 401) {
65 const jsonData = await response.json()
66 Object.assign(this.state, {
67 authenticated: false,
68 setupComplete: 'setupComplete' in jsonData ? jsonData.setupComplete : true,
69 error: false
70 })
71 } else {
72 this.state.error = true
73 }
74 console.log("New auth state")
75 console.log(this.state)
76
77 if (this.onAuthChanged)
78 this.onAuthChanged(this.state)
79 })
80 }
81
82 deinit() {
83 console.log("Deinit")
84 this.onAuthChanged = undefined
85 }
86
87 async setup(password) {
88 if (this.authenticating || this.state.setupComplete)
89 return
90 console.log("Starting setup")
91 this.authenticating = true
92 const response = await fetch(`/setup`, {
93 method: 'POST',
94 headers: {
95 'Accept': 'application/json',
96 'Content-Type': 'application/json'
97 },
98 body: JSON.stringify({ password })
99 })
100 console.log(response)
101 if (response.ok) {
102 console.log("Success, going home")
103 //history.replace('/')
104 } else {
105 }
106 this.authenticating = false
107 this.state.setupComplete = true
108 if (this.onAuthChanged)
109 this.onAuthChanged(this.state)
110 return response.ok
111 }
112
113 authenticate(username, password) {
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400114 if (this.authenticating)
115 return
116 console.log("Starting authentication")
117 this.authenticating = true
Adrien Béraude74741b2021-04-19 13:22:54 -0400118 fetch(`/auth/local?username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`, { method:"POST" })
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400119 .then(response => {
120 console.log(response)
121 this.authenticating = false
Adrien Béraude74741b2021-04-19 13:22:54 -0400122 this.state.authenticated = response.ok && response.status === 200
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400123 if (this.onAuthChanged)
Adrien Béraude74741b2021-04-19 13:22:54 -0400124 this.onAuthChanged(this.state)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400125 while (this.tasks.length !== 0) {
126 const task = this.tasks.shift()
Adrien Béraude74741b2021-04-19 13:22:54 -0400127 if (this.state.authenticated)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400128 fetch(task.url, task.init).then(res => task.resolve(res))
129 else
130 task.reject(new Error("Authentication failed"))
131 }
132 })
133 }
134
135 disconnect() {
136 console.log("Disconnect")
Adrien Béraude74741b2021-04-19 13:22:54 -0400137 this.state.authenticated = false
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400138 if (this.onAuthChanged)
Adrien Béraude74741b2021-04-19 13:22:54 -0400139 this.onAuthChanged(this.state)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400140 }
141
142 fetch(url, init) {
143 console.log(`get ${url}`)
Adrien Béraude74741b2021-04-19 13:22:54 -0400144 if (!this.state.authenticated) {
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400145 return new Promise((resolve, reject) => this.tasks.push({url, init, resolve, reject}))
146 }
147 return fetch(url, init)
148 .then(response => {
149 console.log(`Got status ${response.status}`)
150 if (response.status === 401) {
151 this.disconnect()
152 return this.fetch(url, init)
153 }
154 return response
155 })
156 }
157}
158
159export default new AuthManager()