Selaa lähdekoodia

Fix API to add a file to favorites

Vishnu Mohandas 4 vuotta sitten
vanhempi
commit
26f3e62c0e

+ 5 - 4
lib/db/collections_db.dart

@@ -148,8 +148,8 @@ class CollectionsDB {
     row[columnKeyDecryptionNonce] = collection.keyDecryptionNonce;
     row[columnName] = collection.name;
     row[columnType] = Collection.typeToString(collection.type);
-    row[columnEncryptedPath] = collection.encryptedPath;
-    row[columnPathDecryptionNonce] = collection.pathDecryptionNonce;
+    row[columnEncryptedPath] = collection.attributes.encryptedPath;
+    row[columnPathDecryptionNonce] = collection.attributes.pathDecryptionNonce;
     row[columnCreationTime] = collection.creationTime;
     return row;
   }
@@ -162,8 +162,9 @@ class CollectionsDB {
       row[columnKeyDecryptionNonce],
       row[columnName],
       Collection.typeFromString(row[columnType]),
-      row[columnEncryptedPath],
-      row[columnPathDecryptionNonce],
+      CollectionAttributes(
+          encryptedPath: row[columnEncryptedPath],
+          pathDecryptionNonce: row[columnPathDecryptionNonce]),
       int.parse(row[columnCreationTime]),
     );
   }

+ 91 - 39
lib/models/collection.dart

