From 77b11d78dbe530590bfde66d05efb0a3c715ea1d Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Wed, 19 Feb 2020 14:26:38 +0100 Subject: [PATCH] [Client] Implement device management --- lib/src/client.dart | 35 ++++++++++++++++++++++ lib/src/utils/user_device.dart | 54 ++++++++++++++++++++++++++++++++++ test/client_test.dart | 11 +++++++ test/fake_matrix_api.dart | 10 +++++++ 4 files changed, 110 insertions(+) create mode 100644 lib/src/utils/user_device.dart diff --git a/lib/src/client.dart b/lib/src/client.dart index c250656..8ef45c1 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -36,6 +36,7 @@ import 'package:famedlysdk/src/utils/open_id_credentials.dart'; import 'package:famedlysdk/src/utils/session_key.dart'; import 'package:famedlysdk/src/utils/to_device_event.dart'; import 'package:famedlysdk/src/utils/turn_server_credentials.dart'; +import 'package:famedlysdk/src/utils/user_device.dart'; import 'package:olm/olm.dart' as olm; import 'package:pedantic/pedantic.dart'; import 'room.dart'; @@ -1745,4 +1746,38 @@ class Client { } } } + + /// Gets information about all devices for the current user. + Future> requestUserDevices() async { + final Map response = + await jsonRequest(type: HTTPType.GET, action: "/client/r0/devices"); + List userDevices = []; + for (final rawDevice in response["devices"]) { + userDevices.add( + UserDevice.fromJson(rawDevice, this), + ); + } + return userDevices; + } + + /// Gets information about all devices for the current user. + Future requestUserDevice(String deviceId) async { + final Map response = await jsonRequest( + type: HTTPType.GET, action: "/client/r0/devices/$deviceId"); + return UserDevice.fromJson(response, this); + } + + /// Deletes the given devices, and invalidates any access token associated with them. + Future deleteDevices(List deviceIds, + {Map auth}) async { + await jsonRequest( + type: HTTPType.POST, + action: "/client/r0/delete_devices", + data: { + "devices": deviceIds, + if (auth != null) "auth": auth, + }, + ); + return; + } } diff --git a/lib/src/utils/user_device.dart b/lib/src/utils/user_device.dart new file mode 100644 index 0000000..b81105d --- /dev/null +++ b/lib/src/utils/user_device.dart @@ -0,0 +1,54 @@ +import '../client.dart'; + +/// Registered device for this user. +class UserDevice { + /// Identifier of this device. + final String deviceId; + + /// Display name set by the user for this device. Absent if no name has been set. + final String displayName; + + /// The IP address where this device was last seen. (May be a few minutes out of date, for efficiency reasons). + final String lastSeenIp; + + /// The time when this devices was last seen. (May be a few minutes out of date, for efficiency reasons). + final DateTime lastSeenTs; + + final Client _client; + + /// Updates the metadata on the given device. + Future updateMetaData(String newName) async { + await _client.jsonRequest( + type: HTTPType.PUT, + action: "/client/r0/devices/$deviceId", + data: {"display_name": newName}, + ); + return; + } + + /// Deletes the given device, and invalidates any access token associated with it. + Future deleteDevice(Map auth) async { + await _client.jsonRequest( + type: HTTPType.DELETE, + action: "/client/r0/devices/$deviceId", + data: auth != null ? {"auth": auth} : null, + ); + return; + } + + UserDevice( + this._client, { + this.deviceId, + this.displayName, + this.lastSeenIp, + this.lastSeenTs, + }); + + UserDevice.fromJson(Map json, Client client) + : deviceId = json['device_id'], + displayName = json['display_name'], + lastSeenIp = json['last_seen_ip'], + lastSeenTs = + DateTime.fromMillisecondsSinceEpoch(json['last_seen_ts'] ?? 0), + _client = client; +} diff --git a/test/client_test.dart b/test/client_test.dart index 3638db4..9ef4f52 100644 --- a/test/client_test.dart +++ b/test/client_test.dart @@ -36,6 +36,7 @@ import 'package:famedlysdk/src/sync/user_update.dart'; import 'package:famedlysdk/src/utils/matrix_exception.dart'; import 'package:famedlysdk/src/utils/matrix_file.dart'; import 'package:famedlysdk/src/utils/profile.dart'; +import 'package:famedlysdk/src/utils/user_device.dart'; import 'package:olm/olm.dart' as olm; import 'package:test/test.dart'; @@ -448,6 +449,16 @@ void main() { expect(resp["room_id"], roomID); }); + test('requestUserDevices', () async { + final List userDevices = await matrix.requestUserDevices(); + expect(userDevices.length, 1); + expect(userDevices.first.deviceId, "QBUAZIFURK"); + expect(userDevices.first.displayName, "android"); + expect(userDevices.first.lastSeenIp, "1.2.3.4"); + expect( + userDevices.first.lastSeenTs.millisecondsSinceEpoch, 1474491775024); + }); + test('get archive', () async { List archive = await matrix.archive; diff --git a/test/fake_matrix_api.dart b/test/fake_matrix_api.dart index 2f68a09..2c1afcc 100644 --- a/test/fake_matrix_api.dart +++ b/test/fake_matrix_api.dart @@ -548,6 +548,16 @@ class FakeMatrixApi extends MockClient { static final Map> api = { "GET": { + "/client/r0/devices": (var req) => { + "devices": [ + { + "device_id": "QBUAZIFURK", + "display_name": "android", + "last_seen_ip": "1.2.3.4", + "last_seen_ts": 1474491775024 + } + ] + }, "/client/r0/rooms/1/state/m.room.member/@alice:example.com": (var req) => {"displayname": "Alice"}, "/client/r0/profile/@getme:example.com": (var req) => {