mirror of
https://github.com/documenso/documenso.git
synced 2026-07-27 10:25:00 +10:00
feat: per-recipient envelope expiration (#2519)
This commit is contained in:
@@ -571,6 +571,14 @@ export const formatDocumentAuditLogAction = (
|
||||
you: msg`You deleted an envelope item with title ${data.envelopeItemTitle}`,
|
||||
user: msg`${user} deleted an envelope item with title ${data.envelopeItemTitle}`,
|
||||
}))
|
||||
.with({ type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_RECIPIENT_EXPIRED }, ({ data }) => ({
|
||||
anonymous: msg({
|
||||
message: `Recipient signing window expired`,
|
||||
context: `Audit log format`,
|
||||
}),
|
||||
you: msg`Signing window expired for ${data.recipientName || data.recipientEmail}`,
|
||||
user: msg`Signing window expired for ${data.recipientName || data.recipientEmail}`,
|
||||
}))
|
||||
.with({ type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_DELEGATED_OWNER_CREATED }, ({ data }) => {
|
||||
const message = msg({
|
||||
message: `The document ownership was delegated to ${data.delegatedOwnerName || data.delegatedOwnerEmail} on behalf of ${data.teamName}`,
|
||||
|
||||
@@ -62,6 +62,10 @@ export const extractDerivedDocumentMeta = (
|
||||
emailReplyTo: meta.emailReplyTo ?? settings.emailReplyTo,
|
||||
emailSettings:
|
||||
meta.emailSettings || settings.emailDocumentSettings || DEFAULT_DOCUMENT_EMAIL_SETTINGS,
|
||||
|
||||
// Envelope expiration.
|
||||
envelopeExpirationPeriod:
|
||||
meta.envelopeExpirationPeriod ?? settings.envelopeExpirationPeriod ?? null,
|
||||
} satisfies Omit<DocumentMeta, 'id'>;
|
||||
};
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
import type { ORGANISATION_MEMBER_ROLE_MAP } from '@documenso/lib/constants/organisations-translations';
|
||||
|
||||
import { DEFAULT_DOCUMENT_DATE_FORMAT } from '../constants/date-formats';
|
||||
import { DEFAULT_ENVELOPE_EXPIRATION_PERIOD } from '../constants/envelope-expiration';
|
||||
import {
|
||||
LOWEST_ORGANISATION_ROLE,
|
||||
ORGANISATION_MEMBER_ROLE_HIERARCHY,
|
||||
@@ -138,6 +139,9 @@ export const generateDefaultOrganisationSettings = (): Omit<
|
||||
emailDocumentSettings: DEFAULT_DOCUMENT_EMAIL_SETTINGS,
|
||||
|
||||
defaultRecipients: null,
|
||||
|
||||
envelopeExpirationPeriod: DEFAULT_ENVELOPE_EXPIRATION_PERIOD,
|
||||
|
||||
aiFeaturesEnabled: false,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ import { z } from 'zod';
|
||||
import { isSignatureFieldType } from '@documenso/prisma/guards/is-signature-field';
|
||||
|
||||
import { NEXT_PUBLIC_WEBAPP_URL } from '../constants/app';
|
||||
import { AppError, AppErrorCode } from '../errors/app-error';
|
||||
import { extractLegacyIds } from '../universal/id';
|
||||
|
||||
/**
|
||||
@@ -94,3 +95,23 @@ export const mapRecipientToLegacyRecipient = (
|
||||
export const isRecipientEmailValidForSending = (recipient: Pick<Recipient, 'email'>) => {
|
||||
return z.string().email().safeParse(recipient.email).success;
|
||||
};
|
||||
|
||||
/**
|
||||
* Whether the recipient's signing window has expired.
|
||||
*/
|
||||
export const isRecipientExpired = (recipient: { expiresAt: Date | null }) => {
|
||||
return Boolean(recipient.expiresAt && new Date(recipient.expiresAt) <= new Date());
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that the recipient's signing window has not expired.
|
||||
*
|
||||
* Throws an AppError with RECIPIENT_EXPIRED if the expiration date has passed.
|
||||
*/
|
||||
export const assertRecipientNotExpired = (recipient: { expiresAt: Date | null }) => {
|
||||
if (isRecipientExpired(recipient)) {
|
||||
throw new AppError(AppErrorCode.RECIPIENT_EXPIRED, {
|
||||
message: 'Recipient signing window has expired',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -205,6 +205,9 @@ export const generateDefaultTeamSettings = (): Omit<TeamGlobalSettings, 'id' | '
|
||||
// emailReplyToName: null,
|
||||
|
||||
defaultRecipients: null,
|
||||
|
||||
envelopeExpirationPeriod: null,
|
||||
|
||||
aiFeaturesEnabled: null,
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user