@@ -7,8 +7,7 @@ class Collection {
   final String keyDecryptionNonce;
   final String name;
   final CollectionType type;
-  final String encryptedPath;
-  final String pathDecryptionNonce;
+  final CollectionAttributes attributes;
   final int creationTime;
 
   Collection(
@@ -18,11 +17,31 @@ class Collection {
     this.keyDecryptionNonce,
     this.name,
     this.type,
-    this.encryptedPath,
-    this.pathDecryptionNonce,
+    this.attributes,
     this.creationTime,
   );
 
+  static CollectionType typeFromString(String type) {
+    switch (type) {
+      case "folder":
+        return CollectionType.folder;
+      case "favorites":
+        return CollectionType.favorites;
+    }
+    return CollectionType.album;
+  }
+
+  static String typeToString(CollectionType type) {
+    switch (type) {
+      case CollectionType.folder:
+        return "folder";
+      case CollectionType.favorites:
+        return "favorites";
+      default:
+        return "album";
+    }
+  }
+
   Collection copyWith({
     int id,
     int ownerID,
@@ -30,10 +49,8 @@ class Collection {
     String keyDecryptionNonce,
     String name,
     CollectionType type,
-    String encryptedPath,
-    String pathDecryptionNonce,
+    CollectionAttributes attributes,
     int creationTime,
-    List<String> sharees,
   }) {
     return Collection(
       id ?? this.id,
@@ -42,8 +59,7 @@ class Collection {
       keyDecryptionNonce ?? this.keyDecryptionNonce,
       name ?? this.name,
       type ?? this.type,
-      encryptedPath ?? this.encryptedPath,
-      encryptedPath ?? this.pathDecryptionNonce,
+      attributes ?? this.attributes,
       creationTime ?? this.creationTime,
     );
   }
@@ -56,9 +72,8 @@ class Collection {
       'keyDecryptionNonce': keyDecryptionNonce,
       'name': name,
       'type': typeToString(type),
+      'attributes': attributes?.toMap(),
       'creationTime': creationTime,
-      'encryptedPath': encryptedPath,
-      'pathDecryptionNonce': pathDecryptionNonce,
     };
   }
 
@@ -72,8 +87,7 @@ class Collection {
       map['keyDecryptionNonce'],
       map['name'],
       typeFromString(map['type']),
-      map['encryptedPath'],
-      map['pathDecryptionNonce'],
+      CollectionAttributes.fromMap(map['attributes']),
       map['creationTime'],
     );
   }
@@ -85,7 +99,7 @@ class Collection {
 
   @override
   String toString() {
-    return 'Collection(id: $id, ownerID: $ownerID, encryptedKey: $encryptedKey, keyDecryptionNonce: $keyDecryptionNonce, name: $name, type: $type, encryptedPath: $encryptedPath, pathDecryptionNonce: $pathDecryptionNonce, creationTime: $creationTime)';
+    return 'Collection(id: $id, ownerID: $ownerID, encryptedKey: $encryptedKey, keyDecryptionNonce: $keyDecryptionNonce, name: $name, type: $type, attributes: $attributes, creationTime: $creationTime)';
   }
 
   @override
@@ -99,8 +113,7 @@ class Collection {
         o.keyDecryptionNonce == keyDecryptionNonce &&
         o.name == name &&
         o.type == type &&
-        o.encryptedPath == encryptedPath &&
-        o.pathDecryptionNonce == pathDecryptionNonce &&
+        o.attributes == attributes &&
         o.creationTime == creationTime;
   }
 
@@ -112,31 +125,9 @@ class Collection {
         keyDecryptionNonce.hashCode ^
         name.hashCode ^
         type.hashCode ^
-        encryptedPath.hashCode ^
-        pathDecryptionNonce.hashCode ^
+        attributes.hashCode ^
         creationTime.hashCode;
   }
-
-  static CollectionType typeFromString(String type) {
-    switch (type) {
-      case "folder":
-        return CollectionType.folder;
-      case "favorites":
-        return CollectionType.favorites;
-    }
-    return CollectionType.album;
-  }
-
-  static String typeToString(CollectionType type) {
-    switch (type) {
-      case CollectionType.folder:
-        return "folder";
-      case CollectionType.favorites:
-        return "favorites";
-      default:
-        return "album";
-    }
-  }
 }
 
 enum CollectionType {
@@ -144,3 +135,64 @@ enum CollectionType {
   favorites,
   album,
 }
+
+class CollectionAttributes {
+  final String encryptedPath;
+  final String pathDecryptionNonce;
+
+  CollectionAttributes({
+    this.encryptedPath,
+    this.pathDecryptionNonce,
+  });
+
+  CollectionAttributes copyWith({
+    String encryptedPath,
+    String pathDecryptionNonce,
+  }) {
+    return CollectionAttributes(
+      encryptedPath: encryptedPath ?? this.encryptedPath,
+      pathDecryptionNonce: pathDecryptionNonce ?? this.pathDecryptionNonce,
+    );
+  }
+
+  Map<String, dynamic> toMap() {
+    final map = Map<String, dynamic>();
+    if (encryptedPath != null) {
+      map['encryptedPath'] = encryptedPath;
+    }
+    if (pathDecryptionNonce != null) {
+      map['pathDecryptionNonce'] = pathDecryptionNonce;
+    }
+    return map;
+  }
+
+  factory CollectionAttributes.fromMap(Map<String, dynamic> map) {
+    if (map == null) return null;
+
+    return CollectionAttributes(
+      encryptedPath: map['encryptedPath'],
+      pathDecryptionNonce: map['pathDecryptionNonce'],
+    );
+  }
+
+  String toJson() => json.encode(toMap());
+
+  factory CollectionAttributes.fromJson(String source) =>
+      CollectionAttributes.fromMap(json.decode(source));
+
+  @override
+  String toString() =>
+      'CollectionAttributes(encryptedPath: $encryptedPath, pathDecryptionNonce: $pathDecryptionNonce)';
+
+  @override
+  bool operator ==(Object o) {
+    if (identical(this, o)) return true;
+
+    return o is CollectionAttributes &&
+        o.encryptedPath == encryptedPath &&
+        o.pathDecryptionNonce == pathDecryptionNonce;
+  }
+
+  @override
+  int get hashCode => encryptedPath.hashCode ^ pathDecryptionNonce.hashCode;
+}

+ 74 - 12
lib/services/collections_service.dart

@@ -2,8 +2,10 @@ import 'dart:convert';
 import 'dart:typed_data';
 
 import 'package:dio/dio.dart';
+import 'package:flutter/foundation.dart';
 import 'package:flutter_sodium/flutter_sodium.dart';
 import 'package:logging/logging.dart';
+
 import 'package:photos/core/configuration.dart';
 import 'package:photos/db/collections_db.dart';
 import 'package:photos/models/collection.dart';
@@ -172,31 +174,33 @@ class CollectionsService {
       Sodium.bin2base64(encryptedKeyData.nonce),
       path,
       CollectionType.folder,
-      Sodium.bin2base64(encryptedPath.encryptedData),
-      Sodium.bin2base64(encryptedPath.nonce),
+      CollectionAttributes(
+          encryptedPath: Sodium.bin2base64(encryptedPath.encryptedData),
+          pathDecryptionNonce: Sodium.bin2base64(encryptedPath.nonce)),
       null,
     ));
     return collection;
   }
 
   Future<void> addToCollection(int collectionID, List<File> files) {
-    final items = List<CollectionFileItem>();
+    final params = Map<String, dynamic>();
+    params["collectionID"] = collectionID;
     for (final file in files) {
       final key = decryptFileKey(file);
       final encryptedKeyData =
           CryptoUtil.encryptSync(key, getCollectionKey(collectionID));
-      items.add(CollectionFileItem(
+      if (params["files"] == null) {
+        params["files"] = [];
+      }
+      params["files"].add(CollectionFileItem(
         file.uploadedFileID,
         Sodium.bin2base64(encryptedKeyData.encryptedData),
         Sodium.bin2base64(encryptedKeyData.nonce),
-      ));
+      ).toMap());
     }
     return Dio().post(
       Configuration.instance.getHttpEndpoint() + "/collections/add-files",
-      data: {
-        "id": collectionID,
-        "files": items,
-      },
+      data: params,
       options:
           Options(headers: {"X-Auth-Token": Configuration.instance.getToken()}),
     );
@@ -218,14 +222,72 @@ class CollectionsService {
   }
 
   void _cacheOwnedCollectionAttributes(Collection collection) {
-    if (collection.encryptedPath != null) {
+    if (collection.attributes.encryptedPath != null) {
       var path = utf8.decode(CryptoUtil.decryptSync(
-          Sodium.base642bin(collection.encryptedPath),
+          Sodium.base642bin(collection.attributes.encryptedPath),
           _config.getKey(),
-          Sodium.base642bin(collection.pathDecryptionNonce)));
+          Sodium.base642bin(collection.attributes.pathDecryptionNonce)));
       _localCollections[path] = collection;
     }
     _collectionIDToOwnedCollections[collection.id] = collection;
     getCollectionKey(collection.id);
   }
 }
