fix : not allow to delete message while ticket closed

This commit is contained in:
2026-10-02 21:29:12 +07:00 Unverified
parent f5b432a496
commit ddd36ba4a6
3 changed files with 12 additions and 2 deletions
@@ -38,7 +38,7 @@ describe("commission message deletion", () => {
beforeEach(() => { beforeEach(() => {
process.env.BETTER_AUTH_URL = "https://guide.sudloh.com"; process.env.BETTER_AUTH_URL = "https://guide.sudloh.com";
vi.clearAllMocks(); vi.clearAllMocks();
authorizeTicket.mockResolvedValue({ ticket: { userId: ownerId }, user: { id: ownerId } }); authorizeTicket.mockResolvedValue({ ticket: { userId: ownerId, status: "open" }, user: { id: ownerId } });
deleteWhere.mockImplementation(() => ({ returning: deleteReturning })); deleteWhere.mockImplementation(() => ({ returning: deleteReturning }));
deleteReturning.mockResolvedValue([{ imageObjectKey: "commission/messages/image-1" }]); deleteReturning.mockResolvedValue([{ imageObjectKey: "commission/messages/image-1" }]);
updateWhere.mockResolvedValue(undefined); updateWhere.mockResolvedValue(undefined);
@@ -66,6 +66,15 @@ describe("commission message deletion", () => {
expect(notifyCommission).toHaveBeenCalledWith(ticketId, ownerId); expect(notifyCommission).toHaveBeenCalledWith(ticketId, ownerId);
}); });
it("rejects deletion when the ticket is closed", async () => {
authorizeTicket.mockResolvedValue({ ticket: { userId: ownerId, status: "closed" }, user: { id: ownerId } });
const response = await DELETE(deletionRequest(), context());
expect(response.status).toBe(409);
expect(tx.delete).not.toHaveBeenCalled();
expect(deleteObject).not.toHaveBeenCalled();
expect(notifyCommission).not.toHaveBeenCalled();
});
it("leaves storage and notifications untouched when no owned message exists", async () => { it("leaves storage and notifications untouched when no owned message exists", async () => {
deleteReturning.mockResolvedValue([]); deleteReturning.mockResolvedValue([]);
const response = await DELETE(deletionRequest(), context()); const response = await DELETE(deletionRequest(), context());
@@ -15,6 +15,7 @@ export async function DELETE(request: Request,
const { id, messageId } = await context.params; const { id, messageId } = await context.params;
if (!z.uuid().safeParse(messageId).success) throw new HttpError(404, "message-not-found"); if (!z.uuid().safeParse(messageId).success) throw new HttpError(404, "message-not-found");
const { ticket, user } = await authorizeTicket(id); const { ticket, user } = await authorizeTicket(id);
if (ticket.status !== "open") throw new HttpError(409, "ticket-closed");
await limitRequest("commission-message-delete", user.id, 30); await limitRequest("commission-message-delete", user.id, 30);
const imageObjectKey = await getDb().transaction(async (tx) => { const imageObjectKey = await getDb().transaction(async (tx) => {
const [message] = await tx.delete(commissionMessages) const [message] = await tx.delete(commissionMessages)
+1 -1
View File
@@ -869,7 +869,7 @@ export function CommissionTicketChat({
<ReplyIcon /> <ReplyIcon />
</Button> </Button>
)} )}
{mine && ( {mine && status === "open" && (
<AlertDialog <AlertDialog
open={deleteFor === message.id} open={deleteFor === message.id}
onOpenChange={(open) => onOpenChange={(open) =>