mirror of
https://github.com/documenso/documenso.git
synced 2026-07-24 08:54:20 +10:00
baa2c51123
When using an API key created in a team context, the documents/templates’ owner always defaults to the team API token creator, rather than the actual uploader. For example, John creates the API key for the team "Lawyers". Tom and Maria use the API key to upload documents. All the uploaded documents are attributed to John. This makes it impossible to see who actually uploaded a document. The new feature allows users to enable document ownership delegation from the organization/team settings.
169 lines
4.9 KiB
TypeScript
169 lines
4.9 KiB
TypeScript
import { OrganisationType } from '@prisma/client';
|
|
|
|
import { ORGANISATION_MEMBER_ROLE_PERMISSIONS_MAP } from '@documenso/lib/constants/organisations';
|
|
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
|
import { buildOrganisationWhereQuery } from '@documenso/lib/utils/organisations';
|
|
import { prisma } from '@documenso/prisma';
|
|
|
|
import { authenticatedProcedure } from '../trpc';
|
|
import {
|
|
ZUpdateOrganisationSettingsRequestSchema,
|
|
ZUpdateOrganisationSettingsResponseSchema,
|
|
} from './update-organisation-settings.types';
|
|
|
|
export const updateOrganisationSettingsRoute = authenticatedProcedure
|
|
.input(ZUpdateOrganisationSettingsRequestSchema)
|
|
.output(ZUpdateOrganisationSettingsResponseSchema)
|
|
.mutation(async ({ ctx, input }) => {
|
|
const { user } = ctx;
|
|
const { organisationId, data } = input;
|
|
|
|
ctx.logger.info({
|
|
input: {
|
|
organisationId,
|
|
},
|
|
});
|
|
|
|
const {
|
|
// Document related settings.
|
|
documentVisibility,
|
|
documentLanguage,
|
|
documentTimezone,
|
|
documentDateFormat,
|
|
includeSenderDetails,
|
|
includeSigningCertificate,
|
|
includeAuditLog,
|
|
typedSignatureEnabled,
|
|
uploadSignatureEnabled,
|
|
drawSignatureEnabled,
|
|
delegateDocumentOwnership,
|
|
|
|
// Branding related settings.
|
|
brandingEnabled,
|
|
brandingLogo,
|
|
brandingUrl,
|
|
brandingCompanyDetails,
|
|
|
|
// Email related settings.
|
|
emailId,
|
|
emailReplyTo,
|
|
// emailReplyToName,
|
|
emailDocumentSettings,
|
|
|
|
// AI features settings.
|
|
aiFeaturesEnabled,
|
|
} = data;
|
|
|
|
if (Object.values(data).length === 0) {
|
|
throw new AppError(AppErrorCode.INVALID_BODY, {
|
|
message: 'No settings to update',
|
|
});
|
|
}
|
|
|
|
const organisation = await prisma.organisation.findFirst({
|
|
where: buildOrganisationWhereQuery({
|
|
organisationId,
|
|
userId: user.id,
|
|
roles: ORGANISATION_MEMBER_ROLE_PERMISSIONS_MAP['MANAGE_ORGANISATION'],
|
|
}),
|
|
include: {
|
|
organisationGlobalSettings: true,
|
|
},
|
|
});
|
|
|
|
if (!organisation) {
|
|
throw new AppError(AppErrorCode.UNAUTHORIZED, {
|
|
message: 'You do not have permission to update this organisation.',
|
|
});
|
|
}
|
|
|
|
// Validate that the email ID belongs to the organisation.
|
|
if (emailId) {
|
|
const email = await prisma.organisationEmail.findFirst({
|
|
where: {
|
|
id: emailId,
|
|
organisationId,
|
|
},
|
|
});
|
|
|
|
if (!email) {
|
|
throw new AppError(AppErrorCode.NOT_FOUND, {
|
|
message: 'Email not found',
|
|
});
|
|
}
|
|
}
|
|
|
|
const derivedTypedSignatureEnabled =
|
|
typedSignatureEnabled ?? organisation.organisationGlobalSettings.typedSignatureEnabled;
|
|
const derivedUploadSignatureEnabled =
|
|
uploadSignatureEnabled ?? organisation.organisationGlobalSettings.uploadSignatureEnabled;
|
|
const derivedDrawSignatureEnabled =
|
|
drawSignatureEnabled ?? organisation.organisationGlobalSettings.drawSignatureEnabled;
|
|
|
|
const derivedDelegateDocumentOwnership =
|
|
delegateDocumentOwnership ??
|
|
organisation.organisationGlobalSettings.delegateDocumentOwnership;
|
|
|
|
if (
|
|
derivedTypedSignatureEnabled === false &&
|
|
derivedUploadSignatureEnabled === false &&
|
|
derivedDrawSignatureEnabled === false
|
|
) {
|
|
throw new AppError(AppErrorCode.INVALID_BODY, {
|
|
message: 'At least one signature type must be enabled',
|
|
});
|
|
}
|
|
|
|
const isPersonalOrganisation = organisation.type === OrganisationType.PERSONAL;
|
|
const currentIncludeSenderDetails =
|
|
organisation.organisationGlobalSettings.includeSenderDetails;
|
|
|
|
const isChangingIncludeSenderDetails =
|
|
includeSenderDetails !== undefined && includeSenderDetails !== currentIncludeSenderDetails;
|
|
|
|
if (isPersonalOrganisation && isChangingIncludeSenderDetails) {
|
|
throw new AppError(AppErrorCode.INVALID_BODY, {
|
|
message: 'Personal organisations cannot update the sender details',
|
|
});
|
|
}
|
|
|
|
await prisma.organisation.update({
|
|
where: {
|
|
id: organisationId,
|
|
},
|
|
data: {
|
|
organisationGlobalSettings: {
|
|
update: {
|
|
// Document related settings.
|
|
documentVisibility,
|
|
documentLanguage,
|
|
documentTimezone,
|
|
documentDateFormat,
|
|
includeSenderDetails,
|
|
includeSigningCertificate,
|
|
includeAuditLog,
|
|
typedSignatureEnabled,
|
|
uploadSignatureEnabled,
|
|
drawSignatureEnabled,
|
|
delegateDocumentOwnership: derivedDelegateDocumentOwnership,
|
|
|
|
// Branding related settings.
|
|
brandingEnabled,
|
|
brandingLogo,
|
|
brandingUrl,
|
|
brandingCompanyDetails,
|
|
|
|
// Email related settings.
|
|
emailId,
|
|
emailReplyTo,
|
|
// emailReplyToName,
|
|
emailDocumentSettings,
|
|
|
|
// AI features settings.
|
|
aiFeaturesEnabled,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
});
|