1- import AdminJS from "adminjs" ;
2- import { Router } from "express" ;
3- import { AuthenticationOptions } from "../types" ;
1+ import AdminJS from 'adminjs' ;
2+ import { Router } from 'express' ;
3+ import {
4+ AuthenticationMaxRetriesOptions ,
5+ AuthenticationOptions ,
6+ } from '../types' ;
47
58const getLoginPath = ( admin : AdminJS ) : string => {
69 const { loginPath, rootPath } = admin . options ;
@@ -15,6 +18,48 @@ const getLoginPath = (admin: AdminJS): string => {
1518 : `/${ normalizedLoginPath } ` ;
1619} ;
1720
21+ class Retry {
22+ private static retriesContainer : Map < string , Retry > = new Map ( ) ;
23+ private lastRetry : Date | undefined ;
24+ private retriesCount = 0 ;
25+
26+ constructor ( ip : string ) {
27+ const existing = Retry . retriesContainer . get ( ip ) ;
28+ if ( existing ) {
29+ return existing ;
30+ }
31+ Retry . retriesContainer . set ( ip , this ) ;
32+ }
33+
34+ public canLogin (
35+ maxRetries : number | AuthenticationMaxRetriesOptions | undefined
36+ ) : boolean {
37+ if ( maxRetries === undefined ) {
38+ return true ;
39+ } else if ( typeof maxRetries === "number" ) {
40+ maxRetries = {
41+ count : maxRetries ,
42+ duration : 60 ,
43+ } ;
44+ } else if ( maxRetries . count <= 0 ) {
45+ return true ;
46+ }
47+ if (
48+ ! this . lastRetry ||
49+ new Date ( ) . getTime ( ) - this . lastRetry . getTime ( ) >
50+ maxRetries . duration * 1000
51+ ) {
52+ this . lastRetry = new Date ( ) ;
53+ this . retriesCount = 1 ;
54+ return true ;
55+ } else {
56+ this . lastRetry = new Date ( ) ;
57+ this . retriesCount ++ ;
58+ return this . retriesCount <= maxRetries . count ;
59+ }
60+ }
61+ }
62+
1863export const withLogin = (
1964 router : Router ,
2065 admin : AdminJS ,
@@ -32,6 +77,14 @@ export const withLogin = (
3277 } ) ;
3378
3479 router . post ( loginPath , async ( req , res , next ) => {
80+ if ( ! new Retry ( req . ip ) . canLogin ( auth . maxRetries ) ) {
81+ const login = await admin . renderLogin ( {
82+ action : admin . options . loginPath ,
83+ errorMessage : "tooManyRequests" ,
84+ } ) ;
85+ res . send ( login ) ;
86+ return ;
87+ }
3588 const { email, password } = req . fields as {
3689 email : string ;
3790 password : string ;
0 commit comments