import 'dart:convert'; import 'package:famedlysdk/matrix_api.dart'; import '../client.dart'; import '../database/database.dart' show DbUserDeviceKey, DbUserDeviceKeysKey; import '../event.dart'; import 'key_verification.dart'; class DeviceKeysList { String userId; bool outdated = true; Map deviceKeys = {}; DeviceKeysList.fromDb( DbUserDeviceKey dbEntry, List childEntries) { userId = dbEntry.userId; outdated = dbEntry.outdated; deviceKeys = {}; for (final childEntry in childEntries) { final entry = DeviceKeys.fromDb(childEntry); if (entry.isValid) { deviceKeys[childEntry.deviceId] = entry; } else { outdated = true; } } } DeviceKeysList.fromJson(Map json) { userId = json['user_id']; outdated = json['outdated']; deviceKeys = {}; for (final rawDeviceKeyEntry in json['device_keys'].entries) { deviceKeys[rawDeviceKeyEntry.key] = DeviceKeys.fromJson(rawDeviceKeyEntry.value); } } Map toJson() { var map = {}; final data = map; data['user_id'] = userId; data['outdated'] = outdated ?? true; var rawDeviceKeys = {}; for (final deviceKeyEntry in deviceKeys.entries) { rawDeviceKeys[deviceKeyEntry.key] = deviceKeyEntry.value.toJson(); } data['device_keys'] = rawDeviceKeys; return data; } @override String toString() => json.encode(toJson()); DeviceKeysList(this.userId); } class DeviceKeys extends MatrixDeviceKeys { bool verified; bool blocked; String get curve25519Key => keys['curve25519:$deviceId']; String get ed25519Key => keys['ed25519:$deviceId']; bool get isValid => userId != null && deviceId != null && curve25519Key != null && ed25519Key != null; Future setVerified(bool newVerified, Client client) { verified = newVerified; return client.database ?.setVerifiedUserDeviceKey(newVerified, client.id, userId, deviceId); } Future setBlocked(bool newBlocked, Client client) { blocked = newBlocked; for (var room in client.rooms) { if (!room.encrypted) continue; if (room.getParticipants().indexWhere((u) => u.id == userId) != -1) { room.clearOutboundGroupSession(); } } return client.database ?.setBlockedUserDeviceKey(newBlocked, client.id, userId, deviceId); } DeviceKeys({ String userId, String deviceId, List algorithms, Map keys, Map> signatures, Map unsigned, this.verified, this.blocked, }) : super(userId, deviceId, algorithms, keys, signatures, unsigned: unsigned); factory DeviceKeys.fromMatrixDeviceKeys(MatrixDeviceKeys matrixDeviceKeys) => DeviceKeys( userId: matrixDeviceKeys.userId, deviceId: matrixDeviceKeys.deviceId, algorithms: matrixDeviceKeys.algorithms, keys: matrixDeviceKeys.keys, signatures: matrixDeviceKeys.signatures, unsigned: matrixDeviceKeys.unsigned, verified: false, blocked: false, ); static DeviceKeys fromDb(DbUserDeviceKeysKey dbEntry) { var deviceKeys = DeviceKeys(); final content = Event.getMapFromPayload(dbEntry.content); deviceKeys.userId = dbEntry.userId; deviceKeys.deviceId = dbEntry.deviceId; deviceKeys.algorithms = content['algorithms'].cast(); deviceKeys.keys = content['keys'] != null ? Map.from(content['keys']) : null; deviceKeys.signatures = content['signatures'] != null ? Map>.from((content['signatures'] as Map) .map((k, v) => MapEntry(k, Map.from(v)))) : null; deviceKeys.unsigned = content['unsigned'] != null ? Map.from(content['unsigned']) : null; deviceKeys.verified = dbEntry.verified; deviceKeys.blocked = dbEntry.blocked; return deviceKeys; } static DeviceKeys fromJson(Map json) { var matrixDeviceKeys = MatrixDeviceKeys.fromJson(json); var deviceKeys = DeviceKeys( userId: matrixDeviceKeys.userId, deviceId: matrixDeviceKeys.deviceId, algorithms: matrixDeviceKeys.algorithms, keys: matrixDeviceKeys.keys, signatures: matrixDeviceKeys.signatures, unsigned: matrixDeviceKeys.unsigned, ); deviceKeys.verified = json['verified'] ?? false; deviceKeys.blocked = json['blocked'] ?? false; return deviceKeys; } @override Map toJson() { final data = super.toJson(); data['verified'] = verified; data['blocked'] = blocked; return data; } KeyVerification startVerification(Client client) { final request = KeyVerification(client: client, userId: userId, deviceId: deviceId); request.start(); client.addKeyVerificationRequest(request); return request; } }