Add support for updating/saving sharee json

This commit is contained in:
Neeraj Gupta 2023-05-29 18:39:41 +05:30
parent d7afc65769
commit 392d39b5f2
3 changed files with 111 additions and 0 deletions

View file

@ -33,6 +33,10 @@ class CollectionsDB {
static const columnPubMMdEncodedJson = 'pub_mmd_encoded_json';
static const columnPubMMdVersion = 'pub_mmd_ver';
static const columnSharedMMdJson = 'shared_mmd_json';
static const columnSharedMMdVersion = 'shared_mmd_ver';
static const columnUpdationTime = 'updation_time';
static const columnIsDeleted = 'is_deleted';
@ -45,6 +49,7 @@ class CollectionsDB {
...addPublicURLs(),
...addPrivateMetadata(),
...addPublicMetadata(),
...addShareeMetadata(),
];
final dbConfig = MigrationConfig(
@ -172,6 +177,18 @@ class CollectionsDB {
];
}
static List<String> addShareeMetadata() {
return [
'''
ALTER TABLE $table ADD COLUMN $columnSharedMMdJson TEXT DEFAULT '
{}';
''',
'''
ALTER TABLE $table ADD COLUMN $columnSharedMMdVersion INTEGER DEFAULT 0;
'''
];
}
Future<void> insert(List<Collection> collections) async {
final db = await instance.database;
var batch = db.batch();
@ -256,6 +273,9 @@ class CollectionsDB {
row[columnMMdEncodedJson] = collection.mMdEncodedJson ?? '{}';
row[columnPubMMdVersion] = collection.mMbPubVersion;
row[columnPubMMdEncodedJson] = collection.mMdPubEncodedJson ?? '{}';
row[columnSharedMMdVersion] = collection.sharedMmdVersion;
row[columnSharedMMdJson] = collection.sharedMmdJson ?? '{}';
return row;
}
@ -291,6 +311,9 @@ class CollectionsDB {
result.mMdEncodedJson = row[columnMMdEncodedJson] ?? '{}';
result.mMbPubVersion = row[columnPubMMdVersion] ?? 0;
result.mMdPubEncodedJson = row[columnPubMMdEncodedJson] ?? '{}';
result.sharedMmdVersion = row[columnSharedMMdVersion] ?? 0;
result.sharedMmdJson = row[columnSharedMMdJson] ?? '{}';
return result;
}
}

View file

@ -23,10 +23,13 @@ class Collection {
final bool isDeleted;
String? mMdEncodedJson;
String? mMdPubEncodedJson;
String? sharedMmdJson;
int mMdVersion = 0;
int mMbPubVersion = 0;
int sharedMmdVersion = 0;
CollectionMagicMetadata? _mmd;
CollectionPubMagicMetadata? _pubMmd;
ShareeMagicMetadata? _sharedMmd;
CollectionMagicMetadata get magicMetadata =>
_mmd ?? CollectionMagicMetadata.fromEncodedJson(mMdEncodedJson ?? '{}');
@ -35,10 +38,15 @@ class Collection {
_pubMmd ??
CollectionPubMagicMetadata.fromEncodedJson(mMdPubEncodedJson ?? '{}');
ShareeMagicMetadata get sharedMagicMetadata =>
_sharedMmd ?? ShareeMagicMetadata.fromEncodedJson(sharedMmdJson ?? '{}');
set magicMetadata(CollectionMagicMetadata? val) => _mmd = val;
set pubMagicMetadata(CollectionPubMagicMetadata? val) => _pubMmd = val;
set sharedMagicMetadata(ShareeMagicMetadata? val) => _sharedMmd = val;
Collection(
this.id,
this.owner,
@ -173,6 +181,8 @@ class Collection {
result.mMdEncodedJson = mMdEncodedJson ?? this.mMdEncodedJson;
result.mMbPubVersion = mMbPubVersion;
result.mMdPubEncodedJson = mMdPubEncodedJson;
result.sharedMmdVersion = sharedMmdVersion;
result.sharedMmdJson = sharedMmdJson;
return result;
}

View file

@ -669,6 +669,66 @@ class CollectionsService {
}
}
Future<void> updateShareeMagicMetadata(
Collection collection,
Map<String, dynamic> newMetadataUpdate,
) async {
final int ownerID = Configuration.instance.getUserID()!;
try {
if (collection.owner?.id == ownerID) {
throw AssertionError("cannot modify sharee settings for albums owned "
"by you");
}
// read the existing magic metadata and apply new updates to existing data
// current update is simple replace. This will be enhanced in the future,
// as required.
final Map<String, dynamic> jsonToUpdate =
jsonDecode(collection.sharedMmdJson ?? '{}');
newMetadataUpdate.forEach((key, value) {
jsonToUpdate[key] = value;
});
final key = getCollectionKey(collection.id);
final encryptedMMd = await CryptoUtil.encryptChaCha(
utf8.encode(jsonEncode(jsonToUpdate)) as Uint8List,
key,
);
// 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.
final int currentVersion = max(collection.sharedMmdVersion, 1);
final params = UpdateMagicMetadataRequest(
id: collection.id,
magicMetadata: MetadataRequest(
version: currentVersion,
count: jsonToUpdate.length,
data: CryptoUtil.bin2base64(encryptedMMd.encryptedData!),
header: CryptoUtil.bin2base64(encryptedMMd.header!),
),
);
await _enteDio.put(
"/collections/public-magic-metadata",
data: params,
);
// update the local information so that it's reflected on UI
collection.sharedMmdJson = jsonEncode(jsonToUpdate);
collection.sharedMagicMetadata =
ShareeMagicMetadata.fromJson(jsonToUpdate);
collection.sharedMmdVersion = currentVersion + 1;
_cacheCollectionAttributes(collection);
// trigger sync to fetch the latest collection state from server
sync().ignore();
} on DioError catch (e) {
if (e.response != null && e.response?.statusCode == 409) {
_logger.severe('collection magic data out of sync');
sync().ignore();
}
rethrow;
} catch (e, s) {
_logger.severe("failed to sync magic metadata", e, s);
rethrow;
}
}
Future<void> createShareUrl(
Collection collection, {
bool enableCollect = false,
@ -792,6 +852,24 @@ class CollectionsService {
collection.mMdPubEncodedJson ?? '{}',
);
}
if (collectionData['sharedMagicMetadata'] != null) {
final utfEncodedMmd = await CryptoUtil.decryptChaCha(
CryptoUtil.base642bin(
collectionData['sharedMagicMetadata']['data'],
),
collectionKey,
CryptoUtil.base642bin(
collectionData['sharedMagicMetadata']['header'],
),
);
collection.sharedMmdJson = utf8.decode(utfEncodedMmd);
collection.sharedMmdVersion =
collectionData['sharedMagicMetadata']['version'];
collection.sharedMagicMetadata =
ShareeMagicMetadata.fromEncodedJson(
collection.sharedMmdJson ?? '{}',
);
}
}
collections.add(collection);
}