Skip to content

Commit 5f2d8ca

Browse files
committed
reset
1 parent fbee009 commit 5f2d8ca

File tree

8 files changed

+175
-27
lines changed

8 files changed

+175
-27
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"@types/passport-http": "^0.3.11",
3131
"bullmq": "^4.14.0",
3232
"class-validator": "^0.14.0",
33+
"ioredis": "^5.3.2",
3334
"passport": "^0.6.0",
3435
"passport-headerapikey": "^1.2.2",
3536
"reflect-metadata": "^0.1.13",

src/config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export default () => ({
66
password: process.env.REDIS_PASSWORD ||''
77
},
88
logLevel: process.env.LOG_LEVEL || 'info',
9-
nameQueue: process.env.NAME_QUEUE || 'backend',
9+
nameQueue: process.env.NAME_QUEUE || 'backend',
10+
secret: process.env.SECRET || 'mySecret',
1011
});
1112

src/passwd/dto/ask-token.dto.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { IsInt, IsString } from 'class-validator';
2+
import { ApiProperty } from '@nestjs/swagger';
3+
export class AskTokenDto {
4+
@IsString()
5+
@ApiProperty({ example: 'paul.bismuth',description: 'User Uid' })
6+
uid: string;
7+
@ApiProperty({ example: 'monemail@mondomaine.com',description: 'secondary mail' })
8+
@IsString()
9+
mail: string
10+
}

