Fix API to add a file to favorites

This commit is contained in:
Vishnu Mohandas 2020-10-22 03:52:09 +05:30
parent 9f88eb413d
commit 26f3e62c0e
4 changed files with 230 additions and 116 deletions

View file

@ -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]),
);
}

View file

@ -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,105 +17,10 @@ class Collection {
this.keyDecryptionNonce,
this.name,
this.type,
this.encryptedPath,
this.pathDecryptionNonce,
this.attributes,
this.creationTime,
);
Collection copyWith({
int id,
int ownerID,
String encryptedKey,
String keyDecryptionNonce,
String name,
CollectionType type,
String encryptedPath,
String pathDecryptionNonce,
int creationTime,
List<String> sharees,
}) {
return Collection(
id ?? this.id,
ownerID ?? this.ownerID,
encryptedKey ?? this.encryptedKey,
keyDecryptionNonce ?? this.keyDecryptionNonce,
name ?? this.name,
type ?? this.type,
encryptedPath ?? this.encryptedPath,
encryptedPath ?? this.pathDecryptionNonce,
creationTime ?? this.creationTime,
);
}
Map<String, dynamic> toMap() {
return {
'id': id,
'ownerID': ownerID,
'encryptedKey': encryptedKey,
'keyDecryptionNonce': keyDecryptionNonce,
'name': name,
'type': typeToString(type),
'creationTime': creationTime,
'encryptedPath': encryptedPath,
'pathDecryptionNonce': pathDecryptionNonce,
};
}
factory Collection.fromMap(Map<String, dynamic> map) {
if (map == null) return null;
return Collection(
map['id'],
map['ownerID'],
map['encryptedKey'],
map['keyDecryptionNonce'],
map['name'],
typeFromString(map['type']),
map['encryptedPath'],
map['pathDecryptionNonce'],
map['creationTime'],
);
}
String toJson() => json.encode(toMap());
factory Collection.fromJson(String source) =>
Collection.fromMap(json.decode(source));
@override
String toString() {
return 'Collection(id: $id, ownerID: $ownerID, encryptedKey: $encryptedKey, keyDecryptionNonce: $keyDecryptionNonce, name: $name, type: $type, encryptedPath: $encryptedPath, pathDecryptionNonce: $pathDecryptionNonce, creationTime: $creationTime)';
}
@override
bool operator ==(Object o) {
if (identical(this, o)) return true;
return o is Collection &&
o.id == id &&
o.ownerID == ownerID &&
o.encryptedKey == encryptedKey &&
o.keyDecryptionNonce == keyDecryptionNonce &&
o.name == name &&
o.type == type &&
o.encryptedPath == encryptedPath &&
o.pathDecryptionNonce == pathDecryptionNonce &&
o.creationTime == creationTime;
}
@override
int get hashCode {
return id.hashCode ^
ownerID.hashCode ^
encryptedKey.hashCode ^
keyDecryptionNonce.hashCode ^
name.hashCode ^
type.hashCode ^
encryptedPath.hashCode ^
pathDecryptionNonce.hashCode ^
creationTime.hashCode;
}
static CollectionType typeFromString(String type) {
switch (type) {
case "folder":
@ -137,6 +41,93 @@ class Collection {
return "album";
}
}
Collection copyWith({
int id,
int ownerID,
String encryptedKey,
String keyDecryptionNonce,
String name,
CollectionType type,
CollectionAttributes attributes,
int creationTime,
}) {
return Collection(
id ?? this.id,
ownerID ?? this.ownerID,
encryptedKey ?? this.encryptedKey,
keyDecryptionNonce ?? this.keyDecryptionNonce,
name ?? this.name,
type ?? this.type,
attributes ?? this.attributes,
creationTime ?? this.creationTime,
);
}
Map<String, dynamic> toMap() {
return {
'id': id,
'ownerID': ownerID,
'encryptedKey': encryptedKey,
'keyDecryptionNonce': keyDecryptionNonce,
'name': name,
'type': typeToString(type),
'attributes': attributes?.toMap(),
'creationTime': creationTime,
};
}
factory Collection.fromMap(Map<String, dynamic> map) {
if (map == null) return null;
return Collection(
map['id'],
map['ownerID'],
map['encryptedKey'],
map['keyDecryptionNonce'],
map['name'],
typeFromString(map['type']),
CollectionAttributes.fromMap(map['attributes']),
map['creationTime'],
);
}
String toJson() => json.encode(toMap());
factory Collection.fromJson(String source) =>
Collection.fromMap(json.decode(source));
@override
String toString() {
return 'Collection(id: $id, ownerID: $ownerID, encryptedKey: $encryptedKey, keyDecryptionNonce: $keyDecryptionNonce, name: $name, type: $type, attributes: $attributes, creationTime: $creationTime)';
}
@override
bool operator ==(Object o) {
if (identical(this, o)) return true;
return o is Collection &&
o.id == id &&
o.ownerID == ownerID &&
o.encryptedKey == encryptedKey &&
o.keyDecryptionNonce == keyDecryptionNonce &&
o.name == name &&
o.type == type &&
o.attributes == attributes &&
o.creationTime == creationTime;
}
@override
int get hashCode {
return id.hashCode ^
ownerID.hashCode ^
encryptedKey.hashCode ^
keyDecryptionNonce.hashCode ^
name.hashCode ^
type.hashCode ^
attributes.hashCode ^
creationTime.hashCode;
}
}
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;
}

View file

@ -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;
}

View file

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