feat: Replay last sent olm message on olm session recovery from other device
This commit is contained in:
parent
667d8e919d
commit
a35266f1e4
|
|
@ -93,6 +93,11 @@ class Encryption {
|
|||
// them in the background
|
||||
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.')) {
|
||||
// some key verification event. No need to handle it now, we can easily
|
||||
// do this in the background
|
||||
|
|
@ -336,12 +341,6 @@ class Encryption {
|
|||
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(
|
||||
List<DeviceKeys> deviceKeys,
|
||||
String type,
|
||||
|
|
|
|||
|
|
@ -444,7 +444,7 @@ class OlmManager {
|
|||
}
|
||||
_restoredOlmSessionsTime[mapKey] = DateTime.now();
|
||||
await startOutgoingOlmSessions([device]);
|
||||
await client.sendToDeviceEncrypted([device], 'm.dummy', {});
|
||||
await client.sendToDeviceEncrypted([device], EventTypes.Dummy, {});
|
||||
}
|
||||
|
||||
Future<ToDeviceEvent> decryptToDeviceEvent(ToDeviceEvent event) async {
|
||||
|
|
@ -542,6 +542,16 @@ class OlmManager {
|
|||
};
|
||||
final encryptResult = sess.first.session.encrypt(json.encode(fullPayload));
|
||||
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>{
|
||||
'algorithm': AlgorithmTypes.olmV1Curve25519AesSha2,
|
||||
'sender_key': identityKey,
|
||||
|
|
@ -587,6 +597,35 @@ class OlmManager {
|
|||
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() {
|
||||
for (final sessions in olmSessions.values) {
|
||||
for (final sess in sessions) {
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ class Database extends _$Database {
|
|||
Database.connect(DatabaseConnection connection) : super.connect(connection);
|
||||
|
||||
@override
|
||||
int get schemaVersion => 9;
|
||||
int get schemaVersion => 10;
|
||||
|
||||
int get maxFileSize => 1 * 1024 * 1024;
|
||||
|
||||
|
|
@ -164,6 +164,12 @@ class Database extends _$Database {
|
|||
userDeviceKeysKey, userDeviceKeysKey.lastActive);
|
||||
from++;
|
||||
}
|
||||
if (from == 9) {
|
||||
await m.addColumnIfNotExists(
|
||||
userDeviceKeysKey, userDeviceKeysKey.lastSentMessage);
|
||||
await m.createIndexIfNotExists(olmSessionsIdentityIndex);
|
||||
from++;
|
||||
}
|
||||
} catch (e, s) {
|
||||
api.Logs().e('Database migration failed', e, s);
|
||||
onError.add(SdkError(exception: e, stackTrace: s));
|
||||
|
|
|
|||
|
|
@ -769,6 +769,7 @@ class DbUserDeviceKeysKey extends DataClass
|
|||
final bool verified;
|
||||
final bool blocked;
|
||||
final int lastActive;
|
||||
final String lastSentMessage;
|
||||
DbUserDeviceKeysKey(
|
||||
{@required this.clientId,
|
||||
@required this.userId,
|
||||
|
|
@ -776,7 +777,8 @@ class DbUserDeviceKeysKey extends DataClass
|
|||
@required this.content,
|
||||
this.verified,
|
||||
this.blocked,
|
||||
this.lastActive});
|
||||
this.lastActive,
|
||||
this.lastSentMessage});
|
||||
factory DbUserDeviceKeysKey.fromData(
|
||||
Map<String, dynamic> data, GeneratedDatabase db,
|
||||
{String prefix}) {
|
||||
|
|
@ -799,6 +801,8 @@ class DbUserDeviceKeysKey extends DataClass
|
|||
boolType.mapFromDatabaseResponse(data['${effectivePrefix}blocked']),
|
||||
lastActive: intType
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}last_active']),
|
||||
lastSentMessage: stringType
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}last_sent_message']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
|
|
@ -825,6 +829,9 @@ class DbUserDeviceKeysKey extends DataClass
|
|||
if (!nullToAbsent || lastActive != null) {
|
||||
map['last_active'] = Variable<int>(lastActive);
|
||||
}
|
||||
if (!nullToAbsent || lastSentMessage != null) {
|
||||
map['last_sent_message'] = Variable<String>(lastSentMessage);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
|
|
@ -850,6 +857,9 @@ class DbUserDeviceKeysKey extends DataClass
|
|||
lastActive: lastActive == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: 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']),
|
||||
blocked: serializer.fromJson<bool>(json['blocked']),
|
||||
lastActive: serializer.fromJson<int>(json['last_active']),
|
||||
lastSentMessage: serializer.fromJson<String>(json['last_sent_message']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
|
|
@ -877,6 +888,7 @@ class DbUserDeviceKeysKey extends DataClass
|
|||
'verified': serializer.toJson<bool>(verified),
|
||||
'blocked': serializer.toJson<bool>(blocked),
|
||||
'last_active': serializer.toJson<int>(lastActive),
|
||||
'last_sent_message': serializer.toJson<String>(lastSentMessage),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -887,7 +899,8 @@ class DbUserDeviceKeysKey extends DataClass
|
|||
String content,
|
||||
bool verified,
|
||||
bool blocked,
|
||||
int lastActive}) =>
|
||||
int lastActive,
|
||||
String lastSentMessage}) =>
|
||||
DbUserDeviceKeysKey(
|
||||
clientId: clientId ?? this.clientId,
|
||||
userId: userId ?? this.userId,
|
||||
|
|
@ -896,6 +909,7 @@ class DbUserDeviceKeysKey extends DataClass
|
|||
verified: verified ?? this.verified,
|
||||
blocked: blocked ?? this.blocked,
|
||||
lastActive: lastActive ?? this.lastActive,
|
||||
lastSentMessage: lastSentMessage ?? this.lastSentMessage,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
|
|
@ -906,7 +920,8 @@ class DbUserDeviceKeysKey extends DataClass
|
|||
..write('content: $content, ')
|
||||
..write('verified: $verified, ')
|
||||
..write('blocked: $blocked, ')
|
||||
..write('lastActive: $lastActive')
|
||||
..write('lastActive: $lastActive, ')
|
||||
..write('lastSentMessage: $lastSentMessage')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
|
@ -920,8 +935,12 @@ class DbUserDeviceKeysKey extends DataClass
|
|||
deviceId.hashCode,
|
||||
$mrjc(
|
||||
content.hashCode,
|
||||
$mrjc(verified.hashCode,
|
||||
$mrjc(blocked.hashCode, lastActive.hashCode)))))));
|
||||
$mrjc(
|
||||
verified.hashCode,
|
||||
$mrjc(
|
||||
blocked.hashCode,
|
||||
$mrjc(lastActive.hashCode,
|
||||
lastSentMessage.hashCode))))))));
|
||||
@override
|
||||
bool operator ==(dynamic other) =>
|
||||
identical(this, other) ||
|
||||
|
|
@ -932,7 +951,8 @@ class DbUserDeviceKeysKey extends DataClass
|
|||
other.content == this.content &&
|
||||
other.verified == this.verified &&
|
||||
other.blocked == this.blocked &&
|
||||
other.lastActive == this.lastActive);
|
||||
other.lastActive == this.lastActive &&
|
||||
other.lastSentMessage == this.lastSentMessage);
|
||||
}
|
||||
|
||||
class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
|
||||
|
|
@ -943,6 +963,7 @@ class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
|
|||
final Value<bool> verified;
|
||||
final Value<bool> blocked;
|
||||
final Value<int> lastActive;
|
||||
final Value<String> lastSentMessage;
|
||||
const UserDeviceKeysKeyCompanion({
|
||||
this.clientId = const Value.absent(),
|
||||
this.userId = const Value.absent(),
|
||||
|
|
@ -951,6 +972,7 @@ class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
|
|||
this.verified = const Value.absent(),
|
||||
this.blocked = const Value.absent(),
|
||||
this.lastActive = const Value.absent(),
|
||||
this.lastSentMessage = const Value.absent(),
|
||||
});
|
||||
UserDeviceKeysKeyCompanion.insert({
|
||||
@required int clientId,
|
||||
|
|
@ -960,6 +982,7 @@ class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
|
|||
this.verified = const Value.absent(),
|
||||
this.blocked = const Value.absent(),
|
||||
this.lastActive = const Value.absent(),
|
||||
this.lastSentMessage = const Value.absent(),
|
||||
}) : clientId = Value(clientId),
|
||||
userId = Value(userId),
|
||||
deviceId = Value(deviceId),
|
||||
|
|
@ -972,6 +995,7 @@ class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
|
|||
Expression<bool> verified,
|
||||
Expression<bool> blocked,
|
||||
Expression<int> lastActive,
|
||||
Expression<String> lastSentMessage,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (clientId != null) 'client_id': clientId,
|
||||
|
|
@ -981,6 +1005,7 @@ class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
|
|||
if (verified != null) 'verified': verified,
|
||||
if (blocked != null) 'blocked': blocked,
|
||||
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<bool> verified,
|
||||
Value<bool> blocked,
|
||||
Value<int> lastActive}) {
|
||||
Value<int> lastActive,
|
||||
Value<String> lastSentMessage}) {
|
||||
return UserDeviceKeysKeyCompanion(
|
||||
clientId: clientId ?? this.clientId,
|
||||
userId: userId ?? this.userId,
|
||||
|
|
@ -1000,6 +1026,7 @@ class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
|
|||
verified: verified ?? this.verified,
|
||||
blocked: blocked ?? this.blocked,
|
||||
lastActive: lastActive ?? this.lastActive,
|
||||
lastSentMessage: lastSentMessage ?? this.lastSentMessage,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1027,6 +1054,9 @@ class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
|
|||
if (lastActive.present) {
|
||||
map['last_active'] = Variable<int>(lastActive.value);
|
||||
}
|
||||
if (lastSentMessage.present) {
|
||||
map['last_sent_message'] = Variable<String>(lastSentMessage.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
|
|
@ -1039,7 +1069,8 @@ class UserDeviceKeysKeyCompanion extends UpdateCompanion<DbUserDeviceKeysKey> {
|
|||
..write('content: $content, ')
|
||||
..write('verified: $verified, ')
|
||||
..write('blocked: $blocked, ')
|
||||
..write('lastActive: $lastActive')
|
||||
..write('lastActive: $lastActive, ')
|
||||
..write('lastSentMessage: $lastSentMessage')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
|
@ -1108,9 +1139,27 @@ class UserDeviceKeysKey extends Table
|
|||
$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
|
||||
List<GeneratedColumn> get $columns =>
|
||||
[clientId, userId, deviceId, content, verified, blocked, lastActive];
|
||||
List<GeneratedColumn> get $columns => [
|
||||
clientId,
|
||||
userId,
|
||||
deviceId,
|
||||
content,
|
||||
verified,
|
||||
blocked,
|
||||
lastActive,
|
||||
lastSentMessage
|
||||
];
|
||||
@override
|
||||
UserDeviceKeysKey get asDslTable => this;
|
||||
@override
|
||||
|
|
@ -1161,6 +1210,12 @@ class UserDeviceKeysKey extends Table
|
|||
lastActive.isAcceptableOrUnknown(
|
||||
data['last_active'], _lastActiveMeta));
|
||||
}
|
||||
if (data.containsKey('last_sent_message')) {
|
||||
context.handle(
|
||||
_lastSentMessageMeta,
|
||||
lastSentMessage.isAcceptableOrUnknown(
|
||||
data['last_sent_message'], _lastSentMessageMeta));
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
|
|
@ -6136,6 +6191,10 @@ abstract class _$Database extends GeneratedDatabase {
|
|||
Index get olmSessionsIndex => _olmSessionsIndex ??= Index(
|
||||
'olm_sessions_index',
|
||||
'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 get outboundGroupSessions =>
|
||||
_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(
|
||||
bool verified, int client_id, String user_id, String public_key) {
|
||||
return customUpdate(
|
||||
|
|
@ -7068,6 +7156,7 @@ abstract class _$Database extends GeneratedDatabase {
|
|||
userCrossSigningKeysIndex,
|
||||
olmSessions,
|
||||
olmSessionsIndex,
|
||||
olmSessionsIdentityIndex,
|
||||
outboundGroupSessions,
|
||||
outboundGroupSessionsIndex,
|
||||
inboundGroupSessions,
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ CREATE TABLE user_device_keys_key (
|
|||
verified BOOLEAN DEFAULT false,
|
||||
blocked BOOLEAN DEFAULT false,
|
||||
last_active BIGINT,
|
||||
last_sent_message TEXT,
|
||||
UNIQUE(client_id, user_id, device_id)
|
||||
) as DbUserDeviceKeysKey;
|
||||
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)
|
||||
) AS DbOlmSessions;
|
||||
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 (
|
||||
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);
|
||||
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;
|
||||
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;
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2020 Famedly GmbH
|
||||
*
|
||||
* 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'});
|
||||
});
|
||||
|
||||
test('encryptToDeviceMessagePayload', () async {
|
||||
// just a hard test if nothing errors
|
||||
await otherClient.encryption.encryptToDeviceMessagePayload(
|
||||
device, 'm.to_device', {'hello': 'foxies'});
|
||||
});
|
||||
|
||||
test('decryptToDeviceEvent', () async {
|
||||
final encryptedEvent = ToDeviceEvent(
|
||||
sender: '@othertest:fakeServer.notExisting',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Copyright (C) 2020 Famedly GmbH
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2020, 2021 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
|
|
@ -126,6 +126,88 @@ void main() {
|
|||
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 {
|
||||
await client.dispose(closeDatabase: true);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Ansible inventory script used at Famedly GmbH for managing many hosts
|
||||
* Famedly Matrix SDK
|
||||
* Copyright (C) 2019, 2020 Famedly GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
|||
Loading…
Reference in New Issue