Skip to content

Commit b62e76c

Browse files
committed
feat: add computed config profile retrieval by UUID
1 parent 6cbb5e2 commit b62e76c

File tree

10 files changed

+123
-1
lines changed

10 files changed

+123
-1
lines changed

libs/contract/api/controllers/config-profiles.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ export const CONFIG_PROFILES_ROUTES = {
77
GET_BY_UUID: (uuid: string) => `${uuid}`, // Get config profile by uuid // get
88
DELETE: (uuid: string) => `${uuid}`, // Delete config profile by uuid // delete
99
GET_INBOUNDS_BY_PROFILE_UUID: (uuid: string) => `${uuid}/inbounds`, // Get list of all inbounds by config profile uuid // get
10+
GET_COMPUTED_CONFIG_BY_PROFILE_UUID: (uuid: string) => `${uuid}/computed-config`, // Get computed config by config profile uuid // get
1011
GET_ALL_INBOUNDS: 'inbounds', // Get list of all inbounds // get
1112
} as const;

libs/contract/api/routes.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,10 @@ export const REST_API = {
273273
`${ROOT}/${CONTROLLERS.CONFIG_PROFILES_CONTROLLER}/${CONTROLLERS.CONFIG_PROFILES_ROUTES.GET_INBOUNDS_BY_PROFILE_UUID(
274274
uuid,
275275
)}`,
276+
GET_COMPUTED_CONFIG_BY_PROFILE_UUID: (uuid: string) =>
277+
`${ROOT}/${CONTROLLERS.CONFIG_PROFILES_CONTROLLER}/${CONTROLLERS.CONFIG_PROFILES_ROUTES.GET_COMPUTED_CONFIG_BY_PROFILE_UUID(
278+
uuid,
279+
)}`,
276280
GET_ALL_INBOUNDS: `${ROOT}/${CONTROLLERS.CONFIG_PROFILES_CONTROLLER}/${CONTROLLERS.CONFIG_PROFILES_ROUTES.GET_ALL_INBOUNDS}`,
277281
},
278282
INTERNAL_SQUADS: {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { z } from 'zod';
2+
3+
import { CONFIG_PROFILES_ROUTES, REST_API } from '../../api';
4+
import { getEndpointDetails } from '../../constants';
5+
import { ConfigProfileSchema } from '../../models';
6+
7+
export namespace GetComputedConfigProfileByUuidCommand {
8+
export const url = REST_API.CONFIG_PROFILES.GET_COMPUTED_CONFIG_BY_PROFILE_UUID;
9+
export const TSQ_url = url(':uuid');
10+
11+
export const endpointDetails = getEndpointDetails(
12+
CONFIG_PROFILES_ROUTES.GET_COMPUTED_CONFIG_BY_PROFILE_UUID(':uuid'),
13+
'get',
14+
'Get computed config profile by uuid',
15+
);
16+
17+
export const RequestSchema = z.object({
18+
uuid: z.string().uuid(),
19+
});
20+
21+
export type Request = z.infer<typeof RequestSchema>;
22+
23+
export const ResponseSchema = z.object({
24+
response: ConfigProfileSchema,
25+
});
26+
27+
export type Response = z.infer<typeof ResponseSchema>;
28+
}

libs/contract/commands/config-profiles/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export * from './create-config-profile.command';
22
export * from './delete-config-profile.command';
33
export * from './get-all-inbounds.command';
4+
export * from './get-computed-config-profile-by-uuid.command';
45
export * from './get-config-profile-by-uuid.command';
56
export * from './get-config-profiles.command';
67
export * from './get-inbounds-by-profile-uuid.command';

libs/contract/constants/errors/errors.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,4 +1004,9 @@ export const ERRORS = {
10041004
httpCode: 500,
10051005
}),
10061006
},
1007+
GET_COMPUTED_CONFIG_PROFILE_BY_UUID_ERROR: {
1008+
code: 'A200',
1009+
message: 'Get computed config profile by UUID error',
1010+
httpCode: 500,
1011+
},
10071012
} 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": "2.2.27",
3+
"version": "2.2.28",
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/config-profiles/config-profile.controller.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
CreateConfigProfileCommand,
1919
DeleteConfigProfileCommand,
2020
GetAllInboundsCommand,
21+
GetComputedConfigProfileByUuidCommand,
2122
GetConfigProfileByUuidCommand,
2223
GetConfigProfilesCommand,
2324
GetInboundsByProfileUuidCommand,
@@ -31,6 +32,7 @@ import {
3132
CreateConfigProfileResponseDto,
3233
DeleteConfigProfileResponseDto,
3334
GetAllInboundsResponseDto,
35+
GetComputedConfigProfileByUuidResponseDto,
3436
GetConfigProfileByUuidResponseDto,
3537
GetConfigProfilesResponseDto,
3638
GetInboundsByProfileUuidResponseDto,
@@ -126,6 +128,28 @@ export class ConfigProfileController {
126128
};
127129
}
128130

