generated from Xen0Xys/NestJS-Template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from Webster-FR/feature/banks
Merge banks to Main
- Loading branch information
Showing
14 changed files
with
349 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
# Encryption des données | ||
## SHA-256 | ||
- Tokens/sum | ||
## Argon2id | ||
- Mots de passe | ||
- Tokens | ||
## Symétrique avec clé encryption API | ||
- Secret utilisateur | ||
- Banks/name | ||
## Symétrique secret utilisateur | ||
- Secret 2FA | ||
- Usernames | ||
- Emails | ||
- Wordings | ||
- Accounts/amount | ||
- Todos/name | ||
|
||
|
||
|
||
# For future | ||
## Auth | ||
### GET /auth/2fa | ||
Take JWT. Generate the 2fa secret and send the link+qrcode. | ||
### POST /auth/2fa | ||
Take JWT and 2fa code and verify it's well configured by the user. | ||
### DELETE /auth/2fa | ||
Take JWT. Remove the 2fa from the account. | ||
### POST /auth/2fa/recover | ||
Take JWT and one 2fa recovery code. Disable the 2fa if code is correct. | ||
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬ | ||
# Naming | ||
- AT: Access token (classic JWT, have user id, token type) | ||
- RT: Refresh token (JWT, have user id, token type) | ||
- CT: Code token (JWT, have user id, token type, and keep logged value) | ||
|
||
# Routes | ||
|
||
## Version | ||
### GET /version | ||
Return the current backend version. | ||
|
||
## Auth | ||
### POST /auth/login?keep | ||
Take username, password. Return AT and RT if keep param is present. If verification code present, return CT. | ||
### POST /auth/logout | ||
Take AT (and RT if existing) and add them to token blacklist. | ||
### POST /auth/logout/all | ||
Take AT, add all existing tokens to blacklist | ||
### POST /auth/register | ||
Take username, email and password. Return CT and send email with confirmation code. | ||
### POST /auth/refresh | ||
Take old AT and RT, add both to token blacklist and re-send new AT and RT. | ||
### POST /auth/register/confirm | ||
Take CT and confirmation code. Return AT. | ||
### POST /auth/register/confirm/resend | ||
Take CT. Re-create and re-send a new confirmation code by email. Return new CT. | ||
|
||
## Users | ||
### GET /users/me | ||
Take JWT and return username and email. | ||
### PATCH /users/me/username | ||
Take JWT and new username. | ||
### PATCH /users/me/password | ||
Take JWT and new password. | ||
### DELETE /users/me | ||
Take JWT. | ||
|
||
## Transactions | ||
### GET /transactions | ||
Take JWT, return list of user transactions. | ||
### POST /transactions | ||
Take JWT, transaction type, amount and wording. | ||
### PATCH /transactions/:ulid/wording | ||
Take JWT and new wording. | ||
### POST /transactions/rectification | ||
Take JWT, transaction ulid, new amount. Return updated transaction. | ||
### GET /transactions/categories | ||
Take JWT, return default and users categories. | ||
### POST /transactions/categories | ||
Take JWT, name, icon and color. Return created category. | ||
### PUT /transactions/categories/:id | ||
Take JWT, name, icon and color. Return updated category. | ||
|
||
## Recurring transactions | ||
### GET /recurring | ||
Take JWT, return user recurring transactions. | ||
### POST /recurring | ||
Take JWT, wording, type and amount. Return created recurring transaction. | ||
### PUT /recurring/:id | ||
Take JWT, wording and amount. Return updated recurring transaction. | ||
### DELETE /recurring/:id | ||
Take JWT. | ||
|
||
## Tips | ||
### GET /tips/tod | ||
Return tips of the day. | ||
|
||
## Accounts | ||
### GET /accounts | ||
Take JWT, return all user accounts. | ||
### POST /accounts | ||
Take JWT, name, bank id and current amount, return created account. | ||
### PATCH /accounts/:id/name | ||
Take JWT and name, return updated account. | ||
### DELETE /accounts/:id | ||
Take JWT. | ||
|
||
## Banks | ||
### GET /banks | ||
Take JWT, return user banks and default banks. | ||
### POST /banks | ||
Take JWT and bank name, return created bank. | ||
### PATCH /banks/:id/name | ||
Take JWT and name, return updated bank. | ||
### DELETE /banks/:id | ||
Take JWT. | ||
|
||
## Todos | ||
### GET /todos | ||
Take JWT. Return all user todos | ||
### POST /todos | ||
Take JWT, name, deadline, parent id, icon, color and recurring. Return created todo. | ||
### PATCH /todos/:id/parent | ||
Take JWT and new parent id. Return updated todo. | ||
### PATCH /todos/:id/completed | ||
Take JWT and new completed value. Return updated todo. | ||
### PUT /todos/:id | ||
Take JWT, name, deadline, icon, color, completed value and frequency. Return updated todo. | ||
### DELETE /todos/:id | ||
Take JWT. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import {Body, Controller, Delete, Get, HttpStatus, Param, Patch, Post, Req, UseGuards} from "@nestjs/common"; | ||
import {MaintenanceGuard} from "../maintenance/guards/maintenance.guard"; | ||
import {ApiBearerAuth, ApiResponse} from "@nestjs/swagger"; | ||
import {AtGuard} from "../auth/guards/at.guard"; | ||
import {BanksService} from "./banks.service"; | ||
import {BankEntity} from "./models/entities/bank.entity"; | ||
import {BankNameDto} from "./models/dto/bank-name.dto"; | ||
import {IdDto} from "../models/dto/id.dto"; | ||
|
||
@Controller("banks") | ||
@UseGuards(MaintenanceGuard) | ||
export class BanksController{ | ||
constructor( | ||
private readonly banksService: BanksService | ||
){} | ||
|
||
@Get() | ||
@UseGuards(AtGuard) | ||
@ApiBearerAuth() | ||
@ApiResponse({status: HttpStatus.OK, description: "User and default banks returned", type: BankEntity, isArray: true}) | ||
@ApiResponse({status: HttpStatus.UNAUTHORIZED, description: "Invalid or missing access token"}) | ||
@ApiResponse({status: HttpStatus.NOT_FOUND, description: "User not found"}) | ||
async getBanks(@Req() req: any): Promise<BankEntity[]>{ | ||
return this.banksService.getBanks(req.user.id); | ||
} | ||
|
||
@Post() | ||
@UseGuards(AtGuard) | ||
@ApiBearerAuth() | ||
@ApiResponse({status: HttpStatus.CREATED, description: "Bank added", type: BankEntity}) | ||
@ApiResponse({status: HttpStatus.UNAUTHORIZED, description: "Invalid or missing access token"}) | ||
@ApiResponse({status: HttpStatus.NOT_FOUND, description: "User not found"}) | ||
@ApiResponse({status: HttpStatus.CONFLICT, description: "Bank already exists"}) | ||
async addBank(@Req() req: any, @Body() bankNameDto: BankNameDto): Promise<BankEntity>{ | ||
return this.banksService.addBank(req.user.id, bankNameDto.name); | ||
} | ||
|
||
@Patch(":id/name") | ||
@UseGuards(AtGuard) | ||
@ApiBearerAuth() | ||
@ApiResponse({status: HttpStatus.OK, description: "Bank name updated", type: BankEntity}) | ||
@ApiResponse({status: HttpStatus.UNAUTHORIZED, description: "Invalid or missing access token"}) | ||
@ApiResponse({status: HttpStatus.NOT_FOUND, description: "User or bank not found"}) | ||
async updateBankName(@Req() req: any, @Param() idDto: IdDto, @Body() bankNameDto: BankNameDto): Promise<BankEntity>{ | ||
return this.banksService.updateBankName(req.user.id, idDto.id, bankNameDto.name); | ||
} | ||
|
||
@Delete(":id") | ||
@UseGuards(AtGuard) | ||
@ApiBearerAuth() | ||
@ApiResponse({status: HttpStatus.OK, description: "Bank deleted", type: BankEntity}) | ||
@ApiResponse({status: HttpStatus.UNAUTHORIZED, description: "Invalid or missing access token"}) | ||
@ApiResponse({status: HttpStatus.NOT_FOUND, description: "User or bank not found"}) | ||
async deleteBank(@Req() req: any, @Param() idDto: IdDto): Promise<BankEntity>{ | ||
return this.banksService.deleteBank(req.user.id, idDto.id); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import {Module} from "@nestjs/common"; | ||
import {BanksService} from "./banks.service"; | ||
import {BanksController} from "./banks.controller"; | ||
import {ServicesModule} from "../services/services.module"; | ||
import {UsersModule} from "../users/users.module"; | ||
|
||
@Module({ | ||
controllers: [BanksController], | ||
providers: [BanksService], | ||
imports: [ServicesModule, UsersModule], | ||
}) | ||
export class BanksModule{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import {Injectable, NotFoundException} from "@nestjs/common"; | ||
import {BankEntity} from "./models/entities/bank.entity"; | ||
import {PrismaService} from "../services/prisma.service"; | ||
import {ConfigService} from "@nestjs/config"; | ||
import {EncryptionService} from "../services/encryption.service"; | ||
import {UsersService} from "../users/users.service"; | ||
|
||
@Injectable() | ||
export class BanksService{ | ||
|
||
constructor( | ||
private readonly prismaService: PrismaService, | ||
private readonly configService: ConfigService, | ||
private readonly encryptionService: EncryptionService, | ||
private readonly usersService: UsersService, | ||
){} | ||
|
||
async getBanks(userId: number): Promise<BankEntity[]>{ | ||
if(!await this.usersService.isUserExists(userId)) | ||
throw new NotFoundException("User not found"); | ||
const banks: BankEntity[] = await this.prismaService.banks.findMany({ | ||
where: { | ||
OR: [ | ||
{user_id: userId}, | ||
{user_id: null}, | ||
], | ||
} | ||
}); | ||
for(const bank of banks) | ||
bank.name = this.encryptionService.decryptSymmetric(bank.name, this.configService.get("SYMMETRIC_ENCRYPTION_KEY")); | ||
return banks; | ||
} | ||
|
||
async addBank(userId: number, bankName: string): Promise<BankEntity>{ | ||
if(!await this.usersService.isUserExists(userId)) | ||
throw new NotFoundException("User not found"); | ||
const banks = await this.getBanks(userId); | ||
for(const bank of banks) | ||
if(bank.name === bankName) | ||
throw new NotFoundException("Bank already exists"); | ||
const bank: BankEntity = await this.prismaService.banks.create({ | ||
data: { | ||
user_id: userId, | ||
name: this.encryptionService.encryptSymmetric(bankName, this.configService.get("SYMMETRIC_ENCRYPTION_KEY")), | ||
} | ||
}); | ||
bank.name = bankName; | ||
return bank; | ||
} | ||
|
||
async updateBankName(userId: number, bankId: number, name: string): Promise<BankEntity>{ | ||
if(!await this.usersService.isUserExists(userId)) | ||
throw new NotFoundException("User not found"); | ||
const bank: BankEntity = await this.prismaService.banks.findUnique({ | ||
where: { | ||
id: bankId, | ||
user_id: userId, | ||
} | ||
}); | ||
if(!bank) | ||
throw new NotFoundException("User bank not found"); | ||
const banks = await this.getBanks(userId); | ||
for(const bank of banks) | ||
if(bank.name === name) | ||
throw new NotFoundException("Bank already exists with this name"); | ||
await this.prismaService.banks.update({ | ||
where: { | ||
id: bankId, | ||
}, | ||
data: { | ||
name: this.encryptionService.encryptSymmetric(name, this.configService.get("SYMMETRIC_ENCRYPTION_KEY")), | ||
} | ||
}); | ||
bank.name = name; | ||
return bank; | ||
} | ||
|
||
async deleteBank(userId: number, bankId: number): Promise<BankEntity>{ | ||
if(!await this.usersService.isUserExists(userId)) | ||
throw new NotFoundException("User not found"); | ||
const bank: BankEntity = await this.prismaService.banks.findUnique({ | ||
where: { | ||
id: bankId, | ||
user_id: userId, | ||
} | ||
}); | ||
if(!bank) | ||
throw new NotFoundException("User bank not found"); | ||
await this.prismaService.banks.delete({ | ||
where: { | ||
id: bankId, | ||
} | ||
}); | ||
bank.name = this.encryptionService.decryptSymmetric(bank.name, this.configService.get("SYMMETRIC_ENCRYPTION_KEY")); | ||
return bank; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import {ApiProperty} from "@nestjs/swagger"; | ||
import {IsNotEmpty, IsString} from "class-validator"; | ||
|
||
export class BankNameDto{ | ||
@ApiProperty() | ||
@IsString() | ||
@IsNotEmpty() | ||
name: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import {Banks} from "@prisma/client"; | ||
import {ApiProperty} from "@nestjs/swagger"; | ||
|
||
export class BankEntity implements Banks{ | ||
@ApiProperty() | ||
id: number; | ||
@ApiProperty() | ||
name: string; | ||
@ApiProperty() | ||
user_id: number; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.