Implemented a password reset timeout

ref #40
This commit is contained in:
Nicolai Ort 2020-12-22 11:12:24 +01:00
parent 48685451be
commit 17ee682029
3 changed files with 25 additions and 2 deletions

View File

@ -115,4 +115,15 @@ export class RefreshTokenCountInvalidError extends NotAcceptableError {
@IsString()
message = "Refresh token count is invalid."
}
/**
* Error to throw when someone tryes to refresh a user's password more than once in 15 minutes.
*/
export class ResetAlreadyRequestedError extends NotAcceptableError {
@IsString()
name = "ResetAlreadyRequestedError"
@IsString()
message = "You already requested a password reset in the last 15 minutes. \n Please wait until the old reset code expires before requesting a new one."
}

View File

@ -1,6 +1,6 @@
import { IsEmail, IsOptional, IsString } from 'class-validator';
import { getConnectionManager } from 'typeorm';
import { UserNotFoundError } from '../../errors/AuthError';
import { ResetAlreadyRequestedError, UserNotFoundError } from '../../errors/AuthError';
import { UsernameOrEmailNeededError } from '../../errors/UserErrors';
import { JwtCreator } from '../../jwtcreator';
import { User } from '../entities/User';
@ -32,12 +32,15 @@ export class CreateResetToken {
if (this.email === undefined && this.username === undefined) {
throw new UsernameOrEmailNeededError();
}
let found_user = await getConnectionManager().get().getRepository(User).findOne({ relations: ['groups', 'permissions', 'actions'], where: [{ username: this.username }, { email: this.email }] });
let found_user = await getConnectionManager().get().getRepository(User).findOne({ where: [{ username: this.username }, { email: this.email }] });
if (!found_user) {
throw new UserNotFoundError();
}
if (found_user.resetRequestedTimestamp > (Math.floor(Date.now() / 1000) - 15 * 60)) { throw new ResetAlreadyRequestedError(); }
found_user.refreshTokenCount = found_user.refreshTokenCount + 1;
found_user.resetRequestedTimestamp = Math.floor(Date.now() / 1000);
await getConnectionManager().get().getRepository(User).save(found_user);
//Create the reset

View File

@ -111,6 +111,15 @@ export class User extends Principal {
@IsOptional()
profilePic?: string;
/**
* The last time the user requested a password reset.
* Used to prevent spamming of the password reset route.
*/
@Column({ nullable: true, unique: true })
@IsString()
@IsOptional()
resetRequestedTimestamp?: number;
/**
* The actions performed by this user.
* For documentation purposes only, will be implemented later.