mirror of
https://github.com/documenso/documenso.git
synced 2026-08-15 02:53:32 +10:00
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.
684 lines
20 KiB
TypeScript
684 lines
20 KiB
TypeScript
import { prepareCscRecipientSigning } from '@documenso/ee/server-only/signing/csc/prepare-recipient-signing';
|
|
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';
|
|
import { deleteEnvelopeRecipient } from '@documenso/lib/server-only/recipient/delete-envelope-recipient';
|
|
import { getRecipientById } from '@documenso/lib/server-only/recipient/get-recipient-by-id';
|
|
import { setDocumentRecipients } from '@documenso/lib/server-only/recipient/set-document-recipients';
|
|
import { setTemplateRecipients } from '@documenso/lib/server-only/recipient/set-template-recipients';
|
|
import { updateEnvelopeRecipients } from '@documenso/lib/server-only/recipient/update-envelope-recipients';
|
|
import { isTspEnvelope } from '@documenso/lib/types/signature-level';
|
|
import { unsafeBuildEnvelopeIdQuery } from '@documenso/lib/utils/envelope';
|
|
import { prisma } from '@documenso/prisma';
|
|
import { EnvelopeType } from '@prisma/client';
|
|
import { ZGenericSuccessResponse, ZSuccessResponseSchema } from '../schema';
|
|
import { authenticatedProcedure, procedure, router } from '../trpc';
|
|
import { findRecipientSuggestionsRoute } from './find-recipient-suggestions';
|
|
import {
|
|
ZCompleteDocumentWithTokenMutationSchema,
|
|
ZCompleteDocumentWithTokenResponseSchema,
|
|
ZCreateDocumentRecipientRequestSchema,
|
|
ZCreateDocumentRecipientResponseSchema,
|
|
ZCreateDocumentRecipientsRequestSchema,
|
|
ZCreateDocumentRecipientsResponseSchema,
|
|
ZCreateTemplateRecipientRequestSchema,
|
|
ZCreateTemplateRecipientResponseSchema,
|
|
ZCreateTemplateRecipientsRequestSchema,
|
|
ZCreateTemplateRecipientsResponseSchema,
|
|
ZDeleteDocumentRecipientRequestSchema,
|
|
ZDeleteTemplateRecipientRequestSchema,
|
|
ZGetRecipientRequestSchema,
|
|
ZGetRecipientResponseSchema,
|
|
ZRejectDocumentWithTokenMutationSchema,
|
|
ZSetDocumentRecipientsRequestSchema,
|
|
ZSetDocumentRecipientsResponseSchema,
|
|
ZSetTemplateRecipientsRequestSchema,
|
|
ZSetTemplateRecipientsResponseSchema,
|
|
ZUpdateDocumentRecipientRequestSchema,
|
|
ZUpdateDocumentRecipientResponseSchema,
|
|
ZUpdateDocumentRecipientsRequestSchema,
|
|
ZUpdateDocumentRecipientsResponseSchema,
|
|
ZUpdateTemplateRecipientRequestSchema,
|
|
ZUpdateTemplateRecipientResponseSchema,
|
|
ZUpdateTemplateRecipientsRequestSchema,
|
|
ZUpdateTemplateRecipientsResponseSchema,
|
|
} from './schema';
|
|
|
|
export const recipientRouter = router({
|
|
suggestions: {
|
|
find: findRecipientSuggestionsRoute,
|
|
},
|
|
|
|
/**
|
|
* @public
|
|
*/
|
|
getDocumentRecipient: authenticatedProcedure
|
|
.meta({
|
|
openapi: {
|
|
method: 'GET',
|
|
path: '/document/recipient/{recipientId}',
|
|
summary: 'Get document recipient',
|
|
description:
|
|
'Deprecated: this endpoint is being replaced by the Envelope API. See https://docs.documenso.com/docs/developers/api/migrate-to-envelopes for the migration guide. Returns a single recipient. If you want to retrieve all the recipients for a document, use the "Get Document" endpoint.',
|
|
tags: ['Document Recipients'],
|
|
deprecated: true,
|
|
},
|
|
})
|
|
.input(ZGetRecipientRequestSchema)
|
|
.output(ZGetRecipientResponseSchema)
|
|
.query(async ({ input, ctx }) => {
|
|
const { teamId } = ctx;
|
|
const { recipientId } = input;
|
|
|
|
ctx.logger.info({
|
|
input: {
|
|
recipientId,
|
|
},
|
|
});
|
|
|
|
return await getRecipientById({
|
|
userId: ctx.user.id,
|
|
teamId,
|
|
recipientId,
|
|
type: EnvelopeType.DOCUMENT,
|
|
});
|
|
}),
|
|
|
|
/**
|
|
* @public
|
|
*/
|
|
createDocumentRecipient: authenticatedProcedure
|
|
.meta({
|
|
openapi: {
|
|
method: 'POST',
|
|
path: '/document/recipient/create',
|
|
summary: 'Create document recipient',
|
|
description:
|
|
'Deprecated: this endpoint is being replaced by the Envelope API. See https://docs.documenso.com/docs/developers/api/migrate-to-envelopes for the migration guide. Create a single recipient for a document.',
|
|
tags: ['Document Recipients'],
|
|
deprecated: true,
|
|
},
|
|
})
|
|
.input(ZCreateDocumentRecipientRequestSchema)
|
|
.output(ZCreateDocumentRecipientResponseSchema)
|
|
.mutation(async ({ input, ctx }) => {
|
|
const { teamId } = ctx;
|
|
const { documentId, recipient } = input;
|
|
|
|
ctx.logger.info({
|
|
input: {
|
|
documentId,
|
|
},
|
|
});
|
|
|
|
const createdRecipients = await createEnvelopeRecipients({
|
|
userId: ctx.user.id,
|
|
teamId,
|
|
id: {
|
|
type: 'documentId',
|
|
id: documentId,
|
|
},
|
|
recipients: [recipient],
|
|
requestMetadata: ctx.metadata,
|
|
});
|
|
|
|
return createdRecipients.recipients[0];
|
|
}),
|
|
|
|
/**
|
|
* @public
|
|
*/
|
|
createDocumentRecipients: authenticatedProcedure
|
|
.meta({
|
|
openapi: {
|
|
method: 'POST',
|
|
path: '/document/recipient/create-many',
|
|
summary: 'Create document recipients',
|
|
description:
|
|
'Deprecated: this endpoint is being replaced by the Envelope API. See https://docs.documenso.com/docs/developers/api/migrate-to-envelopes for the migration guide. Create multiple recipients for a document.',
|
|
tags: ['Document Recipients'],
|
|
deprecated: true,
|
|
},
|
|
})
|
|
.input(ZCreateDocumentRecipientsRequestSchema)
|
|
.output(ZCreateDocumentRecipientsResponseSchema)
|
|
.mutation(async ({ input, ctx }) => {
|
|
const { teamId } = ctx;
|
|
const { documentId, recipients } = input;
|
|
|
|
ctx.logger.info({
|
|
input: {
|
|
documentId,
|
|
},
|
|
});
|
|
|
|
return await createEnvelopeRecipients({
|
|
userId: ctx.user.id,
|
|
teamId,
|
|
id: {
|
|
type: 'documentId',
|
|
id: documentId,
|
|
},
|
|
recipients,
|
|
requestMetadata: ctx.metadata,
|
|
});
|
|
}),
|
|
|
|
/**
|
|
* @public
|
|
*/
|
|
updateDocumentRecipient: authenticatedProcedure
|
|
.meta({
|
|
openapi: {
|
|
method: 'POST',
|
|
path: '/document/recipient/update',
|
|
summary: 'Update document recipient',
|
|
description:
|
|
'Deprecated: this endpoint is being replaced by the Envelope API. See https://docs.documenso.com/docs/developers/api/migrate-to-envelopes for the migration guide. Update a single recipient for a document.',
|
|
tags: ['Document Recipients'],
|
|
deprecated: true,
|
|
},
|
|
})
|
|
.input(ZUpdateDocumentRecipientRequestSchema)
|
|
.output(ZUpdateDocumentRecipientResponseSchema)
|
|
.mutation(async ({ input, ctx }) => {
|
|
const { teamId } = ctx;
|
|
const { documentId, recipient } = input;
|
|
|
|
ctx.logger.info({
|
|
input: {
|
|
documentId,
|
|
},
|
|
});
|
|
|
|
const updatedRecipients = await updateEnvelopeRecipients({
|
|
userId: ctx.user.id,
|
|
teamId,
|
|
id: {
|
|
type: 'documentId',
|
|
id: documentId,
|
|
},
|
|
recipients: [recipient],
|
|
requestMetadata: ctx.metadata,
|
|
});
|
|
|
|
return updatedRecipients.recipients[0];
|
|
}),
|
|
|
|
/**
|
|
* @public
|
|
*/
|
|
updateDocumentRecipients: authenticatedProcedure
|
|
.meta({
|
|
openapi: {
|
|
method: 'POST',
|
|
path: '/document/recipient/update-many',
|
|
summary: 'Update document recipients',
|
|
description:
|
|
'Deprecated: this endpoint is being replaced by the Envelope API. See https://docs.documenso.com/docs/developers/api/migrate-to-envelopes for the migration guide. Update multiple recipients for a document.',
|
|
tags: ['Document Recipients'],
|
|
deprecated: true,
|
|
},
|
|
})
|
|
.input(ZUpdateDocumentRecipientsRequestSchema)
|
|
.output(ZUpdateDocumentRecipientsResponseSchema)
|
|
.mutation(async ({ input, ctx }) => {
|
|
const { teamId } = ctx;
|
|
const { documentId, recipients } = input;
|
|
|
|
ctx.logger.info({
|
|
input: {
|
|
documentId,
|
|
},
|
|
});
|
|
|
|
return await updateEnvelopeRecipients({
|
|
userId: ctx.user.id,
|
|
teamId,
|
|
id: {
|
|
type: 'documentId',
|
|
id: documentId,
|
|
},
|
|
recipients,
|
|
requestMetadata: ctx.metadata,
|
|
});
|
|
}),
|
|
|
|
/**
|
|
* @public
|
|
*/
|
|
deleteDocumentRecipient: authenticatedProcedure
|
|
.meta({
|
|
openapi: {
|
|
method: 'POST',
|
|
path: '/document/recipient/delete',
|
|
summary: 'Delete document recipient',
|
|
description:
|
|
'Deprecated: this endpoint is being replaced by the Envelope API. See https://docs.documenso.com/docs/developers/api/migrate-to-envelopes for the migration guide.',
|
|
tags: ['Document Recipients'],
|
|
deprecated: true,
|
|
},
|
|
})
|
|
.input(ZDeleteDocumentRecipientRequestSchema)
|
|
.output(ZSuccessResponseSchema)
|
|
.mutation(async ({ input, ctx }) => {
|
|
const { teamId } = ctx;
|
|
const { recipientId } = input;
|
|
|
|
ctx.logger.info({
|
|
input: {
|
|
recipientId,
|
|
},
|
|
});
|
|
|
|
await deleteEnvelopeRecipient({
|
|
userId: ctx.user.id,
|
|
teamId,
|
|
recipientId,
|
|
requestMetadata: ctx.metadata,
|
|
});
|
|
|
|
return ZGenericSuccessResponse;
|
|
}),
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
setDocumentRecipients: authenticatedProcedure
|
|
.input(ZSetDocumentRecipientsRequestSchema)
|
|
.output(ZSetDocumentRecipientsResponseSchema)
|
|
.mutation(async ({ input, ctx }) => {
|
|
const { teamId } = ctx;
|
|
const { documentId, recipients } = input;
|
|
|
|
ctx.logger.info({
|
|
input: {
|
|
documentId,
|
|
},
|
|
});
|
|
|
|
return await setDocumentRecipients({
|
|
userId: ctx.user.id,
|
|
teamId,
|
|
id: {
|
|
type: 'documentId',
|
|
id: documentId,
|
|
},
|
|
recipients: recipients.map((recipient) => ({
|
|
id: recipient.id,
|
|
email: recipient.email,
|
|
name: recipient.name,
|
|
role: recipient.role,
|
|
signingOrder: recipient.signingOrder,
|
|
actionAuth: recipient.actionAuth,
|
|
})),
|
|
requestMetadata: ctx.metadata,
|
|
});
|
|
}),
|
|
|
|
/**
|
|
* @public
|
|
*/
|
|
getTemplateRecipient: authenticatedProcedure
|
|
.meta({
|
|
openapi: {
|
|
method: 'GET',
|
|
path: '/template/recipient/{recipientId}',
|
|
summary: 'Get template recipient',
|
|
description:
|
|
'Deprecated: this endpoint is being replaced by the Envelope API. See https://docs.documenso.com/docs/developers/api/migrate-to-envelopes for the migration guide. Returns a single recipient. If you want to retrieve all the recipients for a template, use the "Get Template" endpoint.',
|
|
tags: ['Template Recipients'],
|
|
deprecated: true,
|
|
},
|
|
})
|
|
.input(ZGetRecipientRequestSchema)
|
|
.output(ZGetRecipientResponseSchema)
|
|
.query(async ({ input, ctx }) => {
|
|
const { teamId } = ctx;
|
|
const { recipientId } = input;
|
|
|
|
ctx.logger.info({
|
|
input: {
|
|
recipientId,
|
|
},
|
|
});
|
|
|
|
return await getRecipientById({
|
|
userId: ctx.user.id,
|
|
teamId,
|
|
recipientId,
|
|
type: EnvelopeType.TEMPLATE,
|
|
});
|
|
}),
|
|
|
|
/**
|
|
* @public
|
|
*/
|
|
createTemplateRecipient: authenticatedProcedure
|
|
.meta({
|
|
openapi: {
|
|
method: 'POST',
|
|
path: '/template/recipient/create',
|
|
summary: 'Create template recipient',
|
|
description:
|
|
'Deprecated: this endpoint is being replaced by the Envelope API. See https://docs.documenso.com/docs/developers/api/migrate-to-envelopes for the migration guide. Create a single recipient for a template.',
|
|
tags: ['Template Recipients'],
|
|
deprecated: true,
|
|
},
|
|
})
|
|
.input(ZCreateTemplateRecipientRequestSchema)
|
|
.output(ZCreateTemplateRecipientResponseSchema)
|
|
.mutation(async ({ input, ctx }) => {
|
|
const { teamId } = ctx;
|
|
const { templateId, recipient } = input;
|
|
|
|
ctx.logger.info({
|
|
input: {
|
|
templateId,
|
|
},
|
|
});
|
|
|
|
const createdRecipients = await createEnvelopeRecipients({
|
|
userId: ctx.user.id,
|
|
teamId,
|
|
id: {
|
|
id: templateId,
|
|
type: 'templateId',
|
|
},
|
|
recipients: [recipient],
|
|
requestMetadata: ctx.metadata,
|
|
});
|
|
|
|
return createdRecipients.recipients[0];
|
|
}),
|
|
|
|
/**
|
|
* @public
|
|
*/
|
|
createTemplateRecipients: authenticatedProcedure
|
|
.meta({
|
|
openapi: {
|
|
method: 'POST',
|
|
path: '/template/recipient/create-many',
|
|
summary: 'Create template recipients',
|
|
description:
|
|
'Deprecated: this endpoint is being replaced by the Envelope API. See https://docs.documenso.com/docs/developers/api/migrate-to-envelopes for the migration guide. Create multiple recipients for a template.',
|
|
tags: ['Template Recipients'],
|
|
deprecated: true,
|
|
},
|
|
})
|
|
.input(ZCreateTemplateRecipientsRequestSchema)
|
|
.output(ZCreateTemplateRecipientsResponseSchema)
|
|
.mutation(async ({ input, ctx }) => {
|
|
const { teamId } = ctx;
|
|
const { templateId, recipients } = input;
|
|
|
|
ctx.logger.info({
|
|
input: {
|
|
templateId,
|
|
},
|
|
});
|
|
|
|
return await createEnvelopeRecipients({
|
|
userId: ctx.user.id,
|
|
teamId,
|
|
id: {
|
|
id: templateId,
|
|
type: 'templateId',
|
|
},
|
|
recipients,
|
|
requestMetadata: ctx.metadata,
|
|
});
|
|
}),
|
|
|
|
/**
|
|
* @public
|
|
*/
|
|
updateTemplateRecipient: authenticatedProcedure
|
|
.meta({
|
|
openapi: {
|
|
method: 'POST',
|
|
path: '/template/recipient/update',
|
|
summary: 'Update template recipient',
|
|
description:
|
|
'Deprecated: this endpoint is being replaced by the Envelope API. See https://docs.documenso.com/docs/developers/api/migrate-to-envelopes for the migration guide. Update a single recipient for a template.',
|
|
tags: ['Template Recipients'],
|
|
deprecated: true,
|
|
},
|
|
})
|
|
.input(ZUpdateTemplateRecipientRequestSchema)
|
|
.output(ZUpdateTemplateRecipientResponseSchema)
|
|
.mutation(async ({ input, ctx }) => {
|
|
const { teamId } = ctx;
|
|
const { templateId, recipient } = input;
|
|
|
|
ctx.logger.info({
|
|
input: {
|
|
templateId,
|
|
},
|
|
});
|
|
|
|
const updatedRecipients = await updateEnvelopeRecipients({
|
|
userId: ctx.user.id,
|
|
teamId,
|
|
id: {
|
|
type: 'templateId',
|
|
id: templateId,
|
|
},
|
|
recipients: [recipient],
|
|
requestMetadata: ctx.metadata,
|
|
});
|
|
|
|
return updatedRecipients.recipients[0];
|
|
}),
|
|
|
|
/**
|
|
* @public
|
|
*/
|
|
updateTemplateRecipients: authenticatedProcedure
|
|
.meta({
|
|
openapi: {
|
|
method: 'POST',
|
|
path: '/template/recipient/update-many',
|
|
summary: 'Update template recipients',
|
|
description:
|
|
'Deprecated: this endpoint is being replaced by the Envelope API. See https://docs.documenso.com/docs/developers/api/migrate-to-envelopes for the migration guide. Update multiple recipients for a template.',
|
|
tags: ['Template Recipients'],
|
|
deprecated: true,
|
|
},
|
|
})
|
|
.input(ZUpdateTemplateRecipientsRequestSchema)
|
|
.output(ZUpdateTemplateRecipientsResponseSchema)
|
|
.mutation(async ({ input, ctx }) => {
|
|
const { teamId } = ctx;
|
|
const { templateId, recipients } = input;
|
|
|
|
ctx.logger.info({
|
|
input: {
|
|
templateId,
|
|
},
|
|
});
|
|
|
|
return await updateEnvelopeRecipients({
|
|
userId: ctx.user.id,
|
|
teamId,
|
|
id: {
|
|
type: 'templateId',
|
|
id: templateId,
|
|
},
|
|
recipients,
|
|
requestMetadata: ctx.metadata,
|
|
});
|
|
}),
|
|
|
|
/**
|
|
* @public
|
|
*/
|
|
deleteTemplateRecipient: authenticatedProcedure
|
|
.meta({
|
|
openapi: {
|
|
method: 'POST',
|
|
path: '/template/recipient/delete',
|
|
summary: 'Delete template recipient',
|
|
description:
|
|
'Deprecated: this endpoint is being replaced by the Envelope API. See https://docs.documenso.com/docs/developers/api/migrate-to-envelopes for the migration guide.',
|
|
tags: ['Template Recipients'],
|
|
deprecated: true,
|
|
},
|
|
})
|
|
.input(ZDeleteTemplateRecipientRequestSchema)
|
|
.output(ZSuccessResponseSchema)
|
|
.mutation(async ({ input, ctx }) => {
|
|
const { teamId } = ctx;
|
|
const { recipientId } = input;
|
|
|
|
ctx.logger.info({
|
|
input: {
|
|
recipientId,
|
|
},
|
|
});
|
|
|
|
await deleteEnvelopeRecipient({
|
|
recipientId,
|
|
userId: ctx.user.id,
|
|
teamId,
|
|
requestMetadata: ctx.metadata,
|
|
});
|
|
|
|
return ZGenericSuccessResponse;
|
|
}),
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
setTemplateRecipients: authenticatedProcedure
|
|
.input(ZSetTemplateRecipientsRequestSchema)
|
|
.output(ZSetTemplateRecipientsResponseSchema)
|
|
.mutation(async ({ input, ctx }) => {
|
|
const { teamId } = ctx;
|
|
const { templateId, recipients } = input;
|
|
|
|
ctx.logger.info({
|
|
input: {
|
|
templateId,
|
|
},
|
|
});
|
|
|
|
return await setTemplateRecipients({
|
|
userId: ctx.user.id,
|
|
teamId,
|
|
id: {
|
|
type: 'templateId',
|
|
id: templateId,
|
|
},
|
|
recipients: recipients.map((recipient) => ({
|
|
id: recipient.id,
|
|
email: recipient.email,
|
|
name: recipient.name,
|
|
role: recipient.role,
|
|
signingOrder: recipient.signingOrder,
|
|
actionAuth: recipient.actionAuth,
|
|
})),
|
|
});
|
|
}),
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
completeDocumentWithToken: procedure
|
|
.input(ZCompleteDocumentWithTokenMutationSchema)
|
|
.output(ZCompleteDocumentWithTokenResponseSchema)
|
|
.mutation(async ({ input, ctx }) => {
|
|
try {
|
|
const { token, documentId, accessAuthOptions, nextSigner, recipientOverride } = input;
|
|
|
|
ctx.logger.info({
|
|
input: {
|
|
documentId,
|
|
},
|
|
});
|
|
|
|
// Branch on TSP envelopes before any SES side effects: TSP recipients
|
|
// can't complete via this route — they go through the CSC sync sign
|
|
// flow (`enterprise.csc.signEnvelope`). This route returns the redirect URL
|
|
// for the credential-scope OAuth round-trip.
|
|
const envelope = await prisma.envelope.findFirstOrThrow({
|
|
where: {
|
|
...unsafeBuildEnvelopeIdQuery({ type: 'documentId', id: documentId }, EnvelopeType.DOCUMENT),
|
|
recipients: { some: { token } },
|
|
},
|
|
select: { signatureLevel: true, internalVersion: true },
|
|
});
|
|
|
|
if (isTspEnvelope(envelope)) {
|
|
return await prepareCscRecipientSigning({
|
|
recipientToken: token,
|
|
requestMetadata: ctx.metadata.requestMetadata,
|
|
});
|
|
}
|
|
|
|
await completeDocumentWithToken({
|
|
token,
|
|
id: {
|
|
type: 'documentId',
|
|
id: documentId,
|
|
},
|
|
accessAuthOptions,
|
|
nextSigner,
|
|
recipientOverride,
|
|
userId: ctx.user?.id,
|
|
requestMetadata: ctx.metadata.requestMetadata,
|
|
});
|
|
|
|
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',
|
|
error: err instanceof AppError ? `[${err.code}]: ${err.message}` : String(err),
|
|
});
|
|
|
|
// Raw console.log incase we're somehow dealing with a funky error object that doesn't serialize well.
|
|
console.log('Error completing document with token', err);
|
|
|
|
// Rethrow the error so that the client receives the appropriate error response.
|
|
throw err;
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
rejectDocumentWithToken: procedure.input(ZRejectDocumentWithTokenMutationSchema).mutation(async ({ input, ctx }) => {
|
|
const { token, documentId, reason } = input;
|
|
|
|
ctx.logger.info({
|
|
input: {
|
|
documentId,
|
|
},
|
|
});
|
|
|
|
return await rejectDocumentWithToken({
|
|
token,
|
|
id: {
|
|
type: 'documentId',
|
|
id: documentId,
|
|
},
|
|
reason,
|
|
requestMetadata: ctx.metadata.requestMetadata,
|
|
});
|
|
}),
|
|
});
|