Skip to content

Commit e1604da

Browse files
authored
Merge pull request #72 from gujiangjiang/main
feat: 新增通知功能的用户隔离
2 parents fda06de + dca2dd0 commit e1604da

File tree

8 files changed

+150
-89
lines changed

8 files changed

+150
-89
lines changed

backend/src/api/agents.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ agents.put("/:id", async (c) => {
5555
agents.delete("/:id", async (c) => {
5656
try {
5757
const agentId = Number(c.req.param("id"));
58+
const payload = c.get("jwtPayload"); // 获取用户信息
5859

59-
await deleteAgentService(agentId);
60+
await deleteAgentService(agentId, payload.id); // 传入 userId
6061

6162
return c.json(
6263
{
@@ -76,6 +77,7 @@ agents.delete("/:id", async (c) => {
7677
}
7778
});
7879

80+
7981
// 生成客户端Token
8082
agents.post("/token/generate", async (c) => {
8183
// 生成新令牌

backend/src/api/notifications.ts

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ import { z } from "zod";
33
import { Bindings } from "../models/db";
44
import * as NotificationService from "../services/NotificationService";
55

6-
const notifications = new Hono<{ Bindings: Bindings }>();
6+
const notifications = new Hono<{ Bindings: Bindings; Variables: { jwtPayload: any } }>();
77

88
// 获取通知配置
99
notifications.get("/", async (c) => {
1010
try {
11-
const config = await NotificationService.getNotificationConfig();
11+
const userId = c.get("jwtPayload").id;
12+
const config = await NotificationService.getNotificationConfig(userId);
1213

1314
return c.json({
1415
success: true,
@@ -30,7 +31,8 @@ notifications.get("/", async (c) => {
3031
// 获取通知渠道列表
3132
notifications.get("/channels", async (c) => {
3233
try {
33-
const channels = await NotificationService.getNotificationChannels();
34+
const userId = c.get("jwtPayload").id;
35+
const channels = await NotificationService.getNotificationChannels(userId);
3436

3537
return c.json({
3638
success: true,
@@ -53,6 +55,7 @@ notifications.get("/channels", async (c) => {
5355
notifications.get("/channels/:id", async (c) => {
5456
try {
5557
const id = parseInt(c.req.param("id"));
58+
const userId = c.get("jwtPayload").id;
5659

5760
if (isNaN(id)) {
5861
return c.json(
@@ -64,7 +67,7 @@ notifications.get("/channels/:id", async (c) => {
6467
);
6568
}
6669

67-
const channel = await NotificationService.getNotificationChannelById(id);
70+
const channel = await NotificationService.getNotificationChannelById(id, userId);
6871

6972
if (!channel) {
7073
return c.json(
@@ -96,15 +99,14 @@ notifications.get("/channels/:id", async (c) => {
9699
// 创建通知渠道
97100
notifications.post("/channels", async (c) => {
98101
try {
99-
const db = c.env.DB;
100102
const userId = c.get("jwtPayload").id;
101103
const body = await c.req.json();
102104

103105
// 验证请求数据
104106
const schema = z.object({
105107
name: z.string().min(1, "名称不能为空"),
106108
type: z.string().min(1, "类型不能为空"),
107-
config: z.string().min(1, "配置不能为空"),
109+
config: z.any(),
108110
enabled: z.boolean().optional(),
109111
});
110112

@@ -114,7 +116,7 @@ notifications.post("/channels", async (c) => {
114116
const result = await NotificationService.createNotificationChannel({
115117
name: validatedData.name,
116118
type: validatedData.type,
117-
config: validatedData.config,
119+
config: JSON.stringify(validatedData.config),
118120
enabled:
119121
validatedData.enabled !== undefined ? validatedData.enabled : true,
120122
created_by: userId,
@@ -153,10 +155,12 @@ notifications.post("/channels", async (c) => {
153155
}
154156
});
155157

158+
156159
// 更新通知渠道
157160
notifications.put("/channels/:id", async (c) => {
158161
try {
159162
const id = parseInt(c.req.param("id"));
163+
const userId = c.get("jwtPayload").id;
160164

161165
if (isNaN(id)) {
162166
return c.json(
@@ -174,15 +178,19 @@ notifications.put("/channels/:id", async (c) => {
174178
const schema = z.object({
175179
name: z.string().min(1, "名称不能为空").optional(),
176180
type: z.string().min(1, "类型不能为空").optional(),
177-
config: z.string().min(1, "配置不能为空").optional(),
181+
config: z.any().optional(),
178182
enabled: z.boolean().optional(),
179183
});
180184

181185
const validatedData = schema.parse(body);
186+
if (validatedData.config) {
187+
validatedData.config = JSON.stringify(validatedData.config)
188+
}
182189

183190
// 更新渠道
184191
const result = await NotificationService.updateNotificationChannel(
185192
id,
193+
userId,
186194
validatedData
187195
);
188196

@@ -217,6 +225,7 @@ notifications.put("/channels/:id", async (c) => {
217225
notifications.delete("/channels/:id", async (c) => {
218226
try {
219227
const id = parseInt(c.req.param("id"));
228+
const userId = c.get("jwtPayload").id;
220229

221230
if (isNaN(id)) {
222231
return c.json(
@@ -228,7 +237,7 @@ notifications.delete("/channels/:id", async (c) => {
228237
);
229238
}
230239

231-
const result = await NotificationService.deleteNotificationChannel(id);
240+
const result = await NotificationService.deleteNotificationChannel(id, userId);
232241

233242
if (!result.success) {
234243
return c.json(
@@ -257,10 +266,12 @@ notifications.delete("/channels/:id", async (c) => {
257266
}
258267
});
259268

269+
260270
// 获取通知模板列表
261271
notifications.get("/templates", async (c) => {
262272
try {
263-
const templates = await NotificationService.getNotificationTemplates();
273+
const userId = c.get("jwtPayload").id;
274+
const templates = await NotificationService.getNotificationTemplates(userId);
264275

265276
return c.json({
266277
success: true,
@@ -283,6 +294,7 @@ notifications.get("/templates", async (c) => {
283294
notifications.get("/templates/:id", async (c) => {
284295
try {
285296
const id = parseInt(c.req.param("id"));
297+
const userId = c.get("jwtPayload").id; // 获取 userId
286298

287299
if (isNaN(id)) {
288300
return c.json(
@@ -294,7 +306,7 @@ notifications.get("/templates/:id", async (c) => {
294306
);
295307
}
296308

297-
const template = await NotificationService.getNotificationTemplateById(id);
309+
const template = await NotificationService.getNotificationTemplateById(id, userId); // 传入 userId
298310

299311
if (!template) {
300312
return c.json(
@@ -390,6 +402,7 @@ notifications.post("/templates", async (c) => {
390402
notifications.put("/templates/:id", async (c) => {
391403
try {
392404
const id = parseInt(c.req.param("id"));
405+
const userId = c.get("jwtPayload").id; // 获取 userId
393406

394407
if (isNaN(id)) {
395408
return c.json(
@@ -417,6 +430,7 @@ notifications.put("/templates/:id", async (c) => {
417430
// 更新模板
418431
const result = await NotificationService.updateNotificationTemplate(
419432
id,
433+
userId, // 传入 userId
420434
validatedData
421435
);
422436

@@ -451,6 +465,7 @@ notifications.put("/templates/:id", async (c) => {
451465
notifications.delete("/templates/:id", async (c) => {
452466
try {
453467
const id = parseInt(c.req.param("id"));
468+
const userId = c.get("jwtPayload").id; // 获取 userId
454469

455470
if (isNaN(id)) {
456471
return c.json(
@@ -462,7 +477,7 @@ notifications.delete("/templates/:id", async (c) => {
462477
);
463478
}
464479

465-
const result = await NotificationService.deleteNotificationTemplate(id);
480+
const result = await NotificationService.deleteNotificationTemplate(id, userId); // 传入 userId
466481

467482
if (!result.success) {
468483
return c.json(
@@ -491,6 +506,7 @@ notifications.delete("/templates/:id", async (c) => {
491506
}
492507
});
493508

509+
494510
// 保存通知设置
495511
notifications.post("/settings", async (c) => {
496512
try {

backend/src/jobs/agent-task.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ interface AgentResult {
1919
status: string;
2020
updated_at: string;
2121
keepalive: string;
22+
created_by: number; // 添加 created_by 以便获取 userId
2223
}
2324

2425
export const checkAgentsStatus = async (c: any) => {
@@ -53,7 +54,7 @@ export const checkAgentsStatus = async (c: any) => {
5354
await setAgentInactive(agent.id);
5455

5556
// 处理通知
56-
await handleAgentOfflineNotification(c.env, agent.id, agent.name);
57+
await handleAgentOfflineNotification(c.env, agent.id, agent.name, agent.created_by);
5758
}
5859
}
5960
} catch (error) {
@@ -66,15 +67,18 @@ export const checkAgentsStatus = async (c: any) => {
6667
* @param env 环境变量
6768
* @param agentId 客户端ID
6869
* @param agentName 客户端名称
70+
* @param userId 用户ID
6971
*/
7072
async function handleAgentOfflineNotification(
7173
env: any,
7274
agentId: number,
73-
agentName: string
75+
agentName: string,
76+
userId: number
7477
) {
7578
try {
7679
// 检查是否需要发送通知
7780
const notificationCheck = await shouldSendNotification(
81+
userId, // 修复: 传入 userId
7882
"agent",
7983
agentId,
8084
"online", // 上一个状态
@@ -125,7 +129,8 @@ async function handleAgentOfflineNotification(
125129
"agent",
126130
agentId,
127131
variables,
128-
notificationCheck.channels
132+
notificationCheck.channels,
133+
userId // 修复: 传入 userId
129134
);
130135

131136
if (notificationResult.success) {
@@ -158,6 +163,9 @@ export async function handleAgentThresholdNotification(
158163
console.error(`找不到客户端 (ID: ${agentId})`);
159164
throw new Error(`找不到客户端 (ID: ${agentId})`);
160165
}
166+
167+
// @ts-ignore
168+
const userId = agent.created_by; // 获取 userId
161169

162170
// 根据具体的指标类型
163171
let metricName = "";
@@ -172,7 +180,8 @@ export async function handleAgentThresholdNotification(
172180
and(
173181
eq(notificationSettings.enabled, 1),
174182
eq(notificationSettings.target_id, agentId),
175-
eq(notificationSettings.target_type, "agent")
183+
eq(notificationSettings.target_type, "agent"),
184+
eq(notificationSettings.user_id, userId) // 增加 userId 过滤
176185
)
177186
);
178187

@@ -184,7 +193,8 @@ export async function handleAgentThresholdNotification(
184193
.where(
185194
and(
186195
eq(notificationSettings.enabled, 1),
187-
eq(notificationSettings.target_type, "global-agent")
196+
eq(notificationSettings.target_type, "global-agent"),
197+
eq(notificationSettings.user_id, userId) // 增加 userId 过滤
188198
)
189199
)
190200
: null;
@@ -272,7 +282,8 @@ export async function handleAgentThresholdNotification(
272282
"agent",
273283
agentId,
274284
variables,
275-
channels
285+
channels,
286+
userId // 修复: 传入 userId
276287
);
277288

278289
if (notificationResult.success) {

backend/src/jobs/monitor-task.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ async function handleMonitorNotification(
7777
// 检查是否需要发送通知
7878
console.log(`检查通知设置...`);
7979
const notificationCheck = await shouldSendNotification(
80+
monitor.created_by, // 修复: 传入 userId
8081
"monitor",
8182
monitor.id,
8283
checkResult.previous_status,
@@ -132,7 +133,8 @@ async function handleMonitorNotification(
132133
"monitor",
133134
monitor.id,
134135
variables,
135-
notificationCheck.channels
136+
notificationCheck.channels,
137+
monitor.created_by // 修复: 传入 userId
136138
);
137139

138140
console.log(`通知发送结果: ${JSON.stringify(notificationResult)}`);

0 commit comments

Comments
 (0)