Skip to content

Commit

Permalink
feat: reset pasword backend (#197)
Browse files Browse the repository at this point in the history
* feat: reset token and mailer

* feat: reset token

* feat: reset token

* chore: package-lock update

* chore: updated dependencies

* chore: minor bug fix

* feat: reset token frontend

* feat: reset token update password backend

* feat: reset password

* chore: minor bug fixes

* feat: reset token and mailer

* feat: reset token

* chore: package-lock update

* chore: updated dependencies

* chore: minor bug fix

* feat: reset token frontend

* feat: reset token update password backend

* feat: reset password

* feat: reset password

reset password

* chore: merge fixes

* fix: rebase
fix: rebase

* chore: merge fixes

* chore: merge fixes

* chore: merge fixes

* chore: pr suggestion

* chore: pr suggestions frontend

* chore: frontend bug fixes

* chore: pr sugestions

* chore: route fixes

* chore: new route

* chore: pr suggestions

* chore: pr suggestions Frontend

* chore: new pr suggestions Frontend

* chore: new pr suggestions backend

* chore: pr suggestion

* chore: change regex

* chore: pr suggestion

* chore: pr suggestions

* fix: background fix
  • Loading branch information
r-dmatos authored Jun 3, 2022
1 parent 26f599a commit f2e03d1
Show file tree
Hide file tree
Showing 37 changed files with 694 additions and 4,089 deletions.
48 changes: 48 additions & 0 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@
"eslint-config-airbnb-typescript": "^17.0.0",
"express": "^4.17.3",
"joi": "^17.6.0",
"jsonwebtoken": "^8.5.1",
"jwt-decode": "^3.1.2",
"jwt-encode": "^1.0.1",
"lint-staged": "^12.3.7",
"luxon": "^1.28.0",
"moment-business-days": "^1.2.0",
Expand All @@ -70,6 +72,7 @@
"@nestjs/testing": "^8.4.4",
"@types/express": "^4.17.13",
"@types/jest": "^27.4.1",
"@types/mongodb": "^4.0.7",
"@types/node": "^17.0.23",
"@types/supertest": "^2.0.12",
"@typescript-eslint/eslint-plugin": "^5.18.0",
Expand Down
6 changes: 6 additions & 0 deletions backend/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import { configuration } from './infrastructure/config/configuration';
import AzureModule from './modules/azure/azure.module';
import TeamsModule from './modules/teams/teams.module';
import EmailModule from './modules/mailer/mailer.module';
import {
mongooseResetModule,
mongooseUserModule,
} from './infrastructure/database/mongoose.module';

const imports = [
AppConfigModule,
Expand All @@ -26,6 +30,8 @@ const imports = [
VotesModule,
EmailModule,
TeamsModule,
mongooseResetModule,
mongooseUserModule,
ScheduleModule.forRoot(),
];

Expand Down
7 changes: 6 additions & 1 deletion backend/src/modules/auth/auth.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { PassportModule } from '@nestjs/passport';
import { mongooseResetModule } from 'src/infrastructure/database/mongoose.module';
import {
mongooseResetModule,
mongooseUserModule,
} from 'src/infrastructure/database/mongoose.module';
import AuthController from './controller/auth.controller';
import UsersModule from '../users/users.module';
import LocalStrategy from './strategy/local.strategy';
Expand Down Expand Up @@ -29,6 +32,7 @@ import { JwtRegister } from '../../infrastructure/config/jwt.register';
PassportModule,
ConfigModule,
mongooseResetModule,
mongooseUserModule,
],
providers: [
getTokenAuthService,
Expand All @@ -38,6 +42,7 @@ import { JwtRegister } from '../../infrastructure/config/jwt.register';
registerAuthApplication,
createResetTokenAuthApplication,
createResetTokenAuthService,
UsersModule,
LocalStrategy,
JwtStrategy,
JwtRefreshTokenStrategy,
Expand Down
26 changes: 25 additions & 1 deletion backend/src/modules/auth/controller/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import {
NotFoundException,
BadRequestException,
Param,
HttpStatus,
} from '@nestjs/common';
import { UpdateUserApplication } from '../../users/interfaces/applications/update.user.service.interface';
import { ResetPasswordDto } from '../../users/dto/reset-password.dto';
import LocalAuthGuard from '../../../libs/guards/localAuth.guard';
import RequestWithUser from '../../../libs/interfaces/requestWithUser.interface';
import JwtRefreshGuard from '../../../libs/guards/jwtRefreshAuth.guard';
Expand Down Expand Up @@ -49,12 +52,14 @@ export default class AuthController {
private getBoardApp: GetBoardApplicationInterface,
@Inject(TYPES.applications.CreateResetTokenAuthApplication)
private createResetTokenAuthApp: CreateResetTokenAuthApplication,
@Inject(TYPES.applications.UpdateUserApplication)
private updateUserApp: UpdateUserApplication,
) {}

@Post('register')
async register(@Body() registrationData: CreateUserDto) {
try {
const { _id, firstName, lastName, email, password } =
const { _id, firstName, lastName, email } =
await this.registerAuthApp.register(registrationData);

return { _id, firstName, lastName, email };
Expand Down Expand Up @@ -96,6 +101,25 @@ export default class AuthController {
return this.createResetTokenAuthApp.create(email);
}

@Post('updatepassword')
@HttpCode(HttpStatus.OK)
async setNewPassword(
@Body() { token, newPassword, newPasswordConf }: ResetPasswordDto,
) {
const email = await this.updateUserApp.checkEmail(token);
if (!email) return { message: 'token not valid' };
return (
(await this.updateUserApp.setPassword(
email,
newPassword,
newPasswordConf,
)) && {
status: 'ok',
message: 'Password updated successfully!',
}
);
}

@UseGuards(JwtAuthenticationGuard)
@Get('/dashboardStatistics')
async getDashboardHeaderInfo(@Req() request: RequestWithUser) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// success: true => message, data
// success: false => errorMessage, error

export interface IResponse {
success: boolean;
message: string;
errorMessage: string;
data: unknown[];
error: unknown[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Token } from '../../../../libs/interfaces/jwt/token.interface';
import { Tokens } from '../../../../libs/interfaces/jwt/tokens.interface';

export interface GetTokenAuthService {
getNewPassword(newPassword: string);
getTokens(userId: string): Promise<Tokens | null>;
getAccessToken(userId: string): Token;
getRefreshToken(userId: string): Token;
Expand Down
3 changes: 3 additions & 0 deletions backend/src/modules/auth/interfaces/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ export const TYPES = {
RegisterAuthService: 'RegisterAuthService',
CreateResetTokenAuthService: 'CreateResetTokenAuthService',
AzureAuthService: 'AzureAuthService',
UpdateUserService: 'UpdateUserService',
},
applications: {
GetTokenAuthApplication: 'GetTokenAuthApplication',
RegisterAuthApplication: 'RegisterAuthApplication',
CreateResetTokenAuthApplication: 'CreateResetTokenAuthApplication',
UpdatePasswordAuthApplication: 'UpdatePasswordAuthApplication',
UpdateUserApplication: 'UpdateUserApplication',
},
};
3 changes: 3 additions & 0 deletions backend/src/modules/auth/schemas/reset-password.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ export default class ResetPassword {

@Prop({ default: Date.now })
updatedAt!: Date;

@Prop({ nullable: false })
newPassword?: string;
}

export const ResetPasswordSchema = SchemaFactory.createForClass(ResetPassword);
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ export default class CreateResetTokenAuthServiceImpl
) {}

public async emailBody(token: string, emailAddress: string) {
const url = `${this.configService.get<string>('frontend.url')}?${token}`;
const url = `${this.configService.get<string>(
'frontend.url',
)}/reset-password/${token}`;
const msg = 'please check your email';
await this.mailerService.sendMail({
to: emailAddress,
Expand Down
4 changes: 4 additions & 0 deletions backend/src/modules/auth/services/get-token.auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ export default class GetTokenAuthServiceImpl implements GetTokenAuthService {
};
}

async getNewPassword(newPassword: string) {
return this.getNewPassword(newPassword);
}

public getAccessToken(userId: string) {
const token = this.jwtService.sign(
{ userId },
Expand Down
30 changes: 30 additions & 0 deletions backend/src/modules/users/applications/update.user.application.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Injectable, Inject } from '@nestjs/common';

import { UpdateUserApplication } from '../interfaces/applications/update.user.service.interface';
import { UpdateUserService } from '../interfaces/services/update.user.service.interface';

import { TYPES } from '../interfaces/types';

@Injectable()
export class UpdateUserApplicationImpl implements UpdateUserApplication {
constructor(
@Inject(TYPES.services.UpdateUserService)
private updateUserService: UpdateUserService,
) {}

setCurrentRefreshToken(refreshToken: string, userId: string) {
return this.updateUserService.setCurrentRefreshToken(refreshToken, userId);
}

setPassword(userEmail: string, newPassword: string, newPasswordConf: string) {
return this.updateUserService.setPassword(
userEmail,
newPassword,
newPasswordConf,
);
}

checkEmail(token: string) {
return this.updateUserService.checkEmail(token);
}
}
28 changes: 28 additions & 0 deletions backend/src/modules/users/dto/reset-password.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Transform, TransformFnParams } from 'class-transformer';
import { IsNotEmpty, IsString, Matches, MinLength } from 'class-validator';

export class ResetPasswordDto {
@IsString()
@IsNotEmpty()
token!: string;

@IsString()
@IsNotEmpty()
@Transform(({ value }: TransformFnParams) => value.trim())
@MinLength(7)
@Matches(/^(?=.*[A-Za-z])(?=.*\d)(?=.*\W)[A-Za-z\d\W]{8,}/, {
message:
'Password too weak. Must have 1 uppercase, 1 lowercase, 1 number and 1 special character',
})
newPassword!: string;

@IsString()
@IsNotEmpty()
@Transform(({ value }: TransformFnParams) => value.trim())
@MinLength(7)
@Matches(/^(?=.*[A-Za-z])(?=.*\d)(?=.*\W)[A-Za-z\d\W]{8,}/, {
message:
'Password too weak. Must have 1 uppercase, 1 lowercase, 1 number and 1 special character',
})
newPasswordConf!: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { LeanDocument } from 'mongoose';
import { UserDocument } from '../../schemas/user.schema';

export interface UpdateUserApplication {
setCurrentRefreshToken(
refreshToken: string,
userId: string,
): Promise<LeanDocument<UserDocument> | null>;
setPassword(
userEmail: string,
newPassword: string,
newPasswordConf: string,
): Promise<UserDocument | null>;
checkEmail(token: string): Promise<string>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,10 @@ export interface UpdateUserService {
refreshToken: string,
userId: string,
): Promise<LeanDocument<UserDocument> | null>;
setPassword(
userEmail: string,
newPassword: string,
newPasswordConf: string,
): Promise<UserDocument | null>;
checkEmail(token: string): Promise<string>;
}
1 change: 1 addition & 0 deletions backend/src/modules/users/interfaces/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ export const TYPES = {
},
applications: {
GetUserApplication: 'GetUserApplication',
UpdateUserApplication: 'UpdateUserApplication',
},
};
Loading

0 comments on commit f2e03d1

Please sign in to comment.