Skip to content

Commit

Permalink
feat(account_repository): Allow registering callback to be executed b…
Browse files Browse the repository at this point in the history
…efore an account is logged out

Signed-off-by: provokateurin <kate@provokateurin.de>
  • Loading branch information
provokateurin committed Nov 20, 2024
1 parent 89f0cde commit 3a7c457
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import 'package:rxdart/rxdart.dart';

part 'account_storage.dart';

/// Signature of a callback that executed right before the [account] is logged out.
typedef BeforeLogOutCallback = Future<void> Function(Account account);

/// {@template account_failure}
/// A base failure for the account repository failures.
/// {@endtemplate}
Expand Down Expand Up @@ -86,6 +89,7 @@ class AccountRepository {
final String _userAgent;
final http.Client _httpClient;
final AccountStorage _storage;
final List<BeforeLogOutCallback> _beforeLogOutCallbacks = [];

final BehaviorSubject<({String? active, BuiltMap<String, Account> accounts})> _accounts =
BehaviorSubject.seeded((active: null, accounts: BuiltMap()));
Expand Down Expand Up @@ -272,6 +276,18 @@ class AccountRepository {
]);
}

/// Registers a new [callback] that is executed right before an account is logged out.
///
/// The callback must not throw any exceptions and handle them gracefully itself.
void registerBeforeLogOutCallback(BeforeLogOutCallback callback) {
_beforeLogOutCallbacks.add(callback);
}

/// Unregisters a [callback] that was previously registered with [registerBeforeLogOutCallback].
void unregisterBeforeLogOutCallback(BeforeLogOutCallback callback) {
_beforeLogOutCallbacks.remove(callback);
}

/// Logs out the user from the server.
///
/// May throw a [DeleteCredentialsFailure].
Expand Down Expand Up @@ -299,8 +315,12 @@ class AccountRepository {

_accounts.add((active: active, accounts: accounts));

for (final callback in _beforeLogOutCallbacks) {
await callback(account!);
}

try {
await account?.client.authentication.appPassword.deleteAppPassword();
await account!.client.authentication.appPassword.deleteAppPassword();
} on http.ClientException catch (error, stackTrace) {
Error.throwWithStackTrace(DeleteCredentialsFailure(error), stackTrace);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ class _UsersClientMock extends Mock implements provisioning_api.$UsersClient {}

class _AccountStorageMock extends Mock implements AccountStorage {}

class _FakeAccount extends Fake implements Account {}

class _BeforeLogOutCallbackMock extends Mock {
Future<void> call(Account account);
}

typedef _AccountStream = ({BuiltList<Account> accounts, Account? active});

void main() {
Expand All @@ -54,6 +60,7 @@ void main() {
setUpAll(() {
registerFallbackValue(_FakeUri());
registerFallbackValue(_FakePollRequest());
registerFallbackValue(_FakeAccount());
MockNeonStorage();
});

Expand Down Expand Up @@ -506,6 +513,20 @@ void main() {
when(() => appPassword.deleteAppPassword()).thenAnswer(
(_) async => _DynamiteResponseMock<core.AppPasswordDeleteAppPasswordResponseApplicationJson, void>(),
);

final callback1 = _BeforeLogOutCallbackMock();
when(() => callback1.call(any())).thenAnswer((_) async {});
repository.registerBeforeLogOutCallback(callback1.call);

final callback2 = _BeforeLogOutCallbackMock();
repository
..registerBeforeLogOutCallback(callback2.call)
..unregisterBeforeLogOutCallback(callback2.call);

final callback3 = _BeforeLogOutCallbackMock();
when(() => callback3.call(any())).thenAnswer((_) async {});
repository.registerBeforeLogOutCallback(callback3.call);

await repository.logOut(credentialsList.first.id);

await expectLater(
Expand All @@ -517,6 +538,10 @@ void main() {
),
);

verify(() => callback1(accountsList.first)).called(1);
verifyNever(() => callback2(accountsList.first));
verify(() => callback3(accountsList.first)).called(1);

verify(() => appPassword.deleteAppPassword()).called(1);
verify(() => storage.saveLastAccount(credentialsList[1].id)).called(1);
verify(() => storage.saveCredentials(any(that: equals([credentialsList[1]])))).called(1);
Expand Down

0 comments on commit 3a7c457

Please sign in to comment.