Skip to content

Commit

Permalink
CRYP-46 Increase quota when sending webhook
Browse files Browse the repository at this point in the history
  • Loading branch information
thongnguyen5 authored and thongnguyendev committed Apr 17, 2024
1 parent 7e4aece commit 2d847a8
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 4 deletions.
2 changes: 2 additions & 0 deletions app/apps/monitor-service/src/ethereum/ethereum.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Module } from '@nestjs/common';
import { ClientsModule, Transport } from '@nestjs/microservices';
import { EthereumController } from './ethereum.controller';
import { EthereumService } from './ethereum.service';
import { ProjectModule } from '@app/shared_modules/project/project.module';

@Module({
providers: [EthereumService],
Expand All @@ -29,6 +30,7 @@ import { EthereumService } from './ethereum.service';
]),
WebhookModule,
MonitorModule,
ProjectModule,
],
})
export class EthereumModule {}
5 changes: 5 additions & 0 deletions app/apps/monitor-service/src/ethereum/ethereum.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
MonitoringType,
WebhookNotification,
} from '@app/shared_modules/monitor/schemas/monitor.schema';
import { ProjectQuotaService } from '@app/shared_modules/project/services/project.quota.service';
import { WebhookService } from '@app/shared_modules/webhook/webhook.service';
import { SupportedChain } from '@app/utils/supportedChain.util';
import { Inject, Injectable, Logger } from '@nestjs/common';
Expand All @@ -32,6 +33,9 @@ export class EthereumService {
@Inject()
private readonly webhookService: WebhookService;

@Inject()
private readonly projectQuotaService: ProjectQuotaService;

async findEthAddress(address: string): Promise<MonitorAddress[]> {
return this.ethMonitorAddressRepository.findByAddress(address);
}
Expand Down Expand Up @@ -320,6 +324,7 @@ export class EthereumService {
this.logger.debug(
`Dispatch webhook successfully response: ${JSON.stringify(respone)}`,
);
this.projectQuotaService.increaseUsed(monitor.projectId);
} catch (error) {
this.logger.error(
`Error while sending webhook request to: ${webhook.url}`,
Expand Down
36 changes: 36 additions & 0 deletions app/apps/onebox/src/modules/project/dto/project.dto.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
Project,
ProjectQuota,
ProjectStatus,
} from '@app/shared_modules/project/schemas/project.schema';
import { ApiProperty, ApiResponseProperty } from '@nestjs/swagger';
Expand Down Expand Up @@ -46,6 +47,9 @@ export class ProjectResponseDto {
@ApiResponseProperty()
dateCreated: Date;

@ApiResponseProperty()
currentQuota: number;

static from(project: Project) {
return Builder<ProjectResponseDto>()
.projectId(project.projectId)
Expand All @@ -59,6 +63,38 @@ export class ProjectResponseDto {
.maxAddress(project.maxAddress)
.addressCount(project.addressCount)
.dateCreated(project.dateCreated)
.currentQuota(project.currentQuota)
.build();
}
}

export class ProjectQuotaResponseDto {
@ApiResponseProperty()
projectId: string;

@ApiResponseProperty()
month: string;

@ApiResponseProperty()
ownerId: string;

@ApiResponseProperty()
quota: number;

@ApiResponseProperty()
used: number;

@ApiResponseProperty()
dateCreated: Date;

static from(projectQuota: ProjectQuota): ProjectQuotaResponseDto {
return Builder<ProjectQuotaResponseDto>()
.projectId(projectQuota.projectId)
.month(projectQuota.month)
.ownerId(projectQuota.ownerId)
.quota(projectQuota.quota)
.used(projectQuota.used)
.dateCreated(projectQuota.dateCreated)
.build();
}
}
22 changes: 21 additions & 1 deletion app/apps/onebox/src/modules/project/project.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
Get,
Param,
Post,
Query,
Req,
UseGuards,
} from '@nestjs/common';
Expand All @@ -17,7 +18,11 @@ import {
import { Request } from 'express';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { User } from '../users/schemas/user.schema';
import { CreateProjectDto, ProjectResponseDto } from './dto/project.dto';
import {
CreateProjectDto,
ProjectQuotaResponseDto,
ProjectResponseDto,
} from './dto/project.dto';
import { ProjectService } from './project.service';

@ApiTags('Project')
Expand Down Expand Up @@ -57,4 +62,19 @@ export class ProjectController {
): Promise<ProjectResponseDto> {
return await this.projectService.createProject(req.user as User, body);
}

@ApiOperation({ summary: 'Get project current month quota' })
@ApiBearerAuth('JWT')
@UseGuards(JwtAuthGuard)
@Get('/quota/current')
@ApiOkResponse({ type: ProjectQuotaResponseDto })
async getProjectQuotaCurrentMonth(
@Req() req: Request,
@Query('projectId') projectId: string,
): Promise<ProjectQuotaResponseDto> {
return await this.projectService.getProjectCurrentQuora(
req.user as User,
projectId,
);
}
}
43 changes: 42 additions & 1 deletion app/apps/onebox/src/modules/project/project.service.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
import { ErrorCode } from '@app/global/global.error';
import { ProjectMemberRepository } from '@app/shared_modules/project/repositories/project.member.repository';
import { ProjectQuotaRepository } from '@app/shared_modules/project/repositories/project.quota.repository';
import { ProjectRepository } from '@app/shared_modules/project/repositories/project.repository';
import {
Project,
ProjectMember,
ProjectQuota,
ProjectRole,
ProjectStatus,
} from '@app/shared_modules/project/schemas/project.schema';
import { generateProjectId } from '@app/utils/uuidUtils';
import { Injectable } from '@nestjs/common';
import { Builder } from 'builder-pattern';
import { User } from '../users/schemas/user.schema';
import { CreateProjectDto, ProjectResponseDto } from './dto/project.dto';
import {
CreateProjectDto,
ProjectQuotaResponseDto,
ProjectResponseDto,
} from './dto/project.dto';

@Injectable()
export class ProjectService {
constructor(
private readonly projectRepository: ProjectRepository,
private readonly projectMemberRepository: ProjectMemberRepository,
private readonly projectQuotaRepository: ProjectQuotaRepository,
) {}

async checkProjectPermission(
Expand Down Expand Up @@ -61,6 +68,7 @@ export class ProjectService {
.maxAddress(1000)
.addressCount(0)
.dateCreated(new Date())
.currentQuota(1000)
.build();

const createdProject = await this.projectRepository.saveProject(project);
Expand All @@ -77,4 +85,37 @@ export class ProjectService {
const projects = await this.projectRepository.listUserProjects(user.userId);
return projects.map((project) => ProjectResponseDto.from(project));
}

async getProjectCurrentQuora(
user: User,
projectId: string,
): Promise<ProjectQuotaResponseDto> {
const project = await this.projectRepository.findById(projectId);
if (!project) {
throw ErrorCode.PROJECT_NOT_FOUND.asException();
}

this.checkProjectPermission(user, project.projectId);
return this.projectQuotaRepository
.getCurrentMonthQuota(projectId)
.then((quota) => {
if (quota) {
return ProjectQuotaResponseDto.from(quota);
} else {
const date = new Date();
const month =
`${date.getMonth() + 1}`.padStart(2, '0') + `${date.getFullYear()}`;
return ProjectQuotaResponseDto.from(
Builder<ProjectQuota>()
.projectId(project.projectId)
.month(month)
.ownerId(project.ownerId)
.quota(project.currentQuota)
.used(0)
.dateCreated(date)
.build(),
);
}
});
}
}
3 changes: 3 additions & 0 deletions app/libs/shared_modules/src/project/project.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ProjectProviders } from './project.provider';
import { ProjectMemberRepository } from './repositories/project.member.repository';
import { ProjectQuotaRepository } from './repositories/project.quota.repository';
import { ProjectRepository } from './repositories/project.repository';
import { ProjectQuotaService } from './services/project.quota.service';

@Module({
imports: [DatabaseModule],
Expand All @@ -12,12 +13,14 @@ import { ProjectRepository } from './repositories/project.repository';
ProjectRepository,
ProjectQuotaRepository,
ProjectMemberRepository,
ProjectQuotaService,
],
exports: [
...ProjectProviders,
ProjectRepository,
ProjectQuotaRepository,
ProjectMemberRepository,
ProjectQuotaService,
],
})
export class ProjectModule {}
Original file line number Diff line number Diff line change
@@ -1,11 +1,48 @@
import { Inject, Injectable } from '@nestjs/common';
import { Model } from 'mongoose';
import { ProjectQuota } from '../schemas/project.schema';
import { Project, ProjectQuota } from '../schemas/project.schema';

@Injectable()
export class ProjectQuotaRepository {
constructor(
@Inject('PROJECT_QUOTA_MODEL')
private readonly projectQuotaModel: Model<ProjectQuota>,
) {}

async increaseUsed(project: Project, used = 1): Promise<boolean> {
const date = new Date();
const month =
`${date.getMonth() + 1}`.padStart(2, '0') + `${date.getFullYear()}`;
return this.projectQuotaModel
.updateOne(
{
projectId: project.projectId,
month: month,
},
{
$inc: { used: used },
$setOnInsert: {
ownerId: project.ownerId,
quota: project.currentQuota || 0,
dateCreated: date,
},
},
{
upsert: true,
},
)
.then((result) => result.modifiedCount > 0 || result.upsertedCount > 0);
}

async getCurrentMonthQuota(projectId: string): Promise<ProjectQuota> {
const date = new Date();
const month =
`${date.getMonth() + 1}`.padStart(2, '0') + `${date.getFullYear()}`;
return this.projectQuotaModel
.findOne({
projectId: projectId,
month: month,
})
.exec();
}
}
3 changes: 3 additions & 0 deletions app/libs/shared_modules/src/project/schemas/project.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ export class Project {

@Prop()
dateCreated: Date;

@Prop()
currentQuota: number;
}
export type ProjectDocument = HydratedDocument<Project>;
export const ProjectSchema = SchemaFactory.createForClass(Project);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Injectable } from '@nestjs/common';
import { ProjectQuotaRepository } from '../repositories/project.quota.repository';
import { ProjectRepository } from '../repositories/project.repository';
import { ProjectQuota } from '../schemas/project.schema';

@Injectable()
export class ProjectQuotaService {
constructor(
private readonly projectQuotaRepository: ProjectQuotaRepository,
private readonly projectRepository: ProjectRepository,
) {}

async increaseUsed(projectId: string, used = 1): Promise<boolean> {
const project = await this.projectRepository.findById(projectId);
if (!project) return false;
return this.projectQuotaRepository.increaseUsed(project, used);
}

async getCurrentMonthQuota(projectId: string): Promise<ProjectQuota> {
return this.projectQuotaRepository.getCurrentMonthQuota(projectId);
}
}
2 changes: 1 addition & 1 deletion app/libs/shared_modules/src/webhook/webhook.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ export class WebhookServiceResponseDto {
valid_status_codes: [];
}

interface DispatchWebhookResponse {
export class DispatchWebhookResponse {
id: string;
webhook_id: string;
payload: string;
Expand Down

0 comments on commit 2d847a8

Please sign in to comment.