Fix files also shared in other albums being unshared

This commit is contained in:
Ming Ming 2021-11-27 17:21:57 +08:00
parent 1586193c83
commit 7c0c4db045
2 changed files with 69 additions and 10 deletions

View file

@ -28,14 +28,14 @@ class UnshareFileFromAlbum {
_log.info(
"[call] Unshare ${files.length} files from album '${album.name}' with ${unshareWith.length} users");
// list albums with shares identical to any element in [unshareWith]
final otherAlbums = (await ListAlbum(fileRepo, albumRepo)(account)
final otherAlbums = await ListAlbum(fileRepo, albumRepo)(account)
.where((event) => event is Album)
.cast<Album>()
.where((album) =>
!album.albumFile!.compareServerIdentity(album.albumFile!) &&
album.provider is AlbumStaticProvider &&
album.shares?.any((s) => unshareWith.contains(s.userId)) == true)
.toList());
.where((a) =>
!a.albumFile!.compareServerIdentity(album.albumFile!) &&
a.provider is AlbumStaticProvider &&
a.shares?.any((s) => unshareWith.contains(s.userId)) == true)
.toList();
// look for shares that are exclusive to this album
final exclusiveShares = <Share>[];
@ -49,10 +49,12 @@ class UnshareFileFromAlbum {
e, stackTrace);
}
}
_log.fine("[call] Pre-filter shares: $exclusiveShares");
for (final a in otherAlbums) {
// check if the album is shared with the same users
if (!a.shares!
.any((as) => exclusiveShares.any((s) => s.shareWith == as.userId))) {
final sharesOfInterest =
a.shares?.where((as) => unshareWith.contains(as.userId)).toList();
if (sharesOfInterest == null || sharesOfInterest.isEmpty) {
continue;
}
final albumFiles = AlbumStaticProvider.of(a)
@ -60,9 +62,12 @@ class UnshareFileFromAlbum {
.whereType<AlbumFileItem>()
.map((e) => e.file)
.toList();
exclusiveShares.removeWhere(
(s) => albumFiles.any((element) => element.fileId == s.itemSource));
// remove files shared as part of this other shared album
exclusiveShares.removeWhere((s) =>
sharesOfInterest.any((i) => i.userId == s.shareWith) &&
albumFiles.any((f) => f.fileId == s.itemSource));
}
_log.fine("[call] Post-filter shares: $exclusiveShares");
// unshare them
await _unshare(account, exclusiveShares, onUnshareFileFailed);

View file

@ -27,6 +27,8 @@ void main() {
test("file w/ shares managed by others",
_removeFromSharedAlbumOwnedWithOtherShare);
test("file w/ extra share", _removeFromSharedAlbumOwnedLeaveExtraShare);
test("file w/ share in other album",
_removeFromSharedAlbumOwnedFileInOtherAlbum);
});
group("shared album (not owned)", () {
test("file", _removeFromSharedAlbumNotOwned);
@ -396,6 +398,58 @@ Future<void> _removeFromSharedAlbumOwnedLeaveExtraShare() async {
);
}
/// Remove a file from a shared album (admin -> user1, user2) where the file is
/// also shared in other album (admin -> user1)
///
/// Expect: share (admin -> user2) for the file deleted;
/// share (admin -> user1) for the file unchanged
Future<void> _removeFromSharedAlbumOwnedFileInOtherAlbum() async {
final account = util.buildAccount();
final pref = Pref.scoped(PrefMemoryProvider({
"isLabEnableSharedAlbum": true,
}));
final files =
(util.FilesBuilder(initialFileId: 2)..addJpeg("admin/test1.jpg")).build();
final album1 = (util.AlbumBuilder()
..addFileItem(files[0])
..addShare("user1")
..addShare("user2"))
.build();
final album2 = (util.AlbumBuilder.ofId(albumId: 1)
..addFileItem(files[0])
..addShare("user1"))
.build();
final album1fileItems = util.AlbumBuilder.fileItemsOf(album1);
final album1File = album1.albumFile!;
final album2File = album2.albumFile!;
final appDb = MockAppDb();
await appDb.use((db) async {
final transaction = db.transaction(AppDb.fileDbStoreName, idbModeReadWrite);
final store = transaction.objectStore(AppDb.fileDbStoreName);
await store.put(AppDbFileDbEntry.fromFile(account, files[0]).toJson(),
AppDbFileDbEntry.toPrimaryKey(account, files[0]));
});
final albumRepo = MockAlbumMemoryRepo([album1, album2]);
final shareRepo = MockShareMemoryRepo([
util.buildShare(id: "0", file: album1File, shareWith: "user1"),
util.buildShare(id: "1", file: files[0], shareWith: "user1"),
util.buildShare(id: "2", file: files[0], shareWith: "user2"),
util.buildShare(id: "3", file: album2File, shareWith: "user1"),
]);
final fileRepo = MockFileMemoryRepo([album1File, album2File, ...files]);
await RemoveFromAlbum(albumRepo, shareRepo, fileRepo, appDb, pref)(account,
albumRepo.findAlbumByPath(album1File.path), [album1fileItems[0]]);
expect(
shareRepo.shares,
[
util.buildShare(id: "0", file: album1File, shareWith: "user1"),
util.buildShare(id: "1", file: files[0], shareWith: "user1"),
util.buildShare(id: "3", file: album2File, shareWith: "user1"),
],
);
}
/// Remove a file from a shared album (user1 -> admin, user2)
///
/// Expect: shares (admin -> user1, user2) for the file deleted