From 0b393497f8d6835e8734c46e5c5e55b2c7baed02 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Tue, 14 Jan 2020 15:16:24 +0000 Subject: [PATCH] =?UTF-8?q?[Client]=C2=A0Add=20register=20methods?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/src/client.dart | 116 +++++++++++++++++++++------- lib/src/utils/matrix_exception.dart | 4 +- test/client_test.dart | 12 +++ test/fake_matrix_api.dart | 7 ++ 4 files changed, 109 insertions(+), 30 deletions(-) diff --git a/lib/src/client.dart b/lib/src/client.dart index 82669a4b..30951079 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -234,39 +234,99 @@ class Client { } } + /// Checks to see if a username is available, and valid, for the server. + /// You have to call [checkServer] first to set a homeserver. + Future usernameAvailable(String username) async { + final Map response = await this.jsonRequest( + type: HTTPType.GET, + action: "/client/r0/register/available?username=$username", + ); + return response["available"]; + } + + /// 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. + Future> register({ + String kind, + String username, + String password, + Map auth, + String deviceId, + String initialDeviceDisplayName, + bool inhibitLogin, + }) async { + final String action = + "/client/r0/register" + (kind != null ? "?kind=$kind" : ""); + Map data = {}; + if (username != null) data["username"] = username; + if (password != null) data["password"] = password; + if (auth != null) data["auth"] = auth; + if (deviceId != null) data["device_id"] = deviceId; + if (initialDeviceDisplayName != null) { + data["initial_device_display_name"] = initialDeviceDisplayName; + } + if (inhibitLogin != null) data["inhibit_login"] = inhibitLogin; + final Map response = + await this.jsonRequest(type: HTTPType.POST, action: action, data: data); + + // Connect if there is an access token in the response. + if (response.containsKey("access_token") && + response.containsKey("device_id") && + response.containsKey("user_id")) { + await this.connect( + newToken: response["access_token"], + newUserID: response["user_id"], + newHomeserver: homeserver, + newDeviceName: initialDeviceDisplayName ?? "", + newDeviceID: response["device_id"], + newMatrixVersions: matrixVersions, + newLazyLoadMembers: lazyLoadMembers); + } + return response; + } + /// 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. - Future login(String username, String password) async { - final loginResp = await jsonRequest( - type: HTTPType.POST, - action: "/client/r0/login", - data: { - "type": "m.login.password", - "user": username, - "identifier": { - "type": "m.id.user", - "user": username, - }, - "password": password, - "initial_device_display_name": "Famedly Talk" - }); - - final userID = loginResp["user_id"]; - final accessToken = loginResp["access_token"]; - if (userID == null || accessToken == null) { - return false; + /// You have to call [checkServer] first to set a homeserver. + Future login( + String username, + String password, { + String initialDeviceDisplayName, + String deviceId, + }) async { + Map data = { + "type": "m.login.password", + "user": username, + "identifier": { + "type": "m.id.user", + "user": username, + }, + "password": password, + }; + if (deviceId != null) data["device_id"] = deviceId; + if (initialDeviceDisplayName != null) { + data["initial_device_display_name"] = initialDeviceDisplayName; } - await this.connect( - newToken: accessToken, - newUserID: userID, - newHomeserver: homeserver, - newDeviceName: "", - newDeviceID: "", - newMatrixVersions: matrixVersions, - newLazyLoadMembers: lazyLoadMembers); - return true; + final loginResp = await jsonRequest( + type: HTTPType.POST, action: "/client/r0/login", data: data); + + if (loginResp.containsKey("user_id") && + loginResp.containsKey("access_token") && + loginResp.containsKey("device_id")) { + await this.connect( + newToken: loginResp["access_token"], + newUserID: loginResp["user_id"], + newHomeserver: homeserver, + newDeviceName: initialDeviceDisplayName ?? "", + newDeviceID: loginResp["device_id"], + newMatrixVersions: matrixVersions, + newLazyLoadMembers: lazyLoadMembers); + return true; + } + return false; } /// Sends a logout command to the homeserver and clears all local data, diff --git a/lib/src/utils/matrix_exception.dart b/lib/src/utils/matrix_exception.dart index 44f447e8..d1c1685c 100644 --- a/lib/src/utils/matrix_exception.dart +++ b/lib/src/utils/matrix_exception.dart @@ -87,8 +87,8 @@ class MatrixException implements Exception { if (!raw.containsKey("flows") || !(raw["flows"] is List)) return null; List flows = []; for (Map flow in raw["flows"]) { - if (flow["stages"] is List) { - flows.add(AuthenticationFlow(flow["stages"])); + if (flow["stages"] is List) { + flows.add(AuthenticationFlow(List.from(flow["stages"]))); } } return flows; diff --git a/test/client_test.dart b/test/client_test.dart index ebbe3de1..17342de0 100644 --- a/test/client_test.dart +++ b/test/client_test.dart @@ -88,6 +88,18 @@ void main() { "initial_device_display_name": "Fluffy Matrix Client" }); + final bool available = await matrix.usernameAvailable("testuser"); + expect(available, true); + + Map registerResponse = await matrix.register(username: "testuser"); + expect(registerResponse["user_id"], "@testuser:example.com"); + registerResponse = + await matrix.register(username: "testuser", kind: "user"); + expect(registerResponse["user_id"], "@testuser:example.com"); + registerResponse = + await matrix.register(username: "testuser", kind: "guest"); + expect(registerResponse["user_id"], "@testuser:example.com"); + Future loginStateFuture = matrix.onLoginStateChanged.stream.first; Future firstSyncFuture = matrix.onFirstSync.stream.first; diff --git a/test/fake_matrix_api.dart b/test/fake_matrix_api.dart index 3eb58ff5..1911b473 100644 --- a/test/fake_matrix_api.dart +++ b/test/fake_matrix_api.dart @@ -756,8 +756,15 @@ class FakeMatrixApi extends MockClient { (var req) => archiveSyncResponse, "/client/r0/sync?filter=%7B%22room%22:%7B%22state%22:%7B%22lazy_load_members%22:true%7D%7D%7D": (var req) => syncResponse, + "/client/r0/register/available?username=testuser": (var req) => + {"available": true}, }, "POST": { + "/client/r0/register": (var req) => {"user_id": "@testuser:example.com"}, + "/client/r0/register?kind=user": (var req) => + {"user_id": "@testuser:example.com"}, + "/client/r0/register?kind=guest": (var req) => + {"user_id": "@testuser:example.com"}, "/client/r0/user/@test:fakeServer.notExisting/openid/request_token": (var req) => { "access_token": "SomeT0kenHere",