From 5381c3935cd6aa0676ae5c38308437907b955268 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Fri, 23 Oct 2020 11:34:08 +0200 Subject: [PATCH] refactor: Check server --- README.md | 31 ++++------ lib/src/client.dart | 61 +++++++++++-------- test/client_test.dart | 9 ++- .../encrypt_decrypt_to_device_test.dart | 2 +- test/encryption/key_verification_test.dart | 2 +- test/event_test.dart | 8 +-- test/fake_client.dart | 2 +- test/mxc_uri_extension_test.dart | 2 +- test/timeline_test.dart | 2 +- test/user_test.dart | 18 +++--- test_driver/famedlysdk_test.dart | 6 +- 11 files changed, 73 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index 2b95b35..4ca1a18 100644 --- a/README.md +++ b/README.md @@ -26,45 +26,38 @@ import 'package:famedlysdk/famedlysdk.dart'; 2. Create a new client: ```dart -Client matrix = Client("HappyChat"); +Client client = Client("HappyChat"); ``` Take a look here for an example store: [https://gitlab.com/ChristianPauly/fluffychat-flutter/snippets](https://gitlab.com/ChristianPauly/fluffychat-flutter/snippets) -```dart -Client matrix = Client("HappyChat"); -``` - 3. Connect to a Matrix Homeserver and listen to the streams: ```dart -matrix.onLoginStateChanged.stream.listen((bool loginState){ +client.onLoginStateChanged.stream.listen((bool loginState){ print("LoginState: ${loginState.toString()}"); }); -matrix.onEvent.stream.listen((EventUpdate eventUpdate){ +client.onEvent.stream.listen((EventUpdate eventUpdate){ print("New event update!"); }); -matrix.onRoomUpdate.stream.listen((RoomUpdate eventUpdate){ +client.onRoomUpdate.stream.listen((RoomUpdate eventUpdate){ print("New room update!"); }); -final bool serverValid = await matrix.checkServer("https://yourhomeserver.abc"); - -final bool loginValid = await matrix.login("username", "password"); +try { + await client.checkHomeserver("https://yourhomeserver.abc"); + await client.login("username", "password"); +} +catch(e) { + print('No luck...'); +} ``` 4. Send a message to a Room: ```dart -final resp = await matrix.jsonRequest( - type: "PUT", - action: "/r0/rooms/!fjd823j:example.com/send/m.room.message/$txnId", - data: { - "msgtype": "m.text", - "body": "hello" - } -); +await client.getRoomById('your_room_id').sendTextEvent('Hello world'); ``` diff --git a/lib/src/client.dart b/lib/src/client.dart index 37baef5..7d8c0c9 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -232,43 +232,51 @@ class Client extends MatrixApi { return WellKnownInformations.fromJson(rawJson); } - /// Checks the supported versions of the Matrix protocol and the supported - /// login types. Returns false if the server is not compatible with the - /// client. - /// Throws FormatException, TimeoutException and MatrixException on error. + @Deprecated('Use [checkHomeserver] instead.') Future checkServer(dynamic serverUrl) async { try { - if (serverUrl is Uri) { - homeserver = serverUrl; + await checkHomeserver(serverUrl); + } catch (_) { + return false; + } + return true; + } + + /// Checks the supported versions of the Matrix protocol and the supported + /// login types. Throws an exception if the server is not compatible with the + /// client and sets [homeserver] to [serverUrl] if it is. Supports the types [Uri] + /// and [String]. + Future checkHomeserver(dynamic homeserverUrl, + {Set supportedLoginTypes = supportedLoginTypes}) async { + try { + if (homeserverUrl is Uri) { + homeserver = homeserverUrl; } else { // URLs allow to have whitespace surrounding them, see https://www.w3.org/TR/2011/WD-html5-20110525/urls.html // As we want to strip a trailing slash, though, we have to trim the url ourself // and thus can't let Uri.parse() deal with it. - serverUrl = serverUrl.trim(); + homeserverUrl = homeserverUrl.trim(); // strip a trailing slash - if (serverUrl.endsWith('/')) { - serverUrl = serverUrl.substring(0, serverUrl.length - 1); + if (homeserverUrl.endsWith('/')) { + homeserverUrl = homeserverUrl.substring(0, homeserverUrl.length - 1); } - homeserver = Uri.parse(serverUrl); + homeserver = Uri.parse(homeserverUrl); } final versions = await requestSupportedVersions(); - for (var i = 0; i < versions.versions.length; i++) { - if (versions.versions[i] == 'r0.5.0' || - versions.versions[i] == 'r0.6.0') { - break; - } else if (i == versions.versions.length - 1) { - return false; - } + if (!versions.versions + .any((version) => supportedVersions.contains(version))) { + throw Exception( + 'Server supports the versions: ${versions.versions.toString()} but this application is only compatible with ${supportedVersions.toString()}.'); } final loginTypes = await requestLoginTypes(); - if (loginTypes.flows.indexWhere((f) => f.type == 'm.login.password') == - -1) { - return false; + if (!loginTypes.flows.any((f) => supportedLoginTypes.contains(f.type))) { + throw Exception( + 'Server supports the Login Types: ${loginTypes.flows.map((f) => f.toJson).toList().toString()} but this application is only compatible with ${supportedLoginTypes.toString()}.'); } - return true; + return; } catch (_) { homeserver = null; rethrow; @@ -277,7 +285,7 @@ class Client extends MatrixApi { /// Checks to see if a username is available, and valid, for the server. /// Returns the fully-qualified Matrix user ID (MXID) that has been registered. - /// You have to call [checkServer] first to set a homeserver. + /// You have to call [checkHomeserver] first to set a homeserver. @override Future register({ String username, @@ -315,7 +323,7 @@ class Client extends MatrixApi { /// Handles the login and allows the client to call all APIs which require /// authentication. Returns false if the login was not successful. Throws /// MatrixException if login was not successful. - /// You have to call [checkServer] first to set a homeserver. + /// You have to call [checkHomeserver] first to set a homeserver. @override Future login({ String type = 'm.login.password', @@ -479,8 +487,11 @@ class Client extends MatrixApi { ? PushRuleSet.fromJson(accountData['m.push_rules'].content) : null; - static String syncFilters = '{"room":{"state":{"lazy_load_members":true}}}'; - static String messagesFilters = '{"lazy_load_members":true}'; + static const Set supportedVersions = {'r0.5.0', 'r0.6.0'}; + static const Set supportedLoginTypes = {'m.login.password'}; + static const String syncFilters = + '{"room":{"state":{"lazy_load_members":true}}}'; + static const String messagesFilters = '{"lazy_load_members":true}'; static const List supportedDirectEncryptionAlgorithms = [ 'm.olm.v1.curve25519-aes-sha2' ]; diff --git a/test/client_test.dart b/test/client_test.dart index 266559b..1f125c9 100644 --- a/test/client_test.dart +++ b/test/client_test.dart @@ -77,11 +77,11 @@ void main() { expect(matrix.homeserver, null); try { - await matrix.checkServer('https://fakeserver.wrongaddress'); + await matrix.checkHomeserver('https://fakeserver.wrongaddress'); } on FormatException catch (exception) { expect(exception != null, true); } - await matrix.checkServer('https://fakeserver.notexisting'); + await matrix.checkHomeserver('https://fakeserver.notexisting'); expect(matrix.homeserver.toString(), 'https://fakeserver.notexisting'); final available = await matrix.usernameAvailable('testuser'); @@ -311,12 +311,11 @@ void main() { roomUpdateListFuture = matrix.onRoomUpdate.stream.toList(); eventUpdateListFuture = matrix.onEvent.stream.toList(); - final checkResp = - await matrix.checkServer('https://fakeServer.notExisting'); + + await matrix.checkHomeserver('https://fakeServer.notExisting'); final loginResp = await matrix.login(user: 'test', password: '1234'); - expect(checkResp, true); expect(loginResp != null, true); }); diff --git a/test/encryption/encrypt_decrypt_to_device_test.dart b/test/encryption/encrypt_decrypt_to_device_test.dart index 4fbde05..3a95f75 100644 --- a/test/encryption/encrypt_decrypt_to_device_test.dart +++ b/test/encryption/encrypt_decrypt_to_device_test.dart @@ -50,7 +50,7 @@ void main() { test('setupClient', () async { client = await getClient(); otherClient.database = client.database; - await otherClient.checkServer('https://fakeServer.notExisting'); + await otherClient.checkHomeserver('https://fakeServer.notExisting'); otherClient.connect( newToken: 'abc', newUserID: '@othertest:fakeServer.notExisting', diff --git a/test/encryption/key_verification_test.dart b/test/encryption/key_verification_test.dart index 698cb61..27db626 100644 --- a/test/encryption/key_verification_test.dart +++ b/test/encryption/key_verification_test.dart @@ -85,7 +85,7 @@ void main() { client1 = await getClient(); client2 = Client('othertestclient', httpClient: FakeMatrixApi()); client2.database = client1.database; - await client2.checkServer('https://fakeServer.notExisting'); + await client2.checkHomeserver('https://fakeServer.notExisting'); client2.connect( newToken: 'abc', newUserID: '@othertest:fakeServer.notExisting', diff --git a/test/event_test.dart b/test/event_test.dart index 74d7c6a..645d7b0 100644 --- a/test/event_test.dart +++ b/test/event_test.dart @@ -264,7 +264,7 @@ void main() { test('sendAgain', () async { var matrix = Client('testclient', httpClient: FakeMatrixApi()); - await matrix.checkServer('https://fakeServer.notExisting'); + await matrix.checkHomeserver('https://fakeServer.notExisting'); await matrix.login(user: 'test', password: '1234'); var event = Event.fromJson( @@ -280,7 +280,7 @@ void main() { test('requestKey', () async { var matrix = Client('testclient', httpClient: FakeMatrixApi()); - await matrix.checkServer('https://fakeServer.notExisting'); + await matrix.checkHomeserver('https://fakeServer.notExisting'); await matrix.login(user: 'test', password: '1234'); var event = Event.fromJson( @@ -990,7 +990,7 @@ void main() { THUMBNAIL_BUFF, }[url]; }; - await client.checkServer('https://fakeServer.notExisting'); + await client.checkHomeserver('https://fakeServer.notExisting'); final room = Room(id: '!localpart:server.abc', client: client); var event = Event.fromJson({ 'type': EventTypes.Message, @@ -1133,7 +1133,7 @@ void main() { FILE_BUFF, }[url]; }; - await client.checkServer('https://fakeServer.notExisting'); + await client.checkHomeserver('https://fakeServer.notExisting'); final room = Room(id: '!localpart:server.abc', client: await getClient()); var event = Event.fromJson({ 'type': EventTypes.Message, diff --git a/test/fake_client.dart b/test/fake_client.dart index 5f30487..bcc7f18 100644 --- a/test/fake_client.dart +++ b/test/fake_client.dart @@ -31,7 +31,7 @@ const pickledOlmAccount = Future getClient() async { final client = Client('testclient', httpClient: FakeMatrixApi()); client.database = getDatabase(); - await client.checkServer('https://fakeServer.notExisting'); + await client.checkHomeserver('https://fakeServer.notExisting'); client.connect( newToken: 'abcd', newUserID: '@test:fakeServer.notExisting', diff --git a/test/mxc_uri_extension_test.dart b/test/mxc_uri_extension_test.dart index 30e6f84..37fdca2 100644 --- a/test/mxc_uri_extension_test.dart +++ b/test/mxc_uri_extension_test.dart @@ -27,7 +27,7 @@ void main() { group('MxContent', () { test('Formatting', () async { var client = Client('testclient', httpClient: FakeMatrixApi()); - await client.checkServer('https://fakeserver.notexisting'); + await client.checkHomeserver('https://fakeserver.notexisting'); final mxc = 'mxc://exampleserver.abc/abcdefghijklmn'; final content = Uri.parse(mxc); expect(content.isScheme('mxc'), true); diff --git a/test/timeline_test.dart b/test/timeline_test.dart index 6e1ddfa..428e772 100644 --- a/test/timeline_test.dart +++ b/test/timeline_test.dart @@ -49,7 +49,7 @@ void main() { }); test('Create', () async { - await client.checkServer('https://fakeServer.notExisting'); + await client.checkHomeserver('https://fakeServer.notExisting'); client.onEvent.add(EventUpdate( type: EventUpdateType.timeline, diff --git a/test/user_test.dart b/test/user_test.dart index fdb8c0b..e136bb8 100644 --- a/test/user_test.dart +++ b/test/user_test.dart @@ -85,28 +85,28 @@ void main() { user3.calcDisplayname(mxidLocalPartFallback: false), 'Unknown user'); }); test('kick', () async { - await client.checkServer('https://fakeserver.notexisting'); + await client.checkHomeserver('https://fakeserver.notexisting'); await user1.kick(); }); test('ban', () async { - await client.checkServer('https://fakeserver.notexisting'); + await client.checkHomeserver('https://fakeserver.notexisting'); await user1.ban(); }); test('unban', () async { - await client.checkServer('https://fakeserver.notexisting'); + await client.checkHomeserver('https://fakeserver.notexisting'); await user1.unban(); }); test('setPower', () async { - await client.checkServer('https://fakeserver.notexisting'); + await client.checkHomeserver('https://fakeserver.notexisting'); await user1.setPower(50); }); test('startDirectChat', () async { - await client.checkServer('https://fakeserver.notexisting'); + await client.checkHomeserver('https://fakeserver.notexisting'); await client.login(user: 'test', password: '1234'); await user1.startDirectChat(); }); test('getPresence', () async { - await client.checkServer('https://fakeserver.notexisting'); + await client.checkHomeserver('https://fakeserver.notexisting'); await client.handleSync(SyncUpdate.fromJson({ 'presence': { 'events': [ @@ -121,15 +121,15 @@ void main() { expect(user1.presence.presence.presence, PresenceType.online); }); test('canBan', () async { - await client.checkServer('https://fakeserver.notexisting'); + await client.checkHomeserver('https://fakeserver.notexisting'); expect(user1.canBan, false); }); test('canKick', () async { - await client.checkServer('https://fakeserver.notexisting'); + await client.checkHomeserver('https://fakeserver.notexisting'); expect(user1.canKick, false); }); test('canChangePowerLevel', () async { - await client.checkServer('https://fakeserver.notexisting'); + await client.checkHomeserver('https://fakeserver.notexisting'); expect(user1.canChangePowerLevel, false); }); test('dispose client', () async { diff --git a/test_driver/famedlysdk_test.dart b/test_driver/famedlysdk_test.dart index 1c19612..81300e4 100644 --- a/test_driver/famedlysdk_test.dart +++ b/test_driver/famedlysdk_test.dart @@ -24,7 +24,7 @@ void test() async { Logs.success('++++ Login Alice at ++++'); testClientA = Client('TestClientA'); testClientA.database = getDatabase(); - await testClientA.checkServer(TestUser.homeserver); + await testClientA.checkHomeserver(TestUser.homeserver); await testClientA.login( user: TestUser.username, password: TestUser.password); assert(testClientA.encryptionEnabled); @@ -32,7 +32,7 @@ void test() async { Logs.success('++++ Login Bob ++++'); testClientB = Client('TestClientB'); testClientB.database = getDatabase(); - await testClientB.checkServer(TestUser.homeserver); + await testClientB.checkHomeserver(TestUser.homeserver); await testClientB.login( user: TestUser.username2, password: TestUser.password); assert(testClientB.encryptionEnabled); @@ -222,7 +222,7 @@ void test() async { Logs.success('++++ Login Bob in another client ++++'); var testClientC = Client('TestClientC', database: getDatabase()); - await testClientC.checkServer(TestUser.homeserver); + await testClientC.checkHomeserver(TestUser.homeserver); await testClientC.login( user: TestUser.username2, password: TestUser.password); await Future.delayed(Duration(seconds: 3));