aboutsummaryrefslogtreecommitdiffstats
path: root/app/Controllers/Http/Dashboard
diff options
context:
space:
mode:
Diffstat (limited to 'app/Controllers/Http/Dashboard')
-rw-r--r--app/Controllers/Http/Dashboard/AccountController.ts40
-rw-r--r--app/Controllers/Http/Dashboard/DataController.ts12
-rw-r--r--app/Controllers/Http/Dashboard/DeleteController.ts14
-rw-r--r--app/Controllers/Http/Dashboard/ExportController.ts29
-rw-r--r--app/Controllers/Http/Dashboard/ForgotPasswordController.ts22
-rw-r--r--app/Controllers/Http/Dashboard/LogOutController.ts8
-rw-r--r--app/Controllers/Http/Dashboard/LoginController.ts58
-rw-r--r--app/Controllers/Http/Dashboard/ResetPasswordController.ts51
-rw-r--r--app/Controllers/Http/Dashboard/TransferController.ts77
9 files changed, 138 insertions, 173 deletions
diff --git a/app/Controllers/Http/Dashboard/AccountController.ts b/app/Controllers/Http/Dashboard/AccountController.ts
index 3c4e919..5870f19 100644
--- a/app/Controllers/Http/Dashboard/AccountController.ts
+++ b/app/Controllers/Http/Dashboard/AccountController.ts
@@ -1,29 +1,23 @@
1import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; 1import type { HttpContext } from '@adonisjs/core/http'
2import { schema, rules, validator } from '@ioc:Adonis/Core/Validator'; 2import { schema, rules, validator } from '@adonisjs/validator'
3import crypto from 'node:crypto'; 3import crypto from 'node:crypto'
4 4
5export default class AccountController { 5export default class AccountController {
6 /** 6 /**
7 * Shows the user account page 7 * Shows the user account page
8 */ 8 */
9 public async show({ auth, view }: HttpContextContract) { 9 public async show({ auth, view }: HttpContext) {
10 return view.render('dashboard/account', { 10 return view.render('dashboard/account', {
11 username: auth.user?.username, 11 username: auth.user?.username,
12 email: auth.user?.email, 12 email: auth.user?.email,
13 lastname: auth.user?.lastname, 13 lastname: auth.user?.lastname,
14 }); 14 })
15 } 15 }
16 16
17 /** 17 /**
18 * Stores user account data 18 * Stores user account data
19 */ 19 */
20 public async store({ 20 public async store({ auth, request, response, session, view }: HttpContext) {
21 auth,
22 request,
23 response,
24 session,
25 view,
26 }: HttpContextContract) {
27 try { 21 try {
28 await validator.validate({ 22 await validator.validate({
29 schema: schema.create({ 23 schema: schema.create({
@@ -48,26 +42,26 @@ export default class AccountController {
48 lastname: schema.string([rules.required()]), 42 lastname: schema.string([rules.required()]),
49 }), 43 }),
50 data: request.only(['username', 'email', 'lastname']), 44 data: request.only(['username', 'email', 'lastname']),
51 }); 45 })
52 } catch (error) { 46 } catch (error) {
53 session.flash(error.messages); 47 session.flash(error.messages)
54 return response.redirect('/user/account'); 48 return response.redirect('/user/account')
55 } 49 }
56 50
57 // Update user account 51 // Update user account
58 const { user } = auth; 52 const { user } = auth
59 if (user) { 53 if (user) {
60 user.username = request.input('username'); 54 user.username = request.input('username')
61 user.lastname = request.input('lastname'); 55 user.lastname = request.input('lastname')
62 user.email = request.input('email'); 56 user.email = request.input('email')
63 if (request.input('password')) { 57 if (request.input('password')) {
64 const hashedPassword = crypto 58 const hashedPassword = crypto
65 .createHash('sha256') 59 .createHash('sha256')
66 .update(request.input('password')) 60 .update(request.input('password'))
67 .digest('base64'); 61 .digest('base64')
68 user.password = hashedPassword; 62 user.password = hashedPassword
69 } 63 }
70 await user.save(); 64 await user.save()
71 } 65 }
72 66
73 return view.render('dashboard/account', { 67 return view.render('dashboard/account', {
@@ -75,6 +69,6 @@ export default class AccountController {
75 lastname: user?.lastname, 69 lastname: user?.lastname,
76 email: user?.email, 70 email: user?.email,
77 success: user !== undefined, 71 success: user !== undefined,
78 }); 72 })
79 } 73 }
80} 74}
diff --git a/app/Controllers/Http/Dashboard/DataController.ts b/app/Controllers/Http/Dashboard/DataController.ts
index f77702f..8a77329 100644
--- a/app/Controllers/Http/Dashboard/DataController.ts
+++ b/app/Controllers/Http/Dashboard/DataController.ts
@@ -1,14 +1,14 @@
1import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; 1import type { HttpContext } from '@adonisjs/core/http'
2 2
3export default class DataController { 3export default class DataController {
4 /** 4 /**
5 * Display the data page 5 * Display the data page
6 */ 6 */
7 public async show({ view, auth }: HttpContextContract) { 7 public async show({ view, auth }: HttpContext) {
8 const { user } = auth; 8 const { user } = auth
9 9
10 const services = await user?.related('services').query(); 10 const services = await user?.related('services').query()
11 const workspaces = await user?.related('workspaces').query(); 11 const workspaces = await user?.related('workspaces').query()
12 12
13 return view.render('dashboard/data', { 13 return view.render('dashboard/data', {
14 username: user?.username, 14 username: user?.username,
@@ -19,6 +19,6 @@ export default class DataController {
19 stringify: JSON.stringify, 19 stringify: JSON.stringify,
20 services, 20 services,
21 workspaces, 21 workspaces,
22 }); 22 })
23 } 23 }
24} 24}
diff --git a/app/Controllers/Http/Dashboard/DeleteController.ts b/app/Controllers/Http/Dashboard/DeleteController.ts
index ef8188c..bd824b0 100644
--- a/app/Controllers/Http/Dashboard/DeleteController.ts
+++ b/app/Controllers/Http/Dashboard/DeleteController.ts
@@ -1,20 +1,20 @@
1import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; 1import type { HttpContext } from '@adonisjs/core/http'
2 2
3export default class DeleteController { 3export default class DeleteController {
4 /** 4 /**
5 * Display the delete page 5 * Display the delete page
6 */ 6 */
7 public async show({ view }: HttpContextContract) { 7 public async show({ view }: HttpContext) {
8 return view.render('dashboard/delete'); 8 return view.render('dashboard/delete')
9 } 9 }
10 10
11 /** 11 /**
12 * Delete user and session 12 * Delete user and session
13 */ 13 */
14 public async delete({ auth, response }: HttpContextContract) { 14 public async delete({ auth, response }: HttpContext) {
15 auth.user?.delete(); 15 auth.user?.delete()
16 auth.use('web').logout(); 16 auth.use('web').logout()
17 17
18 return response.redirect('/user/login'); 18 return response.redirect('/user/login')
19 } 19 }
20} 20}
diff --git a/app/Controllers/Http/Dashboard/ExportController.ts b/app/Controllers/Http/Dashboard/ExportController.ts
index 7155eab..5b6df70 100644
--- a/app/Controllers/Http/Dashboard/ExportController.ts
+++ b/app/Controllers/Http/Dashboard/ExportController.ts
@@ -1,33 +1,30 @@
1import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; 1import type { HttpContext } from '@adonisjs/core/http'
2 2
3// eslint-disable-next-line @typescript-eslint/no-explicit-any 3// eslint-disable-next-line @typescript-eslint/no-explicit-any
4function deepParseToJSON(obj: any): Record<string, unknown> { 4function deepParseToJSON(obj: any): Record<string, unknown> {
5 if (typeof obj !== 'object' || obj === null) { 5 if (typeof obj !== 'object' || obj === null) {
6 try { 6 try {
7 // Try to parse the object as JSON 7 // Try to parse the object as JSON
8 return JSON.parse(obj) as Record<string, unknown>; 8 return JSON.parse(obj) as Record<string, unknown>
9 } catch { 9 } catch {
10 // If parsing fails, return the original value 10 // If parsing fails, return the original value
11 return obj; 11 return obj
12 } 12 }
13 } 13 }
14 14
15 // If obj is an object, recursively parse its keys 15 // If obj is an object, recursively parse its keys
16 if (Array.isArray(obj)) { 16 if (Array.isArray(obj)) {
17 // If obj is an array, recursively parse each element 17 // If obj is an array, recursively parse each element
18 return obj.map(item => deepParseToJSON(item)) as unknown as Record< 18 return obj.map((item) => deepParseToJSON(item)) as unknown as Record<string, unknown>
19 string,
20 unknown
21 >;
22 } else { 19 } else {
23 // If obj is an object, recursively parse its keys 20 // If obj is an object, recursively parse its keys
24 const parsedObj: Record<string, unknown> = {}; 21 const parsedObj: Record<string, unknown> = {}
25 for (const key in obj) { 22 for (const key in obj) {
26 if (obj.hasOwnProperty(key)) { 23 if (obj.hasOwnProperty(key)) {
27 parsedObj[key] = deepParseToJSON(obj[key]); 24 parsedObj[key] = deepParseToJSON(obj[key])
28 } 25 }
29 } 26 }
30 return parsedObj; 27 return parsedObj
31 } 28 }
32} 29}
33 30
@@ -35,10 +32,10 @@ export default class ExportController {
35 /** 32 /**
36 * Display the export page 33 * Display the export page
37 */ 34 */
38 public async show({ auth, response }: HttpContextContract) { 35 public async show({ auth, response }: HttpContext) {
39 const user = auth.user!; 36 const user = auth.user!
40 const services = await user.related('services').query(); 37 const services = await user.related('services').query()
41 const workspaces = await user.related('workspaces').query(); 38 const workspaces = await user.related('workspaces').query()
42 39
43 const exportData = { 40 const exportData = {
44 username: user.username, 41 username: user.username,
@@ -46,11 +43,11 @@ export default class ExportController {
46 mail: user.email, 43 mail: user.email,
47 services: deepParseToJSON(JSON.parse(JSON.stringify(services))), 44 services: deepParseToJSON(JSON.parse(JSON.stringify(services))),
48 workspaces: deepParseToJSON(JSON.parse(JSON.stringify(workspaces))), 45 workspaces: deepParseToJSON(JSON.parse(JSON.stringify(workspaces))),
49 }; 46 }
50 47
51 return response 48 return response
52 .header('Content-Type', 'application/force-download') 49 .header('Content-Type', 'application/force-download')
53 .header('Content-disposition', 'attachment; filename=export.ferdium-data') 50 .header('Content-disposition', 'attachment; filename=export.ferdium-data')
54 .send(exportData); 51 .send(exportData)
55 } 52 }
56} 53}
diff --git a/app/Controllers/Http/Dashboard/ForgotPasswordController.ts b/app/Controllers/Http/Dashboard/ForgotPasswordController.ts
index da05bbd..f7b1d0e 100644
--- a/app/Controllers/Http/Dashboard/ForgotPasswordController.ts
+++ b/app/Controllers/Http/Dashboard/ForgotPasswordController.ts
@@ -1,41 +1,41 @@
1import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; 1import type { HttpContext } from '@adonisjs/core/http'
2import { schema, rules, validator } from '@ioc:Adonis/Core/Validator'; 2import { schema, rules, validator } from '@adonisjs/validator'
3import User from 'App/Models/User'; 3import User from '#app/Models/User'
4 4
5export default class ForgotPasswordController { 5export default class ForgotPasswordController {
6 /** 6 /**
7 * Display the forgot password form 7 * Display the forgot password form
8 */ 8 */
9 public async show({ view }: HttpContextContract) { 9 public async show({ view }: HttpContext) {
10 return view.render('dashboard/forgotPassword'); 10 return view.render('dashboard/forgotPassword')
11 } 11 }
12 12
13 /** 13 /**
14 * Send forget password email to user 14 * Send forget password email to user
15 */ 15 */
16 public async forgotPassword({ view, request }: HttpContextContract) { 16 public async forgotPassword({ view, request }: HttpContext) {
17 try { 17 try {
18 await validator.validate({ 18 await validator.validate({
19 schema: schema.create({ 19 schema: schema.create({
20 mail: schema.string([rules.email(), rules.required()]), 20 mail: schema.string([rules.email(), rules.required()]),
21 }), 21 }),
22 data: request.only(['mail']), 22 data: request.only(['mail']),
23 }); 23 })
24 } catch { 24 } catch {
25 return view.render('others/message', { 25 return view.render('others/message', {
26 heading: 'Cannot reset your password', 26 heading: 'Cannot reset your password',
27 text: 'Please enter a valid email address', 27 text: 'Please enter a valid email address',
28 }); 28 })
29 } 29 }
30 30
31 try { 31 try {
32 const user = await User.findByOrFail('email', request.input('mail')); 32 const user = await User.findByOrFail('email', request.input('mail'))
33 await user.forgotPassword(); 33 await user.forgotPassword()
34 } catch {} 34 } catch {}
35 35
36 return view.render('others/message', { 36 return view.render('others/message', {
37 heading: 'Reset password', 37 heading: 'Reset password',
38 text: 'If your provided E-Mail address is linked to an account, we have just sent an E-Mail to that address.', 38 text: 'If your provided E-Mail address is linked to an account, we have just sent an E-Mail to that address.',
39 }); 39 })
40 } 40 }
41} 41}
diff --git a/app/Controllers/Http/Dashboard/LogOutController.ts b/app/Controllers/Http/Dashboard/LogOutController.ts
index 41cbd31..5d250c4 100644
--- a/app/Controllers/Http/Dashboard/LogOutController.ts
+++ b/app/Controllers/Http/Dashboard/LogOutController.ts
@@ -1,12 +1,12 @@
1import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; 1import type { HttpContext } from '@adonisjs/core/http'
2 2
3export default class LogOutController { 3export default class LogOutController {
4 /** 4 /**
5 * Login a user 5 * Login a user
6 */ 6 */
7 public async logout({ auth, response }: HttpContextContract) { 7 public async logout({ auth, response }: HttpContext) {
8 auth.logout(); 8 auth.logout()
9 9
10 return response.redirect('/user/login'); 10 return response.redirect('/user/login')
11 } 11 }
12} 12}
diff --git a/app/Controllers/Http/Dashboard/LoginController.ts b/app/Controllers/Http/Dashboard/LoginController.ts
index ffb9eeb..5a54448 100644
--- a/app/Controllers/Http/Dashboard/LoginController.ts
+++ b/app/Controllers/Http/Dashboard/LoginController.ts
@@ -1,26 +1,21 @@
1import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; 1import type { HttpContext } from '@adonisjs/core/http'
2import { schema, rules, validator } from '@ioc:Adonis/Core/Validator'; 2import { schema, rules, validator } from '@adonisjs/validator'
3import User from 'App/Models/User'; 3import User from '#app/Models/User'
4import crypto from 'node:crypto'; 4import crypto from 'node:crypto'
5import { handleVerifyAndReHash } from '../../../../helpers/PasswordHash'; 5import { handleVerifyAndReHash } from '../../../../helpers/PasswordHash.js'
6 6
7export default class LoginController { 7export default class LoginController {
8 /** 8 /**
9 * Display the login form 9 * Display the login form
10 */ 10 */
11 public async show({ view }: HttpContextContract) { 11 public async show({ view }: HttpContext) {
12 return view.render('dashboard/login'); 12 return view.render('dashboard/login')
13 } 13 }
14 14
15 /** 15 /**
16 * Login a user 16 * Login a user
17 */ 17 */
18 public async login({ 18 public async login({ request, response, auth, session }: HttpContext) {
19 request,
20 response,
21 auth,
22 session,
23 }: HttpContextContract) {
24 try { 19 try {
25 await validator.validate({ 20 await validator.validate({
26 schema: schema.create({ 21 schema: schema.create({
@@ -28,54 +23,51 @@ export default class LoginController {
28 password: schema.string([rules.required()]), 23 password: schema.string([rules.required()]),
29 }), 24 }),
30 data: request.only(['mail', 'password']), 25 data: request.only(['mail', 'password']),
31 }); 26 })
32 } catch { 27 } catch {
33 session.flash({ 28 session.flash({
34 type: 'danger', 29 type: 'danger',
35 message: 'Invalid mail or password', 30 message: 'Invalid mail or password',
36 }); 31 })
37 session.flashExcept(['password']); 32 session.flashExcept(['password'])
38 33
39 return response.redirect('/user/login'); 34 return response.redirect('/user/login')
40 } 35 }
41 36
42 try { 37 try {
43 const { mail, password } = request.all(); 38 const { mail, password } = request.all()
44 39
45 // Check if user with email exists 40 // Check if user with email exists
46 const user = await User.query().where('email', mail).first(); 41 const user = await User.query().where('email', mail).first()
47 if (!user?.email) { 42 if (!user?.email) {
48 throw new Error('User credentials not valid (Invalid email)'); 43 throw new Error('User credentials not valid (Invalid email)')
49 } 44 }
50 45
51 const hashedPassword = crypto 46 const hashedPassword = crypto.createHash('sha256').update(password).digest('base64')
52 .createHash('sha256')
53 .update(password)
54 .digest('base64');
55 47
56 // Verify password 48 // Verify password
57 let isMatchedPassword = false; 49 let isMatchedPassword = false
58 try { 50 try {
59 isMatchedPassword = await handleVerifyAndReHash(user, hashedPassword); 51 isMatchedPassword = await handleVerifyAndReHash(user, hashedPassword)
60 } catch (error) { 52 } catch (error) {
61 return response.internalServerError({ message: error.message }); 53 return response.internalServerError({ message: error.message })
62 } 54 }
63 55
64 if (!isMatchedPassword) { 56 if (!isMatchedPassword) {
65 throw new Error('User credentials not valid (Invalid password)'); 57 throw new Error('User credentials not valid (Invalid password)')
66 } 58 }
67 59
68 await auth.use('web').login(user); 60 await auth.use('web').login(user)
69 61
70 return response.redirect('/user/account'); 62 return response.redirect('/user/account')
71 } catch { 63 } catch {
72 session.flash({ 64 session.flash({
73 type: 'danger', 65 type: 'danger',
74 message: 'Invalid mail or password', 66 message: 'Invalid mail or password',
75 }); 67 })
76 session.flashExcept(['password']); 68 session.flashExcept(['password'])
77 69
78 return response.redirect('/user/login'); 70 return response.redirect('/user/login')
79 } 71 }
80 } 72 }
81} 73}
diff --git a/app/Controllers/Http/Dashboard/ResetPasswordController.ts b/app/Controllers/Http/Dashboard/ResetPasswordController.ts
index 0b9053f..b62b5d2 100644
--- a/app/Controllers/Http/Dashboard/ResetPasswordController.ts
+++ b/app/Controllers/Http/Dashboard/ResetPasswordController.ts
@@ -1,35 +1,30 @@
1import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; 1import type { HttpContext } from '@adonisjs/core/http'
2import { schema, rules, validator } from '@ioc:Adonis/Core/Validator'; 2import { schema, rules, validator } from '@adonisjs/validator'
3import Token from 'App/Models/Token'; 3import Token from '#app/Models/Token'
4import moment from 'moment'; 4import moment from 'moment'
5import crypto from 'node:crypto'; 5import crypto from 'node:crypto'
6 6
7export default class ResetPasswordController { 7export default class ResetPasswordController {
8 /** 8 /**
9 * Display the reset password form 9 * Display the reset password form
10 */ 10 */
11 public async show({ view, request }: HttpContextContract) { 11 public async show({ view, request }: HttpContext) {
12 const { token } = request.qs(); 12 const { token } = request.qs()
13 13
14 if (token) { 14 if (token) {
15 return view.render('dashboard/resetPassword', { token }); 15 return view.render('dashboard/resetPassword', { token })
16 } 16 }
17 17
18 return view.render('others/message', { 18 return view.render('others/message', {
19 heading: 'Invalid token', 19 heading: 'Invalid token',
20 text: 'Please make sure you are using a valid and recent link to reset your password.', 20 text: 'Please make sure you are using a valid and recent link to reset your password.',
21 }); 21 })
22 } 22 }
23 23
24 /** 24 /**
25 * Resets user password 25 * Resets user password
26 */ 26 */
27 public async resetPassword({ 27 public async resetPassword({ response, request, session, view }: HttpContext) {
28 response,
29 request,
30 session,
31 view,
32 }: HttpContextContract) {
33 try { 28 try {
34 await validator.validate({ 29 await validator.validate({
35 schema: schema.create({ 30 schema: schema.create({
@@ -37,14 +32,14 @@ export default class ResetPasswordController {
37 token: schema.string([rules.required()]), 32 token: schema.string([rules.required()]),
38 }), 33 }),
39 data: request.only(['password', 'password_confirmation', 'token']), 34 data: request.only(['password', 'password_confirmation', 'token']),
40 }); 35 })
41 } catch { 36 } catch {
42 session.flash({ 37 session.flash({
43 type: 'danger', 38 type: 'danger',
44 message: 'Passwords do not match', 39 message: 'Passwords do not match',
45 }); 40 })
46 41
47 return response.redirect(`/user/reset?token=${request.input('token')}`); 42 return response.redirect(`/user/reset?token=${request.input('token')}`)
48 } 43 }
49 44
50 const tokenRow = await Token.query() 45 const tokenRow = await Token.query()
@@ -52,34 +47,30 @@ export default class ResetPasswordController {
52 .where('token', request.input('token')) 47 .where('token', request.input('token'))
53 .where('type', 'forgot_password') 48 .where('type', 'forgot_password')
54 .where('is_revoked', false) 49 .where('is_revoked', false)
55 .where( 50 .where('updated_at', '>=', moment().subtract(24, 'hours').format('YYYY-MM-DD HH:mm:ss'))
56 'updated_at', 51 .first()
57 '>=',
58 moment().subtract(24, 'hours').format('YYYY-MM-DD HH:mm:ss'),
59 )
60 .first();
61 52
62 if (!tokenRow) { 53 if (!tokenRow) {
63 return view.render('others/message', { 54 return view.render('others/message', {
64 heading: 'Cannot reset your password', 55 heading: 'Cannot reset your password',
65 text: 'Please make sure you are using a valid and recent link to reset your password and that your passwords entered match.', 56 text: 'Please make sure you are using a valid and recent link to reset your password and that your passwords entered match.',
66 }); 57 })
67 } 58 }
68 59
69 // Update user password 60 // Update user password
70 const hashedPassword = crypto 61 const hashedPassword = crypto
71 .createHash('sha256') 62 .createHash('sha256')
72 .update(request.input('password')) 63 .update(request.input('password'))
73 .digest('base64'); 64 .digest('base64')
74 tokenRow.user.password = hashedPassword; 65 tokenRow.user.password = hashedPassword
75 await tokenRow.user.save(); 66 await tokenRow.user.save()
76 67
77 // Delete token to prevent it from being used again 68 // Delete token to prevent it from being used again
78 await tokenRow.delete(); 69 await tokenRow.delete()
79 70
80 return view.render('others/message', { 71 return view.render('others/message', {
81 heading: 'Reset password', 72 heading: 'Reset password',
82 text: 'Successfully reset your password. You can now login to your account using your new password.', 73 text: 'Successfully reset your password. You can now login to your account using your new password.',
83 }); 74 })
84 } 75 }
85} 76}
diff --git a/app/Controllers/Http/Dashboard/TransferController.ts b/app/Controllers/Http/Dashboard/TransferController.ts
index b113e50..0296973 100644
--- a/app/Controllers/Http/Dashboard/TransferController.ts
+++ b/app/Controllers/Http/Dashboard/TransferController.ts
@@ -1,8 +1,8 @@
1import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; 1import type { HttpContext } from '@adonisjs/core/http'
2import { schema, validator } from '@ioc:Adonis/Core/Validator'; 2import { schema, validator } from '@adonisjs/validator'
3import Service from 'App/Models/Service'; 3import Service from '#app/Models/Service'
4import Workspace from 'App/Models/Workspace'; 4import Workspace from '#app/Models/Workspace'
5import { v4 as uuidv4 } from 'uuid'; 5import { v4 as uuidv4 } from 'uuid'
6 6
7const importSchema = schema.create({ 7const importSchema = schema.create({
8 username: schema.string(), 8 username: schema.string(),
@@ -10,58 +10,52 @@ const importSchema = schema.create({
10 mail: schema.string(), 10 mail: schema.string(),
11 services: schema.array().anyMembers(), 11 services: schema.array().anyMembers(),
12 workspaces: schema.array().anyMembers(), 12 workspaces: schema.array().anyMembers(),
13}); 13})
14 14
15export default class TransferController { 15export default class TransferController {
16 /** 16 /**
17 * Display the transfer page 17 * Display the transfer page
18 */ 18 */
19 public async show({ view }: HttpContextContract) { 19 public async show({ view }: HttpContext) {
20 return view.render('dashboard/transfer'); 20 return view.render('dashboard/transfer')
21 } 21 }
22 22
23 public async import({ 23 public async import({ auth, request, response, session, view }: HttpContext) {
24 auth, 24 let file
25 request,
26 response,
27 session,
28 view,
29 }: HttpContextContract) {
30 let file;
31 try { 25 try {
32 file = await validator.validate({ 26 file = await validator.validate({
33 schema: importSchema, 27 schema: importSchema,
34 data: JSON.parse(request.body().file), 28 data: JSON.parse(request.body().file),
35 }); 29 })
36 } catch { 30 } catch {
37 session.flash({ 31 session.flash({
38 message: 'Invalid Ferdium account file', 32 message: 'Invalid Ferdium account file',
39 }); 33 })
40 34
41 return response.redirect('/user/transfer'); 35 return response.redirect('/user/transfer')
42 } 36 }
43 37
44 if (!file?.services || !file.workspaces) { 38 if (!file?.services || !file.workspaces) {
45 session.flash({ 39 session.flash({
46 type: 'danger', 40 type: 'danger',
47 message: 'Invalid Ferdium account file (2)', 41 message: 'Invalid Ferdium account file (2)',
48 }); 42 })
49 return response.redirect('/user/transfer'); 43 return response.redirect('/user/transfer')
50 } 44 }
51 45
52 const serviceIdTranslation = {}; 46 const serviceIdTranslation = {}
53 47
54 // Import services 48 // Import services
55 try { 49 try {
56 for (const service of file.services) { 50 for (const service of file.services) {
57 // Get new, unused uuid 51 // Get new, unused uuid
58 let serviceId; 52 let serviceId
59 do { 53 do {
60 serviceId = uuidv4(); 54 serviceId = uuidv4()
61 } while ( 55 } while (
62 // eslint-disable-next-line no-await-in-loop, unicorn/no-await-expression-member 56 // eslint-disable-next-line no-await-in-loop, unicorn/no-await-expression-member
63 (await Service.query().where('serviceId', serviceId)).length > 0 57 (await Service.query().where('serviceId', serviceId)).length > 0
64 ); 58 )
65 59
66 // eslint-disable-next-line no-await-in-loop 60 // eslint-disable-next-line no-await-in-loop
67 await Service.create({ 61 await Service.create({
@@ -73,38 +67,37 @@ export default class TransferController {
73 typeof service.settings === 'string' 67 typeof service.settings === 'string'
74 ? service.settings 68 ? service.settings
75 : JSON.stringify(service.settings), 69 : JSON.stringify(service.settings),
76 }); 70 })
77 71
78 // @ts-expect-error Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{}' 72 // @ts-expect-error Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{}'
79 serviceIdTranslation[service.service_id || service.serviceId] = 73 serviceIdTranslation[service.service_id || service.serviceId] = serviceId
80 serviceId;
81 } 74 }
82 } catch (error) { 75 } catch (error) {
83 // eslint-disable-next-line no-console 76 // eslint-disable-next-line no-console
84 console.log(error); 77 console.log(error)
85 const errorMessage = `Could not import your services into our system.\nError: ${error}`; 78 const errorMessage = `Could not import your services into our system.\nError: ${error}`
86 return view.render('others/message', { 79 return view.render('others/message', {
87 heading: 'Error while importing', 80 heading: 'Error while importing',
88 text: errorMessage, 81 text: errorMessage,
89 }); 82 })
90 } 83 }
91 84
92 // Import workspaces 85 // Import workspaces
93 try { 86 try {
94 for (const workspace of file.workspaces) { 87 for (const workspace of file.workspaces) {
95 let workspaceId; 88 let workspaceId
96 89
97 do { 90 do {
98 workspaceId = uuidv4(); 91 workspaceId = uuidv4()
99 } while ( 92 } while (
100 // eslint-disable-next-line no-await-in-loop, unicorn/no-await-expression-member 93 // eslint-disable-next-line no-await-in-loop, unicorn/no-await-expression-member
101 (await Workspace.query().where('workspaceId', workspaceId)).length > 0 94 (await Workspace.query().where('workspaceId', workspaceId)).length > 0
102 ); 95 )
103 96
104 const services = workspace.services.map( 97 const services = workspace.services.map(
105 // @ts-expect-error Parameter 'service' implicitly has an 'any' type. 98 // @ts-expect-error Parameter 'service' implicitly has an 'any' type.
106 service => serviceIdTranslation[service], 99 (service) => serviceIdTranslation[service]
107 ); 100 )
108 101
109 // eslint-disable-next-line no-await-in-loop 102 // eslint-disable-next-line no-await-in-loop
110 await Workspace.create({ 103 await Workspace.create({
@@ -114,22 +107,20 @@ export default class TransferController {
114 order: workspace.order, 107 order: workspace.order,
115 services: JSON.stringify(services), 108 services: JSON.stringify(services),
116 data: 109 data:
117 typeof workspace.data === 'string' 110 typeof workspace.data === 'string' ? workspace.data : JSON.stringify(workspace.data),
118 ? workspace.data 111 })
119 : JSON.stringify(workspace.data),
120 });
121 } 112 }
122 } catch (error) { 113 } catch (error) {
123 const errorMessage = `Could not import your workspaces into our system.\nError: ${error}`; 114 const errorMessage = `Could not import your workspaces into our system.\nError: ${error}`
124 return view.render('others/message', { 115 return view.render('others/message', {
125 heading: 'Error while importing', 116 heading: 'Error while importing',
126 text: errorMessage, 117 text: errorMessage,
127 }); 118 })
128 } 119 }
129 120
130 return view.render('others/message', { 121 return view.render('others/message', {
131 heading: 'Successfully imported', 122 heading: 'Successfully imported',
132 text: 'Your account has been imported, you can now login as usual!', 123 text: 'Your account has been imported, you can now login as usual!',
133 }); 124 })
134 } 125 }
135} 126}