Skip to content

Commit 0a0c1eb

Browse files
committed
feat: add activate all inbounds functionality
- Updated the contract library to include a new route and controller method for activating all inbounds for a user. - Introduced error handling for activation failures and added relevant error codes. - Enhanced the UsersService to manage the activation process and publish events accordingly. - Added DTOs for request and response handling in the controller. - Updated package version to 0.3.63.
1 parent 3f3f39b commit 0a0c1eb

File tree

13 files changed

+156
-10
lines changed

13 files changed

+156
-10
lines changed

libs/contract/api/controllers/users.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export const USERS_ROUTES = {
1313
DELETE_USER: 'delete',
1414
UPDATE: 'update',
1515
RESET_USER_TRAFFIC: 'reset-traffic',
16+
ACTIVATE_ALL_INBOUNDS: 'activate-all-inbounds',
1617
BULK: {
1718
DELETE_BY_STATUS: 'bulk/delete-by-status',
1819
UPDATE: 'bulk/update',

libs/contract/api/routes.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ export const REST_API = {
7474
DELETE_USER: (uuid: string) =>
7575
`${ROOT}/${CONTROLLERS.USERS_CONTROLLER}/${CONTROLLERS.USERS_ROUTES.DELETE_USER}/${uuid}`,
7676
UPDATE: `${ROOT}/${CONTROLLERS.USERS_CONTROLLER}/${CONTROLLERS.USERS_ROUTES.UPDATE}`,
77+
ACTIVATE_ALL_INBOUNDS: (uuid: string) =>
78+
`${ROOT}/${CONTROLLERS.USERS_CONTROLLER}/${CONTROLLERS.USERS_ROUTES.ACTIVATE_ALL_INBOUNDS}/${uuid}`,
7779
GET_ALL_V2: `${ROOT}/${CONTROLLERS.USERS_CONTROLLER}/${CONTROLLERS.USERS_ROUTES.GET_ALL_V2}`,
7880
RESET_USER_TRAFFIC: (uuid: string) =>
7981
`${ROOT}/${CONTROLLERS.USERS_CONTROLLER}/${CONTROLLERS.USERS_ROUTES.RESET_USER_TRAFFIC}/${uuid}`,
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { z } from 'zod';
2+
3+
import { LastConnectedNodeSchema, UsersSchema } from '../../models';
4+
import { REST_API } from '../../api';
5+
6+
export namespace ActivateAllInboundsCommand {
7+
export const url = REST_API.USERS.ACTIVATE_ALL_INBOUNDS;
8+
export const TSQ_url = url(':uuid');
9+
10+
export const RequestSchema = z.object({
11+
uuid: z.string().uuid(),
12+
});
13+
14+
export type Request = z.infer<typeof RequestSchema>;
15+
16+
export const ResponseSchema = z.object({
17+
response: UsersSchema.extend({
18+
subscriptionUrl: z.string(),
19+
lastConnectedNode: LastConnectedNodeSchema,
20+
}),
21+
});
22+
23+
export type Response = z.infer<typeof ResponseSchema>;
24+
}

libs/contract/commands/users/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export * from './activate-all-inbounds.command';
12
export * from './bulk';
23
export * from './bulk-all';
34
export * from './create-user.command';

libs/contract/constants/errors/errors.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,4 +458,9 @@ export const ERRORS = {
458458
message: 'Keypair not found. Restart app.',
459459
httpCode: 500,
460460
},
461+
ACTIVATE_ALL_INBOUNDS_ERROR: {
462+
code: 'A093',
463+
message: 'Activate all inbounds error',
464+
httpCode: 500,
465+
},
461466
} as const;

libs/contract/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@remnawave/backend-contract",
3-
"version": "0.3.62",
3+
"version": "0.3.63",
44
"public": true,
55
"license": "AGPL-3.0-only",
66
"description": "A contract library for Remnawave Backend. It can be used in backend and frontend.",

src/modules/inbounds/commands/create-many-user-active-inbounds/create-many-user-active-inbounds.handler.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { ERRORS } from '@contract/constants';
22

33
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
4-
import { Transactional } from '@nestjs-cls/transactional';
54
import { Logger } from '@nestjs/common';
65

76
import { ICommandResponse } from '@common/types/command-response.type';
@@ -17,7 +16,6 @@ export class CreateManyUserActiveInboundsHandler
1716

1817
constructor(private readonly activeUserInboundsRepository: ActiveUserInboundsRepository) {}
1918

20-
@Transactional()
2119
async execute(command: CreateManyUserActiveInboundsCommand): Promise<ICommandResponse<number>> {
2220
try {
2321
const response = await this.activeUserInboundsRepository.createMany(

src/modules/inbounds/commands/delete-many-active-inbounds-by-user-uuid/delete-many-active-inbounds-by-user-uuid.handler.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import { ActiveUserInboundsRepository } from 'src/modules/inbounds/repositories/active-user-inbounds.repository';
22
import { ERRORS } from '@contract/constants';
33

4-
import { TransactionalAdapterPrisma } from '@nestjs-cls/transactional-adapter-prisma';
54
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
6-
import { Transactional } from '@nestjs-cls/transactional';
75
import { Logger } from '@nestjs/common';
86

97
import { ICommandResponse } from '@common/types/command-response.type';
@@ -18,10 +16,6 @@ export class DeleteManyActiveInboundsByUserUuidHandler
1816

1917
constructor(private readonly activeUserInboundsRepository: ActiveUserInboundsRepository) {}
2018

21-
@Transactional<TransactionalAdapterPrisma>({
22-
maxWait: 20_000,
23-
timeout: 120_000,
24-
})
2519
async execute(
2620
command: DeleteManyActiveInboundsByUserUuidCommand,
2721
): Promise<ICommandResponse<number>> {

src/modules/inbounds/repositories/active-user-inbounds.repository.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export class ActiveUserInboundsRepository implements ICrud<ActiveUserInboundEnti
4646
public async createMany(userUuid: string, inboundUuids: string[]): Promise<number> {
4747
const result = await this.prisma.tx.activeUserInbounds.createMany({
4848
data: inboundUuids.map((inboundUuid) => ({ userUuid, inboundUuid })),
49+
skipDuplicates: true,
4950
});
5051
return result.count;
5152
}

src/modules/users/controllers/users.controller.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ import { USERS_CONTROLLER, USERS_ROUTES } from '@libs/contracts/api';
3434
import { ROLE } from '@libs/contracts/constants';
3535

3636
import {
37+
ActivateAllInboundsRequestDto,
38+
ActivateAllInboundsResponseDto,
3739
CreateUserRequestDto,
3840
CreateUserResponseDto,
3941
DeleteUserRequestDto,
@@ -482,4 +484,33 @@ export class UsersController {
482484
response: data.map((item) => new GetFullUserResponseModel(item, this.subPublicDomain)),
483485
};
484486
}
487+
488+
@ApiNotFoundResponse({
489+
description: 'User not found',
490+
})
491+
@ApiOkResponse({
492+
type: ActivateAllInboundsResponseDto,
493+
description: 'All inbounds activated successfully',
494+
})
495+
@ApiOperation({
496+
summary: 'Activate All Inbounds',
497+
description: 'Activate all inbounds',
498+
})
499+
@ApiParam({ name: 'uuid', type: String, description: 'UUID of the user', required: true })
500+
@HttpCode(HttpStatus.OK)
501+
@Patch(USERS_ROUTES.ACTIVATE_ALL_INBOUNDS + '/:uuid')
502+
async activateAllInbounds(
503+
@Param() paramData: ActivateAllInboundsRequestDto,
504+
): Promise<ActivateAllInboundsResponseDto> {
505+
const result = await this.usersService.activateAllInbounds(paramData.uuid);
506+
507+
const data = errorHandler(result);
508+
return {
509+
response: new GetUserResponseModel(
510+
data.user,
511+
data.lastConnectedNode,
512+
this.subPublicDomain,
513+
),
514+
};
515+
}
485516
}

0 commit comments

Comments
 (0)