+
+class AddFilesRequest {
+  final int collectionID;
+  final List<CollectionFileItem> files;
+
+  AddFilesRequest(
+    this.collectionID,
+    this.files,
+  );
+
+  AddFilesRequest copyWith({
+    int collectionID,
+    List<CollectionFileItem> files,
+  }) {
+    return AddFilesRequest(
+      collectionID ?? this.collectionID,
+      files ?? this.files,
+    );
+  }
+
+  Map<String, dynamic> toMap() {
+    return {
+      'collectionID': collectionID,
+      'files': files?.map((x) => x?.toMap())?.toList(),
+    };
+  }
+
+  factory AddFilesRequest.fromMap(Map<String, dynamic> map) {
+    if (map == null) return null;
+
+    return AddFilesRequest(
+      map['collectionID'],
+      List<CollectionFileItem>.from(
+          map['files']?.map((x) => CollectionFileItem.fromMap(x))),
+    );
+  }
+
+  String toJson() => json.encode(toMap());
+
+  factory AddFilesRequest.fromJson(String source) =>
+      AddFilesRequest.fromMap(json.decode(source));
+
+  @override
+  String toString() =>
+      'AddFilesRequest(collectionID: $collectionID, files: $files)';
+
+  @override
+  bool operator ==(Object o) {
+    if (identical(this, o)) return true;
+
+    return o is AddFilesRequest &&
+        o.collectionID == collectionID &&
+        listEquals(o.files, files);
+  }
+
+  @override
+  int get hashCode => collectionID.hashCode ^ files.hashCode;
+}

+ 1 - 2
lib/services/favorites_service.dart

@@ -84,8 +84,7 @@ class FavoritesService {
       Sodium.bin2base64(encryptedKeyData.nonce),
       "Favorites",
       CollectionType.favorites,
-      null,
-      null,
+      CollectionAttributes(),
       null,
     ));
     await _preferences.setInt(_favoritesCollectionIDKey, collection.id);