Merge pull request #1720 from famedly/krille/allow-init-on-soft-logout

refactor: Allow calling init when in soft logout state
This commit is contained in:
Krille-chan 2024-03-08 11:03:49 +01:00 committed by GitHub
commit fdee8ee845
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 54 additions and 17 deletions

View File

@ -43,7 +43,7 @@ import 'package:matrix/src/utils/try_get_push_rule.dart';
typedef RoomSorter = int Function(Room a, Room b); typedef RoomSorter = int Function(Room a, Room b);
enum LoginState { loggedIn, loggedOut } enum LoginState { loggedIn, loggedOut, softLoggedOut }
extension TrailingSlash on Uri { extension TrailingSlash on Uri {
Uri stripTrailingSlash() => path.endsWith('/') Uri stripTrailingSlash() => path.endsWith('/')
@ -267,10 +267,15 @@ class Client extends MatrixApi {
final tokenResponse = await refresh(refreshToken); final tokenResponse = await refresh(refreshToken);
accessToken = tokenResponse.accessToken; accessToken = tokenResponse.accessToken;
final expiresInMs = tokenResponse.expiresInMs;
final tokenExpiresAt = expiresInMs == null
? null
: DateTime.now().add(Duration(milliseconds: expiresInMs));
accessTokenExpiresAt = tokenExpiresAt;
await database?.updateClient( await database?.updateClient(
homeserverUrl, homeserverUrl,
tokenResponse.accessToken, tokenResponse.accessToken,
accessTokenExpiresAt, tokenExpiresAt,
tokenResponse.refreshToken, tokenResponse.refreshToken,
userId, userId,
deviceId, deviceId,
@ -1574,7 +1579,7 @@ class Client extends MatrixApi {
String? userID; String? userID;
try { try {
Logs().i('Initialize client $clientName'); Logs().i('Initialize client $clientName');
if (isLogged()) { if (onLoginStateChanged.value == LoginState.loggedIn) {
throw ClientInitPreconditionError( throw ClientInitPreconditionError(
'User is already logged in! Call [logout()] first!', 'User is already logged in! Call [logout()] first!',
); );
@ -1592,6 +1597,7 @@ class Client extends MatrixApi {
_serverConfigCache.invalidate(); _serverConfigCache.invalidate();
final account = await this.database?.getClient(clientName); final account = await this.database?.getClient(clientName);
newRefreshToken ??= account?.tryGet<String>('refresh_token');
if (account != null) { if (account != null) {
_id = account['client_id']; _id = account['client_id'];
homeserver = Uri.parse(account['homeserver_url']); homeserver = Uri.parse(account['homeserver_url']);
@ -1626,6 +1632,26 @@ class Client extends MatrixApi {
olmAccount = newOlmAccount ?? olmAccount; olmAccount = newOlmAccount ?? olmAccount;
} }
// If we are refreshing the session, we are done here:
if (onLoginStateChanged.value == LoginState.softLoggedOut) {
if (newRefreshToken != null && accessToken != null && userID != null) {
// Store the new tokens:
await _database?.updateClient(
homeserver.toString(),
accessToken,
accessTokenExpiresAt,
newRefreshToken,
userID,
_deviceID,
_deviceName,
prevBatch,
encryption?.pickledOlmAccount,
);
}
onLoginStateChanged.add(LoginState.loggedIn);
return;
}
if (accessToken == null || homeserver == null || userID == null) { if (accessToken == null || homeserver == null || userID == null) {
if (legacyDatabaseBuilder != null) { if (legacyDatabaseBuilder != null) {
await _migrateFromLegacyDatabase(onMigration: onMigration); await _migrateFromLegacyDatabase(onMigration: onMigration);
@ -1806,6 +1832,21 @@ class Client extends MatrixApi {
return; return;
} }
Future<void> _handleSoftLogout() async {
final onSoftLogout = this.onSoftLogout;
if (onSoftLogout == null) return;
onLoginStateChanged.add(LoginState.softLoggedOut);
try {
await onSoftLogout(this);
onLoginStateChanged.add(LoginState.loggedIn);
} catch (e, s) {
Logs().w('Unable to refresh session after soft logout', e, s);
await clear();
rethrow;
}
}
/// Pass a timeout to set how long the server waits before sending an empty response. /// Pass a timeout to set how long the server waits before sending an empty response.
/// (Corresponds to the timeout param on the /sync request.) /// (Corresponds to the timeout param on the /sync request.)
Future<void> _innerSync({Duration? timeout}) async { Future<void> _innerSync({Duration? timeout}) async {
@ -1820,20 +1861,20 @@ class Client extends MatrixApi {
Object? syncError; Object? syncError;
await _checkSyncFilter(); await _checkSyncFilter();
// The timeout we send to the server for the sync loop. It says to the
// server that we want to receive an empty sync response after this
// amount of time if nothing happens.
timeout ??= const Duration(seconds: 30);
// Call onSoftLogout 5 minutes before access token expires to prevent // Call onSoftLogout 5 minutes before access token expires to prevent
// failing network requests. // failing network requests.
final tokenExpiresAt = accessTokenExpiresAt; final tokenExpiresAt = accessTokenExpiresAt;
if (onSoftLogout != null && if (onSoftLogout != null &&
tokenExpiresAt != null && tokenExpiresAt != null &&
tokenExpiresAt.difference(DateTime.now()) <= Duration(minutes: 5)) { tokenExpiresAt.difference(DateTime.now()) <= timeout * 2) {
await onSoftLogout?.call(this); await _handleSoftLogout();
} }
// The timeout we send to the server for the sync loop. It says to the
// server that we want to receive an empty sync response after this
// amount of time if nothing happens.
timeout ??= const Duration(seconds: 30);
final syncRequest = sync( final syncRequest = sync(
filter: syncFilterId, filter: syncFilterId,
since: prevBatch, since: prevBatch,
@ -1910,12 +1951,8 @@ class Client extends MatrixApi {
final onSoftLogout = this.onSoftLogout; final onSoftLogout = this.onSoftLogout;
if (e.raw.tryGet<bool>('soft_logout') == true && onSoftLogout != null) { if (e.raw.tryGet<bool>('soft_logout') == true && onSoftLogout != null) {
Logs().w('The user has been soft logged out! Try to login again...'); Logs().w('The user has been soft logged out! Try to login again...');
try {
await onSoftLogout(this); await _handleSoftLogout();
} catch (e, s) {
Logs().e('Unable to login again', e, s);
await clear();
}
} else { } else {
Logs().w('The user has been logged out!'); Logs().w('The user has been logged out!');
await clear(); await clear();

View File

@ -2034,7 +2034,7 @@ class FakeMatrixApi extends BaseClient {
'POST': { 'POST': {
'/client/v3/refresh': (var req) => { '/client/v3/refresh': (var req) => {
'access_token': 'a_new_token', 'access_token': 'a_new_token',
'expires_in_ms': 60000, 'expires_in_ms': 1000 * 60 * 5,
'refresh_token': 'another_new_token' 'refresh_token': 'another_new_token'
}, },
'/client/v3/delete_devices': (var req) => {}, '/client/v3/delete_devices': (var req) => {},