mirror of
https://github.com/documenso/documenso.git
synced 2026-07-25 01:15:49 +10:00
Merge branch 'main' into feature/pdf-placeholder-selection-fields
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
import { AppError, AppErrorCode } from '../../errors/app-error';
|
||||
import { putFileServerSide } from '../../universal/upload/put-file.server';
|
||||
import { optimiseBrandingLogo } from '../../utils/images/logo';
|
||||
|
||||
/**
|
||||
* Validate, sanitise and store an uploaded branding logo. Returns the
|
||||
* `JSON.stringify({ type, data })` reference persisted in the `brandingLogo`
|
||||
* column (the same format the serving endpoints already expect).
|
||||
*/
|
||||
export const buildBrandingLogoData = async (file: File): Promise<string> => {
|
||||
const buffer = Buffer.from(await file.arrayBuffer());
|
||||
|
||||
const optimised = await optimiseBrandingLogo(buffer).catch(() => {
|
||||
throw new AppError(AppErrorCode.INVALID_BODY, {
|
||||
message: 'The branding logo must be a valid image file.',
|
||||
});
|
||||
});
|
||||
|
||||
const documentData = await putFileServerSide({
|
||||
name: 'branding-logo.png',
|
||||
type: 'image/png',
|
||||
arrayBuffer: async () => Promise.resolve(optimised),
|
||||
});
|
||||
|
||||
return JSON.stringify(documentData);
|
||||
};
|
||||
@@ -83,15 +83,17 @@ export const deleteDocument = async ({ id, userId, teamId, requestMetadata }: De
|
||||
|
||||
// Handle hard or soft deleting the actual document if user has permission.
|
||||
if (hasDeleteAccess) {
|
||||
await handleDocumentOwnerDelete({
|
||||
const updatedEnvelope = await handleDocumentOwnerDelete({
|
||||
envelope,
|
||||
user,
|
||||
requestMetadata,
|
||||
});
|
||||
|
||||
const envelopeForWebhook = { ...envelope, ...(updatedEnvelope ?? {}) };
|
||||
|
||||
await triggerWebhook({
|
||||
event: WebhookTriggerEvents.DOCUMENT_CANCELLED,
|
||||
data: ZWebhookDocumentSchema.parse(mapEnvelopeToWebhookDocumentPayload(envelope)),
|
||||
data: ZWebhookDocumentSchema.parse(mapEnvelopeToWebhookDocumentPayload(envelopeForWebhook)),
|
||||
userId,
|
||||
teamId,
|
||||
});
|
||||
|
||||
@@ -37,9 +37,9 @@ import { extractDerivedDocumentMeta } from '../../utils/document';
|
||||
import { createDocumentAuthOptions, createRecipientAuthOptions } from '../../utils/document-auth';
|
||||
import { buildTeamWhereQuery } from '../../utils/teams';
|
||||
import { incrementDocumentId, incrementTemplateId } from '../envelope/increment-id';
|
||||
import { assertOrganisationRatesAndLimits } from '../rate-limit/assert-organisation-rates-and-limits';
|
||||
import { assertCompatibleRecipientRole } from '../signature-level/assert-compatible-recipient-role';
|
||||
import { resolveSignatureLevel } from '../signature-level/resolve-signature-level';
|
||||
import { assertOrganisationRatesAndLimits } from '../rate-limit/assert-organisation-rates-and-limits';
|
||||
import { getTeamSettings } from '../team/get-team-settings';
|
||||
import { assertUserNotDisabledById } from '../user/assert-user-not-disabled';
|
||||
import { triggerWebhook } from '../webhooks/trigger/trigger-webhook';
|
||||
|
||||
@@ -10,8 +10,8 @@ import { nanoid, prefixedId } from '../../universal/id';
|
||||
import type { EnvelopeIdOptions } from '../../utils/envelope';
|
||||
import { getEnvelopeWhereInput } from '../envelope/get-envelope-by-id';
|
||||
import { incrementDocumentId, incrementTemplateId } from '../envelope/increment-id';
|
||||
import { resolveSignatureLevel } from '../signature-level/resolve-signature-level';
|
||||
import { assertOrganisationRatesAndLimits } from '../rate-limit/assert-organisation-rates-and-limits';
|
||||
import { resolveSignatureLevel } from '../signature-level/resolve-signature-level';
|
||||
import { triggerWebhook } from '../webhooks/trigger/trigger-webhook';
|
||||
|
||||
export interface DuplicateEnvelopeOptions {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { QUOTA_WARNING_THRESHOLD } from './get-quota-alert-kind';
|
||||
import { isQuotaExceeded, isQuotaNearing } from '../../universal/quota-usage';
|
||||
|
||||
export type QuotaFlags = {
|
||||
isDocumentQuotaExceeded: boolean;
|
||||
@@ -22,39 +22,6 @@ type ComputeQuotaFlagsOptions = {
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* A quota of `null` means unlimited (never exceeded). A quota of `0` means
|
||||
* blocked (always exceeded). Otherwise usage `>=` quota is exceeded.
|
||||
*/
|
||||
const isQuotaExceeded = (quota: number | null, usage: number): boolean => {
|
||||
if (quota === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (quota === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return usage >= quota;
|
||||
};
|
||||
|
||||
/**
|
||||
* A counter is "nearing" its quota once usage reaches the warning threshold
|
||||
* (80% of the quota, rounded up) but has not yet been exceeded. Nearing and
|
||||
* exceeded are mutually exclusive per counter.
|
||||
*/
|
||||
const isQuotaNearing = (quota: number | null, usage: number): boolean => {
|
||||
if (quota === null || quota === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isQuotaExceeded(quota, usage)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return usage >= Math.ceil(quota * QUOTA_WARNING_THRESHOLD);
|
||||
};
|
||||
|
||||
export const computeQuotaFlags = ({ quotas, usage }: ComputeQuotaFlagsOptions): QuotaFlags => {
|
||||
return {
|
||||
isDocumentQuotaExceeded: isQuotaExceeded(quotas.documentQuota, usage?.documentCount ?? 0),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export const QUOTA_WARNING_THRESHOLD = 0.8;
|
||||
import { getQuotaWarningCount } from '../../universal/quota-usage';
|
||||
|
||||
export type QuotaAlertKind = 'quota' | 'quotaNearing';
|
||||
|
||||
@@ -32,7 +32,7 @@ export const getQuotaAlertKind = (opts: GetQuotaAlertKindOptions): QuotaAlertKin
|
||||
// From here newCount < quota, so for tiny quotas (1-4) where the rounded-up
|
||||
// warning threshold equals the quota itself, the warning can never fire — the
|
||||
// exhausting request is handled by the quota branch above.
|
||||
const warningCount = Math.ceil(quota * QUOTA_WARNING_THRESHOLD);
|
||||
const warningCount = getQuotaWarningCount(quota);
|
||||
|
||||
const didCrossWarning = newCount >= warningCount && previousCount < warningCount;
|
||||
|
||||
|
||||
@@ -51,8 +51,8 @@ import { buildTeamWhereQuery } from '../../utils/teams';
|
||||
import { getEnvelopeWhereInput } from '../envelope/get-envelope-by-id';
|
||||
import { incrementDocumentId } from '../envelope/increment-id';
|
||||
import { insertFormValuesInPdf } from '../pdf/insert-form-values-in-pdf';
|
||||
import { resolveSignatureLevel } from '../signature-level/resolve-signature-level';
|
||||
import { assertOrganisationRatesAndLimits } from '../rate-limit/assert-organisation-rates-and-limits';
|
||||
import { resolveSignatureLevel } from '../signature-level/resolve-signature-level';
|
||||
import { getTeamSettings } from '../team/get-team-settings';
|
||||
import { triggerWebhook } from '../webhooks/trigger/trigger-webhook';
|
||||
import { getOrganisationTemplateWhereInput } from './get-organisation-template-by-id';
|
||||
|
||||
Reference in New Issue
Block a user