( input: AcceptInvitationInput )
| 581 | | { success: false; kind: AcceptInvitationFailure['kind'] } |
| 582 | |
| 583 | export async function rejectInvitation( |
| 584 | input: AcceptInvitationInput |
| 585 | ): Promise<RejectInvitationResult> { |
| 586 | const inv = await getInvitationById(input.invitationId) |
| 587 | |
| 588 | if (!inv) return { success: false, kind: 'not-found' } |
| 589 | if (input.token && inv.token !== input.token) return { success: false, kind: 'invalid-token' } |
| 590 | if (inv.status !== 'pending') return { success: false, kind: 'already-processed' } |
| 591 | if (isInvitationExpired(inv)) { |
| 592 | await db |
| 593 | .update(invitation) |
| 594 | .set({ status: 'expired', updatedAt: new Date() }) |
| 595 | .where(and(eq(invitation.id, inv.id), eq(invitation.status, 'pending'))) |
| 596 | return { success: false, kind: 'expired' } |
| 597 | } |
| 598 | if (normalizeEmail(input.userEmail) !== normalizeEmail(inv.email)) { |
| 599 | return { success: false, kind: 'email-mismatch' } |
| 600 | } |
| 601 | |
| 602 | await db |
| 603 | .update(invitation) |
| 604 | .set({ status: 'rejected', updatedAt: new Date() }) |
| 605 | .where(eq(invitation.id, inv.id)) |
| 606 | |
| 607 | return { success: true, invitation: { ...inv, status: 'rejected' } } |
| 608 | } |
| 609 | |
| 610 | export async function cancelInvitation(invitationId: string): Promise<boolean> { |
| 611 | const result = await db |
no test coverage detected