|
1 | 1 | import { Request, Response } from "express"; |
| 2 | +import { AppDataSource } from "../database/data-source"; |
| 3 | +import { User } from "../database/entities/User"; |
2 | 4 | import { ReferenceService } from "../services/ReferenceService"; |
3 | 5 | import { ReferenceSigningSessionService } from "../services/ReferenceSigningSessionService"; |
4 | 6 | import { authGuard } from "../middleware/auth"; |
5 | 7 |
|
| 8 | +const SYSTEM_AUTHOR_NAME = "Cerberus Platform"; |
| 9 | + |
6 | 10 | export class ReferenceController { |
7 | 11 | private referenceService: ReferenceService; |
8 | 12 | private signingSessionService: ReferenceSigningSessionService; |
@@ -307,25 +311,51 @@ export class ReferenceController { |
307 | 311 | return res.status(401).json({ error: "Unauthorized" }); |
308 | 312 | } |
309 | 313 |
|
310 | | - const { targetType, targetId, targetName, content, referenceType, numericScore, authorId, anonymous } = req.body; |
| 314 | + const { targetType, targetId, targetName, targetEname, content, referenceType, numericScore, anonymous } = req.body; |
311 | 315 |
|
312 | | - if (!targetType || !targetId || !targetName || !content || !authorId) { |
313 | | - return res.status(400).json({ error: "Missing required fields: targetType, targetId, targetName, content, authorId" }); |
| 316 | + if (!targetType || !targetName || !content) { |
| 317 | + return res.status(400).json({ error: "Missing required fields: targetType, targetName, content" }); |
314 | 318 | } |
315 | 319 |
|
316 | 320 | if (numericScore && (numericScore < 1 || numericScore > 5)) { |
317 | 321 | return res.status(400).json({ error: "Numeric score must be between 1 and 5" }); |
318 | 322 | } |
319 | 323 |
|
| 324 | + // Resolve the system author — use the "Cerberus Platform" user |
| 325 | + const userRepo = AppDataSource.getRepository(User); |
| 326 | + let systemUser = await userRepo.findOneBy({ name: SYSTEM_AUTHOR_NAME }); |
| 327 | + if (!systemUser) { |
| 328 | + systemUser = userRepo.create({ name: SYSTEM_AUTHOR_NAME, handle: "cerberus" }); |
| 329 | + systemUser = await userRepo.save(systemUser); |
| 330 | + console.log(`[erep] Created system user "${SYSTEM_AUTHOR_NAME}" id=${systemUser.id}`); |
| 331 | + } |
| 332 | + |
| 333 | + // Resolve the target user by ename to get the correct local eReputation user ID. |
| 334 | + // Cross-platform calls (e.g. from Cerberus) send their own DB user ID which |
| 335 | + // won't match eReputation's user ID — ename is the shared identifier. |
| 336 | + let resolvedTargetId = targetId; |
| 337 | + if (targetEname && targetType === "user") { |
| 338 | + // Try both with and without @ prefix |
| 339 | + const cleanEname = targetEname.replace(/^@/, ""); |
| 340 | + const targetUser = await userRepo.findOneBy({ ename: cleanEname }) |
| 341 | + ?? await userRepo.findOneBy({ ename: `@${cleanEname}` }); |
| 342 | + if (targetUser) { |
| 343 | + resolvedTargetId = targetUser.id; |
| 344 | + console.log(`[erep] Resolved target ename=${targetEname} to local id=${targetUser.id}`); |
| 345 | + } else { |
| 346 | + console.warn(`[erep] Could not resolve target ename=${targetEname}, using provided targetId=${targetId}`); |
| 347 | + } |
| 348 | + } |
| 349 | + |
320 | 350 | // Create reference directly with "signed" status (trusted platform call) |
321 | 351 | const reference = this.referenceService.referenceRepository.create({ |
322 | 352 | targetType, |
323 | | - targetId, |
| 353 | + targetId: resolvedTargetId, |
324 | 354 | targetName, |
325 | 355 | content, |
326 | 356 | referenceType: referenceType || "violation", |
327 | 357 | numericScore, |
328 | | - authorId, |
| 358 | + authorId: systemUser.id, |
329 | 359 | anonymous: anonymous ?? false, |
330 | 360 | status: "signed" |
331 | 361 | }); |
|
0 commit comments