|
@@ -192,7 +192,9 @@ class CollectionsService {
|
|
|
|
|
|
Future<void> share(int collectionID, String email, String publicKey) async {
|
|
Future<void> share(int collectionID, String email, String publicKey) async {
|
|
final encryptedKey = CryptoUtil.sealSync(
|
|
final encryptedKey = CryptoUtil.sealSync(
|
|
- getCollectionKey(collectionID), Sodium.base642bin(publicKey),);
|
|
|
|
|
|
+ getCollectionKey(collectionID),
|
|
|
|
+ Sodium.base642bin(publicKey),
|
|
|
|
+ );
|
|
try {
|
|
try {
|
|
await _dio.post(
|
|
await _dio.post(
|
|
Configuration.instance.getHttpEndpoint() + "/collections/share",
|
|
Configuration.instance.getHttpEndpoint() + "/collections/share",
|
|
@@ -202,7 +204,8 @@ class CollectionsService {
|
|
"encryptedKey": Sodium.bin2base64(encryptedKey),
|
|
"encryptedKey": Sodium.bin2base64(encryptedKey),
|
|
},
|
|
},
|
|
options: Options(
|
|
options: Options(
|
|
- headers: {"X-Auth-Token": Configuration.instance.getToken()},),
|
|
|
|
|
|
+ headers: {"X-Auth-Token": Configuration.instance.getToken()},
|
|
|
|
+ ),
|
|
);
|
|
);
|
|
} on DioError catch (e) {
|
|
} on DioError catch (e) {
|
|
if (e.response.statusCode == 402) {
|
|
if (e.response.statusCode == 402) {
|
|
@@ -222,7 +225,8 @@ class CollectionsService {
|
|
"email": email,
|
|
"email": email,
|
|
},
|
|
},
|
|
options: Options(
|
|
options: Options(
|
|
- headers: {"X-Auth-Token": Configuration.instance.getToken()},),
|
|
|
|
|
|
+ headers: {"X-Auth-Token": Configuration.instance.getToken()},
|
|
|
|
+ ),
|
|
);
|
|
);
|
|
_collectionIDToCollections[collectionID]
|
|
_collectionIDToCollections[collectionID]
|
|
.sharees
|
|
.sharees
|
|
@@ -253,20 +257,26 @@ class CollectionsService {
|
|
Uint8List _getDecryptedKey(Collection collection) {
|
|
Uint8List _getDecryptedKey(Collection collection) {
|
|
final encryptedKey = Sodium.base642bin(collection.encryptedKey);
|
|
final encryptedKey = Sodium.base642bin(collection.encryptedKey);
|
|
if (collection.owner.id == _config.getUserID()) {
|
|
if (collection.owner.id == _config.getUserID()) {
|
|
- return CryptoUtil.decryptSync(encryptedKey, _config.getKey(),
|
|
|
|
- Sodium.base642bin(collection.keyDecryptionNonce),);
|
|
|
|
|
|
+ return CryptoUtil.decryptSync(
|
|
|
|
+ encryptedKey,
|
|
|
|
+ _config.getKey(),
|
|
|
|
+ Sodium.base642bin(collection.keyDecryptionNonce),
|
|
|
|
+ );
|
|
} else {
|
|
} else {
|
|
return CryptoUtil.openSealSync(
|
|
return CryptoUtil.openSealSync(
|
|
- encryptedKey,
|
|
|
|
- Sodium.base642bin(_config.getKeyAttributes().publicKey),
|
|
|
|
- _config.getSecretKey(),);
|
|
|
|
|
|
+ encryptedKey,
|
|
|
|
+ Sodium.base642bin(_config.getKeyAttributes().publicKey),
|
|
|
|
+ _config.getSecretKey(),
|
|
|
|
+ );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
Future<void> rename(Collection collection, String newName) async {
|
|
Future<void> rename(Collection collection, String newName) async {
|
|
try {
|
|
try {
|
|
final encryptedName = CryptoUtil.encryptSync(
|
|
final encryptedName = CryptoUtil.encryptSync(
|
|
- utf8.encode(newName), getCollectionKey(collection.id),);
|
|
|
|
|
|
+ utf8.encode(newName),
|
|
|
|
+ getCollectionKey(collection.id),
|
|
|
|
+ );
|
|
await _dio.post(
|
|
await _dio.post(
|
|
Configuration.instance.getHttpEndpoint() + "/collections/rename",
|
|
Configuration.instance.getHttpEndpoint() + "/collections/rename",
|
|
data: {
|
|
data: {
|
|
@@ -275,7 +285,8 @@ class CollectionsService {
|
|
"nameDecryptionNonce": Sodium.bin2base64(encryptedName.nonce)
|
|
"nameDecryptionNonce": Sodium.bin2base64(encryptedName.nonce)
|
|
},
|
|
},
|
|
options: Options(
|
|
options: Options(
|
|
- headers: {"X-Auth-Token": Configuration.instance.getToken()},),
|
|
|
|
|
|
+ headers: {"X-Auth-Token": Configuration.instance.getToken()},
|
|
|
|
+ ),
|
|
);
|
|
);
|
|
// trigger sync to fetch the latest name from server
|
|
// trigger sync to fetch the latest name from server
|
|
sync();
|
|
sync();
|
|
@@ -286,7 +297,9 @@ class CollectionsService {
|
|
}
|
|
}
|
|
|
|
|
|
Future<void> updateMagicMetadata(
|
|
Future<void> updateMagicMetadata(
|
|
- Collection collection, Map<String, dynamic> newMetadataUpdate,) async {
|
|
|
|
|
|
+ Collection collection,
|
|
|
|
+ Map<String, dynamic> newMetadataUpdate,
|
|
|
|
+ ) async {
|
|
final int ownerID = Configuration.instance.getUserID();
|
|
final int ownerID = Configuration.instance.getUserID();
|
|
try {
|
|
try {
|
|
if (collection.owner.id != ownerID) {
|
|
if (collection.owner.id != ownerID) {
|
|
@@ -307,7 +320,9 @@ class CollectionsService {
|
|
|
|
|
|
final key = getCollectionKey(collection.id);
|
|
final key = getCollectionKey(collection.id);
|
|
final encryptedMMd = await CryptoUtil.encryptChaCha(
|
|
final encryptedMMd = await CryptoUtil.encryptChaCha(
|
|
- utf8.encode(jsonEncode(jsonToUpdate)), key,);
|
|
|
|
|
|
+ utf8.encode(jsonEncode(jsonToUpdate)),
|
|
|
|
+ key,
|
|
|
|
+ );
|
|
// for required field, the json validator on golang doesn't treat 0 as valid
|
|
// for required field, the json validator on golang doesn't treat 0 as valid
|
|
// value. Instead of changing version to ptr, decided to start version with 1.
|
|
// value. Instead of changing version to ptr, decided to start version with 1.
|
|
int currentVersion = max(collection.mMdVersion, 1);
|
|
int currentVersion = max(collection.mMdVersion, 1);
|
|
@@ -325,7 +340,8 @@ class CollectionsService {
|
|
"/collections/magic-metadata",
|
|
"/collections/magic-metadata",
|
|
data: params,
|
|
data: params,
|
|
options: Options(
|
|
options: Options(
|
|
- headers: {"X-Auth-Token": Configuration.instance.getToken()},),
|
|
|
|
|
|
+ headers: {"X-Auth-Token": Configuration.instance.getToken()},
|
|
|
|
+ ),
|
|
);
|
|
);
|
|
collection.mMdVersion = currentVersion + 1;
|
|
collection.mMdVersion = currentVersion + 1;
|
|
_cacheCollectionAttributes(collection);
|
|
_cacheCollectionAttributes(collection);
|
|
@@ -351,7 +367,8 @@ class CollectionsService {
|
|
"collectionID": collection.id,
|
|
"collectionID": collection.id,
|
|
},
|
|
},
|
|
options: Options(
|
|
options: Options(
|
|
- headers: {"X-Auth-Token": Configuration.instance.getToken()},),
|
|
|
|
|
|
+ headers: {"X-Auth-Token": Configuration.instance.getToken()},
|
|
|
|
+ ),
|
|
);
|
|
);
|
|
collection.publicURLs?.add(PublicURL.fromMap(response.data["result"]));
|
|
collection.publicURLs?.add(PublicURL.fromMap(response.data["result"]));
|
|
await _db.insert(List.from([collection]));
|
|
await _db.insert(List.from([collection]));
|
|
@@ -369,14 +386,17 @@ class CollectionsService {
|
|
}
|
|
}
|
|
|
|
|
|
Future<void> updateShareUrl(
|
|
Future<void> updateShareUrl(
|
|
- Collection collection, Map<String, dynamic> prop,) async {
|
|
|
|
|
|
+ Collection collection,
|
|
|
|
+ Map<String, dynamic> prop,
|
|
|
|
+ ) async {
|
|
prop.putIfAbsent('collectionID', () => collection.id);
|
|
prop.putIfAbsent('collectionID', () => collection.id);
|
|
try {
|
|
try {
|
|
final response = await _dio.put(
|
|
final response = await _dio.put(
|
|
Configuration.instance.getHttpEndpoint() + "/collections/share-url",
|
|
Configuration.instance.getHttpEndpoint() + "/collections/share-url",
|
|
data: json.encode(prop),
|
|
data: json.encode(prop),
|
|
options: Options(
|
|
options: Options(
|
|
- headers: {"X-Auth-Token": Configuration.instance.getToken()},),
|
|
|
|
|
|
+ headers: {"X-Auth-Token": Configuration.instance.getToken()},
|
|
|
|
+ ),
|
|
);
|
|
);
|
|
// remove existing url information
|
|
// remove existing url information
|
|
collection.publicURLs?.clear();
|
|
collection.publicURLs?.clear();
|
|
@@ -426,7 +446,8 @@ class CollectionsService {
|
|
"source": AppLifecycleService.instance.isForeground ? "fg" : "bg",
|
|
"source": AppLifecycleService.instance.isForeground ? "fg" : "bg",
|
|
},
|
|
},
|
|
options: Options(
|
|
options: Options(
|
|
- headers: {"X-Auth-Token": Configuration.instance.getToken()},),
|
|
|
|
|
|
+ headers: {"X-Auth-Token": Configuration.instance.getToken()},
|
|
|
|
+ ),
|
|
);
|
|
);
|
|
final List<Collection> collections = [];
|
|
final List<Collection> collections = [];
|
|
if (response != null) {
|
|
if (response != null) {
|
|
@@ -436,13 +457,15 @@ class CollectionsService {
|
|
if (collectionData['magicMetadata'] != null) {
|
|
if (collectionData['magicMetadata'] != null) {
|
|
final decryptionKey = _getDecryptedKey(collection);
|
|
final decryptionKey = _getDecryptedKey(collection);
|
|
final utfEncodedMmd = await CryptoUtil.decryptChaCha(
|
|
final utfEncodedMmd = await CryptoUtil.decryptChaCha(
|
|
- Sodium.base642bin(collectionData['magicMetadata']['data']),
|
|
|
|
- decryptionKey,
|
|
|
|
- Sodium.base642bin(collectionData['magicMetadata']['header']),);
|
|
|
|
|
|
+ Sodium.base642bin(collectionData['magicMetadata']['data']),
|
|
|
|
+ decryptionKey,
|
|
|
|
+ Sodium.base642bin(collectionData['magicMetadata']['header']),
|
|
|
|
+ );
|
|
collection.mMdEncodedJson = utf8.decode(utfEncodedMmd);
|
|
collection.mMdEncodedJson = utf8.decode(utfEncodedMmd);
|
|
collection.mMdVersion = collectionData['magicMetadata']['version'];
|
|
collection.mMdVersion = collectionData['magicMetadata']['version'];
|
|
collection.magicMetadata = CollectionMagicMetadata.fromEncodedJson(
|
|
collection.magicMetadata = CollectionMagicMetadata.fromEncodedJson(
|
|
- collection.mMdEncodedJson,);
|
|
|
|
|
|
+ collection.mMdEncodedJson,
|
|
|
|
+ );
|
|
}
|
|
}
|
|
collections.add(collection);
|
|
collections.add(collection);
|
|
}
|
|
}
|
|
@@ -464,20 +487,22 @@ class CollectionsService {
|
|
final key = CryptoUtil.generateKey();
|
|
final key = CryptoUtil.generateKey();
|
|
final encryptedKeyData = CryptoUtil.encryptSync(key, _config.getKey());
|
|
final encryptedKeyData = CryptoUtil.encryptSync(key, _config.getKey());
|
|
final encryptedName = CryptoUtil.encryptSync(utf8.encode(albumName), key);
|
|
final encryptedName = CryptoUtil.encryptSync(utf8.encode(albumName), key);
|
|
- final collection = await createAndCacheCollection(Collection(
|
|
|
|
- null,
|
|
|
|
- null,
|
|
|
|
- Sodium.bin2base64(encryptedKeyData.encryptedData),
|
|
|
|
- Sodium.bin2base64(encryptedKeyData.nonce),
|
|
|
|
- null,
|
|
|
|
- Sodium.bin2base64(encryptedName.encryptedData),
|
|
|
|
- Sodium.bin2base64(encryptedName.nonce),
|
|
|
|
- CollectionType.album,
|
|
|
|
- CollectionAttributes(),
|
|
|
|
- null,
|
|
|
|
- null,
|
|
|
|
- null,
|
|
|
|
- ),);
|
|
|
|
|
|
+ final collection = await createAndCacheCollection(
|
|
|
|
+ Collection(
|
|
|
|
+ null,
|
|
|
|
+ null,
|
|
|
|
+ Sodium.bin2base64(encryptedKeyData.encryptedData),
|
|
|
|
+ Sodium.bin2base64(encryptedKeyData.nonce),
|
|
|
|
+ null,
|
|
|
|
+ Sodium.bin2base64(encryptedName.encryptedData),
|
|
|
|
+ Sodium.bin2base64(encryptedName.nonce),
|
|
|
|
+ CollectionType.album,
|
|
|
|
+ CollectionAttributes(),
|
|
|
|
+ null,
|
|
|
|
+ null,
|
|
|
|
+ null,
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
return collection;
|
|
return collection;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -487,7 +512,8 @@ class CollectionsService {
|
|
final response = await _dio.get(
|
|
final response = await _dio.get(
|
|
Configuration.instance.getHttpEndpoint() + "/collections/$collectionID",
|
|
Configuration.instance.getHttpEndpoint() + "/collections/$collectionID",
|
|
options: Options(
|
|
options: Options(
|
|
- headers: {"X-Auth-Token": Configuration.instance.getToken()},),
|
|
|
|
|
|
+ headers: {"X-Auth-Token": Configuration.instance.getToken()},
|
|
|
|
+ ),
|
|
);
|
|
);
|
|
assert(response != null && response.data != null);
|
|
assert(response != null && response.data != null);
|
|
final collectionData = response.data["collection"];
|
|
final collectionData = response.data["collection"];
|
|
@@ -495,9 +521,10 @@ class CollectionsService {
|
|
if (collectionData['magicMetadata'] != null) {
|
|
if (collectionData['magicMetadata'] != null) {
|
|
final decryptionKey = _getDecryptedKey(collection);
|
|
final decryptionKey = _getDecryptedKey(collection);
|
|
final utfEncodedMmd = await CryptoUtil.decryptChaCha(
|
|
final utfEncodedMmd = await CryptoUtil.decryptChaCha(
|
|
- Sodium.base642bin(collectionData['magicMetadata']['data']),
|
|
|
|
- decryptionKey,
|
|
|
|
- Sodium.base642bin(collectionData['magicMetadata']['header']),);
|
|
|
|
|
|
+ Sodium.base642bin(collectionData['magicMetadata']['data']),
|
|
|
|
+ decryptionKey,
|
|
|
|
+ Sodium.base642bin(collectionData['magicMetadata']['header']),
|
|
|
|
+ );
|
|
collection.mMdEncodedJson = utf8.decode(utfEncodedMmd);
|
|
collection.mMdEncodedJson = utf8.decode(utfEncodedMmd);
|
|
collection.mMdVersion = collectionData['magicMetadata']['version'];
|
|
collection.mMdVersion = collectionData['magicMetadata']['version'];
|
|
collection.magicMetadata =
|
|
collection.magicMetadata =
|
|
@@ -523,38 +550,43 @@ class CollectionsService {
|
|
final key = CryptoUtil.generateKey();
|
|
final key = CryptoUtil.generateKey();
|
|
final encryptedKeyData = CryptoUtil.encryptSync(key, _config.getKey());
|
|
final encryptedKeyData = CryptoUtil.encryptSync(key, _config.getKey());
|
|
final encryptedPath = CryptoUtil.encryptSync(utf8.encode(path), key);
|
|
final encryptedPath = CryptoUtil.encryptSync(utf8.encode(path), key);
|
|
- final collection = await createAndCacheCollection(Collection(
|
|
|
|
- null,
|
|
|
|
- null,
|
|
|
|
- Sodium.bin2base64(encryptedKeyData.encryptedData),
|
|
|
|
- Sodium.bin2base64(encryptedKeyData.nonce),
|
|
|
|
- null,
|
|
|
|
- Sodium.bin2base64(encryptedPath.encryptedData),
|
|
|
|
- Sodium.bin2base64(encryptedPath.nonce),
|
|
|
|
- CollectionType.folder,
|
|
|
|
- CollectionAttributes(
|
|
|
|
- encryptedPath: Sodium.bin2base64(encryptedPath.encryptedData),
|
|
|
|
- pathDecryptionNonce: Sodium.bin2base64(encryptedPath.nonce),
|
|
|
|
- version: 1,
|
|
|
|
|
|
+ final collection = await createAndCacheCollection(
|
|
|
|
+ Collection(
|
|
|
|
+ null,
|
|
|
|
+ null,
|
|
|
|
+ Sodium.bin2base64(encryptedKeyData.encryptedData),
|
|
|
|
+ Sodium.bin2base64(encryptedKeyData.nonce),
|
|
|
|
+ null,
|
|
|
|
+ Sodium.bin2base64(encryptedPath.encryptedData),
|
|
|
|
+ Sodium.bin2base64(encryptedPath.nonce),
|
|
|
|
+ CollectionType.folder,
|
|
|
|
+ CollectionAttributes(
|
|
|
|
+ encryptedPath: Sodium.bin2base64(encryptedPath.encryptedData),
|
|
|
|
+ pathDecryptionNonce: Sodium.bin2base64(encryptedPath.nonce),
|
|
|
|
+ version: 1,
|
|
|
|
+ ),
|
|
|
|
+ null,
|
|
|
|
+ null,
|
|
|
|
+ null,
|
|
),
|
|
),
|
|
- null,
|
|
|
|
- null,
|
|
|
|
- null,
|
|
|
|
- ),);
|
|
|
|
|
|
+ );
|
|
return collection;
|
|
return collection;
|
|
}
|
|
}
|
|
|
|
|
|
Future<void> addToCollection(int collectionID, List<File> files) async {
|
|
Future<void> addToCollection(int collectionID, List<File> files) async {
|
|
final containsUploadedFile = files.firstWhere(
|
|
final containsUploadedFile = files.firstWhere(
|
|
- (element) => element.uploadedFileID != null,
|
|
|
|
- orElse: () => null,) !=
|
|
|
|
|
|
+ (element) => element.uploadedFileID != null,
|
|
|
|
+ orElse: () => null,
|
|
|
|
+ ) !=
|
|
null;
|
|
null;
|
|
if (containsUploadedFile) {
|
|
if (containsUploadedFile) {
|
|
final existingFileIDsInCollection =
|
|
final existingFileIDsInCollection =
|
|
await FilesDB.instance.getUploadedFileIDs(collectionID);
|
|
await FilesDB.instance.getUploadedFileIDs(collectionID);
|
|
- files.removeWhere((element) =>
|
|
|
|
- element.uploadedFileID != null &&
|
|
|
|
- existingFileIDsInCollection.contains(element.uploadedFileID),);
|
|
|
|
|
|
+ files.removeWhere(
|
|
|
|
+ (element) =>
|
|
|
|
+ element.uploadedFileID != null &&
|
|
|
|
+ existingFileIDsInCollection.contains(element.uploadedFileID),
|
|
|
|
+ );
|
|
}
|
|
}
|
|
if (files.isEmpty || !containsUploadedFile) {
|
|
if (files.isEmpty || !containsUploadedFile) {
|
|
_logger.info("nothing to add to the collection");
|
|
_logger.info("nothing to add to the collection");
|
|
@@ -574,9 +606,13 @@ class CollectionsService {
|
|
if (params["files"] == null) {
|
|
if (params["files"] == null) {
|
|
params["files"] = [];
|
|
params["files"] = [];
|
|
}
|
|
}
|
|
- params["files"].add(CollectionFileItem(
|
|
|
|
- file.uploadedFileID, file.encryptedKey, file.keyDecryptionNonce,)
|
|
|
|
- .toMap(),);
|
|
|
|
|
|
+ params["files"].add(
|
|
|
|
+ CollectionFileItem(
|
|
|
|
+ file.uploadedFileID,
|
|
|
|
+ file.encryptedKey,
|
|
|
|
+ file.keyDecryptionNonce,
|
|
|
|
+ ).toMap(),
|
|
|
|
+ );
|
|
}
|
|
}
|
|
|
|
|
|
try {
|
|
try {
|
|
@@ -584,7 +620,8 @@ class CollectionsService {
|
|
Configuration.instance.getHttpEndpoint() + "/collections/add-files",
|
|
Configuration.instance.getHttpEndpoint() + "/collections/add-files",
|
|
data: params,
|
|
data: params,
|
|
options: Options(
|
|
options: Options(
|
|
- headers: {"X-Auth-Token": Configuration.instance.getToken()},),
|
|
|
|
|
|
+ headers: {"X-Auth-Token": Configuration.instance.getToken()},
|
|
|
|
+ ),
|
|
);
|
|
);
|
|
await _filesDB.insertMultiple(files);
|
|
await _filesDB.insertMultiple(files);
|
|
Bus.instance.fire(CollectionUpdatedEvent(collectionID, files));
|
|
Bus.instance.fire(CollectionUpdatedEvent(collectionID, files));
|
|
@@ -605,16 +642,21 @@ class CollectionsService {
|
|
final encryptedKeyData = CryptoUtil.encryptSync(key, toCollectionKey);
|
|
final encryptedKeyData = CryptoUtil.encryptSync(key, toCollectionKey);
|
|
file.encryptedKey = Sodium.bin2base64(encryptedKeyData.encryptedData);
|
|
file.encryptedKey = Sodium.bin2base64(encryptedKeyData.encryptedData);
|
|
file.keyDecryptionNonce = Sodium.bin2base64(encryptedKeyData.nonce);
|
|
file.keyDecryptionNonce = Sodium.bin2base64(encryptedKeyData.nonce);
|
|
- params["files"].add(CollectionFileItem(
|
|
|
|
- file.uploadedFileID, file.encryptedKey, file.keyDecryptionNonce,)
|
|
|
|
- .toMap(),);
|
|
|
|
|
|
+ params["files"].add(
|
|
|
|
+ CollectionFileItem(
|
|
|
|
+ file.uploadedFileID,
|
|
|
|
+ file.encryptedKey,
|
|
|
|
+ file.keyDecryptionNonce,
|
|
|
|
+ ).toMap(),
|
|
|
|
+ );
|
|
}
|
|
}
|
|
try {
|
|
try {
|
|
await _dio.post(
|
|
await _dio.post(
|
|
Configuration.instance.getHttpEndpoint() + "/collections/restore-files",
|
|
Configuration.instance.getHttpEndpoint() + "/collections/restore-files",
|
|
data: params,
|
|
data: params,
|
|
options: Options(
|
|
options: Options(
|
|
- headers: {"X-Auth-Token": Configuration.instance.getToken()},),
|
|
|
|
|
|
+ headers: {"X-Auth-Token": Configuration.instance.getToken()},
|
|
|
|
+ ),
|
|
);
|
|
);
|
|
await _filesDB.insertMultiple(files);
|
|
await _filesDB.insertMultiple(files);
|
|
await TrashDB.instance
|
|
await TrashDB.instance
|
|
@@ -641,7 +683,10 @@ class CollectionsService {
|
|
}
|
|
}
|
|
|
|
|
|
Future<void> move(
|
|
Future<void> move(
|
|
- int toCollectionID, int fromCollectionID, List<File> files,) async {
|
|
|
|
|
|
+ int toCollectionID,
|
|
|
|
+ int fromCollectionID,
|
|
|
|
+ List<File> files,
|
|
|
|
+ ) async {
|
|
_validateMoveRequest(toCollectionID, fromCollectionID, files);
|
|
_validateMoveRequest(toCollectionID, fromCollectionID, files);
|
|
files.removeWhere((element) => element.uploadedFileID == null);
|
|
files.removeWhere((element) => element.uploadedFileID == null);
|
|
if (files.isEmpty) {
|
|
if (files.isEmpty) {
|
|
@@ -660,9 +705,13 @@ class CollectionsService {
|
|
CryptoUtil.encryptSync(fileKey, getCollectionKey(toCollectionID));
|
|
CryptoUtil.encryptSync(fileKey, getCollectionKey(toCollectionID));
|
|
file.encryptedKey = Sodium.bin2base64(encryptedKeyData.encryptedData);
|
|
file.encryptedKey = Sodium.bin2base64(encryptedKeyData.encryptedData);
|
|
file.keyDecryptionNonce = Sodium.bin2base64(encryptedKeyData.nonce);
|
|
file.keyDecryptionNonce = Sodium.bin2base64(encryptedKeyData.nonce);
|
|
- params["files"].add(CollectionFileItem(
|
|
|
|
- file.uploadedFileID, file.encryptedKey, file.keyDecryptionNonce,)
|
|
|
|
- .toMap(),);
|
|
|
|
|
|
+ params["files"].add(
|
|
|
|
+ CollectionFileItem(
|
|
|
|
+ file.uploadedFileID,
|
|
|
|
+ file.encryptedKey,
|
|
|
|
+ file.keyDecryptionNonce,
|
|
|
|
+ ).toMap(),
|
|
|
|
+ );
|
|
}
|
|
}
|
|
await _dio.post(
|
|
await _dio.post(
|
|
Configuration.instance.getHttpEndpoint() + "/collections/move-files",
|
|
Configuration.instance.getHttpEndpoint() + "/collections/move-files",
|
|
@@ -673,20 +722,31 @@ class CollectionsService {
|
|
|
|
|
|
// remove files from old collection
|
|
// remove files from old collection
|
|
await _filesDB.removeFromCollection(
|
|
await _filesDB.removeFromCollection(
|
|
- fromCollectionID, files.map((e) => e.uploadedFileID).toList(),);
|
|
|
|
- Bus.instance.fire(CollectionUpdatedEvent(fromCollectionID, files,
|
|
|
|
- type: EventType.deletedFromRemote,),);
|
|
|
|
|
|
+ fromCollectionID,
|
|
|
|
+ files.map((e) => e.uploadedFileID).toList(),
|
|
|
|
+ );
|
|
|
|
+ Bus.instance.fire(
|
|
|
|
+ CollectionUpdatedEvent(
|
|
|
|
+ fromCollectionID,
|
|
|
|
+ files,
|
|
|
|
+ type: EventType.deletedFromRemote,
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
// insert new files in the toCollection which are not part of the toCollection
|
|
// insert new files in the toCollection which are not part of the toCollection
|
|
final existingUploadedIDs =
|
|
final existingUploadedIDs =
|
|
await FilesDB.instance.getUploadedFileIDs(toCollectionID);
|
|
await FilesDB.instance.getUploadedFileIDs(toCollectionID);
|
|
files.removeWhere(
|
|
files.removeWhere(
|
|
- (element) => existingUploadedIDs.contains(element.uploadedFileID),);
|
|
|
|
|
|
+ (element) => existingUploadedIDs.contains(element.uploadedFileID),
|
|
|
|
+ );
|
|
await _filesDB.insertMultiple(files);
|
|
await _filesDB.insertMultiple(files);
|
|
Bus.instance.fire(CollectionUpdatedEvent(toCollectionID, files));
|
|
Bus.instance.fire(CollectionUpdatedEvent(toCollectionID, files));
|
|
}
|
|
}
|
|
|
|
|
|
void _validateMoveRequest(
|
|
void _validateMoveRequest(
|
|
- int toCollectionID, int fromCollectionID, List<File> files,) {
|
|
|
|
|
|
+ int toCollectionID,
|
|
|
|
+ int fromCollectionID,
|
|
|
|
+ List<File> files,
|
|
|
|
+ ) {
|
|
if (toCollectionID == fromCollectionID) {
|
|
if (toCollectionID == fromCollectionID) {
|
|
throw AssertionError("can't move to same album");
|
|
throw AssertionError("can't move to same album");
|
|
}
|
|
}
|
|
@@ -754,10 +814,13 @@ class CollectionsService {
|
|
final key = collection.attributes.version == 1
|
|
final key = collection.attributes.version == 1
|
|
? _getDecryptedKey(collection)
|
|
? _getDecryptedKey(collection)
|
|
: _config.getKey();
|
|
: _config.getKey();
|
|
- return utf8.decode(CryptoUtil.decryptSync(
|
|
|
|
|
|
+ return utf8.decode(
|
|
|
|
+ CryptoUtil.decryptSync(
|
|
Sodium.base642bin(collection.attributes.encryptedPath),
|
|
Sodium.base642bin(collection.attributes.encryptedPath),
|
|
key,
|
|
key,
|
|
- Sodium.base642bin(collection.attributes.pathDecryptionNonce),),);
|
|
|
|
|
|
+ Sodium.base642bin(collection.attributes.pathDecryptionNonce),
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
}
|
|
}
|
|
|
|
|
|
bool hasSyncedCollections() {
|
|
bool hasSyncedCollections() {
|
|
@@ -770,13 +833,17 @@ class CollectionsService {
|
|
String name;
|
|
String name;
|
|
try {
|
|
try {
|
|
final result = CryptoUtil.decryptSync(
|
|
final result = CryptoUtil.decryptSync(
|
|
- Sodium.base642bin(collection.encryptedName),
|
|
|
|
- _getDecryptedKey(collection),
|
|
|
|
- Sodium.base642bin(collection.nameDecryptionNonce),);
|
|
|
|
|
|
+ Sodium.base642bin(collection.encryptedName),
|
|
|
|
+ _getDecryptedKey(collection),
|
|
|
|
+ Sodium.base642bin(collection.nameDecryptionNonce),
|
|
|
|
+ );
|
|
name = utf8.decode(result);
|
|
name = utf8.decode(result);
|
|
} catch (e, s) {
|
|
} catch (e, s) {
|
|
_logger.severe(
|
|
_logger.severe(
|
|
- "failed to decrypt collection name: ${collection.id}", e, s,);
|
|
|
|
|
|
+ "failed to decrypt collection name: ${collection.id}",
|
|
|
|
+ e,
|
|
|
|
+ s,
|
|
|
|
+ );
|
|
name = "Unknown Album";
|
|
name = "Unknown Album";
|
|
}
|
|
}
|
|
return collection.copyWith(name: name);
|
|
return collection.copyWith(name: name);
|
|
@@ -830,7 +897,8 @@ class AddFilesRequest {
|
|
return AddFilesRequest(
|
|
return AddFilesRequest(
|
|
map['collectionID'],
|
|
map['collectionID'],
|
|
List<CollectionFileItem>.from(
|
|
List<CollectionFileItem>.from(
|
|
- map['files']?.map((x) => CollectionFileItem.fromMap(x)),),
|
|
|
|
|
|
+ map['files']?.map((x) => CollectionFileItem.fromMap(x)),
|
|
|
|
+ ),
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
|