import type { HttpContext } from '@adonisjs/core/http'; import User from '#models/user'; // import { RenderResponse } from '@ioc:EidelLev/Inertia'; import TwoFactorAuthProvider from '#app/services/TwoFactorAuthProvider'; import hash from '@adonisjs/core/services/hash'; // import { schema, rules } from '@adonisjs/validator'; import vine from '@vinejs/vine'; import BackupCodeStorage, { SecureRandom } from '#services/backup_code_storage'; // Here we are generating secret and recovery codes for the user that’s enabling 2FA and storing them to our database. export default class UserController { /** * Show the user a form to change their personal information & password. * * @return — \Inertia\Response */ public async accountInfo({ inertia, auth }: HttpContext) { // const user = auth.user; const user = (await User.find(auth.user?.id)) as User; // const id = request.param('id'); // const user = await User.query().where('id', id).firstOrFail(); let storage = new BackupCodeStorage(new SecureRandom()); // const codes= user.isTwoFactorEnabled? (await user.getBackupCodes()).map((role) => role.code) : []; let backupState = await storage.getBackupCodesState(user); return inertia.render('Auth/AccountInfo', { user: user, twoFactorEnabled: user.isTwoFactorEnabled, // code: await TwoFactorAuthProvider.generateQrCode(user), backupState: backupState, }); } public async accountInfoStore({ auth, request, response, session }: HttpContext) { // const passwordSchema = schema.create({ // old_password: schema.string({ trim: true }, [rules.required()]), // new_password: schema.string({ trim: true }, [rules.minLength(8), rules.maxLength(255), rules.confirmed('confirm_password')]), // confirm_password: schema.string({ trim: true }, [rules.required()]), // }); const passwordSchema = vine.object({ // first step old_password: vine .string() .trim() .regex(/^[a-zA-Z0-9]+$/), new_password: vine.string().confirmed({ confirmationField: 'confirm_password' }).trim().minLength(8).maxLength(255), }); try { // await request.validate({ schema: passwordSchema }); const validator = vine.compile(passwordSchema); await request.validateUsing(validator); } catch (error) { // return response.badRequest(error.messages); throw error; } try { const user = await auth.user as User; const { old_password, new_password } = request.only(['old_password', 'new_password']); // if (!(old_password && new_password && confirm_password)) { // return response.status(400).send({ warning: 'Old password and new password are required.' }); // } // Verify if the provided old password matches the user's current password const isSame = await hash.verify(user.password, old_password); if (!isSame) { return response.flash('warning', 'Old password is incorrect.').redirect().back(); } // Hash the new password before updating the user's password user.password = new_password; await user.save(); // return response.status(200).send({ message: 'Password updated successfully.' }); session.flash({ message: 'Password updated successfully.' }); return response.redirect().toRoute('settings.user'); } catch (error) { // return response.status(500).send({ message: 'Internal server error.' }); return response.flash('warning', `Invalid server state. Internal server error.`).redirect().back(); } } public async enableTwoFactorAuthentication({ auth, response, session }: HttpContext): Promise { // const user: User | undefined = auth?.user; const user = (await User.find(auth.user?.id)) as User; user.twoFactorSecret = TwoFactorAuthProvider.generateSecret(user); user.twoFactorRecoveryCodes = await TwoFactorAuthProvider.generateRecoveryCodes(); await user.save(); session.flash('message', 'Two factor authentication enabled.'); return response.redirect().back(); // return inertia.render('Auth/AccountInfo', { // // status: { // // type: 'success', // // message: 'Two factor authentication enabled.', // // }, // user: user, // twoFactorEnabled: user.isTwoFactorEnabled, // code: await TwoFactorAuthProvider.generateQrCode(user), // recoveryCodes: user.twoFactorRecoveryCodes, // }); } public async disableTwoFactorAuthentication({ auth, response, session }: HttpContext): Promise { const user: User | undefined = auth.user; if (user) { user.twoFactorSecret = null; user.twoFactorRecoveryCodes = null; await user.save(); session.flash('message', 'Two-factor authentication disabled.'); } else { session.flash('error', 'User not found.'); } return response.redirect().back(); // return inertia.render('Auth/AccountInfo', { // // status: { // // type: 'success', // // message: 'Two factor authentication disabled.', // // }, // user: user, // twoFactorEnabled: user.isTwoFactorEnabled, // }); } // public async fetchRecoveryCodes({ auth, view }) { // const user = auth?.user; // return view.render('pages/settings', { // twoFactorEnabled: user.isTwoFactorEnabled, // recoveryCodes: user.twoFactorRecoveryCodes, // }); // } }