Files
documenso/packages/lib/server-only/document/get-document-by-token.ts
2025-11-07 14:17:52 +11:00

162 lines
3.4 KiB
TypeScript

import { EnvelopeType } from '@prisma/client';
import { prisma } from '@documenso/prisma';
import { AppError, AppErrorCode } from '../../errors/app-error';
import type { TDocumentAuthMethods } from '../../types/document-auth';
import { mapSecondaryIdToDocumentId } from '../../utils/envelope';
import { isRecipientAuthorized } from './is-recipient-authorized';
export interface GetDocumentAndSenderByTokenOptions {
token: string;
userId?: number;
accessAuth?: TDocumentAuthMethods;
/**
* Whether we enforce the access requirement.
*
* Defaults to true.
*/
requireAccessAuth?: boolean;
}
export interface GetDocumentAndRecipientByTokenOptions {
token: string;
userId?: number;
accessAuth?: TDocumentAuthMethods;
/**
* Whether we enforce the access requirement.
*
* Defaults to true.
*/
requireAccessAuth?: boolean;
}
export type GetDocumentByTokenOptions = {
token: string;
};
export const getDocumentByToken = async ({ token }: GetDocumentByTokenOptions) => {
if (!token) {
throw new Error('Missing token');
}
const result = await prisma.envelope.findFirstOrThrow({
where: {
type: EnvelopeType.DOCUMENT,
recipients: {
some: {
token,
},
},
},
});
return result;
};
export type DocumentAndSender = Awaited<ReturnType<typeof getDocumentAndSenderByToken>>;
export const getDocumentAndSenderByToken = async ({
token,
userId,
accessAuth,
requireAccessAuth = true,
}: GetDocumentAndSenderByTokenOptions) => {
if (!token) {
throw new Error('Missing token');
}
const result = await prisma.envelope.findFirstOrThrow({
where: {
type: EnvelopeType.DOCUMENT,
recipients: {
some: {
token,
},
},
},
include: {
user: {
select: {
id: true,
email: true,
name: true,
},
},
documentMeta: true,
recipients: {
where: {
token,
},
},
envelopeItems: {
select: {
id: true,
title: true,
order: true,
envelopeId: true,
documentData: true,
},
},
team: {
select: {
name: true,
teamEmail: true,
teamGlobalSettings: {
select: {
brandingEnabled: true,
brandingLogo: true,
},
},
},
},
},
});
const firstDocumentData = result.envelopeItems[0].documentData;
if (!firstDocumentData) {
throw new Error('Missing document data');
}
const recipient = result.recipients[0];
// Sanity check, should not be possible.
if (!recipient) {
throw new Error('Missing recipient');
}
let documentAccessValid = true;
if (requireAccessAuth) {
documentAccessValid = await isRecipientAuthorized({
type: 'ACCESS',
documentAuthOptions: result.authOptions,
recipient,
userId,
authOptions: accessAuth,
});
}
if (!documentAccessValid) {
throw new AppError(AppErrorCode.UNAUTHORIZED, {
message: 'Invalid access values',
});
}
const legacyDocumentId = mapSecondaryIdToDocumentId(result.secondaryId);
return {
...result,
user: {
id: result.user.id,
email: result.user.email,
name: result.user.name,
},
documentData: firstDocumentData,
id: legacyDocumentId,
envelopeId: result.id,
};
};