diff options
author | 2024-02-10 18:37:40 -0700 | |
---|---|---|
committer | 2024-02-13 06:59:44 +0530 | |
commit | e1c47572a6235fd8fd20af888ac3a11c7ae1369d (patch) | |
tree | 2dccff36a441916d7014037cef3f7ce84a790cad /app/Controllers/Http/UserController.ts | |
parent | refactor: project maintenance (diff) | |
download | ferdium-server-e1c47572a6235fd8fd20af888ac3a11c7ae1369d.tar.gz ferdium-server-e1c47572a6235fd8fd20af888ac3a11c7ae1369d.tar.zst ferdium-server-e1c47572a6235fd8fd20af888ac3a11c7ae1369d.zip |
updates
Diffstat (limited to 'app/Controllers/Http/UserController.ts')
-rw-r--r-- | app/Controllers/Http/UserController.ts | 229 |
1 files changed, 123 insertions, 106 deletions
diff --git a/app/Controllers/Http/UserController.ts b/app/Controllers/Http/UserController.ts index 088f7b1..667786b 100644 --- a/app/Controllers/Http/UserController.ts +++ b/app/Controllers/Http/UserController.ts | |||
@@ -1,49 +1,58 @@ | |||
1 | import type { HttpContext } from '@adonisjs/core/http' | 1 | import type { HttpContext } from '@adonisjs/core/http'; |
2 | import { schema, rules } from '@adonisjs/validator' | 2 | import { schema, rules } from '@adonisjs/validator'; |
3 | import User from '#app/Models/User' | 3 | import User from '#app/Models/User'; |
4 | import { connectWithFranz, isRegistrationEnabled } from '../../../config/app.js' | 4 | import { |
5 | import crypto from 'node:crypto' | 5 | connectWithFranz, |
6 | import { v4 as uuid } from 'uuid' | 6 | isRegistrationEnabled, |
7 | import Workspace from '#app/Models/Workspace' | 7 | } from '../../../config/app.js'; |
8 | import Service from '#app/Models/Service' | 8 | import crypto from 'node:crypto'; |
9 | import { v4 as uuid } from 'uuid'; | ||
10 | import Workspace from '#app/Models/Workspace'; | ||
11 | import Service from '#app/Models/Service'; | ||
9 | 12 | ||
10 | // TODO: This file needs to be refactored and cleaned up to include types | 13 | // TODO: This file needs to be refactored and cleaned up to include types |
11 | import { handleVerifyAndReHash } from '../../../helpers/PasswordHash.js' | 14 | import { handleVerifyAndReHash } from '../../../helpers/PasswordHash.js'; |
12 | 15 | ||
13 | const newPostSchema = schema.create({ | 16 | const newPostSchema = schema.create({ |
14 | firstname: schema.string(), | 17 | firstname: schema.string(), |
15 | lastname: schema.string(), | 18 | lastname: schema.string(), |
16 | email: schema.string([rules.email(), rules.unique({ table: 'users', column: 'email' })]), | 19 | email: schema.string([ |
20 | rules.email(), | ||
21 | rules.unique({ table: 'users', column: 'email' }), | ||
22 | ]), | ||
17 | password: schema.string([rules.minLength(8)]), | 23 | password: schema.string([rules.minLength(8)]), |
18 | }) | 24 | }); |
19 | 25 | ||
20 | const franzImportSchema = schema.create({ | 26 | const franzImportSchema = schema.create({ |
21 | email: schema.string([rules.email(), rules.unique({ table: 'users', column: 'email' })]), | 27 | email: schema.string([ |
28 | rules.email(), | ||
29 | rules.unique({ table: 'users', column: 'email' }), | ||
30 | ]), | ||
22 | password: schema.string([rules.minLength(8)]), | 31 | password: schema.string([rules.minLength(8)]), |
23 | }) | 32 | }); |
24 | 33 | ||
25 | // // TODO: This whole controller needs to be changed such that it can support importing from both Franz and Ferdi | 34 | // // TODO: This whole controller needs to be changed such that it can support importing from both Franz and Ferdi |
26 | // eslint-disable-next-line @typescript-eslint/no-explicit-any | 35 | // eslint-disable-next-line @typescript-eslint/no-explicit-any |
27 | const franzRequest = (route: any, method: any, auth: any) => | 36 | const franzRequest = (route: any, method: any, auth: any) => |
28 | new Promise((resolve, reject) => { | 37 | new Promise((resolve, reject) => { |
29 | const base = 'https://api.franzinfra.com/v1/' | 38 | const base = 'https://api.franzinfra.com/v1/'; |
30 | const user = | 39 | const user = |
31 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Franz/5.3.0-beta.1 Chrome/69.0.3497.128 Electron/4.2.4 Safari/537.36' | 40 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Franz/5.3.0-beta.1 Chrome/69.0.3497.128 Electron/4.2.4 Safari/537.36'; |
32 | 41 | ||
33 | try { | 42 | try { |
34 | fetch(base + route, { | 43 | fetch(base + route, { |
35 | method, | 44 | method, |
36 | headers: { | 45 | headers: { |
37 | 'Authorization': `Bearer ${auth}`, | 46 | Authorization: `Bearer ${auth}`, |
38 | 'User-Agent': user, | 47 | 'User-Agent': user, |
39 | }, | 48 | }, |
40 | }) | 49 | }) |
41 | .then((data) => data.json()) | 50 | .then(data => data.json()) |
42 | .then((json) => resolve(json)) | 51 | .then(json => resolve(json)); |
43 | } catch { | 52 | } catch { |
44 | reject() | 53 | reject(); |
45 | } | 54 | } |
46 | }) | 55 | }); |
47 | 56 | ||
48 | export default class UsersController { | 57 | export default class UsersController { |
49 | // Register a new user | 58 | // Register a new user |
@@ -52,44 +61,44 @@ export default class UsersController { | |||
52 | return response.status(401).send({ | 61 | return response.status(401).send({ |
53 | message: 'Registration is disabled on this server', | 62 | message: 'Registration is disabled on this server', |
54 | status: 401, | 63 | status: 401, |
55 | }) | 64 | }); |
56 | } | 65 | } |
57 | 66 | ||
58 | // Validate user input | 67 | // Validate user input |
59 | let data | 68 | let data; |
60 | try { | 69 | try { |
61 | data = await request.validate({ schema: newPostSchema }) | 70 | data = await request.validate({ schema: newPostSchema }); |
62 | } catch (error) { | 71 | } catch (error) { |
63 | return response.status(401).send({ | 72 | return response.status(401).send({ |
64 | message: 'Invalid POST arguments', | 73 | message: 'Invalid POST arguments', |
65 | messages: error.messages, | 74 | messages: error.messages, |
66 | status: 401, | 75 | status: 401, |
67 | }) | 76 | }); |
68 | } | 77 | } |
69 | 78 | ||
70 | // Create user in DB | 79 | // Create user in DB |
71 | let user | 80 | let user; |
72 | try { | 81 | try { |
73 | user = await User.create({ | 82 | user = await User.create({ |
74 | email: data.email, | 83 | email: data.email, |
75 | password: data.password, | 84 | password: data.password, |
76 | username: data.firstname, | 85 | username: data.firstname, |
77 | lastname: data.lastname, | 86 | lastname: data.lastname, |
78 | }) | 87 | }); |
79 | } catch { | 88 | } catch { |
80 | return response.status(401).send({ | 89 | return response.status(401).send({ |
81 | message: 'E-Mail address already in use', | 90 | message: 'E-Mail address already in use', |
82 | status: 401, | 91 | status: 401, |
83 | }) | 92 | }); |
84 | } | 93 | } |
85 | 94 | ||
86 | // Generate new auth token | 95 | // Generate new auth token |
87 | const token = await auth.use('jwt').login(user, { payload: {} }) | 96 | const token = await auth.use('jwt').login(user, { payload: {} }); |
88 | 97 | ||
89 | return response.send({ | 98 | return response.send({ |
90 | message: 'Successfully created account', | 99 | message: 'Successfully created account', |
91 | token: token.accessToken, | 100 | token: token.accessToken, |
92 | }) | 101 | }); |
93 | } | 102 | } |
94 | 103 | ||
95 | // Login using an existing user | 104 | // Login using an existing user |
@@ -98,28 +107,30 @@ export default class UsersController { | |||
98 | return response.status(401).send({ | 107 | return response.status(401).send({ |
99 | message: 'Please provide authorization', | 108 | message: 'Please provide authorization', |
100 | status: 401, | 109 | status: 401, |
101 | }) | 110 | }); |
102 | } | 111 | } |
103 | 112 | ||
104 | // Get auth data from auth token | 113 | // Get auth data from auth token |
105 | const authHeader = atob(request.header('Authorization')!.replace('Basic ', '')).split(':') | 114 | const authHeader = atob( |
115 | request.header('Authorization')!.replace('Basic ', ''), | ||
116 | ).split(':'); | ||
106 | 117 | ||
107 | // Check if user with email exists | 118 | // Check if user with email exists |
108 | const user = await User.query().where('email', authHeader[0]).first() | 119 | const user = await User.query().where('email', authHeader[0]).first(); |
109 | if (!user?.email) { | 120 | if (!user?.email) { |
110 | return response.status(401).send({ | 121 | return response.status(401).send({ |
111 | message: 'User credentials not valid', | 122 | message: 'User credentials not valid', |
112 | code: 'invalid-credentials', | 123 | code: 'invalid-credentials', |
113 | status: 401, | 124 | status: 401, |
114 | }) | 125 | }); |
115 | } | 126 | } |
116 | 127 | ||
117 | // Verify password | 128 | // Verify password |
118 | let isMatchedPassword = false | 129 | let isMatchedPassword = false; |
119 | try { | 130 | try { |
120 | isMatchedPassword = await handleVerifyAndReHash(user, authHeader[1]) | 131 | isMatchedPassword = await handleVerifyAndReHash(user, authHeader[1]); |
121 | } catch (error) { | 132 | } catch (error) { |
122 | return response.internalServerError({ message: error.message }) | 133 | return response.internalServerError({ message: error.message }); |
123 | } | 134 | } |
124 | 135 | ||
125 | if (!isMatchedPassword) { | 136 | if (!isMatchedPassword) { |
@@ -127,28 +138,31 @@ export default class UsersController { | |||
127 | message: 'User credentials not valid', | 138 | message: 'User credentials not valid', |
128 | code: 'invalid-credentials', | 139 | code: 'invalid-credentials', |
129 | status: 401, | 140 | status: 401, |
130 | }) | 141 | }); |
131 | } | 142 | } |
132 | 143 | ||
133 | // Generate token | 144 | // Generate token |
134 | const token = await auth.use('jwt').login(user, { payload: {} }) | 145 | const token = await auth.use('jwt').login(user, { payload: {} }); |
135 | 146 | ||
136 | return response.send({ | 147 | return response.send({ |
137 | message: 'Successfully logged in', | 148 | message: 'Successfully logged in', |
138 | token: token.accessToken, | 149 | token: token.accessToken, |
139 | }) | 150 | }); |
140 | } | 151 | } |
141 | 152 | ||
142 | // Return information about the current user | 153 | // Return information about the current user |
143 | public async me({ request, response, auth }: HttpContext) { | 154 | public async me({ request, response, auth }: HttpContext) { |
144 | // @ts-expect-error Property 'user' does not exist on type 'HttpContextContract'. | 155 | // @ts-expect-error Property 'user' does not exist on type 'HttpContextContract'. |
145 | const user = auth.user ?? request.user | 156 | const user = auth.user ?? request.user; |
146 | 157 | ||
147 | if (!user) { | 158 | if (!user) { |
148 | return response.send('Missing or invalid api token') | 159 | return response.send('Missing or invalid api token'); |
149 | } | 160 | } |
150 | 161 | ||
151 | const settings = typeof user.settings === 'string' ? JSON.parse(user.settings) : user.settings | 162 | const settings = |
163 | typeof user.settings === 'string' | ||
164 | ? JSON.parse(user.settings) | ||
165 | : user.settings; | ||
152 | 166 | ||
153 | return response.send({ | 167 | return response.send({ |
154 | accountType: 'individual', | 168 | accountType: 'individual', |
@@ -164,29 +178,29 @@ export default class UsersController { | |||
164 | lastname: user.lastname, | 178 | lastname: user.lastname, |
165 | locale: 'en-US', | 179 | locale: 'en-US', |
166 | ...settings, | 180 | ...settings, |
167 | }) | 181 | }); |
168 | } | 182 | } |
169 | 183 | ||
170 | public async updateMe({ request, response, auth }: HttpContext) { | 184 | public async updateMe({ request, response, auth }: HttpContext) { |
171 | // @ts-expect-error Property 'user' does not exist on type 'HttpContextContract'. | 185 | // @ts-expect-error Property 'user' does not exist on type 'HttpContextContract'. |
172 | const user = auth.user ?? request.user | 186 | const user = auth.user ?? request.user; |
173 | 187 | ||
174 | if (!user) { | 188 | if (!user) { |
175 | return response.send('Missing or invalid api token') | 189 | return response.send('Missing or invalid api token'); |
176 | } | 190 | } |
177 | 191 | ||
178 | let settings = user.settings || {} | 192 | let settings = user.settings || {}; |
179 | if (typeof settings === 'string') { | 193 | if (typeof settings === 'string') { |
180 | settings = JSON.parse(settings) | 194 | settings = JSON.parse(settings); |
181 | } | 195 | } |
182 | 196 | ||
183 | const newSettings = { | 197 | const newSettings = { |
184 | ...settings, | 198 | ...settings, |
185 | ...request.all(), | 199 | ...request.all(), |
186 | } | 200 | }; |
187 | 201 | ||
188 | user.settings = JSON.stringify(newSettings) | 202 | user.settings = JSON.stringify(newSettings); |
189 | await user.save() | 203 | await user.save(); |
190 | 204 | ||
191 | return response.send({ | 205 | return response.send({ |
192 | data: { | 206 | data: { |
@@ -205,22 +219,22 @@ export default class UsersController { | |||
205 | ...newSettings, | 219 | ...newSettings, |
206 | }, | 220 | }, |
207 | status: ['data-updated'], | 221 | status: ['data-updated'], |
208 | }) | 222 | }); |
209 | } | 223 | } |
210 | 224 | ||
211 | public async newToken({ request, response, auth }: HttpContext) { | 225 | public async newToken({ request, response, auth }: HttpContext) { |
212 | // @ts-expect-error Property 'user' does not exist on type 'HttpContextContract'. | 226 | // @ts-expect-error Property 'user' does not exist on type 'HttpContextContract'. |
213 | const user = auth.user ?? request.user | 227 | const user = auth.user ?? request.user; |
214 | 228 | ||
215 | if (!user) { | 229 | if (!user) { |
216 | return response.send('Missing or invalid api token') | 230 | return response.send('Missing or invalid api token'); |
217 | } | 231 | } |
218 | 232 | ||
219 | const token = await auth.use('jwt').generate(user, { payload: {} }) | 233 | const token = await auth.use('jwt').generate(user, { payload: {} }); |
220 | 234 | ||
221 | return response.send({ | 235 | return response.send({ |
222 | token: token.accessToken, | 236 | token: token.accessToken, |
223 | }) | 237 | }); |
224 | } | 238 | } |
225 | 239 | ||
226 | public async import({ request, response, view }: HttpContext) { | 240 | public async import({ request, response, view }: HttpContext) { |
@@ -228,114 +242,117 @@ export default class UsersController { | |||
228 | return response.status(401).send({ | 242 | return response.status(401).send({ |
229 | message: 'Registration is disabled on this server', | 243 | message: 'Registration is disabled on this server', |
230 | status: 401, | 244 | status: 401, |
231 | }) | 245 | }); |
232 | } | 246 | } |
233 | 247 | ||
234 | if (connectWithFranz === 'false') { | 248 | if (connectWithFranz === 'false') { |
235 | return response.send( | 249 | return response.send( |
236 | '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.' | 250 | '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.', |
237 | ) | 251 | ); |
238 | } | 252 | } |
239 | 253 | ||
240 | // Validate user input | 254 | // Validate user input |
241 | let data | 255 | let data; |
242 | try { | 256 | try { |
243 | data = await request.validate({ schema: franzImportSchema }) | 257 | data = await request.validate({ schema: franzImportSchema }); |
244 | } catch (error) { | 258 | } catch (error) { |
245 | return view.render('others.message', { | 259 | return view.render('others.message', { |
246 | heading: 'Error while importing', | 260 | heading: 'Error while importing', |
247 | text: error.messages, | 261 | text: error.messages, |
248 | }) | 262 | }); |
249 | } | 263 | } |
250 | 264 | ||
251 | const { email, password } = data | 265 | const { email, password } = data; |
252 | 266 | ||
253 | const hashedPassword = crypto.createHash('sha256').update(password).digest('base64') | 267 | const hashedPassword = crypto |
268 | .createHash('sha256') | ||
269 | .update(password) | ||
270 | .digest('base64'); | ||
254 | 271 | ||
255 | const base = 'https://api.franzinfra.com/v1/' | 272 | const base = 'https://api.franzinfra.com/v1/'; |
256 | const userAgent = | 273 | const userAgent = |
257 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Franz/5.3.0-beta.1 Chrome/69.0.3497.128 Electron/4.2.4 Safari/537.36' | 274 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Franz/5.3.0-beta.1 Chrome/69.0.3497.128 Electron/4.2.4 Safari/537.36'; |
258 | 275 | ||
259 | // Try to get an authentication token | 276 | // Try to get an authentication token |
260 | let token | 277 | let token; |
261 | try { | 278 | try { |
262 | const basicToken = btoa(`${email}:${hashedPassword}`) | 279 | const basicToken = btoa(`${email}:${hashedPassword}`); |
263 | const loginBody = { | 280 | const loginBody = { |
264 | isZendeskLogin: false, | 281 | isZendeskLogin: false, |
265 | } | 282 | }; |
266 | 283 | ||
267 | const rawResponse = await fetch(`${base}auth/login`, { | 284 | const rawResponse = await fetch(`${base}auth/login`, { |
268 | method: 'POST', | 285 | method: 'POST', |
269 | body: JSON.stringify(loginBody), | 286 | body: JSON.stringify(loginBody), |
270 | headers: { | 287 | headers: { |
271 | 'Authorization': `Basic ${basicToken}`, | 288 | Authorization: `Basic ${basicToken}`, |
272 | 'User-Agent': userAgent, | 289 | 'User-Agent': userAgent, |
273 | 'Content-Type': 'application/json', | 290 | 'Content-Type': 'application/json', |
274 | 'accept': '*/*', | 291 | accept: '*/*', |
275 | 'x-franz-source': 'Web', | 292 | 'x-franz-source': 'Web', |
276 | }, | 293 | }, |
277 | }) | 294 | }); |
278 | const content = await rawResponse.json() | 295 | const content = await rawResponse.json(); |
279 | 296 | ||
280 | if (!content.message || content.message !== 'Successfully logged in') { | 297 | if (!content.message || content.message !== 'Successfully logged in') { |
281 | const errorMessage = | 298 | const errorMessage = |
282 | 'Could not login into Franz with your supplied credentials. Please check and try again' | 299 | 'Could not login into Franz with your supplied credentials. Please check and try again'; |
283 | return response.status(401).send(errorMessage) | 300 | return response.status(401).send(errorMessage); |
284 | } | 301 | } |
285 | 302 | ||
286 | token = content.token | 303 | token = content.token; |
287 | } catch (error) { | 304 | } catch (error) { |
288 | return response.status(401).send({ | 305 | return response.status(401).send({ |
289 | message: 'Cannot login to Franz', | 306 | message: 'Cannot login to Franz', |
290 | error: error, | 307 | error: error, |
291 | }) | 308 | }); |
292 | } | 309 | } |
293 | 310 | ||
294 | // Get user information | 311 | // Get user information |
295 | // eslint-disable-next-line @typescript-eslint/no-explicit-any | 312 | // eslint-disable-next-line @typescript-eslint/no-explicit-any |
296 | let userInf: any = false | 313 | let userInf: any = false; |
297 | try { | 314 | try { |
298 | userInf = await franzRequest('me', 'GET', token) | 315 | userInf = await franzRequest('me', 'GET', token); |
299 | } catch (error) { | 316 | } catch (error) { |
300 | const errorMessage = `Could not get your user info from Franz. Please check your credentials or try again later.\nError: ${error}` | 317 | const errorMessage = `Could not get your user info from Franz. Please check your credentials or try again later.\nError: ${error}`; |
301 | return response.status(401).send(errorMessage) | 318 | return response.status(401).send(errorMessage); |
302 | } | 319 | } |
303 | if (!userInf) { | 320 | if (!userInf) { |
304 | const errorMessage = | 321 | const errorMessage = |
305 | 'Could not get your user info from Franz. Please check your credentials or try again later' | 322 | 'Could not get your user info from Franz. Please check your credentials or try again later'; |
306 | return response.status(401).send(errorMessage) | 323 | return response.status(401).send(errorMessage); |
307 | } | 324 | } |
308 | 325 | ||
309 | // Create user in DB | 326 | // Create user in DB |
310 | let user | 327 | let user; |
311 | try { | 328 | try { |
312 | user = await User.create({ | 329 | user = await User.create({ |
313 | email: userInf.email, | 330 | email: userInf.email, |
314 | password: hashedPassword, | 331 | password: hashedPassword, |
315 | username: userInf.firstname, | 332 | username: userInf.firstname, |
316 | lastname: userInf.lastname, | 333 | lastname: userInf.lastname, |
317 | }) | 334 | }); |
318 | } catch (error) { | 335 | } catch (error) { |
319 | const errorMessage = `Could not create your user in our system.\nError: ${error}` | 336 | const errorMessage = `Could not create your user in our system.\nError: ${error}`; |
320 | return response.status(401).send(errorMessage) | 337 | return response.status(401).send(errorMessage); |
321 | } | 338 | } |
322 | 339 | ||
323 | const serviceIdTranslation = {} | 340 | const serviceIdTranslation = {}; |
324 | 341 | ||
325 | // Import services | 342 | // Import services |
326 | try { | 343 | try { |
327 | const services = await franzRequest('me/services', 'GET', token) | 344 | const services = await franzRequest('me/services', 'GET', token); |
328 | 345 | ||
329 | // @ts-expect-error | 346 | // @ts-expect-error |
330 | for (const service of services) { | 347 | for (const service of services) { |
331 | // Get new, unused uuid | 348 | // Get new, unused uuid |
332 | let serviceId | 349 | let serviceId; |
333 | do { | 350 | do { |
334 | serviceId = uuid() | 351 | serviceId = uuid(); |
335 | } while ( | 352 | } while ( |
336 | // eslint-disable-next-line no-await-in-loop, unicorn/no-await-expression-member | 353 | // eslint-disable-next-line no-await-in-loop, unicorn/no-await-expression-member |
337 | (await Service.query().where('serviceId', serviceId)).length > 0 | 354 | (await Service.query().where('serviceId', serviceId)).length > 0 |
338 | ) | 355 | ); |
339 | 356 | ||
340 | // eslint-disable-next-line no-await-in-loop | 357 | // eslint-disable-next-line no-await-in-loop |
341 | await Service.create({ | 358 | await Service.create({ |
@@ -344,34 +361,34 @@ export default class UsersController { | |||
344 | name: service.name, | 361 | name: service.name, |
345 | recipeId: service.recipeId, | 362 | recipeId: service.recipeId, |
346 | settings: JSON.stringify(service), | 363 | settings: JSON.stringify(service), |
347 | }) | 364 | }); |
348 | 365 | ||
349 | // @ts-expect-error | 366 | // @ts-expect-error |
350 | serviceIdTranslation[service.id] = serviceId | 367 | serviceIdTranslation[service.id] = serviceId; |
351 | } | 368 | } |
352 | } catch (error) { | 369 | } catch (error) { |
353 | const errorMessage = `Could not import your services into our system.\nError: ${error}` | 370 | const errorMessage = `Could not import your services into our system.\nError: ${error}`; |
354 | return response.status(401).send(errorMessage) | 371 | return response.status(401).send(errorMessage); |
355 | } | 372 | } |
356 | 373 | ||
357 | // Import workspaces | 374 | // Import workspaces |
358 | try { | 375 | try { |
359 | const workspaces = await franzRequest('workspace', 'GET', token) | 376 | const workspaces = await franzRequest('workspace', 'GET', token); |
360 | 377 | ||
361 | // @ts-expect-error | 378 | // @ts-expect-error |
362 | for (const workspace of workspaces) { | 379 | for (const workspace of workspaces) { |
363 | let workspaceId | 380 | let workspaceId; |
364 | do { | 381 | do { |
365 | workspaceId = uuid() | 382 | workspaceId = uuid(); |
366 | } while ( | 383 | } while ( |
367 | // eslint-disable-next-line unicorn/no-await-expression-member, no-await-in-loop | 384 | // eslint-disable-next-line unicorn/no-await-expression-member, no-await-in-loop |
368 | (await Workspace.query().where('workspaceId', workspaceId)).length > 0 | 385 | (await Workspace.query().where('workspaceId', workspaceId)).length > 0 |
369 | ) | 386 | ); |
370 | 387 | ||
371 | const services = workspace.services.map( | 388 | const services = workspace.services.map( |
372 | // @ts-expect-error | 389 | // @ts-expect-error |
373 | (service) => serviceIdTranslation[service] | 390 | service => serviceIdTranslation[service], |
374 | ) | 391 | ); |
375 | 392 | ||
376 | // eslint-disable-next-line no-await-in-loop | 393 | // eslint-disable-next-line no-await-in-loop |
377 | await Workspace.create({ | 394 | await Workspace.create({ |
@@ -381,15 +398,15 @@ export default class UsersController { | |||
381 | order: workspace.order, | 398 | order: workspace.order, |
382 | services: JSON.stringify(services), | 399 | services: JSON.stringify(services), |
383 | data: JSON.stringify({}), | 400 | data: JSON.stringify({}), |
384 | }) | 401 | }); |
385 | } | 402 | } |
386 | } catch (error) { | 403 | } catch (error) { |
387 | const errorMessage = `Could not import your workspaces into our system.\nError: ${error}` | 404 | const errorMessage = `Could not import your workspaces into our system.\nError: ${error}`; |
388 | return response.status(401).send(errorMessage) | 405 | return response.status(401).send(errorMessage); |
389 | } | 406 | } |
390 | 407 | ||
391 | return response.send( | 408 | return response.send( |
392 | 'Your account has been imported. You can now use your Franz/Ferdi account in Ferdium.' | 409 | 'Your account has been imported. You can now use your Franz/Ferdi account in Ferdium.', |
393 | ) | 410 | ); |
394 | } | 411 | } |
395 | } | 412 | } |