mirror of
https://github.com/caprover/caprover
synced 2025-10-30 10:07:01 +00:00
Added limit on wrong password
This commit is contained in:
@@ -45,6 +45,7 @@ class ApiStatusCodes {
|
||||
static readonly ILLEGAL_PARAMETER = 1110
|
||||
static readonly NOT_FOUND = 1111
|
||||
static readonly AUTHENTICATION_FAILED = 1112
|
||||
static readonly STATUS_PASSWORD_BACK_OFF = 1113
|
||||
}
|
||||
|
||||
export = ApiStatusCodes
|
||||
|
||||
@@ -6,9 +6,12 @@ import InjectionExtractor = require('../../injection/InjectionExtractor')
|
||||
import DataStoreProvider = require('../../datastore/DataStoreProvider')
|
||||
import CaptainManager = require('../../user/system/CaptainManager')
|
||||
import Authenticator = require('../../user/Authenticator')
|
||||
import CircularQueue from '../../utils/CircularQueue'
|
||||
|
||||
const router = express.Router()
|
||||
|
||||
const failedLoginCircularTimestamps = new CircularQueue<number>(5)
|
||||
|
||||
router.post('/', function(req, res, next) {
|
||||
let password = req.body.password || ''
|
||||
|
||||
@@ -30,6 +33,16 @@ router.post('/', function(req, res, next) {
|
||||
|
||||
Promise.resolve() //
|
||||
.then(function() {
|
||||
const oldestKnownFailedLogin = failedLoginCircularTimestamps.peek()
|
||||
if (
|
||||
oldestKnownFailedLogin &&
|
||||
new Date().getTime() - oldestKnownFailedLogin < 30000
|
||||
)
|
||||
throw ApiStatusCodes.createError(
|
||||
ApiStatusCodes.STATUS_PASSWORD_BACK_OFF,
|
||||
'Too many wrong passwords... Wait for 30 seconds and retry.'
|
||||
)
|
||||
|
||||
return DataStoreProvider.getDataStore(namespace).getHashedPassword()
|
||||
})
|
||||
.then(function(savedHashedPassword) {
|
||||
@@ -54,6 +67,19 @@ router.post('/', function(req, res, next) {
|
||||
baseApi.data = { token: authToken }
|
||||
res.send(baseApi)
|
||||
})
|
||||
.catch(function(err) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (
|
||||
err &&
|
||||
err.captainErrorType &&
|
||||
err.captainErrorType ===
|
||||
ApiStatusCodes.STATUS_WRONG_PASSWORD
|
||||
) {
|
||||
failedLoginCircularTimestamps.push(new Date().getTime())
|
||||
}
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
.catch(ApiStatusCodes.createCatcher(res))
|
||||
})
|
||||
|
||||
|
||||
23
src/utils/CircularQueue.ts
Normal file
23
src/utils/CircularQueue.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
export default class CircularQueue<T> {
|
||||
private values: (T | undefined)[] = []
|
||||
private currSize = 0
|
||||
|
||||
constructor(private maxSize: number) {
|
||||
if (!this.maxSize) throw new Error('invalid size of zero')
|
||||
if (this.maxSize === 1) throw new Error('invalid size of one')
|
||||
for (let index = 0; index < this.maxSize; index++) {
|
||||
this.values.push(undefined)
|
||||
}
|
||||
}
|
||||
|
||||
push(value: T) {
|
||||
this.values[this.currSize % this.maxSize] = value
|
||||
this.currSize++
|
||||
}
|
||||
|
||||
peek(): T | undefined {
|
||||
const nextPositionToBeOverwritten = this.currSize % this.maxSize
|
||||
return this.values[nextPositionToBeOverwritten]
|
||||
}
|
||||
}
|
||||
38
tests/CircularQueue.test.ts
Normal file
38
tests/CircularQueue.test.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import CircularQueue from '../src/utils/CircularQueue'
|
||||
|
||||
function createTest(size: number, initWith: number) {
|
||||
const testQueue = new CircularQueue<string>(size)
|
||||
for (let index = 0; index < initWith; index++) {
|
||||
testQueue.push('val:' + (index + 1))
|
||||
}
|
||||
|
||||
return testQueue
|
||||
}
|
||||
|
||||
test('Large Circular Queue', () => {
|
||||
for (let index = 5; index < 20; index++) {
|
||||
expect(createTest(4, index).peek()) //
|
||||
.toBe('val:' + (index - 3))
|
||||
}
|
||||
})
|
||||
|
||||
test('Basic Circular Queue', () => {
|
||||
expect(createTest(2, 10).peek()) //
|
||||
.toBe('val:9')
|
||||
|
||||
})
|
||||
|
||||
test('Basic Circular Queue', () => {
|
||||
expect(createTest(2, 1).peek()) //
|
||||
.toBe(undefined)
|
||||
})
|
||||
|
||||
test('Basic Circular Queue', () => {
|
||||
expect(createTest(2, 2).peek()) //
|
||||
.toBe('val:1')
|
||||
})
|
||||
|
||||
test('Basic Circular Queue', () => {
|
||||
expect(createTest(2, 3).peek()) //
|
||||
.toBe('val:2')
|
||||
})
|
||||
Reference in New Issue
Block a user