mirror of
https://github.com/documenso/documenso.git
synced 2026-07-26 18:04:55 +10:00
feat: add cancellable document status (#2992)
Adds a CANCELLED envelope status that privileged members (owner or team admin/manager) can move a pending document into. Sending recipient notifications via a background job while retaining the document in the dashboard as proof of distribution. Includes a dedicated Cancelled tab, single and bulk cancel actions, the ENVELOPE_CANCELLED mutability guard, and e2e coverage for permissions and visibility.
This commit is contained in:
@@ -13,7 +13,27 @@ type File = {
|
||||
arrayBuffer: () => Promise<ArrayBuffer>;
|
||||
};
|
||||
|
||||
export const putPdfFile = async (file: File) => {
|
||||
/**
|
||||
* Options for uploads that are not authorized by a logged-in session.
|
||||
*
|
||||
* Embedded authoring flows run cross-origin without a session cookie, so they
|
||||
* must authorize uploads with their embedding presign token instead.
|
||||
*/
|
||||
export type PutFileOptions = {
|
||||
presignToken?: string;
|
||||
};
|
||||
|
||||
const buildUploadAuthHeaders = (options?: PutFileOptions): Record<string, string> => {
|
||||
if (!options?.presignToken) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
Authorization: `Bearer ${options.presignToken}`,
|
||||
};
|
||||
};
|
||||
|
||||
export const putPdfFile = async (file: File, options?: PutFileOptions) => {
|
||||
const formData = new FormData();
|
||||
|
||||
// Create a proper File object from the data
|
||||
@@ -25,6 +45,7 @@ export const putPdfFile = async (file: File) => {
|
||||
|
||||
const response = await fetch('/api/files/upload-pdf', {
|
||||
method: 'POST',
|
||||
headers: buildUploadAuthHeaders(options),
|
||||
body: formData,
|
||||
});
|
||||
|
||||
@@ -41,12 +62,12 @@ export const putPdfFile = async (file: File) => {
|
||||
/**
|
||||
* Uploads a file to the appropriate storage location.
|
||||
*/
|
||||
export const putFile = async (file: File) => {
|
||||
export const putFile = async (file: File, options?: PutFileOptions) => {
|
||||
const NEXT_PUBLIC_UPLOAD_TRANSPORT = env('NEXT_PUBLIC_UPLOAD_TRANSPORT');
|
||||
|
||||
return await match(NEXT_PUBLIC_UPLOAD_TRANSPORT)
|
||||
.with('s3', async () => putFileInObjectStorage(file, {}))
|
||||
.with('azure-blob', async () => putFileInObjectStorage(file, { 'x-ms-blob-type': 'BlockBlob' }))
|
||||
.with('s3', async () => putFileInObjectStorage(file, {}, options))
|
||||
.with('azure-blob', async () => putFileInObjectStorage(file, { 'x-ms-blob-type': 'BlockBlob' }, options))
|
||||
.otherwise(async () => putFileInDatabase(file));
|
||||
};
|
||||
|
||||
@@ -63,11 +84,12 @@ const putFileInDatabase = async (file: File) => {
|
||||
};
|
||||
};
|
||||
|
||||
const putFileInObjectStorage = async (file: File, extraHeaders: Record<string, string>) => {
|
||||
const putFileInObjectStorage = async (file: File, extraHeaders: Record<string, string>, options?: PutFileOptions) => {
|
||||
const getPresignedUrlResponse = await fetch(`${NEXT_PUBLIC_WEBAPP_URL()}/api/files/presigned-post-url`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...buildUploadAuthHeaders(options),
|
||||
},
|
||||
body: JSON.stringify({
|
||||
fileName: file.name,
|
||||
|
||||
Reference in New Issue
Block a user