Skip to content

Commit 61442e5

Browse files
committed
feat: enhance user management with bulk operations and error handling
- Added new bulk operations for user management, including bulk delete, revoke subscriptions, reset traffic, and update users. - Introduced error handling constants for bulk operations to improve error reporting. - Updated UsersService to incorporate new bulk operations and handle user inbounds more effectively. - Enhanced API routes and commands to support the new bulk functionalities. - Bumped version to 0.3.45 in package.json for the contract library.
1 parent 0afd640 commit 61442e5

File tree

66 files changed

+2140
-319
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+2140
-319
lines changed

Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ COPY docker-entrypoint.sh ./
4242
RUN npm ci --omit=dev --legacy-peer-deps \
4343
&& npm run migrate:generate \
4444
&& npm cache clean --force \
45-
&& npm install pm2 -g
45+
&& npm install pm2 -g \
46+
&& npm link
4647

4748
# CMD [ "npm", "run", "migrate:deploy", "&&", "pm2-runtime", "start", "ecosystem.config.js", "--env", "production" ]
4849

DockerfileDev

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ COPY docker-entrypoint.sh ./
3838
RUN npm ci --omit=dev --legacy-peer-deps \
3939
&& npm run migrate:generate \
4040
&& npm cache clean --force \
41-
&& npm install pm2 -g
41+
&& npm install pm2 -g \
42+
&& npm link
4243

4344
CMD [ "/bin/sh", "docker-entrypoint.sh" ]

