auth defined test required
This commit is contained in:
@@ -1,8 +1,196 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PrismaService } from '@/src/prisma.service';
|
||||
import {
|
||||
Injectable,
|
||||
BadRequestException,
|
||||
UnauthorizedException,
|
||||
} from '@nestjs/common';
|
||||
import { userChangePasswordValidator } from './dtoValidator';
|
||||
import { RedisHandlers } from '@/src/utils/auth/redis_handlers';
|
||||
import { PasswordHandlers } from '@/src/utils/auth/login_handler';
|
||||
|
||||
@Injectable()
|
||||
export class ChangePasswordService {
|
||||
async run(dto: any) {
|
||||
return dto;
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly redis: RedisHandlers,
|
||||
private readonly passHandlers: PasswordHandlers,
|
||||
) {}
|
||||
|
||||
private async syncPasswordHistory(
|
||||
foundUser: any,
|
||||
dto: userChangePasswordValidator,
|
||||
hashPassword: string,
|
||||
) {
|
||||
const passwordHistory = await this.prisma.password_history.findFirst({
|
||||
where: { userUUID: foundUser.uu_id },
|
||||
});
|
||||
console.log('passwordHistory', passwordHistory);
|
||||
console.log('dto', dto);
|
||||
console.log('hashPassword', hashPassword);
|
||||
|
||||
if (passwordHistory) {
|
||||
if (!passwordHistory.old_password_first) {
|
||||
await this.prisma.password_history.update({
|
||||
where: { id: passwordHistory.id },
|
||||
data: {
|
||||
password: hashPassword,
|
||||
old_password_first: dto.password,
|
||||
old_password_first_modified_at: new Date(),
|
||||
},
|
||||
});
|
||||
} else if (!passwordHistory.old_password_second) {
|
||||
await this.prisma.password_history.update({
|
||||
where: { id: passwordHistory.id },
|
||||
data: {
|
||||
password: hashPassword,
|
||||
old_password_second: dto.password,
|
||||
old_password_second_modified_at: new Date(),
|
||||
},
|
||||
});
|
||||
} else if (!passwordHistory.old_password_third) {
|
||||
await this.prisma.password_history.update({
|
||||
where: { id: passwordHistory.id },
|
||||
data: {
|
||||
password: hashPassword,
|
||||
old_password_third: dto.password,
|
||||
old_password_third_modified_at: new Date(),
|
||||
},
|
||||
});
|
||||
} else {
|
||||
const firstTimestamp = new Date(
|
||||
passwordHistory.old_password_first_modified_at,
|
||||
).getTime();
|
||||
const secondTimestamp = new Date(
|
||||
passwordHistory.old_password_second_modified_at,
|
||||
).getTime();
|
||||
const thirdTimestamp = new Date(
|
||||
passwordHistory.old_password_third_modified_at,
|
||||
).getTime();
|
||||
|
||||
let oldestIndex = 'first';
|
||||
let oldestTimestamp = firstTimestamp;
|
||||
|
||||
if (secondTimestamp < oldestTimestamp) {
|
||||
oldestIndex = 'second';
|
||||
oldestTimestamp = secondTimestamp;
|
||||
}
|
||||
if (thirdTimestamp < oldestTimestamp) {
|
||||
oldestIndex = 'third';
|
||||
}
|
||||
|
||||
await this.prisma.password_history.update({
|
||||
where: { id: passwordHistory.id },
|
||||
data: {
|
||||
password: hashPassword,
|
||||
...(oldestIndex === 'first'
|
||||
? {
|
||||
old_password_first: dto.password,
|
||||
old_password_first_modified_at: new Date(),
|
||||
}
|
||||
: oldestIndex === 'second'
|
||||
? {
|
||||
old_password_second: dto.password,
|
||||
old_password_second_modified_at: new Date(),
|
||||
}
|
||||
: {
|
||||
old_password_third: dto.password,
|
||||
old_password_third_modified_at: new Date(),
|
||||
}),
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
await this.prisma.password_history.create({
|
||||
data: {
|
||||
userUUID: foundUser.uu_id,
|
||||
password: hashPassword,
|
||||
old_password_first: dto.password,
|
||||
old_password_first_modified_at: new Date(),
|
||||
old_password_second: '',
|
||||
old_password_second_modified_at: new Date(),
|
||||
old_password_third: '',
|
||||
old_password_third_modified_at: new Date(),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async run(dto: userChangePasswordValidator, req: Request) {
|
||||
const isValid = () => {
|
||||
const isOldPasswordDifferent = dto.password !== dto.oldPassword;
|
||||
const isPasswordMatchesWithRePassword = dto.password === dto.rePassword;
|
||||
return isOldPasswordDifferent && isPasswordMatchesWithRePassword;
|
||||
};
|
||||
|
||||
if (!isValid()) {
|
||||
throw new BadRequestException(
|
||||
'Passwords do not match or new password is the same as old password',
|
||||
);
|
||||
}
|
||||
const accessObject = await this.redis.getLoginFromRedis(req);
|
||||
const userFromRedis = accessObject?.value.users;
|
||||
if (!userFromRedis) {
|
||||
throw new UnauthorizedException('User not authenticated');
|
||||
}
|
||||
|
||||
const foundUser = await this.prisma.users.findFirstOrThrow({
|
||||
where: { uu_id: userFromRedis.uu_id },
|
||||
});
|
||||
|
||||
if (foundUser.password_token) {
|
||||
throw new BadRequestException('Set password first before changing');
|
||||
}
|
||||
const isPasswordValid = this.passHandlers.check_password(
|
||||
foundUser.uu_id,
|
||||
dto.oldPassword,
|
||||
foundUser.hash_password,
|
||||
);
|
||||
if (!isPasswordValid) {
|
||||
throw new UnauthorizedException('Invalid password');
|
||||
}
|
||||
|
||||
const passwordHistory = await this.prisma.password_history.findFirst({
|
||||
where: {
|
||||
userUUID: foundUser.uu_id,
|
||||
OR: [
|
||||
{
|
||||
old_password_first: {
|
||||
equals: dto.password,
|
||||
mode: 'insensitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
old_password_second: {
|
||||
equals: dto.password,
|
||||
mode: 'insensitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
old_password_third: {
|
||||
equals: dto.password,
|
||||
mode: 'insensitive',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
if (passwordHistory) {
|
||||
throw new UnauthorizedException(
|
||||
'Invalid password, new password can not be same as old password',
|
||||
);
|
||||
}
|
||||
|
||||
const hashPassword = this.passHandlers.create_hashed_password(
|
||||
foundUser.uu_id,
|
||||
dto.password,
|
||||
);
|
||||
await this.prisma.users.update({
|
||||
where: { id: foundUser.id },
|
||||
data: {
|
||||
hash_password: hashPassword,
|
||||
},
|
||||
});
|
||||
await this.syncPasswordHistory(foundUser, dto, hashPassword);
|
||||
return { message: 'Password changed successfully' };
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user