feat: Implement handling soft logout
This commit is contained in:
parent
d7596923ad
commit
38b1eb75e5
|
|
@ -89,6 +89,8 @@ class Client extends MatrixApi {
|
||||||
|
|
||||||
bool shareKeysWithUnverifiedDevices;
|
bool shareKeysWithUnverifiedDevices;
|
||||||
|
|
||||||
|
Future<void> Function(Client client)? onSoftLogout;
|
||||||
|
|
||||||
// For CommandsClientExtension
|
// For CommandsClientExtension
|
||||||
final Map<String, FutureOr<String?> Function(CommandArgs)> commands = {};
|
final Map<String, FutureOr<String?> Function(CommandArgs)> commands = {};
|
||||||
final Filter syncFilter;
|
final Filter syncFilter;
|
||||||
|
|
@ -184,6 +186,13 @@ class Client extends MatrixApi {
|
||||||
this.shareKeysWithUnverifiedDevices = true,
|
this.shareKeysWithUnverifiedDevices = true,
|
||||||
this.enableDehydratedDevices = false,
|
this.enableDehydratedDevices = false,
|
||||||
this.receiptsPublicByDefault = true,
|
this.receiptsPublicByDefault = true,
|
||||||
|
|
||||||
|
/// Implement your https://spec.matrix.org/v1.9/client-server-api/#soft-logout
|
||||||
|
/// logic here.
|
||||||
|
/// Set this to `refreshAccessToken()` for the easiest way to handle the
|
||||||
|
/// most common reason for soft logouts.
|
||||||
|
/// You can also perform a new login here by passing the existing deviceId.
|
||||||
|
this.onSoftLogout,
|
||||||
}) : syncFilter = syncFilter ??
|
}) : syncFilter = syncFilter ??
|
||||||
Filter(
|
Filter(
|
||||||
room: RoomFilter(
|
room: RoomFilter(
|
||||||
|
|
@ -234,6 +243,40 @@ class Client extends MatrixApi {
|
||||||
registerDefaultCommands();
|
registerDefaultCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fetches the refreshToken from the database and tries to get a new
|
||||||
|
/// access token from the server and then stores it correctly. Unlike the
|
||||||
|
/// pure API call of `Client.refresh()` this handles the complete soft
|
||||||
|
/// logout case.
|
||||||
|
/// Throws an Exception if there is no refresh token available or the
|
||||||
|
/// client is not logged in.
|
||||||
|
Future<void> refreshAccessToken() async {
|
||||||
|
final storedClient = await database?.getClient(clientName);
|
||||||
|
final refreshToken = storedClient?.tryGet<String>('refresh_token');
|
||||||
|
if (refreshToken == null) {
|
||||||
|
throw Exception('No refresh token available');
|
||||||
|
}
|
||||||
|
final homeserverUrl = homeserver?.toString();
|
||||||
|
final userId = userID;
|
||||||
|
final deviceId = deviceID;
|
||||||
|
if (homeserverUrl == null || userId == null || deviceId == null) {
|
||||||
|
throw Exception('Cannot refresh access token when not logged in');
|
||||||
|
}
|
||||||
|
|
||||||
|
final tokenResponse = await refresh(refreshToken);
|
||||||
|
|
||||||
|
accessToken = tokenResponse.accessToken;
|
||||||
|
await database?.updateClient(
|
||||||
|
homeserverUrl,
|
||||||
|
tokenResponse.accessToken,
|
||||||
|
tokenResponse.refreshToken,
|
||||||
|
userId,
|
||||||
|
deviceId,
|
||||||
|
deviceName,
|
||||||
|
prevBatch,
|
||||||
|
encryption?.pickledOlmAccount,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// The required name for this client.
|
/// The required name for this client.
|
||||||
final String clientName;
|
final String clientName;
|
||||||
|
|
||||||
|
|
@ -485,6 +528,7 @@ class Client extends MatrixApi {
|
||||||
deviceId: deviceId,
|
deviceId: deviceId,
|
||||||
initialDeviceDisplayName: initialDeviceDisplayName,
|
initialDeviceDisplayName: initialDeviceDisplayName,
|
||||||
inhibitLogin: inhibitLogin,
|
inhibitLogin: inhibitLogin,
|
||||||
|
refreshToken: refreshToken ?? onSoftLogout != null,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Connect if there is an access token in the response.
|
// Connect if there is an access token in the response.
|
||||||
|
|
@ -498,6 +542,7 @@ class Client extends MatrixApi {
|
||||||
}
|
}
|
||||||
await init(
|
await init(
|
||||||
newToken: accessToken,
|
newToken: accessToken,
|
||||||
|
newRefreshToken: response.refreshToken,
|
||||||
newUserID: userId,
|
newUserID: userId,
|
||||||
newHomeserver: homeserver,
|
newHomeserver: homeserver,
|
||||||
newDeviceName: initialDeviceDisplayName ?? '',
|
newDeviceName: initialDeviceDisplayName ?? '',
|
||||||
|
|
@ -548,6 +593,7 @@ class Client extends MatrixApi {
|
||||||
medium: medium,
|
medium: medium,
|
||||||
// ignore: deprecated_member_use
|
// ignore: deprecated_member_use
|
||||||
address: address,
|
address: address,
|
||||||
|
refreshToken: refreshToken ?? onSoftLogout != null,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Connect if there is an access token in the response.
|
// Connect if there is an access token in the response.
|
||||||
|
|
@ -560,6 +606,7 @@ class Client extends MatrixApi {
|
||||||
}
|
}
|
||||||
await init(
|
await init(
|
||||||
newToken: accessToken,
|
newToken: accessToken,
|
||||||
|
newRefreshToken: response.refreshToken,
|
||||||
newUserID: userId,
|
newUserID: userId,
|
||||||
newHomeserver: homeserver_,
|
newHomeserver: homeserver_,
|
||||||
newDeviceName: initialDeviceDisplayName ?? '',
|
newDeviceName: initialDeviceDisplayName ?? '',
|
||||||
|
|
@ -1474,6 +1521,7 @@ class Client extends MatrixApi {
|
||||||
/// `userDeviceKeysLoading` where it is necessary.
|
/// `userDeviceKeysLoading` where it is necessary.
|
||||||
Future<void> init({
|
Future<void> init({
|
||||||
String? newToken,
|
String? newToken,
|
||||||
|
String? newRefreshToken,
|
||||||
Uri? newHomeserver,
|
Uri? newHomeserver,
|
||||||
String? newUserID,
|
String? newUserID,
|
||||||
String? newDeviceName,
|
String? newDeviceName,
|
||||||
|
|
@ -1587,6 +1635,7 @@ class Client extends MatrixApi {
|
||||||
await database.updateClient(
|
await database.updateClient(
|
||||||
homeserver.toString(),
|
homeserver.toString(),
|
||||||
accessToken,
|
accessToken,
|
||||||
|
newRefreshToken,
|
||||||
userID,
|
userID,
|
||||||
_deviceID,
|
_deviceID,
|
||||||
_deviceName,
|
_deviceName,
|
||||||
|
|
@ -1598,6 +1647,7 @@ class Client extends MatrixApi {
|
||||||
clientName,
|
clientName,
|
||||||
homeserver.toString(),
|
homeserver.toString(),
|
||||||
accessToken,
|
accessToken,
|
||||||
|
newRefreshToken,
|
||||||
userID,
|
userID,
|
||||||
_deviceID,
|
_deviceID,
|
||||||
_deviceName,
|
_deviceName,
|
||||||
|
|
@ -1822,8 +1872,19 @@ class Client extends MatrixApi {
|
||||||
onSyncStatus.add(SyncStatusUpdate(SyncStatus.error,
|
onSyncStatus.add(SyncStatusUpdate(SyncStatus.error,
|
||||||
error: SdkError(exception: e, stackTrace: s)));
|
error: SdkError(exception: e, stackTrace: s)));
|
||||||
if (e.error == MatrixError.M_UNKNOWN_TOKEN) {
|
if (e.error == MatrixError.M_UNKNOWN_TOKEN) {
|
||||||
Logs().w('The user has been logged out!');
|
final onSoftLogout = this.onSoftLogout;
|
||||||
await clear();
|
if (e.raw.tryGet<bool>('soft_logout') == true && onSoftLogout != null) {
|
||||||
|
Logs().w('The user has been soft logged out! Try to login again...');
|
||||||
|
try {
|
||||||
|
await onSoftLogout(this);
|
||||||
|
} catch (e, s) {
|
||||||
|
Logs().e('Unable to login again', e, s);
|
||||||
|
await clear();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Logs().w('The user has been logged out!');
|
||||||
|
await clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} on SyncConnectionException catch (e, s) {
|
} on SyncConnectionException catch (e, s) {
|
||||||
Logs().w('Syncloop failed: Client has not connection to the server');
|
Logs().w('Syncloop failed: Client has not connection to the server');
|
||||||
|
|
@ -3112,6 +3173,7 @@ class Client extends MatrixApi {
|
||||||
clientName,
|
clientName,
|
||||||
migrateClient['homeserver_url'],
|
migrateClient['homeserver_url'],
|
||||||
migrateClient['token'],
|
migrateClient['token'],
|
||||||
|
migrateClient['refresh_token'],
|
||||||
migrateClient['user_id'],
|
migrateClient['user_id'],
|
||||||
migrateClient['device_id'],
|
migrateClient['device_id'],
|
||||||
migrateClient['device_name'],
|
migrateClient['device_name'],
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ abstract class DatabaseApi {
|
||||||
Future updateClient(
|
Future updateClient(
|
||||||
String homeserverUrl,
|
String homeserverUrl,
|
||||||
String token,
|
String token,
|
||||||
|
String? refreshToken,
|
||||||
String userId,
|
String userId,
|
||||||
String? deviceId,
|
String? deviceId,
|
||||||
String? deviceName,
|
String? deviceName,
|
||||||
|
|
@ -44,6 +45,7 @@ abstract class DatabaseApi {
|
||||||
String name,
|
String name,
|
||||||
String homeserverUrl,
|
String homeserverUrl,
|
||||||
String token,
|
String token,
|
||||||
|
String? refreshToken,
|
||||||
String userId,
|
String userId,
|
||||||
String? deviceId,
|
String? deviceId,
|
||||||
String? deviceName,
|
String? deviceName,
|
||||||
|
|
|
||||||
|
|
@ -785,6 +785,7 @@ class HiveCollectionsDatabase extends DatabaseApi {
|
||||||
String name,
|
String name,
|
||||||
String homeserverUrl,
|
String homeserverUrl,
|
||||||
String token,
|
String token,
|
||||||
|
String? refreshToken,
|
||||||
String userId,
|
String userId,
|
||||||
String? deviceId,
|
String? deviceId,
|
||||||
String? deviceName,
|
String? deviceName,
|
||||||
|
|
@ -794,6 +795,11 @@ class HiveCollectionsDatabase extends DatabaseApi {
|
||||||
await _clientBox.put('homeserver_url', homeserverUrl);
|
await _clientBox.put('homeserver_url', homeserverUrl);
|
||||||
await _clientBox.put('token', token);
|
await _clientBox.put('token', token);
|
||||||
await _clientBox.put('user_id', userId);
|
await _clientBox.put('user_id', userId);
|
||||||
|
if (refreshToken == null) {
|
||||||
|
await _clientBox.delete('refresh_token');
|
||||||
|
} else {
|
||||||
|
await _clientBox.put('refresh_token', refreshToken);
|
||||||
|
}
|
||||||
if (deviceId == null) {
|
if (deviceId == null) {
|
||||||
await _clientBox.delete('device_id');
|
await _clientBox.delete('device_id');
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1371,6 +1377,7 @@ class HiveCollectionsDatabase extends DatabaseApi {
|
||||||
Future<void> updateClient(
|
Future<void> updateClient(
|
||||||
String homeserverUrl,
|
String homeserverUrl,
|
||||||
String token,
|
String token,
|
||||||
|
String? refreshToken,
|
||||||
String userId,
|
String userId,
|
||||||
String? deviceId,
|
String? deviceId,
|
||||||
String? deviceName,
|
String? deviceName,
|
||||||
|
|
@ -1380,6 +1387,11 @@ class HiveCollectionsDatabase extends DatabaseApi {
|
||||||
await transaction(() async {
|
await transaction(() async {
|
||||||
await _clientBox.put('homeserver_url', homeserverUrl);
|
await _clientBox.put('homeserver_url', homeserverUrl);
|
||||||
await _clientBox.put('token', token);
|
await _clientBox.put('token', token);
|
||||||
|
if (refreshToken == null) {
|
||||||
|
await _clientBox.delete('refresh_token');
|
||||||
|
} else {
|
||||||
|
await _clientBox.put('refresh_token', refreshToken);
|
||||||
|
}
|
||||||
await _clientBox.put('user_id', userId);
|
await _clientBox.put('user_id', userId);
|
||||||
if (deviceId == null) {
|
if (deviceId == null) {
|
||||||
await _clientBox.delete('device_id');
|
await _clientBox.delete('device_id');
|
||||||
|
|
|
||||||
|
|
@ -750,6 +750,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi with ZoneTransactionMixin {
|
||||||
String name,
|
String name,
|
||||||
String homeserverUrl,
|
String homeserverUrl,
|
||||||
String token,
|
String token,
|
||||||
|
String? refreshToken,
|
||||||
String userId,
|
String userId,
|
||||||
String? deviceId,
|
String? deviceId,
|
||||||
String? deviceName,
|
String? deviceName,
|
||||||
|
|
@ -757,6 +758,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi with ZoneTransactionMixin {
|
||||||
String? olmAccount) async {
|
String? olmAccount) async {
|
||||||
await _clientBox.put('homeserver_url', homeserverUrl);
|
await _clientBox.put('homeserver_url', homeserverUrl);
|
||||||
await _clientBox.put('token', token);
|
await _clientBox.put('token', token);
|
||||||
|
await _clientBox.put('refresh_token', refreshToken);
|
||||||
await _clientBox.put('user_id', userId);
|
await _clientBox.put('user_id', userId);
|
||||||
await _clientBox.put('device_id', deviceId);
|
await _clientBox.put('device_id', deviceId);
|
||||||
await _clientBox.put('device_name', deviceName);
|
await _clientBox.put('device_name', deviceName);
|
||||||
|
|
@ -1314,6 +1316,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi with ZoneTransactionMixin {
|
||||||
Future<void> updateClient(
|
Future<void> updateClient(
|
||||||
String homeserverUrl,
|
String homeserverUrl,
|
||||||
String token,
|
String token,
|
||||||
|
String? refreshToken,
|
||||||
String userId,
|
String userId,
|
||||||
String? deviceId,
|
String? deviceId,
|
||||||
String? deviceName,
|
String? deviceName,
|
||||||
|
|
@ -1322,6 +1325,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi with ZoneTransactionMixin {
|
||||||
) async {
|
) async {
|
||||||
await _clientBox.put('homeserver_url', homeserverUrl);
|
await _clientBox.put('homeserver_url', homeserverUrl);
|
||||||
await _clientBox.put('token', token);
|
await _clientBox.put('token', token);
|
||||||
|
await _clientBox.put('refresh_token', refreshToken);
|
||||||
await _clientBox.put('user_id', userId);
|
await _clientBox.put('user_id', userId);
|
||||||
await _clientBox.put('device_id', deviceId);
|
await _clientBox.put('device_id', deviceId);
|
||||||
await _clientBox.put('device_name', deviceName);
|
await _clientBox.put('device_name', deviceName);
|
||||||
|
|
|
||||||
|
|
@ -727,6 +727,7 @@ class MatrixSdkDatabase extends DatabaseApi {
|
||||||
String name,
|
String name,
|
||||||
String homeserverUrl,
|
String homeserverUrl,
|
||||||
String token,
|
String token,
|
||||||
|
String? refreshToken,
|
||||||
String userId,
|
String userId,
|
||||||
String? deviceId,
|
String? deviceId,
|
||||||
String? deviceName,
|
String? deviceName,
|
||||||
|
|
@ -735,6 +736,11 @@ class MatrixSdkDatabase extends DatabaseApi {
|
||||||
await transaction(() async {
|
await transaction(() async {
|
||||||
await _clientBox.put('homeserver_url', homeserverUrl);
|
await _clientBox.put('homeserver_url', homeserverUrl);
|
||||||
await _clientBox.put('token', token);
|
await _clientBox.put('token', token);
|
||||||
|
if (refreshToken == null) {
|
||||||
|
await _clientBox.delete('refresh_token');
|
||||||
|
} else {
|
||||||
|
await _clientBox.put('refresh_token', refreshToken);
|
||||||
|
}
|
||||||
await _clientBox.put('user_id', userId);
|
await _clientBox.put('user_id', userId);
|
||||||
if (deviceId == null) {
|
if (deviceId == null) {
|
||||||
await _clientBox.delete('device_id');
|
await _clientBox.delete('device_id');
|
||||||
|
|
@ -1343,6 +1349,7 @@ class MatrixSdkDatabase extends DatabaseApi {
|
||||||
Future<void> updateClient(
|
Future<void> updateClient(
|
||||||
String homeserverUrl,
|
String homeserverUrl,
|
||||||
String token,
|
String token,
|
||||||
|
String? refreshToken,
|
||||||
String userId,
|
String userId,
|
||||||
String? deviceId,
|
String? deviceId,
|
||||||
String? deviceName,
|
String? deviceName,
|
||||||
|
|
@ -1352,6 +1359,11 @@ class MatrixSdkDatabase extends DatabaseApi {
|
||||||
await transaction(() async {
|
await transaction(() async {
|
||||||
await _clientBox.put('homeserver_url', homeserverUrl);
|
await _clientBox.put('homeserver_url', homeserverUrl);
|
||||||
await _clientBox.put('token', token);
|
await _clientBox.put('token', token);
|
||||||
|
if (refreshToken == null) {
|
||||||
|
await _clientBox.delete('refresh_token');
|
||||||
|
} else {
|
||||||
|
await _clientBox.put('refresh_token', refreshToken);
|
||||||
|
}
|
||||||
await _clientBox.put('user_id', userId);
|
await _clientBox.put('user_id', userId);
|
||||||
if (deviceId == null) {
|
if (deviceId == null) {
|
||||||
await _clientBox.delete('device_id');
|
await _clientBox.delete('device_id');
|
||||||
|
|
|
||||||
|
|
@ -964,6 +964,35 @@ void main() {
|
||||||
await client.dispose(closeDatabase: true);
|
await client.dispose(closeDatabase: true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('refreshAccessToken', () async {
|
||||||
|
final client = await getClient();
|
||||||
|
expect(client.accessToken, 'abcd');
|
||||||
|
await client.refreshAccessToken();
|
||||||
|
expect(client.accessToken, 'a_new_token');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('handleSoftLogout', () async {
|
||||||
|
final client = await getClient();
|
||||||
|
expect(client.accessToken, 'abcd');
|
||||||
|
var softLoggedOut = 0;
|
||||||
|
client.onSoftLogout = (client) {
|
||||||
|
softLoggedOut++;
|
||||||
|
return client.refreshAccessToken();
|
||||||
|
};
|
||||||
|
FakeMatrixApi.expectedAccessToken = 'a_new_token';
|
||||||
|
await client.oneShotSync();
|
||||||
|
await client.oneShotSync();
|
||||||
|
FakeMatrixApi.expectedAccessToken = null;
|
||||||
|
expect(client.accessToken, 'a_new_token');
|
||||||
|
expect(softLoggedOut, 1);
|
||||||
|
final storedClient = await client.database?.getClient(client.clientName);
|
||||||
|
expect(storedClient?.tryGet<String>('token'), 'a_new_token');
|
||||||
|
expect(
|
||||||
|
storedClient?.tryGet<String>('refresh_token'),
|
||||||
|
'another_new_token',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test('object equality', () async {
|
test('object equality', () async {
|
||||||
final time1 = DateTime.fromMillisecondsSinceEpoch(1);
|
final time1 = DateTime.fromMillisecondsSinceEpoch(1);
|
||||||
final time2 = DateTime.fromMillisecondsSinceEpoch(0);
|
final time2 = DateTime.fromMillisecondsSinceEpoch(0);
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,7 @@ void main() {
|
||||||
'name',
|
'name',
|
||||||
'homeserverUrl',
|
'homeserverUrl',
|
||||||
'token',
|
'token',
|
||||||
|
'refresh_token',
|
||||||
'userId',
|
'userId',
|
||||||
'deviceId',
|
'deviceId',
|
||||||
'deviceName',
|
'deviceName',
|
||||||
|
|
@ -147,6 +148,7 @@ void main() {
|
||||||
await database.updateClient(
|
await database.updateClient(
|
||||||
'homeserverUrl',
|
'homeserverUrl',
|
||||||
'token_different',
|
'token_different',
|
||||||
|
'refresh_token',
|
||||||
'userId',
|
'userId',
|
||||||
'deviceId',
|
'deviceId',
|
||||||
'deviceName',
|
'deviceName',
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,14 @@ Future<Client> getClient() async {
|
||||||
'testclient',
|
'testclient',
|
||||||
httpClient: FakeMatrixApi(),
|
httpClient: FakeMatrixApi(),
|
||||||
databaseBuilder: getDatabase,
|
databaseBuilder: getDatabase,
|
||||||
|
onSoftLogout: (client) => client.refreshAccessToken(),
|
||||||
);
|
);
|
||||||
FakeMatrixApi.client = client;
|
FakeMatrixApi.client = client;
|
||||||
await client.checkHomeserver(Uri.parse('https://fakeServer.notExisting'),
|
await client.checkHomeserver(Uri.parse('https://fakeServer.notExisting'),
|
||||||
checkWellKnown: false);
|
checkWellKnown: false);
|
||||||
await client.init(
|
await client.init(
|
||||||
newToken: 'abcd',
|
newToken: 'abcd',
|
||||||
|
newRefreshToken: 'refresh_abcd',
|
||||||
newUserID: '@test:fakeServer.notExisting',
|
newUserID: '@test:fakeServer.notExisting',
|
||||||
newHomeserver: client.homeserver,
|
newHomeserver: client.homeserver,
|
||||||
newDeviceName: 'Text Matrix Client',
|
newDeviceName: 'Text Matrix Client',
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,8 @@ Map<String, dynamic> decodeJson(dynamic data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeMatrixApi extends BaseClient {
|
class FakeMatrixApi extends BaseClient {
|
||||||
|
static String? expectedAccessToken;
|
||||||
|
|
||||||
static Map<String, List<dynamic>> get calledEndpoints =>
|
static Map<String, List<dynamic>> get calledEndpoints =>
|
||||||
currentApi!._calledEndpoints;
|
currentApi!._calledEndpoints;
|
||||||
static int get eventCounter => currentApi!._eventCounter;
|
static int get eventCounter => currentApi!._eventCounter;
|
||||||
|
|
@ -129,6 +131,23 @@ class FakeMatrixApi extends BaseClient {
|
||||||
'<html><head></head><body>Not found...</body></html>', 404);
|
'<html><head></head><body>Not found...</body></html>', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!{
|
||||||
|
'/client/v3/refresh',
|
||||||
|
'/client/v3/login',
|
||||||
|
'/client/v3/register',
|
||||||
|
}.contains(action) &&
|
||||||
|
expectedAccessToken != null &&
|
||||||
|
request.headers['Authorization'] != 'Bearer $expectedAccessToken') {
|
||||||
|
return Response(
|
||||||
|
jsonEncode({
|
||||||
|
'errcode': 'M_UNKNOWN_TOKEN',
|
||||||
|
'error': 'Soft logged out',
|
||||||
|
'soft_logout': true,
|
||||||
|
}),
|
||||||
|
401,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Call API
|
// Call API
|
||||||
(_calledEndpoints[action] ??= <dynamic>[]).add(data);
|
(_calledEndpoints[action] ??= <dynamic>[]).add(data);
|
||||||
final act = api[method]?[action];
|
final act = api[method]?[action];
|
||||||
|
|
@ -2013,6 +2032,11 @@ class FakeMatrixApi extends BaseClient {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'POST': {
|
'POST': {
|
||||||
|
'/client/v3/refresh': (var req) => {
|
||||||
|
'access_token': 'a_new_token',
|
||||||
|
'expires_in_ms': 60000,
|
||||||
|
'refresh_token': 'another_new_token'
|
||||||
|
},
|
||||||
'/client/v3/delete_devices': (var req) => {},
|
'/client/v3/delete_devices': (var req) => {},
|
||||||
'/client/v3/account/3pid/add': (var req) => {},
|
'/client/v3/account/3pid/add': (var req) => {},
|
||||||
'/client/v3/account/3pid/bind': (var req) => {},
|
'/client/v3/account/3pid/bind': (var req) => {},
|
||||||
|
|
@ -2397,6 +2421,7 @@ class FakeMatrixApi extends BaseClient {
|
||||||
'/client/v3/login': (var req) => {
|
'/client/v3/login': (var req) => {
|
||||||
'user_id': '@test:fakeServer.notExisting',
|
'user_id': '@test:fakeServer.notExisting',
|
||||||
'access_token': 'abc123',
|
'access_token': 'abc123',
|
||||||
|
'refresh_token': 'refresh_abc123',
|
||||||
'device_id': 'GHTYAJCE',
|
'device_id': 'GHTYAJCE',
|
||||||
'well_known': {
|
'well_known': {
|
||||||
'm.homeserver': {'base_url': 'https://example.org'},
|
'm.homeserver': {'base_url': 'https://example.org'},
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ void main() {
|
||||||
'testclient',
|
'testclient',
|
||||||
'https://example.org',
|
'https://example.org',
|
||||||
'blubb',
|
'blubb',
|
||||||
|
null,
|
||||||
'@test:example.org',
|
'@test:example.org',
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue