Split
This commit is contained in:
@@ -16,7 +16,6 @@ import {
|
||||
type EncryptedMagicMetadata,
|
||||
type EnteFile,
|
||||
type RemoteFileMetadata,
|
||||
type S3FileAttributes,
|
||||
} from "ente-media/file";
|
||||
import { handleUploadError } from "ente-shared/error";
|
||||
import HTTPService from "ente-shared/network/HTTPService";
|
||||
@@ -415,16 +414,67 @@ export const completeMultipartUploadViaWorker = async (
|
||||
}),
|
||||
);
|
||||
|
||||
interface PostEnteFileRequest {
|
||||
export interface PostEnteFileRequest {
|
||||
collectionID: number;
|
||||
encryptedKey: string;
|
||||
keyDecryptionNonce: string;
|
||||
file: S3FileAttributes;
|
||||
thumbnail: S3FileAttributes;
|
||||
file: UploadedFileObjectAttributes;
|
||||
thumbnail: UploadedFileObjectAttributes;
|
||||
metadata: RemoteFileMetadata;
|
||||
pubMagicMetadata: EncryptedMagicMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attributes about an object uploaded to S3.
|
||||
*
|
||||
* This is similar to the {@link FileObjectAttributes} that we get back in the
|
||||
* {@link EnteFile} we get from remote, however it contains more fields.
|
||||
*
|
||||
* - When we're finalizing the upload of {@link EnteFile}, we have at our
|
||||
* disposal the {@link objectKey}, {@link decryptionHeader} and {@link size}
|
||||
* attributes that we need to set in the POST "/files" request.
|
||||
*
|
||||
* - Later when we get back the file from remote as an {@link EnteFile}, it will
|
||||
* only have the {@link decryptionHeader}. This is all we need for obtaining
|
||||
* the decrypted file: the contents of the file get fetched (on demand) using
|
||||
* a presigned URL, and the file's key is the decryption key, so armed with
|
||||
* this decryption header we are good to go.
|
||||
*/
|
||||
export interface UploadedFileObjectAttributes {
|
||||
/**
|
||||
* The "key" (unique ID) of the S3 object that was uploaded.
|
||||
*
|
||||
* This is not related to encryption, it is the "objectKey" that uniquely
|
||||
* identifies the S3 object that was uploaded. We get these as part of the
|
||||
* {@link ObjectUploadURL} we get from remote. We upload the contents of the
|
||||
* object (e.g. file, thumbnail) to the corresponding URL, and then report
|
||||
* back the "objectKey" in the upload finalization request.
|
||||
*/
|
||||
objectKey: string;
|
||||
/**
|
||||
* The decryption header that was used when encrypting the objects's
|
||||
* contents (with the file's key) before uploading them to S3 remote.
|
||||
*
|
||||
* The {@link decryptionHeader} is both required when finalizing the upload,
|
||||
* and is also returned as part of the {@link EnteFile} that clients get
|
||||
* back from remote since it is needed (along with the file's key) to
|
||||
* decrypt the object that the client would download from S3 remote.
|
||||
*/
|
||||
decryptionHeader: string;
|
||||
/**
|
||||
* The size of the uploaded object, in bytes.
|
||||
*
|
||||
* For both file and thumbnails, the client also sends the size of the
|
||||
* encrypted file (as per the client) while creating a new object on remote.
|
||||
* This allows the server to validate that the size of the objects is same
|
||||
* as what client is reporting.
|
||||
*
|
||||
* This should be present during upload, but is not returned back from
|
||||
* remote in the /diff response.
|
||||
*/
|
||||
size: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link EnteFile} on remote by providing remote with information
|
||||
* about the file's contents (objects) that were uploaded, and other metadata
|
||||
|
||||
@@ -33,8 +33,6 @@ import type {
|
||||
EnteFile,
|
||||
FilePublicMagicMetadata,
|
||||
FilePublicMagicMetadataProps,
|
||||
RemoteFileMetadata,
|
||||
S3FileAttributes,
|
||||
} from "ente-media/file";
|
||||
import {
|
||||
metadataHash,
|
||||
@@ -71,6 +69,7 @@ import {
|
||||
putFileViaWorker,
|
||||
type MultipartCompletedPart,
|
||||
type ObjectUploadURL,
|
||||
type PostEnteFileRequest,
|
||||
} from "./remote";
|
||||
import {
|
||||
fallbackThumbnail,
|
||||
@@ -173,10 +172,10 @@ class UploadService {
|
||||
this.ensureUniqueUploadURLs();
|
||||
}
|
||||
|
||||
async uploadFile(uploadFile: UploadFile) {
|
||||
async postFile(file: PostEnteFileRequest) {
|
||||
return this.publicAlbumsCredentials
|
||||
? postPublicAlbumsEnteFile(uploadFile, this.publicAlbumsCredentials)
|
||||
: postEnteFile(uploadFile);
|
||||
? postPublicAlbumsEnteFile(file, this.publicAlbumsCredentials)
|
||||
: postEnteFile(file);
|
||||
}
|
||||
|
||||
private async refillUploadURLs() {
|
||||
@@ -341,19 +340,6 @@ interface EncryptedFilePieces {
|
||||
localID: number;
|
||||
}
|
||||
|
||||
export interface BackupedFile {
|
||||
file: S3FileAttributes;
|
||||
thumbnail: S3FileAttributes;
|
||||
metadata: RemoteFileMetadata;
|
||||
pubMagicMetadata: EncryptedMagicMetadata;
|
||||
}
|
||||
|
||||
export interface UploadFile extends BackupedFile {
|
||||
collectionID: number;
|
||||
encryptedKey: string;
|
||||
keyDecryptionNonce: string;
|
||||
}
|
||||
|
||||
export interface PotentialLivePhotoAsset {
|
||||
fileName: string;
|
||||
fileType: FileType;
|
||||
@@ -716,7 +702,7 @@ export const upload = async (
|
||||
|
||||
abortIfCancelled();
|
||||
|
||||
const uploadedFile = await uploadService.uploadFile({
|
||||
const uploadedFile = await uploadService.postFile({
|
||||
collectionID: collection.id,
|
||||
encryptedKey: encryptedFileKey.encryptedData,
|
||||
keyDecryptionNonce: encryptedFileKey.nonce,
|
||||
@@ -1506,7 +1492,12 @@ const encryptFileStream = async (
|
||||
const uploadToBucket = async (
|
||||
encryptedFilePieces: EncryptedFilePieces,
|
||||
uploadContext: UploadContext,
|
||||
): Promise<BackupedFile> => {
|
||||
): Promise<
|
||||
Pick<
|
||||
PostEnteFileRequest,
|
||||
"file" | "thumbnail" | "metadata" | "pubMagicMetadata"
|
||||
>
|
||||
> => {
|
||||
const { isCFUploadProxyDisabled, abortIfCancelled, updateUploadProgress } =
|
||||
uploadContext;
|
||||
|
||||
|
||||
@@ -44,9 +44,16 @@ export interface EncryptedEnteFile {
|
||||
* {@link FilePublicMagicMetadataData}).
|
||||
*/
|
||||
ownerID: number;
|
||||
file: S3FileAttributes;
|
||||
thumbnail: S3FileAttributes;
|
||||
metadata: RemoteFileMetadata;
|
||||
/**
|
||||
* Information pertaining to the encrypted S3 object that has the file's
|
||||
* contents.
|
||||
*/
|
||||
file: FileObjectAttributes;
|
||||
/**
|
||||
* Information pertaining to the encrypted S3 object that has the contents
|
||||
* of the file's thumbnail.
|
||||
*/
|
||||
thumbnail: FileObjectAttributes;
|
||||
/**
|
||||
* Static, remote visible, information associated with a file.
|
||||
*
|
||||
@@ -57,6 +64,7 @@ export interface EncryptedEnteFile {
|
||||
* Files uploaded by very old versions of Ente might not have this field.
|
||||
*/
|
||||
info?: FileInfo;
|
||||
metadata: RemoteFileMetadata;
|
||||
magicMetadata: EncryptedMagicMetadata;
|
||||
pubMagicMetadata: EncryptedMagicMetadata;
|
||||
/**
|
||||
@@ -172,36 +180,24 @@ export interface EnteFile
|
||||
}
|
||||
|
||||
/**
|
||||
* Attributes about an object uploaded to S3.
|
||||
* Attributes about an object related to the file
|
||||
*
|
||||
* TODO: Split between fields needed during upload, and the fields we get back
|
||||
* from remote in the /diff response.
|
||||
* - The file's contents,
|
||||
*
|
||||
* - The file's thumbnail's contents.
|
||||
*/
|
||||
export interface S3FileAttributes {
|
||||
export interface FileObjectAttributes {
|
||||
/**
|
||||
* Upload only: This should be present during upload, but is not returned
|
||||
* back from remote in the /diff response.
|
||||
*/
|
||||
objectKey: string;
|
||||
/**
|
||||
* Upload and diff: This is present both during upload and also returned by
|
||||
* remote in the /diff response.
|
||||
* The decryption header that was used when encrypting the objects's
|
||||
* contents (with the file's key) before uploading them to S3 remote.
|
||||
*/
|
||||
decryptionHeader: string;
|
||||
/**
|
||||
* The size of the file, in bytes.
|
||||
*
|
||||
* For both file and thumbnails, the client also sends the size of the
|
||||
* encrypted file (as per the client) while creating a new object on remote.
|
||||
* This allows the server to validate that the size of the objects is same
|
||||
* as what client is reporting.
|
||||
*
|
||||
* Upload only: This should be present during upload, but is not returned
|
||||
* back from remote in the /diff response.
|
||||
*/
|
||||
size: number;
|
||||
}
|
||||
|
||||
const RemoteFileObjectAttributes = z.looseObject({
|
||||
decryptionHeader: z.string(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Static information associated with a file.
|
||||
*/
|
||||
@@ -266,8 +262,8 @@ export const RemoteEnteFile = z.looseObject({
|
||||
* Base64 encoded.
|
||||
*/
|
||||
keyDecryptionNonce: z.string(),
|
||||
file: z.unknown(),
|
||||
thumbnail: z.unknown(),
|
||||
file: RemoteFileObjectAttributes,
|
||||
thumbnail: RemoteFileObjectAttributes,
|
||||
info: RemoteFileInfo.nullish().transform(nullToUndefined),
|
||||
updationTime: z.number(),
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user