feat: Replay last sent olm message on olm session recovery from other device

This commit is contained in:
Sorunome 2021-01-15 15:43:31 +01:00
parent 667d8e919d
commit a35266f1e4
No known key found for this signature in database
GPG Key ID: B19471D07FC9BE9C
37 changed files with 270 additions and 57 deletions

View File

@ -93,6 +93,11 @@ class Encryption {
// them in the background // them in the background
unawaited(runInRoot(() => keyManager.handleToDeviceEvent(event))); unawaited(runInRoot(() => keyManager.handleToDeviceEvent(event)));
} }
if (event.type == EventTypes.Dummy) {
// the previous device just had to create a new olm session, due to olm session
// corruption. We want to try to send it the last message we just sent it, if possible
unawaited(runInRoot(() => olmManager.handleToDeviceEvent(event)));
}
if (event.type.startsWith('m.key.verification.')) { if (event.type.startsWith('m.key.verification.')) {
// some key verification event. No need to handle it now, we can easily // some key verification event. No need to handle it now, we can easily
// do this in the background // do this in the background
@ -336,12 +341,6 @@ class Encryption {
return encryptedPayload; return encryptedPayload;
} }
Future<Map<String, dynamic>> encryptToDeviceMessagePayload(
DeviceKeys device, String type, Map<String, dynamic> payload) async {
return await olmManager.encryptToDeviceMessagePayload(
device, type, payload);
}
Future<Map<String, dynamic>> encryptToDeviceMessage( Future<Map<String, dynamic>> encryptToDeviceMessage(
List<DeviceKeys> deviceKeys, List<DeviceKeys> deviceKeys,
String type, String type,

View File

@ -444,7 +444,7 @@ class OlmManager {
} }
_restoredOlmSessionsTime[mapKey] = DateTime.now(); _restoredOlmSessionsTime[mapKey] = DateTime.now();
await startOutgoingOlmSessions([device]); await startOutgoingOlmSessions([device]);
await client.sendToDeviceEncrypted([device], 'm.dummy', {}); await client.sendToDeviceEncrypted([device], EventTypes.Dummy, {});
} }
Future<ToDeviceEvent> decryptToDeviceEvent(ToDeviceEvent event) async { Future<ToDeviceEvent> decryptToDeviceEvent(ToDeviceEvent event) async {
@ -542,6 +542,16 @@ class OlmManager {
}; };
final encryptResult = sess.first.session.encrypt(json.encode(fullPayload)); final encryptResult = sess.first.session.encrypt(json.encode(fullPayload));
storeOlmSession(sess.first); storeOlmSession(sess.first);
if (client.database != null) {
unawaited(client.database.setLastSentMessageUserDeviceKey(
json.encode({
'type': type,
'content': payload,
}),
client.id,
device.userId,
device.deviceId));
}
final encryptedBody = <String, dynamic>{ final encryptedBody = <String, dynamic>{
'algorithm': AlgorithmTypes.olmV1Curve25519AesSha2, 'algorithm': AlgorithmTypes.olmV1Curve25519AesSha2,
'sender_key': identityKey, 'sender_key': identityKey,
@ -587,6 +597,35 @@ class OlmManager {
return data; return data;
} }
Future<void> handleToDeviceEvent(ToDeviceEvent event) async {
if (event.type == EventTypes.Dummy) {
// We receive dan encrypted m.dummy. This means that the other end was not able to
// decrypt our last message. So, we re-send it.
if (event.encryptedContent == null || client.database == null) {
return;
}
final device = client.getUserDeviceKeysByCurve25519Key(
event.encryptedContent.tryGet<String>('sender_key', ''));
if (device == null) {
return; // device not found
}
Logs().v(
'[OlmManager] Device ${device.userId}:${device.deviceId} generated a new olm session, replaying last sent message...');
final lastSentMessageRes = await client.database
.getLastSentMessageUserDeviceKey(
client.id, device.userId, device.deviceId)
.get();
if (lastSentMessageRes.isEmpty ||
(lastSentMessageRes.first?.isEmpty ?? true)) {
return;
}
final lastSentMessage = json.decode(lastSentMessageRes.first);
// okay, time to send the message!
await client.sendToDeviceEncrypted(
[device], lastSentMessage['type'], lastSentMessage['content']);
}
}
void dispose() { void dispose() {
for (final sessions in olmSessions.values) { for (final sessions in olmSessions.values) {
for (final sess in sessions) { for (final sess in sessions) {

View File

@ -70,7 +70,7 @@ class Database extends _$Database {
Database.connect(DatabaseConnection connection) : super.connect(connection); Database.connect(DatabaseConnection connection) : super.connect(connection);
@override @override
int get schemaVersion => 9; int get schemaVersion => 10;
int get maxFileSize => 1 * 1024 * 1024; int get maxFileSize => 1 * 1024 * 1024;
@ -164,6 +164,12 @@ class Database extends _$Database {
userDeviceKeysKey, userDeviceKeysKey.lastActive); userDeviceKeysKey, userDeviceKeysKey.lastActive);
from++; from++;
} }
if (from == 9) {
await m.addColumnIfNotExists(
userDeviceKeysKey, userDeviceKeysKey.lastSentMessage);
await m.createIndexIfNotExists(olmSessionsIdentityIndex);
from++;
}
} catch (e, s) { } catch (e, s) {
api.Logs().e('Database migration failed', e, s); api.Logs().e('Database migration failed', e, s);
onError.add(SdkError(exception: e, stackTrace: s)); onError.add(SdkError(exception: e, stackTrace: s));

View File

@ -769,6 +769,7 @@ class DbUserDeviceKeysKey extends DataClass
final bool verified; final bool verified;
final bool blocked; final bool blocked;
final int lastActive; final int lastActive;
final String lastSentMessage;
DbUserDeviceKeysKey( DbUserDeviceKeysKey(
{@required this.clientId, {@required this.clientId,
@required this.userId, @required this.userId,
@ -776,7 +777,8 @@ class DbUserDeviceKeysKey extends DataClass
@required this.content, @required this.content,
this.verified, this.verified,
this.blocked, this.blocked,
this.lastActive}); this.lastActive,
this.lastSentMessage});
factory DbUserDeviceKeysKey.fromData( factory DbUserDeviceKeysKey.fromData(
Map<String, dynamic> data, GeneratedDatabase db, Map<String, dynamic> data, GeneratedDatabase db,
{String prefix}) { {String prefix}) {
@ -799,6 +801,8 @@ class DbUserDeviceKeysKey extends DataClass
boolType.mapFromDatabaseResponse(data['${effectivePrefix}blocked']), boolType.mapFromDatabaseResponse(data['${effectivePrefix}blocked']),
lastActive: intType lastActive: intType
.mapFromDatabaseResponse(data['${effectivePrefix}last_active']), .mapFromDatabaseResponse(data['${effectivePrefix}last_active']),
lastSentMessage: stringType
.mapFromDatabaseResponse(data['${effectivePrefix}last_sent_message']),
); );
} }
@override @override
@ -825,6 +829,9 @@ class DbUserDeviceKeysKey extends DataClass
if (!nullToAbsent || lastActive != null) { if (!nullToAbsent || lastActive != null) {
map['last_active'] = Variable<int>(lastActive); map['last_active'] = Variable<int>(lastActive);
} }
if (!nullToAbsent || lastSentMessage != null) {
map['last_sent_message'] = Variable<String>(lastSentMessage);
}
return map; return map;
} }
@ -850,6 +857,9 @@ class DbUserDeviceKeysKey extends DataClass
lastActive: lastActive == null && nullToAbsent lastActive: lastActive == null && nullToAbsent
? const Value.absent() ? const Value.absent()
: Value(lastActive), : Value(lastActive),
lastSentMessage: lastSentMessage == null && nullToAbsent
? const Value.absent()
: Value(lastSentMessage),
); );
} }
@ -864,6 +874,7 @@ class DbUserDeviceKeysKey extends DataClass
verified: serializer.fromJson<bool>(json['verified']), verified: serializer.fromJson<bool>(json['verified']),
blocked: serializer.fromJson<bool>(json['blocked']), blocked: serializer.fromJson<bool>(json['blocked']),
lastActive: serializer.fromJson<int>(json['last_active']), lastActive: serializer.fromJson<int>(json['last_active']),
lastSentMessage: serializer.fromJson<String>(json['last_sent_message']),
); );
} }
@override @override
@ -877,6 +888,7 @@ class DbUserDeviceKeysKey extends DataClass
'verified': serializer.toJson<bool>(verified), 'verified': serializer.toJson<bool>(verified),
'blocked': serializer.toJson<bool>(blocked), 'blocked': serializer.toJson<bool>(blocked),
'last_active': serializer.toJson<int>(lastActive), 'last_active': serializer.toJson<int>(lastActive),
'last_sent_message': serializer.toJson<String>(lastSentMessage),
}; };
} }
@ -887,7 +899,8 @@ class DbUserDeviceKeysKey extends DataClass
String content, String content,
bool verified, bool verified,
bool blocked, bool blocked,
int lastActive}) => int lastActive,
String lastSentMessage}) =>
DbUserDeviceKeysKey( DbUserDeviceKeysKey(
clientId: clientId ?? this.clientId, clientId: clientId ?? this.clientId,
userId: userId ?? this.userId, userId: userId ?? this.userId,
@ -896,6 +909,7 @@ class DbUserDeviceKeysKey extends DataClass
verified: verified ?? this.verified, verified: verified ?? this.verified,
blocked: blocked ?? this.blocked, blocked: blocked ?? this.blocked,
lastActive: lastActive ?? this.lastActive, lastActive: lastActive ?? this.lastActive,
lastSentMessage: lastSentMessage ?? this.lastSentMessage,
); );
@override @override
String toString() { String toString() {
@ -906,7 +920,8 @@ class DbUserDeviceKeysKey extends DataClass
..write('content: $content, ') ..write('content: $content, ')
..write('verified: $verified, ') ..write('verified: $verified, ')
..write('blocked: $blocked, ') ..write('blocked: $blocked, ')
..write('lastActive: $lastActive') ..write('lastActive: $lastActive, ')
..write('lastSentMessage: $lastSentMessage')
..write(')')) ..write(')'))
.toString(); .toString();
} }
@ -920,8 +935,12 @@ class DbUserDeviceKeysKey extends DataClass
deviceId.hashCode, deviceId.hashCode,
$mrjc( $mrjc(
content.hashCode, content.hashCode,
$mrjc(verified.hashCode, $mrjc(
$mrjc(blocked.hashCode, lastActive.hashCode))))))); verified.hashCode,
$mrjc(
blocked.hashCode,
$mrjc(lastActive.hashCode,
lastSentMessage.hashCode))))))));
@override @override
bool operator ==(dynamic other) => bool operator ==(dynamic other) =>
identical(this, other) || identical(this, other) ||
@ -932,7 +951,8 @@ class DbUserDeviceKeysKey extends DataClass
other.content == this.content && other.content == this.content &&
other.verified == this.verified && other.verified == this.verified &&
other.blocked == this.blocked && other.blocked == this.blocked &&
other.lastActive == this.lastActive); other.lastActive == this.lastActive &&
other.lastSentMessage == this.lastSentMessage);
} }
class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> { class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
@ -943,6 +963,7 @@ class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
final Value<bool> verified; final Value<bool> verified;
final Value<bool> blocked; final Value<bool> blocked;
final Value<int> lastActive; final Value<int> lastActive;
final Value<String> lastSentMessage;
const UserDeviceKeysKeyCompanion({ const UserDeviceKeysKeyCompanion({
this.clientId = const Value.absent(), this.clientId = const Value.absent(),
this.userId = const Value.absent(), this.userId = const Value.absent(),
@ -951,6 +972,7 @@ class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
this.verified = const Value.absent(), this.verified = const Value.absent(),
this.blocked = const Value.absent(), this.blocked = const Value.absent(),
this.lastActive = const Value.absent(), this.lastActive = const Value.absent(),
this.lastSentMessage = const Value.absent(),
}); });
UserDeviceKeysKeyCompanion.insert({ UserDeviceKeysKeyCompanion.insert({
@required int clientId, @required int clientId,
@ -960,6 +982,7 @@ class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
this.verified = const Value.absent(), this.verified = const Value.absent(),
this.blocked = const Value.absent(), this.blocked = const Value.absent(),
this.lastActive = const Value.absent(), this.lastActive = const Value.absent(),
this.lastSentMessage = const Value.absent(),
}) : clientId = Value(clientId), }) : clientId = Value(clientId),
userId = Value(userId), userId = Value(userId),
deviceId = Value(deviceId), deviceId = Value(deviceId),
@ -972,6 +995,7 @@ class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
Expression<bool> verified, Expression<bool> verified,
Expression<bool> blocked, Expression<bool> blocked,
Expression<int> lastActive, Expression<int> lastActive,
Expression<String> lastSentMessage,
}) { }) {
return RawValuesInsertable({ return RawValuesInsertable({
if (clientId != null) 'client_id': clientId, if (clientId != null) 'client_id': clientId,
@ -981,6 +1005,7 @@ class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
if (verified != null) 'verified': verified, if (verified != null) 'verified': verified,
if (blocked != null) 'blocked': blocked, if (blocked != null) 'blocked': blocked,
if (lastActive != null) 'last_active': lastActive, if (lastActive != null) 'last_active': lastActive,
if (lastSentMessage != null) 'last_sent_message': lastSentMessage,
}); });
} }
@ -991,7 +1016,8 @@ class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
Value<String> content, Value<String> content,
Value<bool> verified, Value<bool> verified,
Value<bool> blocked, Value<bool> blocked,
Value<int> lastActive}) { Value<int> lastActive,
Value<String> lastSentMessage}) {
return UserDeviceKeysKeyCompanion( return UserDeviceKeysKeyCompanion(
clientId: clientId ?? this.clientId, clientId: clientId ?? this.clientId,
userId: userId ?? this.userId, userId: userId ?? this.userId,
@ -1000,6 +1026,7 @@ class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
verified: verified ?? this.verified, verified: verified ?? this.verified,
blocked: blocked ?? this.blocked, blocked: blocked ?? this.blocked,
lastActive: lastActive ?? this.lastActive, lastActive: lastActive ?? this.lastActive,
lastSentMessage: lastSentMessage ?? this.lastSentMessage,
); );
} }
@ -1027,6 +1054,9 @@ class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
if (lastActive.present) { if (lastActive.present) {
map['last_active'] = Variable<int>(lastActive.value); map['last_active'] = Variable<int>(lastActive.value);
} }
if (lastSentMessage.present) {
map['last_sent_message'] = Variable<String>(lastSentMessage.value);
}
return map; return map;
} }
@ -1039,7 +1069,8 @@ class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
..write('content: $content, ') ..write('content: $content, ')
..write('verified: $verified, ') ..write('verified: $verified, ')
..write('blocked: $blocked, ') ..write('blocked: $blocked, ')
..write('lastActive: $lastActive') ..write('lastActive: $lastActive, ')
..write('lastSentMessage: $lastSentMessage')
..write(')')) ..write(')'))
.toString(); .toString();
} }
@ -1108,9 +1139,27 @@ class UserDeviceKeysKey extends Table
$customConstraints: ''); $customConstraints: '');
} }
final VerificationMeta _lastSentMessageMeta =
const VerificationMeta('lastSentMessage');
GeneratedTextColumn _lastSentMessage;
GeneratedTextColumn get lastSentMessage =>
_lastSentMessage ??= _constructLastSentMessage();
GeneratedTextColumn _constructLastSentMessage() {
return GeneratedTextColumn('last_sent_message', $tableName, true,
$customConstraints: '');
}
@override @override
List<GeneratedColumn> get $columns => List<GeneratedColumn> get $columns => [
[clientId, userId, deviceId, content, verified, blocked, lastActive]; clientId,
userId,
deviceId,
content,
verified,
blocked,
lastActive,
lastSentMessage
];
@override @override
UserDeviceKeysKey get asDslTable => this; UserDeviceKeysKey get asDslTable => this;
@override @override
@ -1161,6 +1210,12 @@ class UserDeviceKeysKey extends Table
lastActive.isAcceptableOrUnknown( lastActive.isAcceptableOrUnknown(
data['last_active'], _lastActiveMeta)); data['last_active'], _lastActiveMeta));
} }
if (data.containsKey('last_sent_message')) {
context.handle(
_lastSentMessageMeta,
lastSentMessage.isAcceptableOrUnknown(
data['last_sent_message'], _lastSentMessageMeta));
}
return context; return context;
} }
@ -6136,6 +6191,10 @@ abstract class _$Database extends GeneratedDatabase {
Index get olmSessionsIndex => _olmSessionsIndex ??= Index( Index get olmSessionsIndex => _olmSessionsIndex ??= Index(
'olm_sessions_index', 'olm_sessions_index',
'CREATE INDEX olm_sessions_index ON olm_sessions(client_id);'); 'CREATE INDEX olm_sessions_index ON olm_sessions(client_id);');
Index _olmSessionsIdentityIndex;
Index get olmSessionsIdentityIndex => _olmSessionsIdentityIndex ??= Index(
'olm_sessions_identity_index',
'CREATE INDEX olm_sessions_identity_index ON olm_sessions(client_id, identity_key);');
OutboundGroupSessions _outboundGroupSessions; OutboundGroupSessions _outboundGroupSessions;
OutboundGroupSessions get outboundGroupSessions => OutboundGroupSessions get outboundGroupSessions =>
_outboundGroupSessions ??= OutboundGroupSessions(this); _outboundGroupSessions ??= OutboundGroupSessions(this);
@ -6574,6 +6633,35 @@ abstract class _$Database extends GeneratedDatabase {
); );
} }
Future<int> setLastSentMessageUserDeviceKey(String last_sent_message,
int client_id, String user_id, String device_id) {
return customUpdate(
'UPDATE user_device_keys_key SET last_sent_message = :last_sent_message WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id',
variables: [
Variable.withString(last_sent_message),
Variable.withInt(client_id),
Variable.withString(user_id),
Variable.withString(device_id)
],
updates: {userDeviceKeysKey},
updateKind: UpdateKind.update,
);
}
Selectable<String> getLastSentMessageUserDeviceKey(
int client_id, String user_id, String device_id) {
return customSelect(
'SELECT last_sent_message FROM user_device_keys_key WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id',
variables: [
Variable.withInt(client_id),
Variable.withString(user_id),
Variable.withString(device_id)
],
readsFrom: {
userDeviceKeysKey
}).map((QueryRow row) => row.readString('last_sent_message'));
}
Future<int> setVerifiedUserCrossSigningKey( Future<int> setVerifiedUserCrossSigningKey(
bool verified, int client_id, String user_id, String public_key) { bool verified, int client_id, String user_id, String public_key) {
return customUpdate( return customUpdate(
@ -7068,6 +7156,7 @@ abstract class _$Database extends GeneratedDatabase {
userCrossSigningKeysIndex, userCrossSigningKeysIndex,
olmSessions, olmSessions,
olmSessionsIndex, olmSessionsIndex,
olmSessionsIdentityIndex,
outboundGroupSessions, outboundGroupSessions,
outboundGroupSessionsIndex, outboundGroupSessionsIndex,
inboundGroupSessions, inboundGroupSessions,

View File

@ -29,6 +29,7 @@ CREATE TABLE user_device_keys_key (
verified BOOLEAN DEFAULT false, verified BOOLEAN DEFAULT false,
blocked BOOLEAN DEFAULT false, blocked BOOLEAN DEFAULT false,
last_active BIGINT, last_active BIGINT,
last_sent_message TEXT,
UNIQUE(client_id, user_id, device_id) UNIQUE(client_id, user_id, device_id)
) as DbUserDeviceKeysKey; ) as DbUserDeviceKeysKey;
CREATE INDEX user_device_keys_key_index ON user_device_keys_key(client_id); CREATE INDEX user_device_keys_key_index ON user_device_keys_key(client_id);
@ -53,6 +54,7 @@ CREATE TABLE olm_sessions (
UNIQUE(client_id, identity_key, session_id) UNIQUE(client_id, identity_key, session_id)
) AS DbOlmSessions; ) AS DbOlmSessions;
CREATE INDEX olm_sessions_index ON olm_sessions(client_id); CREATE INDEX olm_sessions_index ON olm_sessions(client_id);
CREATE INDEX olm_sessions_identity_index ON olm_sessions(client_id, identity_key);
CREATE TABLE outbound_group_sessions ( CREATE TABLE outbound_group_sessions (
client_id INTEGER NOT NULL REFERENCES clients(client_id), client_id INTEGER NOT NULL REFERENCES clients(client_id),
@ -204,6 +206,8 @@ setBlockedUserDeviceKey: UPDATE user_device_keys_key SET blocked = :blocked WHER
storeUserDeviceKey: INSERT OR REPLACE INTO user_device_keys_key (client_id, user_id, device_id, content, verified, blocked, last_active) VALUES (:client_id, :user_id, :device_id, :content, :verified, :blocked, :last_active); storeUserDeviceKey: INSERT OR REPLACE INTO user_device_keys_key (client_id, user_id, device_id, content, verified, blocked, last_active) VALUES (:client_id, :user_id, :device_id, :content, :verified, :blocked, :last_active);
removeUserDeviceKey: DELETE FROM user_device_keys_key WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id; removeUserDeviceKey: DELETE FROM user_device_keys_key WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id;
setLastActiveUserDeviceKey: UPDATE user_device_keys_key SET last_active = :last_active WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id; setLastActiveUserDeviceKey: UPDATE user_device_keys_key SET last_active = :last_active WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id;
setLastSentMessageUserDeviceKey: UPDATE user_device_keys_key SET last_sent_message = :last_sent_message WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id;
getLastSentMessageUserDeviceKey: SELECT last_sent_message FROM user_device_keys_key WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id;
setVerifiedUserCrossSigningKey: UPDATE user_cross_signing_keys SET verified = :verified WHERE client_id = :client_id AND user_id = :user_id AND public_key = :public_key; setVerifiedUserCrossSigningKey: UPDATE user_cross_signing_keys SET verified = :verified WHERE client_id = :client_id AND user_id = :user_id AND public_key = :public_key;
setBlockedUserCrossSigningKey: UPDATE user_cross_signing_keys SET blocked = :blocked WHERE client_id = :client_id AND user_id = :user_id AND public_key = :public_key; setBlockedUserCrossSigningKey: UPDATE user_cross_signing_keys SET blocked = :blocked WHERE client_id = :client_id AND user_id = :user_id AND public_key = :public_key;
storeUserCrossSigningKey: INSERT OR REPLACE INTO user_cross_signing_keys (client_id, user_id, public_key, content, verified, blocked) VALUES (:client_id, :user_id, :public_key, :content, :verified, :blocked); storeUserCrossSigningKey: INSERT OR REPLACE INTO user_cross_signing_keys (client_id, user_id, public_key, content, verified, blocked) VALUES (:client_id, :user_id, :public_key, :content, :verified, :blocked);

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH * Copyright (C) 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH * Copyright (C) 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH * Copyright (C) 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH * Copyright (C) 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -82,12 +82,6 @@ void main() {
.encryptToDeviceMessage([device], 'm.to_device', {'hello': 'foxies'}); .encryptToDeviceMessage([device], 'm.to_device', {'hello': 'foxies'});
}); });
test('encryptToDeviceMessagePayload', () async {
// just a hard test if nothing errors
await otherClient.encryption.encryptToDeviceMessagePayload(
device, 'm.to_device', {'hello': 'foxies'});
});
test('decryptToDeviceEvent', () async { test('decryptToDeviceEvent', () async {
final encryptedEvent = ToDeviceEvent( final encryptedEvent = ToDeviceEvent(
sender: '@othertest:fakeServer.notExisting', sender: '@othertest:fakeServer.notExisting',

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH * Copyright (C) 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH * Copyright (C) 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH * Copyright (C) 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,6 +1,6 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH * Copyright (C) 2020, 2021 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@ -126,6 +126,88 @@ void main() {
true); true);
}); });
test('replay to_device events', () async {
final userId = '@alice:example.com';
final deviceId = 'JLAFKJWSCS';
final senderKey = 'L+4+JCl8MD63dgo8z5Ta+9QAHXiANyOVSfgbHA5d3H8';
FakeMatrixApi.calledEndpoints.clear();
await client.database.setLastSentMessageUserDeviceKey(
json.encode({
'type': 'm.foxies',
'content': {
'floof': 'foxhole',
},
}),
client.id,
userId,
deviceId);
var event = ToDeviceEvent(
sender: userId,
type: 'm.dummy',
content: {},
encryptedContent: {
'sender_key': senderKey,
},
);
await client.encryption.olmManager.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
true);
// fail scenarios
// not encrypted
FakeMatrixApi.calledEndpoints.clear();
await client.database.setLastSentMessageUserDeviceKey(
json.encode({
'type': 'm.foxies',
'content': {
'floof': 'foxhole',
},
}),
client.id,
userId,
deviceId);
event = ToDeviceEvent(
sender: userId,
type: 'm.dummy',
content: {},
encryptedContent: null,
);
await client.encryption.olmManager.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
false);
// device not found
FakeMatrixApi.calledEndpoints.clear();
await client.database.setLastSentMessageUserDeviceKey(
json.encode({
'type': 'm.foxies',
'content': {
'floof': 'foxhole',
},
}),
client.id,
userId,
deviceId);
event = ToDeviceEvent(
sender: userId,
type: 'm.dummy',
content: {},
encryptedContent: {
'sender_key': 'invalid',
},
);
await client.encryption.olmManager.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
false);
});
test('dispose client', () async { test('dispose client', () async {
await client.dispose(closeDatabase: true); await client.dispose(closeDatabase: true);
}); });

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH * Copyright (C) 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH * Copyright (C) 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH * Copyright (C) 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH * Copyright (C) 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH * Copyright (C) 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* /*
* Ansible inventory script used at Famedly GmbH for managing many hosts * Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH * Copyright (C) 2019, 2020 Famedly GmbH
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify