import type { HttpContext } from '@adonisjs/core/http' import { requestLoginValidator, verifyCodeValidator } from '#validators/auth' import mail from '@adonisjs/mail/services/main' import { AuthService } from '#services/auth_service' import { inject } from '@adonisjs/core' import app from '@adonisjs/core/services/app' import env from '#start/env' import User from '#models/user' // TODO: When login, set user.email to the email used to request login (lowercase) @inject() export default class AuthController { constructor(private authService: AuthService) {} // POST /auth/request async requestLogin({ request, response, captcha }: HttpContext) { // Validate captcha if (app.inProduction) { const validateResult = await (captcha.use('turnstile') as any).validate() if (!validateResult.success) { return response.badRequest({ message: 'Captcha validation failed', error: validateResult.errorCodes, }) } } // Find user by email const { email } = await request.validateUsing(requestLoginValidator) const user = await this.authService.findUser(email) if (!user) { return response.notFound({ success: false, message: 'Utilisateur non trouvé', }) } // Generate token const expiresIn = '15 minutes' const payload = await this.authService.generateToken(email, user.id, expiresIn) // Send email await mail .send((message) => { message .from(env.get('MAIL_FROM')!) .to(email) .subject(payload.emailTitle) .htmlView('mails/auth', payload) .textView('mails/auth-fallback', payload) }) // TODO: Handle email sending errors .then(console.log) .catch(console.error) return { success: true, data: { token: payload.token, }, } } // POST /auth/verify async verifyCode({ request, response, auth }: HttpContext) { // Validate code const { code } = await request.validateUsing(verifyCodeValidator) const { success, userId, email } = await this.authService.validateCode(code) if (!success || !userId || isNaN(userId)) { return response.badRequest({ success: false, message: 'Code de vérification invalide', }) } // Find user by id const user = await User.findBy('id', userId) if (!user) { return response.notFound({ success: false, message: 'Utilisateur non trouvé', }) } // Set user email to the email used to request login (lowercase) user.email = email.toLowerCase() await user.save() // Perform login await auth.use('web').login(user, true) // true for remember me return user } magicLink({}: HttpContext) { // Validate signed url (adonis) // + login current device // + SSE to notify other devices (and login) } listen({}: HttpContext) { // Listen for SSE events // Need an AUTH token to connect // AUTH token sent to client in requestLogin } }