src/passwd/dto/change-password.dto.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export class ChangePasswordDto {
66
uid: string;
77
@ApiProperty({ example: 'MyOldPassword',description: 'Old Password' })
88
@IsString()
9-
oldPassword: number;
9+
oldPassword:string;
1010
@ApiProperty({ example: 'MyNewPassword',description: 'New Password' })
1111
@IsString()
1212
newPassword: string;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { IsInt, IsString } from 'class-validator';
2+
import { ApiProperty } from '@nestjs/swagger';
3+
export class ResetPasswordDto {
4+
@IsString()
5+
@ApiProperty({ example: 'S9nv9vjxdW7bS0haoWUmdJ3XPbSJ7dSdRj2ND1z9RvqLK/sF1LKZpfnWDvLX1dZuG0WGEyAb9A==',description: 'Token' })
6+
token: string;
7+
@ApiProperty({ example: 'MyNewPassword',description: 'New Password' })
8+
@IsString()
9+
newPassword: string;
10+
}

src/passwd/dto/verify-token.dto.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { IsInt, IsString } from 'class-validator';
2+
import { ApiProperty } from '@nestjs/swagger';
3+
export class VerifyTokenDto {
4+
@ApiProperty({ example: 'S9nv9vjxdW7bS0haoWUmdJ3XPbSJ7dSdRj2ND1z9RvqLK/sF1LKZpfnWDvLX1dZuG0WGEyAb9A==',description: 'token received by getToken' })
5+
@IsString()
6+
token: string
7+
}

src/passwd/passwd.controller.ts

Lines changed: 78 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,94 @@
11
import {Controller, Post, Body, Res, UseGuards, Logger} from '@nestjs/common';
2-
import { PasswdService } from './passwd.service';
2+
import {PasswdService} from './passwd.service';
33
import {
44
ApiTags,
55
ApiOperation,
66
ApiResponse, ApiBearerAuth
77
} from '@nestjs/swagger';
8-
import { Response } from 'express';
9-
import { ChangePasswordDto } from './dto/change-password.dto';
10-
import { AuthGuard } from '@nestjs/passport';
8+
import {Response} from 'express';
9+
import {ChangePasswordDto} from './dto/change-password.dto';
10+
import {AuthGuard} from '@nestjs/passport';
11+
import {AskTokenDto} from "./dto/ask-token.dto";
12+
import {VerifyTokenDto} from "./dto/verify-token.dto";
13+
import {ResetPasswordDto} from "./dto/reset-password.dto";
1114

1215

1316
@Controller('passwd')
1417
@ApiTags('passwd')
1518
export class PasswdController {
1619
private readonly logger = new Logger(PasswdController.name);
17-
constructor(private passwdService: PasswdService) {
18-
}
19-
@Post()
20-
@ApiOperation({ summary: 'change password' })
21-
@ApiResponse({ status: 201, description: 'Password has been successfully changed.'})
22-
@ApiResponse({ status: 403, description: 'Old password wrong'})
23-
@ApiResponse({ status: 500, description: 'Backend error'})
24-
@ApiBearerAuth()
25-
@UseGuards(AuthGuard("api-key"))
26-
async change(@Body() cpwd: ChangePasswordDto,@Res() res: Response): Promise<Response>{
27-
this.logger.log('call passwd')
28-
const data= await this.passwdService.change(cpwd)
29-
console.log(data)
30-
data.data.uid=cpwd.uid
31-
if ( data.data.status === 0){
20+
21+
constructor(private passwdService: PasswdService) {
22+
}
23+
24+
@Post('change')
25+
@ApiOperation({summary: 'change password'})
26+
@ApiResponse({status: 201, description: 'Password has been successfully changed.'})
27+
@ApiResponse({status: 403, description: 'Old password wrong'})
28+
@ApiResponse({status: 500, description: 'Backend error'})
29+
@ApiBearerAuth()
30+
@UseGuards(AuthGuard("api-key"))
31+
async change(@Body() cpwd: ChangePasswordDto, @Res() res: Response): Promise<Response> {
32+
33+
const data = await this.passwdService.change(cpwd)
34+
console.log(data)
35+
data.data.uid = cpwd.uid
36+
this.logger.log('call passwd change for : ' + cpwd.uid)
37+
if (data.data.status === 0) {
38+
return res.status(201).json(data);
39+
} else {
40+
if (data.data.status === 1) {
41+
return res.status(403).json(data);
42+
}
43+
this.logger.log('ERROR : ' + data)
3244
return res.status(201).json(data);
45+
}
46+
}
47+
48+
@Post('gettoken')
49+
@ApiOperation({summary: 'ask token for reseting password'})
50+
@ApiResponse({status: 201, description: 'Token', content: {}})
51+
@ApiResponse({status: 500, description: 'Backend error'})
52+
@ApiBearerAuth()
53+
@UseGuards(AuthGuard("api-key"))
54+
async gettoken(@Body() asktoken: AskTokenDto, @Res() res: Response): Promise<Response> {
55+
const data = await this.passwdService.askToken(asktoken)
56+
const ret = {token: data}
57+
console.log(ret)
58+
return res.status(201).json(ret);
59+
}
60+
@Post('verifytoken')
61+
@ApiOperation({summary: 'ask token for reseting password'})
62+
@ApiResponse({status: 201, description: 'Token OK'})
63+
@ApiResponse({status: 500, description: 'Token KO'})
64+
@ApiBearerAuth()
65+
@UseGuards(AuthGuard("api-key"))
66+
async verifyToken(@Body() token:VerifyTokenDto ,@Res() res: Response): Promise<Response> {
67+
const ok=await this.passwdService.verifyToken(token.token)
68+
if (ok === true){
69+
return res.status(201).json(token)
70+
}else{
71+
return res.status(500).json(token)
72+
}
73+
74+
}
75+
@Post('reset')
76+
@ApiOperation({summary: 'reset password'})
77+
@ApiResponse({status: 201, description: 'Reset OK'})
78+
@ApiResponse({status: 500, description: 'Reset KO'})
79+
@ApiBearerAuth()
80+
@UseGuards(AuthGuard("api-key"))
81+
async reset(@Body() data:ResetPasswordDto,@Res()res:Response):Promise<Response>{
82+
const tokenData=await this.passwdService.decryptToken(data.token)
83+
if (Object.keys(tokenData).length === 0){
84+
return res.status(500).json({'status':1,'error':'invalid token'})
3385
}else{
34-
if (data.data.status === 1){
35-
return res.status(403).json(data);
36-
}
37-
return res.status(201).json(data);
86+
87+
return res.status(200).json({'status':0,'error':''})
88+
89+
3890
}
39-
}
91+
92+
}
4093
}
94+

src/passwd/passwd.service.ts

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import { Injectable } from '@nestjs/common';
22
import {ChangePasswordDto} from "./dto/change-password.dto";
3-
import {InjectQueue} from "@nestjs/bullmq";
43
import { Queue,QueueEvents} from 'bullmq'
54
import { ConfigService } from '@nestjs/config';
5+
import * as crypto from 'crypto'
6+
import {AskTokenDto} from "./dto/ask-token.dto";
7+
import Redis from "ioredis";
8+
import {ResetPasswordDto} from "./dto/reset-password.dto";
69
@Injectable()
710
export class PasswdService {
811

@@ -17,6 +20,68 @@ export class PasswdService {
1720
})
1821
return await job.waitUntilFinished(queueEvents,30000)
1922
}
23+
async askToken(askToken:AskTokenDto){
24+
const redisConfig={host:this.configService.get('redis.host'),port:this.configService.get('redis.port'),db:1}
25+
let redis=new Redis(redisConfig)
26+
const iv = crypto.randomBytes(12).toString('base64')
27+
const key = crypto.randomBytes(16).toString('hex')
28+
const cipher = crypto.createCipheriv("aes-256-gcm", key, iv);
29+
const dataStruct={'uid':askToken.uid,'mail':askToken.mail}
30+
let ciphertext = cipher.update(JSON.stringify(dataStruct), 'utf8', 'base64')
31+
ciphertext += cipher.final('base64');
32+
const tag = cipher.getAuthTag();
33+
const tokenStruct=JSON.stringify({k:key,iv:iv,tag:tag})
34+
await redis.set(ciphertext, tokenStruct)
35+
await redis.expire(ciphertext, 3600)
36+
return ciphertext
37+
}
38+
async verifyToken(token){
39+
const data=await this.decryptToken(token)
40+
console.log('r : '+JSON.stringify(data))
41+
if (Object.keys(data).length === 0){
42+
return false
43+
}else{
44+
return true
45+
}
46+
47+
}
48+
async decryptToken(token:string){
49+
const redisConfig={host:this.configService.get('redis.host'),port:this.configService.get('redis.port'),db:1}
50+
let redis=new Redis(redisConfig)
51+
const ok=await redis.exists(token)
52+
if (ok === 1){
53+
const result=await redis.get(token)
54+
const cypherData=JSON.parse(result)
55+
console.log(cypherData)
56+
const decipher = crypto.createDecipheriv(
57+
"aes-256-gcm",
58+
cypherData.k,
59+
cypherData.iv
60+
);
61+
decipher.setAuthTag(Buffer.from(cypherData.tag, 'base64'));
62+
let plaintext = decipher.update(token, 'base64', 'ascii');
63+
console.log('texte : ' + plaintext)
64+
return JSON.parse(plaintext)
65+
}else{
66+
return {}
67+
}
68+
}
69+
async reset(data:ResetPasswordDto){
70+
const tokenData=await this.decryptToken(data.token)
71+
if (Object.keys(tokenData).length === 0){
72+
return false
73+
}
74+
const redisConfig={host:this.configService.get('redis.host'),port:this.configService.get('redis.port')}
75+
const queue=new Queue(this.configService.get('nameQueue'),{connection:redisConfig})
76+
const queueEvents = new QueueEvents(this.configService.get('nameQueue'),{connection: redisConfig})
77+
const job=await queue.add('RESETPWD',tokenData)
78+
queueEvents.on('failed',(errors)=>{
79+
console.log(errors)
80+
})
81+
return await job.waitUntilFinished(queueEvents,30000)
82+
83+
}
84+
2085
}
2186

2287

0 commit comments

Comments
 (0)