mirror of
https://github.com/documenso/documenso.git
synced 2026-08-23 23:02:22 +10:00
fix: handle completion when already signed (#3159)
Previously attempting to complete a document which is already completed you'd get a generic error toast. Now when completing a document that you have already completed you are redirected to the completed page. Handles cases where two mutations managed to fire racing eachother.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { prepareCscRecipientSigning } from '@documenso/ee/server-only/signing/csc/prepare-recipient-signing';
|
||||
import { AppError } from '@documenso/lib/errors/app-error';
|
||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||
import { completeDocumentWithToken } from '@documenso/lib/server-only/document/complete-document-with-token';
|
||||
import { rejectDocumentWithToken } from '@documenso/lib/server-only/document/reject-document-with-token';
|
||||
import { createEnvelopeRecipients } from '@documenso/lib/server-only/recipient/create-envelope-recipients';
|
||||
@@ -633,6 +633,17 @@ export const recipientRouter = router({
|
||||
|
||||
return { status: 'SIGNED' as const };
|
||||
} catch (err) {
|
||||
// Resolve retried, stale or concurrent duplicate completion requests
|
||||
// idempotently so the client routes the user to the completed page
|
||||
// instead of surfacing an error for a document that is signed.
|
||||
if (err instanceof AppError && err.code === AppErrorCode.RECIPIENT_ALREADY_SIGNED) {
|
||||
ctx.logger.info({
|
||||
message: 'Recipient attempted to complete a document they have already signed',
|
||||
});
|
||||
|
||||
return { status: 'ALREADY_SIGNED' as const };
|
||||
}
|
||||
|
||||
// Log the error for debugging purposes.
|
||||
ctx.logger.error({
|
||||
message: 'Error completing document with token',
|
||||
|
||||
@@ -182,12 +182,16 @@ export type TCompleteDocumentWithTokenMutationSchema = z.infer<typeof ZCompleteD
|
||||
* Discriminated response: SES envelopes return `{ status: 'SIGNED' }` after
|
||||
* the in-place completion; TSP (AES/QES) envelopes return
|
||||
* `{ status: 'REDIRECT', redirectUrl }` pointing at the credential-scope
|
||||
* OAuth authorize endpoint. Frontend callers can branch on `status` —
|
||||
* existing callers ignored the response and remain compatible.
|
||||
* OAuth authorize endpoint. `{ status: 'ALREADY_SIGNED' }` is returned when
|
||||
* the recipient had already signed prior to this request (retries, stale
|
||||
* tabs, concurrent submissions) so callers can notify the user instead of
|
||||
* erroring. Frontend callers can branch on `status` — existing callers
|
||||
* ignored the response and remain compatible.
|
||||
*/
|
||||
export const ZCompleteDocumentWithTokenResponseSchema = z.discriminatedUnion('status', [
|
||||
z.object({ status: z.literal('REDIRECT'), redirectUrl: z.string() }),
|
||||
z.object({ status: z.literal('SIGNED') }),
|
||||
z.object({ status: z.literal('ALREADY_SIGNED') }),
|
||||
]);
|
||||
|
||||
export type TCompleteDocumentWithTokenResponseSchema = z.infer<typeof ZCompleteDocumentWithTokenResponseSchema>;
|
||||
|
||||
Reference in New Issue
Block a user