first commit
This commit is contained in:
commit
3c0479faf0
169 files changed
+27617
No files matched your search
@@ -0,0 +1,59 @@
|
||||
import User from '#models/user'
|
||||
import limiter from '@adonisjs/limiter/services/main'
|
||||
import type { HttpContext } from '@adonisjs/core/http'
|
||||
import totpService from '#services/totp_service'
|
||||
import { audit } from '#services/audit'
|
||||
import { loginValidator } from '#validators/auth'
|
||||
|
||||
class InvalidLogin extends Error {}
|
||||
|
||||
/**
|
||||
* 5 failed attempts per IP, then blocked for 15 minutes.
|
||||
*/
|
||||
const loginLimiter = () =>
|
||||
limiter.use({ requests: 5, duration: '15 mins', blockDuration: '15 mins' })
|
||||
|
||||
export default class AuthController {
|
||||
async login(ctx: HttpContext) {
|
||||
const { request, response, auth } = ctx
|
||||
const { username, password, code } = await request.validateUsing(loginValidator)
|
||||
|
||||
const penalize = () =>
|
||||
loginLimiter().penalize(`login_${request.ip()}`, async (): Promise<User> => {
|
||||
const user = await User.verifyCredentials(username, password).catch(() => null)
|
||||
if (!user || !(await totpService.verify(user, code))) throw new InvalidLogin()
|
||||
return user
|
||||
})
|
||||
|
||||
let result: Awaited<ReturnType<typeof penalize>>
|
||||
try {
|
||||
result = await penalize()
|
||||
} catch (error) {
|
||||
if (!(error instanceof InvalidLogin)) throw error
|
||||
await audit(ctx, { action: 'Connexion refusée', target: username, status: 'error' })
|
||||
return response.badRequest({ message: 'Identifiant, mot de passe ou code incorrect.' })
|
||||
}
|
||||
|
||||
const [throttled, user] = result
|
||||
if (throttled) {
|
||||
const minutes = Math.max(1, Math.ceil(throttled.response.availableIn / 60))
|
||||
return response.tooManyRequests({
|
||||
message: `Trop de tentatives. Réessaie dans ${minutes} min.`,
|
||||
})
|
||||
}
|
||||
|
||||
await auth.use('web').login(user!)
|
||||
await audit(ctx, { action: 'Connexion', username: user!.username, status: 'success' })
|
||||
return { username: user!.username }
|
||||
}
|
||||
|
||||
async logout(ctx: HttpContext) {
|
||||
await audit(ctx, { action: 'Déconnexion', status: 'success' })
|
||||
await ctx.auth.use('web').logout()
|
||||
return { ok: true }
|
||||
}
|
||||
|
||||
async me({ auth }: HttpContext) {
|
||||
return { username: auth.getUserOrFail().username }
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user