diff options
Diffstat (limited to 'app/Controllers/Http/UserController.js')
-rw-r--r-- | app/Controllers/Http/UserController.js | 150 |
1 files changed, 77 insertions, 73 deletions
diff --git a/app/Controllers/Http/UserController.js b/app/Controllers/Http/UserController.js index 0d768a9..99336cb 100644 --- a/app/Controllers/Http/UserController.js +++ b/app/Controllers/Http/UserController.js | |||
@@ -1,44 +1,41 @@ | |||
1 | const User = use('App/Models/User'); | 1 | const User = use('App/Models/User'); |
2 | const Service = use('App/Models/Service'); | 2 | const Service = use('App/Models/Service'); |
3 | const Workspace = use('App/Models/Workspace'); | 3 | const Workspace = use('App/Models/Workspace'); |
4 | const { | 4 | const { validateAll } = use('Validator'); |
5 | validateAll, | ||
6 | } = use('Validator'); | ||
7 | const Env = use('Env'); | 5 | const Env = use('Env'); |
8 | 6 | ||
9 | const atob = require('atob'); | 7 | const atob = require('atob'); |
10 | const btoa = require('btoa'); | 8 | const btoa = require('btoa'); |
11 | const fetch = require('node-fetch'); | 9 | const fetch = require('node-fetch'); |
12 | const uuid = require('uuid/v4'); | 10 | const { v4: uuid } = require('uuid'); |
13 | const crypto = require('crypto'); | 11 | const crypto = require('crypto'); |
14 | 12 | ||
15 | const franzRequest = (route, method, auth) => new Promise((resolve, reject) => { | 13 | const franzRequest = (route, method, auth) => |
16 | const base = 'https://api.franzinfra.com/v1/'; | 14 | new Promise((resolve, reject) => { |
17 | const user = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Ferdi/5.3.0-beta.1 Chrome/69.0.3497.128 Electron/4.2.4 Safari/537.36'; | 15 | const base = 'https://api.franzinfra.com/v1/'; |
16 | const user = | ||
17 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Ferdi/5.3.0-beta.1 Chrome/69.0.3497.128 Electron/4.2.4 Safari/537.36'; | ||
18 | 18 | ||
19 | try { | 19 | try { |
20 | fetch(base + route, { | 20 | fetch(base + route, { |
21 | method, | 21 | method, |
22 | headers: { | 22 | headers: { |
23 | Authorization: `Bearer ${auth}`, | 23 | Authorization: `Bearer ${auth}`, |
24 | 'User-Agent': user, | 24 | 'User-Agent': user, |
25 | }, | 25 | }, |
26 | }) | 26 | }) |
27 | .then((data) => data.json()) | 27 | .then(data => data.json()) |
28 | .then((json) => resolve(json)); | 28 | .then(json => resolve(json)); |
29 | } catch (e) { | 29 | } catch (e) { |
30 | reject(); | 30 | reject(); |
31 | } | 31 | } |
32 | }); | 32 | }); |
33 | 33 | ||
34 | class UserController { | 34 | class UserController { |
35 | // Register a new user | 35 | // Register a new user |
36 | async signup({ | 36 | async signup({ request, response, auth }) { |
37 | request, | 37 | if (Env.get('IS_REGISTRATION_ENABLED') == 'false') { |
38 | response, | 38 | // eslint-disable-line eqeqeq |
39 | auth, | ||
40 | }) { | ||
41 | if (Env.get('IS_REGISTRATION_ENABLED') == 'false') { // eslint-disable-line eqeqeq | ||
42 | return response.status(401).send({ | 39 | return response.status(401).send({ |
43 | message: 'Registration is disabled on this server', | 40 | message: 'Registration is disabled on this server', |
44 | status: 401, | 41 | status: 401, |
@@ -89,11 +86,7 @@ class UserController { | |||
89 | } | 86 | } |
90 | 87 | ||
91 | // Login using an existing user | 88 | // Login using an existing user |
92 | async login({ | 89 | async login({ request, response, auth }) { |
93 | request, | ||
94 | response, | ||
95 | auth, | ||
96 | }) { | ||
97 | if (!request.header('Authorization')) { | 90 | if (!request.header('Authorization')) { |
98 | return response.status(401).send({ | 91 | return response.status(401).send({ |
99 | message: 'Please provide authorization', | 92 | message: 'Please provide authorization', |
@@ -102,10 +95,12 @@ class UserController { | |||
102 | } | 95 | } |
103 | 96 | ||
104 | // Get auth data from auth token | 97 | // Get auth data from auth token |
105 | const authHeader = atob(request.header('Authorization').replace('Basic ', '')).split(':'); | 98 | const authHeader = atob( |
99 | request.header('Authorization').replace('Basic ', ''), | ||
100 | ).split(':'); | ||
106 | 101 | ||
107 | // Check if user with email exists | 102 | // Check if user with email exists |
108 | const user = (await User.query().where('email', authHeader[0]).first()); | 103 | const user = await User.query().where('email', authHeader[0]).first(); |
109 | if (!user || !user.email) { | 104 | if (!user || !user.email) { |
110 | return response.status(401).send({ | 105 | return response.status(401).send({ |
111 | message: 'User credentials not valid (Invalid mail)', | 106 | message: 'User credentials not valid (Invalid mail)', |
@@ -133,17 +128,17 @@ class UserController { | |||
133 | } | 128 | } |
134 | 129 | ||
135 | // Return information about the current user | 130 | // Return information about the current user |
136 | async me({ | 131 | async me({ response, auth }) { |
137 | response, | ||
138 | auth, | ||
139 | }) { | ||
140 | try { | 132 | try { |
141 | await auth.getUser(); | 133 | await auth.getUser(); |
142 | } catch (error) { | 134 | } catch (error) { |
143 | response.send('Missing or invalid api token'); | 135 | response.send('Missing or invalid api token'); |
144 | } | 136 | } |
145 | 137 | ||
146 | const settings = typeof auth.user.settings === 'string' ? JSON.parse(auth.user.settings) : auth.user.settings; | 138 | const settings = |
139 | typeof auth.user.settings === 'string' | ||
140 | ? JSON.parse(auth.user.settings) | ||
141 | : auth.user.settings; | ||
147 | 142 | ||
148 | return response.send({ | 143 | return response.send({ |
149 | accountType: 'individual', | 144 | accountType: 'individual', |
@@ -158,15 +153,11 @@ class UserController { | |||
158 | isSubscriptionOwner: true, | 153 | isSubscriptionOwner: true, |
159 | lastname: auth.user.lastname, | 154 | lastname: auth.user.lastname, |
160 | locale: 'en-US', | 155 | locale: 'en-US', |
161 | ...settings || {}, | 156 | ...(settings || {}), |
162 | }); | 157 | }); |
163 | } | 158 | } |
164 | 159 | ||
165 | async updateMe({ | 160 | async updateMe({ request, response, auth }) { |
166 | request, | ||
167 | response, | ||
168 | auth, | ||
169 | }) { | ||
170 | let settings = auth.user.settings || {}; | 161 | let settings = auth.user.settings || {}; |
171 | if (typeof settings === 'string') { | 162 | if (typeof settings === 'string') { |
172 | settings = JSON.parse(settings); | 163 | settings = JSON.parse(settings); |
@@ -195,21 +186,15 @@ class UserController { | |||
195 | isSubscriptionOwner: true, | 186 | isSubscriptionOwner: true, |
196 | lastname: auth.user.lastname, | 187 | lastname: auth.user.lastname, |
197 | locale: 'en-US', | 188 | locale: 'en-US', |
198 | ...newSettings || {}, | 189 | ...(newSettings || {}), |
199 | }, | 190 | }, |
200 | status: [ | 191 | status: ['data-updated'], |
201 | 'data-updated', | ||
202 | ], | ||
203 | }); | 192 | }); |
204 | } | 193 | } |
205 | 194 | ||
206 | 195 | async import({ request, response, view }) { | |
207 | async import({ | 196 | if (Env.get('IS_REGISTRATION_ENABLED') == 'false') { |
208 | request, | 197 | // eslint-disable-line eqeqeq |
209 | response, | ||
210 | view, | ||
211 | }) { | ||
212 | if (Env.get('IS_REGISTRATION_ENABLED') == 'false') { // eslint-disable-line eqeqeq | ||
213 | return response.status(401).send({ | 198 | return response.status(401).send({ |
214 | message: 'Registration is disabled on this server', | 199 | message: 'Registration is disabled on this server', |
215 | status: 401, | 200 | status: 401, |
@@ -222,7 +207,8 @@ class UserController { | |||
222 | password: 'required', | 207 | password: 'required', |
223 | }); | 208 | }); |
224 | if (validation.fails()) { | 209 | if (validation.fails()) { |
225 | let errorMessage = 'There was an error while trying to import your account:\n'; | 210 | let errorMessage = |
211 | 'There was an error while trying to import your account:\n'; | ||
226 | for (const message of validation.messages()) { | 212 | for (const message of validation.messages()) { |
227 | if (message.validation === 'required') { | 213 | if (message.validation === 'required') { |
228 | errorMessage += `- Please make sure to supply your ${message.field}\n`; | 214 | errorMessage += `- Please make sure to supply your ${message.field}\n`; |
@@ -238,14 +224,15 @@ class UserController { | |||
238 | }); | 224 | }); |
239 | } | 225 | } |
240 | 226 | ||
241 | const { | 227 | const { email, password } = request.all(); |
242 | email, | ||
243 | password, | ||
244 | } = request.all(); | ||
245 | 228 | ||
246 | const hashedPassword = crypto.createHash('sha256').update(password).digest('base64'); | 229 | const hashedPassword = crypto |
230 | .createHash('sha256') | ||
231 | .update(password) | ||
232 | .digest('base64'); | ||
247 | 233 | ||
248 | if (Env.get('CONNECT_WITH_FRANZ') == 'false') { // eslint-disable-line eqeqeq | 234 | if (Env.get('CONNECT_WITH_FRANZ') == 'false') { |
235 | // eslint-disable-line eqeqeq | ||
249 | await User.create({ | 236 | await User.create({ |
250 | email, | 237 | email, |
251 | password: hashedPassword, | 238 | password: hashedPassword, |
@@ -253,11 +240,14 @@ class UserController { | |||
253 | lastname: 'Franz', | 240 | lastname: 'Franz', |
254 | }); | 241 | }); |
255 | 242 | ||
256 | return response.send('Your account has been created but due to this server\'s configuration, we could not import your Franz account data.\n\nIf you are the server owner, please set CONNECT_WITH_FRANZ to true to enable account imports.'); | 243 | return response.send( |
244 | "Your account has been created but due to this server's configuration, we could not import your Franz account data.\n\nIf you are the server owner, please set CONNECT_WITH_FRANZ to true to enable account imports.", | ||
245 | ); | ||
257 | } | 246 | } |
258 | 247 | ||
259 | const base = 'https://api.franzinfra.com/v1/'; | 248 | const base = 'https://api.franzinfra.com/v1/'; |
260 | const userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Ferdi/5.3.0-beta.1 Chrome/69.0.3497.128 Electron/4.2.4 Safari/537.36'; | 249 | const userAgent = |
250 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Ferdi/5.3.0-beta.1 Chrome/69.0.3497.128 Electron/4.2.4 Safari/537.36'; | ||
261 | 251 | ||
262 | // Try to get an authentication token | 252 | // Try to get an authentication token |
263 | let token; | 253 | let token; |
@@ -281,7 +271,8 @@ class UserController { | |||
281 | const content = await rawResponse.json(); | 271 | const content = await rawResponse.json(); |
282 | 272 | ||
283 | if (!content.message || content.message !== 'Successfully logged in') { | 273 | if (!content.message || content.message !== 'Successfully logged in') { |
284 | const errorMessage = 'Could not login into Franz with your supplied credentials. Please check and try again'; | 274 | const errorMessage = |
275 | 'Could not login into Franz with your supplied credentials. Please check and try again'; | ||
285 | return response.status(401).send(errorMessage); | 276 | return response.status(401).send(errorMessage); |
286 | } | 277 | } |
287 | 278 | ||
@@ -302,7 +293,8 @@ class UserController { | |||
302 | return response.status(401).send(errorMessage); | 293 | return response.status(401).send(errorMessage); |
303 | } | 294 | } |
304 | if (!userInf) { | 295 | if (!userInf) { |
305 | const errorMessage = 'Could not get your user info from Franz. Please check your credentials or try again later'; | 296 | const errorMessage = |
297 | 'Could not get your user info from Franz. Please check your credentials or try again later'; | ||
306 | return response.status(401).send(errorMessage); | 298 | return response.status(401).send(errorMessage); |
307 | } | 299 | } |
308 | 300 | ||
@@ -331,9 +323,13 @@ class UserController { | |||
331 | let serviceId; | 323 | let serviceId; |
332 | do { | 324 | do { |
333 | serviceId = uuid(); | 325 | serviceId = uuid(); |
334 | } while ((await Service.query().where('serviceId', serviceId).fetch()).rows.length > 0); // eslint-disable-line no-await-in-loop | 326 | } while ( |
327 | (await Service.query().where('serviceId', serviceId).fetch()).rows | ||
328 | .length > 0 | ||
329 | ); // eslint-disable-line no-await-in-loop | ||
335 | 330 | ||
336 | await Service.create({ // eslint-disable-line no-await-in-loop | 331 | await Service.create({ |
332 | // eslint-disable-line no-await-in-loop | ||
337 | userId: user.id, | 333 | userId: user.id, |
338 | serviceId, | 334 | serviceId, |
339 | name: service.name, | 335 | name: service.name, |
@@ -356,11 +352,17 @@ class UserController { | |||
356 | let workspaceId; | 352 | let workspaceId; |
357 | do { | 353 | do { |
358 | workspaceId = uuid(); | 354 | workspaceId = uuid(); |
359 | } while ((await Workspace.query().where('workspaceId', workspaceId).fetch()).rows.length > 0); // eslint-disable-line no-await-in-loop | 355 | } while ( |
356 | (await Workspace.query().where('workspaceId', workspaceId).fetch()) | ||
357 | .rows.length > 0 | ||
358 | ); // eslint-disable-line no-await-in-loop | ||
360 | 359 | ||
361 | const services = workspace.services.map((service) => serviceIdTranslation[service]); | 360 | const services = workspace.services.map( |
361 | service => serviceIdTranslation[service], | ||
362 | ); | ||
362 | 363 | ||
363 | await Workspace.create({ // eslint-disable-line no-await-in-loop | 364 | await Workspace.create({ |
365 | // eslint-disable-line no-await-in-loop | ||
364 | userId: user.id, | 366 | userId: user.id, |
365 | workspaceId, | 367 | workspaceId, |
366 | name: workspace.name, | 368 | name: workspace.name, |
@@ -374,7 +376,9 @@ class UserController { | |||
374 | return response.status(401).send(errorMessage); | 376 | return response.status(401).send(errorMessage); |
375 | } | 377 | } |
376 | 378 | ||
377 | return response.send('Your account has been imported. You can now use your Franz account in Ferdi.'); | 379 | return response.send( |
380 | 'Your account has been imported. You can now use your Franz account in Ferdi.', | ||
381 | ); | ||
378 | } | 382 | } |
379 | } | 383 | } |
380 | 384 | ||