[CLAUDE] Office: IT staff tự reassign ticket — authz Admin-OR-IT + capability endpoint (S54)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m17s

- BE: GetAssignableItStaffQuery {canReassign,staff} capability endpoint + AssignItTicketHandler authz Admin-OR-dept-IT (Forbidden) + assignee-must-IT (Conflict); controller /assign hạ [Authorize(Roles=Admin)]→[Authorize] (handler enforce fine-grained data-driven)
- FE: fe-admin + fe-user ItTicketsPage SHA256-identical (reverse S53 divergence), nút gate by canReassign, dropdown từ /assignable-staff (không /users)
- Test: +13 authz guard (203→216 PASS), reviewer PASS (role-string Admin chain-verified real)
- No migration (DepartmentId reuse), no menu change

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-06-08 16:12:14 +07:00
parent 18d397f095
commit ca4b60277b
13 changed files with 587 additions and 34 deletions

View File

@ -29,15 +29,20 @@ public class ItTicketsController(IMediator mediator) : ControllerBase
return NoContent();
}
// P11-D: admin re-assign ticket cho IT staff (override round-robin auto-assign).
// P11-D + S54: re-assign ticket cho IT staff. Authz Admin-OR-dept-IT enforce trong handler
// (controller [Authorize] any-auth — gotcha #44-aware: pipeline mở, handler check fine-grained).
[HttpPut("{id:guid}/assign")]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Assign(Guid id, [FromBody] AssignItTicketBody body)
{
await mediator.Send(new AssignItTicketCommand(id, body.AssignedToUserId));
return NoContent();
}
// S54: danh sách IT staff nhận ticket + cờ canReassign (FE gate nút). [Authorize] any-auth.
[HttpGet("assignable-staff")]
public async Task<IActionResult> AssignableStaff()
=> Ok(await mediator.Send(new GetAssignableItStaffQuery()));
public record UpdateItTicketStatusBody(int Status, string? Resolution);
public record AssignItTicketBody(Guid AssignedToUserId);
}