Skip to content

Commit 8626534

Browse files
committed
feat: 重复创建工单保护
1 parent f46d757 commit 8626534

File tree

1 file changed

+26
-2
lines changed

1 file changed

+26
-2
lines changed

api/ticket/api.js

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,18 +101,22 @@ router.post(
101101
const isCS = await isCSInTicket(currentUser)
102102

103103
if (!isCS && redisClient) {
104+
console.log(`[Rate Limit] Checking rate limit for non-CS user ${currentUser.id}.`)
104105
try {
105106
const today = new Date().toISOString().slice(0, 10).replace(/-/g, '') // YYYYMMDD
106107
const redisKey = `rate_limit:ticket:create:${currentUser.id}:${today}`
107108
const currentCount = await redisClient.incr(redisKey)
109+
console.log(`[Rate Limit] Redis INCR result for key ${redisKey}: ${currentCount}`)
108110

109111
if (currentCount === 1) {
110112
// Set expiry to 24 hours when the key is first created today
111113
await redisClient.expire(redisKey, 86400) // 86400 seconds = 24 hours
112114
}
113115

114116
if (currentCount > 20) {
115-
console.warn(`Rate limit exceeded for user ${currentUser.id}. Count: ${currentCount}`)
117+
console.warn(
118+
`[Rate Limit] Limit exceeded for user ${currentUser.id}. Count: ${currentCount}. Denying request.`
119+
)
116120
// Optionally log the violation details
117121
// LogRateLimitViolation({ userId: currentUser.id, limit: 20, resource: 'ticket_create' })
118122
return res.throw(429, 'Rate limit exceeded. You can create up to 20 tickets per day.')
@@ -125,6 +129,10 @@ router.post(
125129
// Fail open: If Redis fails, allow the request to proceed.
126130
// Alternatively, you could fail closed: return res.throw(500, 'Internal server error during rate check.')
127131
}
132+
} else {
133+
console.log(
134+
`[Rate Limit] Redis client is not available for user ${currentUser.id}. Skipping rate limiting check.`
135+
)
128136
}
129137
// === Rate Limiting End ===
130138

@@ -141,10 +149,19 @@ router.post(
141149
const author = req.user
142150

143151
if (redisClient) {
152+
console.log(
153+
`[Duplicate Check] Redis client is available for user ${author.id}. Checking for duplicates...`
154+
)
144155
try {
145156
const titleHash = crypto.createHash('sha1').update(title).digest('hex')
146157
const duplicateCheckKey = `duplicate_check:ticket:${author.id}:${titleHash}`
158+
console.log(
159+
`[Duplicate Check] User: ${author.id}, Title: "${title}", Hash: ${titleHash}, Key: ${duplicateCheckKey}`
160+
)
147161
const existingTicketId = await redisClient.get(duplicateCheckKey)
162+
console.log(
163+
`[Duplicate Check] Redis GET result for key ${duplicateCheckKey}: ${existingTicketId}`
164+
)
148165

149166
if (existingTicketId) {
150167
console.log(
@@ -162,6 +179,9 @@ router.post(
162179
}
163180
// === Duplicate Check End ===
164181

182+
console.log(
183+
`[Ticket Creation] Proceeding to create ticket for user ${author.id}, title: "${title}"`
184+
)
165185
const ticket = await Ticket.create({
166186
title,
167187
category_id,
@@ -180,8 +200,12 @@ router.post(
180200
try {
181201
const titleHash = crypto.createHash('sha1').update(title).digest('hex')
182202
const duplicateCheckKey = `duplicate_check:ticket:${author.id}:${titleHash}`
203+
console.log(
204+
`[Duplicate Set] Storing duplicate check key after creation. Key: ${duplicateCheckKey}, Ticket ID: ${ticket.id}, TTL: 120s`
205+
)
183206
// Set the key with the new ticket ID and 2-minute expiry
184-
await redisClient.set(duplicateCheckKey, ticket.id, 'EX', 120)
207+
const setResult = await redisClient.set(duplicateCheckKey, ticket.id, 'EX', 120)
208+
console.log(`[Duplicate Set] Redis SET result for key ${duplicateCheckKey}: ${setResult}`)
185209
} catch (error) {
186210
console.error(`Redis set after creation failed for ticket ${ticket.id}:`, error)
187211
captureException(error, {

0 commit comments

Comments
 (0)