131+
@ApiNotFoundResponse({
132+
description: 'Config profile not found',
133+
})
134+
@ApiOkResponse({
135+
type: GetComputedConfigProfileByUuidResponseDto,
136+
description: 'Computed config profile retrieved successfully',
137+
})
138+
@Endpoint({
139+
command: GetComputedConfigProfileByUuidCommand,
140+
httpCode: HttpStatus.OK,
141+
})
142+
async getComputedConfigProfileByUuid(
143+
@Param('uuid') uuid: string,
144+
): Promise<GetComputedConfigProfileByUuidResponseDto> {
145+
const result = await this.configProfileService.getComputedConfigProfileByUUID(uuid);
146+
147+
const data = errorHandler(result);
148+
return {
149+
response: data,
150+
};
151+
}
152+
129153
@ApiNotFoundResponse({
130154
description: 'Config profile not found',
131155
})

src/modules/config-profiles/config-profile.service.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import _ from 'lodash';
33

44
import { Transactional } from '@nestjs-cls/transactional';
55
import { Injectable, Logger } from '@nestjs/common';
6+
import { QueryBus } from '@nestjs/cqrs';
67

78
import { ICommandResponse } from '@common/types/command-response.type';
89
import { XRayConfig } from '@common/helpers/xray-config';
@@ -17,6 +18,7 @@ import { GetConfigProfilesResponseModel } from './models/get-config-profiles.res
1718
import { ConfigProfileInboundEntity } from './entities/config-profile-inbound.entity';
1819
import { ConfigProfileRepository } from './repositories/config-profile.repository';
1920
import { ConfigProfileEntity } from './entities/config-profile.entity';
21+
import { GetSnippetsQuery } from './queries/get-snippets';
2022

2123
@Injectable()
2224
export class ConfigProfileService {
@@ -26,6 +28,7 @@ export class ConfigProfileService {
2628
private readonly configProfileRepository: ConfigProfileRepository,
2729
private readonly startAllNodesByProfileQueueService: StartAllNodesByProfileQueueService,
2830
private readonly stopNodeQueueService: StopNodeQueueService,
31+
private readonly queryBus: QueryBus,
2932
) {}
3033

3134
public async getConfigProfiles(): Promise<ICommandResponse<GetConfigProfilesResponseModel>> {
@@ -81,6 +84,51 @@ export class ConfigProfileService {
8184
}
8285
}
8386

87+
public async getComputedConfigProfileByUUID(
88+
uuid: string,
89+
): Promise<ICommandResponse<GetConfigProfileByUuidResponseModel>> {
90+
try {
91+
const configProfile = await this.configProfileRepository.getConfigProfileByUUID(uuid);
92+
93+
if (!configProfile) {
94+
return {
95+
isOk: false,
96+
...ERRORS.CONFIG_PROFILE_NOT_FOUND,
97+
};
98+
}
99+
100+
const snippetsMap: Map<string, unknown> = new Map();
101+
const snippetsResponse = await this.queryBus.execute(new GetSnippetsQuery());
102+
103+
if (!snippetsResponse.isOk || !snippetsResponse.response) {
104+
return {
105+
isOk: false,
106+
...ERRORS.INTERNAL_SERVER_ERROR,
107+
};
108+
}
109+
110+
for (const snippet of snippetsResponse.response) {
111+
snippetsMap.set(snippet.name, snippet.snippet);
112+
}
113+
114+
const config = new XRayConfig(configProfile.config as object);
115+
config.replaceSnippets(snippetsMap);
116+
117+
configProfile.config = config.getSortedConfig();
118+
119+
return {
120+
isOk: true,
121+
response: new GetConfigProfileByUuidResponseModel(configProfile),
122+
};
123+
} catch (error) {
124+
this.logger.error(error);
125+
return {
126+
isOk: false,
127+
...ERRORS.GET_COMPUTED_CONFIG_PROFILE_BY_UUID_ERROR,
128+
};
129+
}
130+
}
131+
84132
public async deleteConfigProfileByUUID(
85133
uuid: string,
86134
): Promise<ICommandResponse<DeleteConfigProfileByUuidResponseModel>> {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { createZodDto } from 'nestjs-zod';
2+
3+
import { GetComputedConfigProfileByUuidCommand } from '@libs/contracts/commands';
4+
5+
export class GetComputedConfigProfileByUuidRequestDto extends createZodDto(
6+
GetComputedConfigProfileByUuidCommand.RequestSchema,
7+
) {}
8+
export class GetComputedConfigProfileByUuidResponseDto extends createZodDto(
9+
GetComputedConfigProfileByUuidCommand.ResponseSchema,
10+
) {}

src/modules/config-profiles/dtos/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export * from './create-config-profile.dto';
22
export * from './delete-config-profile.dto';
33
export * from './get-all-inbounds.dto';
4+
export * from './get-computed-config-profile-by-uuid.dto';
45
export * from './get-config-profile-by-uuid.dto';
56
export * from './get-config-profiles.dto';
67
export * from './get-inbounds-by-profile-uuid.dto';

0 commit comments

Comments
 (0)