libs/contract/api/controllers/users.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@ export const USERS_ROUTES = {
1515
RESET_USER_TRAFFIC: 'reset-traffic',
1616
BULK: {
1717
DELETE_BY_STATUS: 'bulk/delete-by-status',
18+
UPDATE: 'bulk/update',
19+
RESET_TRAFFIC: 'bulk/reset-traffic',
20+
REVOKE_SUBSCRIPTION: 'bulk/revoke-subscription',
21+
DELETE: 'bulk/delete',
22+
UPDATE_INBOUNDS: 'bulk/update-inbounds',
23+
ALL: {
24+
UPDATE: 'bulk/all/update',
25+
RESET_TRAFFIC: 'bulk/all/reset-traffic',
26+
},
1827
},
1928
GET_BY_TELEGRAM_ID: 'tg',
2029
GET_BY_EMAIL: 'email',

libs/contract/api/routes.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,15 @@ export const REST_API = {
7979
`${ROOT}/${CONTROLLERS.USERS_CONTROLLER}/${CONTROLLERS.USERS_ROUTES.RESET_USER_TRAFFIC}/${uuid}`,
8080
BULK: {
8181
DELETE_BY_STATUS: `${ROOT}/${CONTROLLERS.USERS_CONTROLLER}/${CONTROLLERS.USERS_ROUTES.BULK.DELETE_BY_STATUS}`,
82+
UPDATE: `${ROOT}/${CONTROLLERS.USERS_CONTROLLER}/${CONTROLLERS.USERS_ROUTES.BULK.UPDATE}`,
83+
RESET_TRAFFIC: `${ROOT}/${CONTROLLERS.USERS_CONTROLLER}/${CONTROLLERS.USERS_ROUTES.BULK.RESET_TRAFFIC}`,
84+
REVOKE_SUBSCRIPTION: `${ROOT}/${CONTROLLERS.USERS_CONTROLLER}/${CONTROLLERS.USERS_ROUTES.BULK.REVOKE_SUBSCRIPTION}`,
85+
DELETE: `${ROOT}/${CONTROLLERS.USERS_CONTROLLER}/${CONTROLLERS.USERS_ROUTES.BULK.DELETE}`,
86+
UPDATE_INBOUNDS: `${ROOT}/${CONTROLLERS.USERS_CONTROLLER}/${CONTROLLERS.USERS_ROUTES.BULK.UPDATE_INBOUNDS}`,
87+
ALL: {
88+
UPDATE: `${ROOT}/${CONTROLLERS.USERS_CONTROLLER}/${CONTROLLERS.USERS_ROUTES.BULK.ALL.UPDATE}`,
89+
RESET_TRAFFIC: `${ROOT}/${CONTROLLERS.USERS_CONTROLLER}/${CONTROLLERS.USERS_ROUTES.BULK.ALL.RESET_TRAFFIC}`,
90+
},
8291
},
8392
GET_BY_TELEGRAM_ID: (telegramId: string) =>
8493
`${ROOT}/${CONTROLLERS.USERS_CONTROLLER}/${CONTROLLERS.USERS_ROUTES.GET_BY_TELEGRAM_ID}/${telegramId}`,

libs/contract/commands/auth/register.command.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export namespace RegisterCommand {
1212
.min(24, 'Password must contain at least 24 characters')
1313
.regex(
1414
/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{24,}$/,
15-
'Password must contain uppercase and lowercase letters and numbers',
15+
'Password must contain uppercase and lowercase letters and numbers, and be at least 24 characters long.',
1616
),
1717
});
1818

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { z } from 'zod';
2+
3+
import { REST_API } from '../../../api';
4+
5+
export namespace BulkAllResetTrafficUsersCommand {
6+
export const url = REST_API.USERS.BULK.ALL.RESET_TRAFFIC;
7+
export const TSQ_url = url;
8+
9+
export const ResponseSchema = z.object({
10+
response: z.object({
11+
eventSent: z.boolean(),
12+
}),
13+
});
14+
15+
export type Response = z.infer<typeof ResponseSchema>;
16+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { z } from 'zod';
2+
3+
import { RESET_PERIODS } from '../../../constants';
4+
import { UsersSchema } from '../../../models';
5+
import { REST_API } from '../../../api';
6+
7+
export namespace BulkAllUpdateUsersCommand {
8+
export const url = REST_API.USERS.BULK.ALL.UPDATE;
9+
export const TSQ_url = url;
10+
11+
export const RequestSchema = z.object({
12+
status: UsersSchema.shape.status.optional(),
13+
trafficLimitBytes: z.optional(
14+
z
15+
.number({
16+
invalid_type_error: 'Traffic limit must be a number',
17+
})
18+
.int('Traffic limit must be an integer')
19+
.min(0, 'Traffic limit must be greater than 0')
20+
.describe('Traffic limit in bytes. 0 - unlimited'),
21+
),
22+
trafficLimitStrategy: z.optional(
23+
z
24+
.nativeEnum(RESET_PERIODS, {
25+
description: 'Available reset periods',
26+
})
27+
.describe('Traffic limit reset strategy'),
28+
),
29+
expireAt: z.optional(
30+
z
31+
.string()
32+
.datetime({ local: true, offset: true, message: 'Invalid date format' })
33+
.transform((str) => new Date(str))
34+
.refine((date) => date > new Date(), {
35+
message: 'Expiration date cannot be in the past',
36+
})
37+
.describe('Expiration date: 2025-01-17T15:38:45.065Z'),
38+
),
39+
description: z.optional(z.string().nullable()),
40+
telegramId: z.optional(z.number().nullable()),
41+
email: z.optional(z.string().email('Invalid email format').nullable()),
42+
});
43+
44+
export type Request = z.infer<typeof RequestSchema>;
45+
46+
export const ResponseSchema = z.object({
47+
response: z.object({
48+
eventSent: z.boolean(),
49+
}),
50+
});
51+
52+
export type Response = z.infer<typeof ResponseSchema>;
53+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './bulk-all-reset-traffic-users.command';
2+
export * from './bulk-all-update-users.command';
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { z } from 'zod';
2+
3+
import { REST_API } from '../../../api';
4+
5+
export namespace BulkDeleteUsersCommand {
6+
export const url = REST_API.USERS.BULK.DELETE;
7+
export const TSQ_url = url;
8+
9+
export const RequestSchema = z.object({
10+
uuids: z.array(z.string().uuid()),
11+
});
12+
13+
export type Request = z.infer<typeof RequestSchema>;
14+
15+
export const ResponseSchema = z.object({
16+
response: z.object({
17+
affectedRows: z.number(),
18+
}),
19+
});
20+
21+
export type Response = z.infer<typeof ResponseSchema>;
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { z } from 'zod';
2+
3+
import { REST_API } from '../../../api';
4+
5+
export namespace BulkResetTrafficUsersCommand {
6+
export const url = REST_API.USERS.BULK.RESET_TRAFFIC;
7+
export const TSQ_url = url;
8+
9+
export const RequestSchema = z.object({
10+
uuids: z.array(z.string().uuid()),
11+
});
12+
13+
export type Request = z.infer<typeof RequestSchema>;
14+
15+
export const ResponseSchema = z.object({
16+
response: z.object({
17+
affectedRows: z.number(),
18+
}),
19+
});
20+
21+
export type Response = z.infer<typeof ResponseSchema>;
22+
}

0 commit comments

Comments
 (0)