Adopt API to update file if already uploaded

This commit is contained in:
Vishnu Mohandas 2020-11-30 23:15:21 +05:30
parent 58d4635bb5
commit 51f083d290
2 changed files with 137 additions and 50 deletions

View file

@ -38,7 +38,7 @@ EncryptionResult chachaEncryptFile(Map<String, dynamic> args) {
logger.info("Encrypting file of size " + sourceFileLength.toString());
final inputFile = sourceFile.openSync(mode: io.FileMode.read);
final key = Sodium.cryptoSecretstreamXchacha20poly1305Keygen();
final key = args["key"] ?? Sodium.cryptoSecretstreamXchacha20poly1305Keygen();
final initPushResult =
Sodium.cryptoSecretstreamXchacha20poly1305InitPush(key);
var bytesRead = 0;
@ -155,11 +155,13 @@ class CryptoUtil {
static Future<EncryptionResult> encryptFile(
String sourceFilePath,
String destinationFilePath,
) {
String destinationFilePath, {
Uint8List key,
}) {
final args = Map<String, dynamic>();
args["sourceFilePath"] = sourceFilePath;
args["destinationFilePath"] = destinationFilePath;
args["key"] = key;
return Computer().compute(chachaEncryptFile, param: args);
}

View file

@ -4,13 +4,13 @@ import 'dart:convert';
import 'dart:io' as io;
import 'package:connectivity/connectivity.dart';
import 'package:dio/dio.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:flutter_sodium/flutter_sodium.dart';
import 'package:logging/logging.dart';
import 'package:photos/core/configuration.dart';
import 'package:photos/core/constants.dart';
import 'package:photos/core/network.dart';
import 'package:photos/db/files_db.dart';
import 'package:photos/models/encryption_result.dart';
import 'package:photos/models/file.dart';
import 'package:photos/models/location.dart';
import 'package:photos/models/upload_url.dart';
@ -152,13 +152,26 @@ class FileUploader {
final encryptedThumbnailPath =
tempDirectory + file.generatedID.toString() + "_thumbnail.encrypted";
final sourceFile = (await (await file.getAsset()).originFile);
try {
var key;
var isAlreadyUploadedFile = file.uploadedFileID != null;
if (isAlreadyUploadedFile) {
key = decryptFileKey(file);
} else {
key = null;
}
if (io.File(encryptedFilePath).existsSync()) {
io.File(encryptedFilePath).deleteSync();
}
final encryptedFile = io.File(encryptedFilePath);
final fileAttributes =
await CryptoUtil.encryptFile(sourceFile.path, encryptedFilePath);
final fileAttributes = await CryptoUtil.encryptFile(
sourceFile.path,
encryptedFilePath,
key: key,
);
var thumbnailData = (await (await file.getAsset()).thumbDataWithSize(
THUMBNAIL_LARGE_SIZE,
@ -201,15 +214,6 @@ class FileUploader {
final encryptedMetadataData = CryptoUtil.encryptChaCha(
utf8.encode(jsonEncode(file.getMetadata())), fileAttributes.key);
final encryptedFileKeyData = CryptoUtil.encryptSync(
fileAttributes.key,
CollectionsService.instance.getCollectionKey(collectionID),
);
final encryptedKey =
Sodium.bin2base64(encryptedFileKeyData.encryptedData);
final keyDecryptionNonce = Sodium.bin2base64(encryptedFileKeyData.nonce);
final fileDecryptionHeader = Sodium.bin2base64(fileAttributes.header);
final thumbnailDecryptionHeader =
Sodium.bin2base64(encryptedThumbnailData.header);
@ -217,41 +221,29 @@ class FileUploader {
Sodium.bin2base64(encryptedMetadataData.encryptedData);
final metadataDecryptionHeader =
Sodium.bin2base64(encryptedMetadataData.header);
final request = {
"collectionID": collectionID,
"encryptedKey": encryptedKey,
"keyDecryptionNonce": keyDecryptionNonce,
"file": {
"objectKey": fileObjectKey,
"decryptionHeader": fileDecryptionHeader,
},
"thumbnail": {
"objectKey": thumbnailObjectKey,
"decryptionHeader": thumbnailDecryptionHeader,
},
"metadata": {
"encryptedData": encryptedMetadata,
"decryptionHeader": metadataDecryptionHeader,
}
};
final response = await _dio.post(
Configuration.instance.getHttpEndpoint() + "/files",
options: Options(
headers: {"X-Auth-Token": Configuration.instance.getToken()}),
data: request,
);
final data = response.data;
file.uploadedFileID = data["id"];
file.collectionID = collectionID;
file.updationTime = data["updationTime"];
file.ownerID = data["ownerID"];
file.encryptedKey = encryptedKey;
file.keyDecryptionNonce = keyDecryptionNonce;
file.fileDecryptionHeader = fileDecryptionHeader;
file.thumbnailDecryptionHeader = thumbnailDecryptionHeader;
file.metadataDecryptionHeader = metadataDecryptionHeader;
return file;
if (isAlreadyUploadedFile) {
return await _updateFile(
file,
fileObjectKey,
fileDecryptionHeader,
thumbnailObjectKey,
thumbnailDecryptionHeader,
encryptedMetadata,
metadataDecryptionHeader,
);
} else {
return await _uploadFile(
file,
collectionID,
fileAttributes,
fileObjectKey,
fileDecryptionHeader,
thumbnailObjectKey,
thumbnailDecryptionHeader,
encryptedMetadata,
metadataDecryptionHeader,
);
}
} catch (e, s) {
_logger.severe(
"File upload failed for " + file.generatedID.toString(), e, s);
@ -269,6 +261,99 @@ class FileUploader {
}
}
Future<File> _uploadFile(
File file,
int collectionID,
EncryptionResult fileAttributes,
String fileObjectKey,
String fileDecryptionHeader,
String thumbnailObjectKey,
String thumbnailDecryptionHeader,
String encryptedMetadata,
String metadataDecryptionHeader,
) async {
final encryptedFileKeyData = CryptoUtil.encryptSync(
fileAttributes.key,
CollectionsService.instance.getCollectionKey(collectionID),
);
final encryptedKey = Sodium.bin2base64(encryptedFileKeyData.encryptedData);
final keyDecryptionNonce = Sodium.bin2base64(encryptedFileKeyData.nonce);
final request = {
"collectionID": collectionID,
"encryptedKey": encryptedKey,
"keyDecryptionNonce": keyDecryptionNonce,
"file": {
"objectKey": fileObjectKey,
"decryptionHeader": fileDecryptionHeader,
},
"thumbnail": {
"objectKey": thumbnailObjectKey,
"decryptionHeader": thumbnailDecryptionHeader,
},
"metadata": {
"encryptedData": encryptedMetadata,
"decryptionHeader": metadataDecryptionHeader,
}
};
final response = await _dio.post(
Configuration.instance.getHttpEndpoint() + "/files",
options:
Options(headers: {"X-Auth-Token": Configuration.instance.getToken()}),
data: request,
);
final data = response.data;
file.uploadedFileID = data["id"];
file.collectionID = collectionID;
file.updationTime = data["updationTime"];
file.ownerID = data["ownerID"];
file.encryptedKey = encryptedKey;
file.keyDecryptionNonce = keyDecryptionNonce;
file.fileDecryptionHeader = fileDecryptionHeader;
file.thumbnailDecryptionHeader = thumbnailDecryptionHeader;
file.metadataDecryptionHeader = metadataDecryptionHeader;
return file;
}
Future<File> _updateFile(
File file,
String fileObjectKey,
String fileDecryptionHeader,
String thumbnailObjectKey,
String thumbnailDecryptionHeader,
String encryptedMetadata,
String metadataDecryptionHeader,
) async {
final request = {
"id": file.uploadedFileID,
"file": {
"objectKey": fileObjectKey,
"decryptionHeader": fileDecryptionHeader,
},
"thumbnail": {
"objectKey": thumbnailObjectKey,
"decryptionHeader": thumbnailDecryptionHeader,
},
"metadata": {
"encryptedData": encryptedMetadata,
"decryptionHeader": metadataDecryptionHeader,
}
};
final response = await _dio.post(
Configuration.instance.getHttpEndpoint() + "/files",
options:
Options(headers: {"X-Auth-Token": Configuration.instance.getToken()}),
data: request,
);
final data = response.data;
file.uploadedFileID = data["id"];
file.updationTime = data["updationTime"];
file.ownerID = data["ownerID"];
file.fileDecryptionHeader = fileDecryptionHeader;
file.thumbnailDecryptionHeader = thumbnailDecryptionHeader;
file.metadataDecryptionHeader = metadataDecryptionHeader;
return file;
}
Future<UploadURL> _getUploadURL() async {
if (_uploadURLs.isEmpty) {
await _fetchUploadURLs();