feat: new register flow
This commit is contained in:
parent
5598b40d66
commit
cc63e16d9c
4 changed files with 52 additions and 36 deletions
|
|
@ -31,7 +31,6 @@ export default class AuthController {
|
|||
const expiresIn = '15 minutes'
|
||||
const payload = await this.authService.generateCode(email, expiresIn)
|
||||
|
||||
// Send email
|
||||
await mail
|
||||
.send((message) => {
|
||||
message
|
||||
|
|
@ -62,7 +61,6 @@ export default class AuthController {
|
|||
})
|
||||
}
|
||||
|
||||
// Find user by id
|
||||
const user = await User.findBy('email', email)
|
||||
if (!user) {
|
||||
// If the user does not exist, return a token for registration
|
||||
|
|
@ -75,59 +73,83 @@ export default class AuthController {
|
|||
}
|
||||
}
|
||||
|
||||
// Perform login
|
||||
await auth.use('web').login(user, true) // true for remember me
|
||||
return {
|
||||
success: true,
|
||||
user,
|
||||
}
|
||||
}
|
||||
|
||||
// GET /auth/autocomplete
|
||||
async listNames({ request }: HttpContext) {
|
||||
const { className } = request.qs()
|
||||
if (!className) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Veuillez spécifier une classe',
|
||||
}
|
||||
}
|
||||
|
||||
return User.query()
|
||||
.select('firstName', 'lastName')
|
||||
.where('className', className)
|
||||
.orderBy('lastName', 'asc')
|
||||
.then((users) => {
|
||||
return {
|
||||
success: true,
|
||||
data: users.map((user) => ({
|
||||
value: `${user.firstName}::${user.lastName}`,
|
||||
label: user.fullName,
|
||||
})),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// POST /auth/register
|
||||
async register({ request, response, auth }: HttpContext) {
|
||||
const { firstName, lastName, className, token } = await request.validateUsing(registerValidator)
|
||||
const { name, className, token } = await request.validateUsing(registerValidator)
|
||||
|
||||
// Validate token
|
||||
const { success, email } = this.authService.validateToken(token)
|
||||
if (!success || !email) {
|
||||
const [firstName, lastName] = name.split('::')
|
||||
if (!success || !email || !firstName || !lastName) {
|
||||
return response.badRequest({
|
||||
success: false,
|
||||
message: 'Votre lien de connexion est invalide ou a expiré.',
|
||||
})
|
||||
}
|
||||
|
||||
// Check if user already exists
|
||||
const existingUser = await User.findBy('email', email)
|
||||
if (existingUser) {
|
||||
// If user already exists, perform login
|
||||
await auth.use('web').login(existingUser, true) // true for remember me
|
||||
return {
|
||||
success: true,
|
||||
user: existingUser,
|
||||
}
|
||||
const user = await User.query()
|
||||
.where('firstName', firstName)
|
||||
.where('lastName', lastName)
|
||||
.where('className', className)
|
||||
.first()
|
||||
if (!user) {
|
||||
return response.badRequest({
|
||||
success: false,
|
||||
message: 'Utilisateur non trouvé. Veuillez vérifier vos informations.',
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: Check if className is allowed (else redirect for account giving)
|
||||
if (user.email && user.email.toLowerCase() !== email.toLowerCase()) {
|
||||
return response.badRequest({
|
||||
success: false,
|
||||
message:
|
||||
"L'email associé à votre compte ne correspond pas à celui utilisé pour la connexion.",
|
||||
})
|
||||
}
|
||||
|
||||
user.email = email.toLowerCase() // Update email if necessary
|
||||
await user.save()
|
||||
|
||||
// TODO: Rewrite user creation (NEVER CREATE USER - use string similarity)
|
||||
// Create new user
|
||||
const user = await User.create({
|
||||
firstName,
|
||||
lastName,
|
||||
className,
|
||||
email,
|
||||
})
|
||||
// Perform login
|
||||
await auth.use('web').login(user, true) // true for remember me
|
||||
return {
|
||||
success: true,
|
||||
user,
|
||||
}
|
||||
}
|
||||
|
||||
// POST /auth/logout
|
||||
async logout({ auth }: HttpContext) {
|
||||
// Logout user
|
||||
await auth.use('web').logout()
|
||||
return {
|
||||
success: true,
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ export default class User extends BaseModel {
|
|||
@column()
|
||||
declare className: string
|
||||
|
||||
@column()
|
||||
@column({ serializeAs: null})
|
||||
declare firstName: string
|
||||
|
||||
@column()
|
||||
@column({ serializeAs: null})
|
||||
declare lastName: string
|
||||
|
||||
@computed()
|
||||
|
|
|
|||
|
|
@ -19,16 +19,9 @@ export const verifyCodeValidator = vine.compile(
|
|||
})
|
||||
)
|
||||
|
||||
function toTitleCase(value: string) {
|
||||
return value.replace(/\w\S*/g, (txt) => {
|
||||
return txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase()
|
||||
})
|
||||
}
|
||||
|
||||
export const registerValidator = vine.compile(
|
||||
vine.object({
|
||||
firstName: vine.string().minLength(2).maxLength(50).trim().transform(toTitleCase),
|
||||
lastName: vine.string().minLength(2).maxLength(50).trim().toUpperCase(),
|
||||
name: vine.string().minLength(2).maxLength(50).trim(),
|
||||
className: vine.string().minLength(2).maxLength(50),
|
||||
token: vine.string(),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ router.group(() => {
|
|||
router.post('/auth/verify', [AuthController, 'verifyCode']).use(throttle)
|
||||
router.post('/auth/register', [AuthController, 'register']).use(throttle)
|
||||
router.post('/auth/logout', [AuthController, 'logout'])
|
||||
router.get('/auth/autocomplete', [AuthController, 'listNames']).use(throttle)
|
||||
// TODO: Magic link login
|
||||
// router.get('/auth/magic-link', 'AuthController.magicLink').use(throttle)
|
||||
// router.get('/auth/listen', 'AuthController.listen')
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue