From 878699b02c958e485f505b277792e57da9f2419c Mon Sep 17 00:00:00 2001 From: Ming Ming Date: Sat, 16 Jul 2022 02:10:08 +0800 Subject: [PATCH] Fix account not deleted from db after signing out --- app/lib/entity/file/file_cache_manager.dart | 28 ++------------ app/lib/entity/sqlite_table_extension.dart | 42 +++++++++++++++++++++ app/lib/widget/account_picker_dialog.dart | 23 +++++++++++ 3 files changed, 68 insertions(+), 25 deletions(-) diff --git a/app/lib/entity/file/file_cache_manager.dart b/app/lib/entity/file/file_cache_manager.dart index 911f7bef..4a8cd784 100644 --- a/app/lib/entity/file/file_cache_manager.dart +++ b/app/lib/entity/file/file_cache_manager.dart @@ -157,7 +157,7 @@ class FileSqliteCacheUpdater { if (diff.item2.isNotEmpty) { // delete obsolete children await _removeSqliteFiles(db, dbAccount, diff.item2); - await _cleanUpRemovedFile(db, dbAccount); + await db.cleanUpDanglingFiles(); } }); } @@ -313,7 +313,7 @@ class FileSqliteCacheRemover { final dbAccount = await db.accountOf(account); final rowIds = await db.accountFileRowIdsOf(f, sqlAccount: dbAccount); await _removeSqliteFiles(db, dbAccount, [rowIds.fileRowId]); - await _cleanUpRemovedFile(db, dbAccount); + await db.cleanUpDanglingFiles(); }); } @@ -340,7 +340,7 @@ class FileSqliteCacheEmptier { childIds.removeWhere((id) => id == rowIds.fileRowId); if (childIds.isNotEmpty) { await _removeSqliteFiles(db, dbAccount, childIds); - await _cleanUpRemovedFile(db, dbAccount); + await db.cleanUpDanglingFiles(); } // remove dir in DirFiles @@ -380,25 +380,3 @@ Future _removeSqliteFiles( return; } } - -Future _cleanUpRemovedFile(sql.SqliteDb db, sql.Account dbAccount) async { - // delete dangling files: entries in Files w/o a corresponding entry in - // AccountFiles - final danglingFileQuery = db.selectOnly(db.files).join([ - sql.leftOuterJoin( - db.accountFiles, db.accountFiles.file.equalsExp(db.files.rowId), - useColumns: false), - ]) - ..addColumns([db.files.rowId]) - ..where(db.accountFiles.relativePath.isNull()); - final danglingFileRowIds = - await danglingFileQuery.map((r) => r.read(db.files.rowId)!).get(); - if (danglingFileRowIds.isNotEmpty) { - __log.info( - "[_cleanUpRemovedFile] Delete ${danglingFileRowIds.length} files"); - await (db.delete(db.files)..where((t) => t.rowId.isIn(danglingFileRowIds))) - .go(); - } -} - -final __log = Logger("entity.file.file_cache_manager"); diff --git a/app/lib/entity/sqlite_table_extension.dart b/app/lib/entity/sqlite_table_extension.dart index e72fb356..bd3ad456 100644 --- a/app/lib/entity/sqlite_table_extension.dart +++ b/app/lib/entity/sqlite_table_extension.dart @@ -1,4 +1,5 @@ import 'package:drift/drift.dart'; +import 'package:logging/logging.dart'; import 'package:nc_photos/account.dart' as app; import 'package:nc_photos/entity/file.dart' as app; import 'package:nc_photos/entity/sqlite_table.dart'; @@ -158,6 +159,45 @@ extension SqliteDbExtension on SqliteDb { return query.map((r) => r.readTable(accounts)).getSingle(); } + /// Delete Account by app Account + /// + /// If the deleted Account is the last one associated with a Server, then the + /// Server will also be deleted + Future deleteAccountOf(app.Account account) async { + final dbAccount = await accountOf(account); + _log.info("[deleteAccountOf] Remove account: ${dbAccount.rowId}"); + await (delete(accounts)..where((t) => t.rowId.equals(dbAccount.rowId))) + .go(); + final accountCountExp = + accounts.rowId.count(filter: accounts.server.equals(dbAccount.server)); + final accountCountQuery = selectOnly(accounts) + ..addColumns([accountCountExp]); + final accountCount = + await accountCountQuery.map((r) => r.read(accountCountExp)).getSingle(); + _log.info("[deleteAccountOf] Remaining accounts in server: $accountCount"); + if (accountCount == 0) { + _log.info("[deleteAccountOf] Remove server: ${dbAccount.server}"); + await (delete(servers)..where((t) => t.rowId.equals(dbAccount.server))) + .go(); + } + await cleanUpDanglingFiles(); + } + + /// Delete Files without a corresponding entry in AccountFiles + Future cleanUpDanglingFiles() async { + final query = selectOnly(files).join([ + leftOuterJoin(accountFiles, accountFiles.file.equalsExp(files.rowId), + useColumns: false), + ]) + ..addColumns([files.rowId]) + ..where(accountFiles.relativePath.isNull()); + final fileRowIds = await query.map((r) => r.read(files.rowId)!).get(); + if (fileRowIds.isNotEmpty) { + _log.info("[cleanUpDanglingFiles] Delete ${fileRowIds.length} files"); + await (delete(files)..where((t) => t.rowId.isIn(fileRowIds))).go(); + } + } + FilesQueryBuilder queryFiles() => FilesQueryBuilder(this); /// Query File by app File @@ -346,6 +386,8 @@ extension SqliteDbExtension on SqliteDb { )) .get(); } + + static final _log = Logger("entity.sqlite_table_extension.SqliteDbExtension"); } enum FilesQueryMode { diff --git a/app/lib/widget/account_picker_dialog.dart b/app/lib/widget/account_picker_dialog.dart index c7b36a12..2186791e 100644 --- a/app/lib/widget/account_picker_dialog.dart +++ b/app/lib/widget/account_picker_dialog.dart @@ -1,7 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:kiwi/kiwi.dart'; import 'package:logging/logging.dart'; import 'package:nc_photos/account.dart'; import 'package:nc_photos/app_localizations.dart'; +import 'package:nc_photos/di_container.dart'; +import 'package:nc_photos/entity/sqlite_table_extension.dart' as sql; import 'package:nc_photos/exception_util.dart' as exception_util; import 'package:nc_photos/k.dart' as k; import 'package:nc_photos/pref.dart'; @@ -154,6 +157,26 @@ class _AccountPickerDialogState extends State { Pref() ..setAccounts3(accounts) ..setCurrentAccountIndex(newAccountIndex); + + // check if the same account (server + userId) still exists in known + // accounts + if (!accounts + .any((a) => a.url == account.url && a.userId == account.userId)) { + // account removed, clear cache db + await _removeAccountFromDb(account); + } + } + + Future _removeAccountFromDb(Account account) async { + try { + final c = KiwiContainer().resolve(); + await c.sqliteDb.use((db) async { + await db.deleteAccountOf(account); + }); + } catch (e, stackTrace) { + _log.shout("[_removeAccountFromDb] Failed while removing account from db", + e, stackTrace); + } } late List _accounts;