Fix account not deleted from db after signing out

This commit is contained in:
Ming Ming 2022-07-16 02:10:08 +08:00
parent d85ed4102b
commit 878699b02c
3 changed files with 68 additions and 25 deletions

View file

@ -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<void> _removeSqliteFiles(
return;
}
}
Future<void> _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");

View file

@ -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<void> 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<void> 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 {

View file

@ -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<AccountPickerDialog> {
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<void> _removeAccountFromDb(Account account) async {
try {
final c = KiwiContainer().resolve<DiContainer>();
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<Account> _accounts;