refactor(keybackup): Update database for stored megolm keys to prepare for proper online key backup
This commit is contained in:
parent
20d72eb8d7
commit
ea59c4bd94
|
@ -71,7 +71,20 @@ class KeyManager {
|
||||||
|
|
||||||
void setInboundGroupSession(String roomId, String sessionId, String senderKey,
|
void setInboundGroupSession(String roomId, String sessionId, String senderKey,
|
||||||
Map<String, dynamic> content,
|
Map<String, dynamic> content,
|
||||||
{bool forwarded = false}) {
|
{bool forwarded = false, Map<String, String> senderClaimedKeys}) {
|
||||||
|
senderClaimedKeys ??= <String, String>{};
|
||||||
|
if (!senderClaimedKeys.containsKey('ed25519')) {
|
||||||
|
DeviceKeys device;
|
||||||
|
for (final user in client.userDeviceKeys.values) {
|
||||||
|
device = user.deviceKeys.values.firstWhere(
|
||||||
|
(e) => e.curve25519Key == senderKey,
|
||||||
|
orElse: () => null);
|
||||||
|
if (device != null) {
|
||||||
|
senderClaimedKeys['ed25519'] = device.ed25519Key;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
final oldSession =
|
final oldSession =
|
||||||
getInboundGroupSession(roomId, sessionId, senderKey, otherRooms: false);
|
getInboundGroupSession(roomId, sessionId, senderKey, otherRooms: false);
|
||||||
if (content['algorithm'] != 'm.megolm.v1.aes-sha2') {
|
if (content['algorithm'] != 'm.megolm.v1.aes-sha2') {
|
||||||
|
@ -97,6 +110,8 @@ class KeyManager {
|
||||||
inboundGroupSession: inboundGroupSession,
|
inboundGroupSession: inboundGroupSession,
|
||||||
indexes: {},
|
indexes: {},
|
||||||
key: client.userID,
|
key: client.userID,
|
||||||
|
senderKey: senderKey,
|
||||||
|
senderClaimedKeys: senderClaimedKeys,
|
||||||
);
|
);
|
||||||
final oldFirstIndex =
|
final oldFirstIndex =
|
||||||
oldSession?.inboundGroupSession?.first_known_index() ?? 0;
|
oldSession?.inboundGroupSession?.first_known_index() ?? 0;
|
||||||
|
@ -124,6 +139,8 @@ class KeyManager {
|
||||||
inboundGroupSession.pickle(client.userID),
|
inboundGroupSession.pickle(client.userID),
|
||||||
json.encode(content),
|
json.encode(content),
|
||||||
json.encode({}),
|
json.encode({}),
|
||||||
|
senderKey,
|
||||||
|
json.encode(senderClaimedKeys),
|
||||||
);
|
);
|
||||||
// Note to self: When adding key-backup that needs to be unawaited(), else
|
// Note to self: When adding key-backup that needs to be unawaited(), else
|
||||||
// we might accidentally end up with http requests inside of the sync loop
|
// we might accidentally end up with http requests inside of the sync loop
|
||||||
|
@ -139,7 +156,11 @@ class KeyManager {
|
||||||
{bool otherRooms = true}) {
|
{bool otherRooms = true}) {
|
||||||
if (_inboundGroupSessions.containsKey(roomId) &&
|
if (_inboundGroupSessions.containsKey(roomId) &&
|
||||||
_inboundGroupSessions[roomId].containsKey(sessionId)) {
|
_inboundGroupSessions[roomId].containsKey(sessionId)) {
|
||||||
return _inboundGroupSessions[roomId][sessionId];
|
final sess = _inboundGroupSessions[roomId][sessionId];
|
||||||
|
if (sess.senderKey != senderKey && sess.senderKey.isNotEmpty) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return sess;
|
||||||
}
|
}
|
||||||
if (!otherRooms) {
|
if (!otherRooms) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -147,7 +168,11 @@ class KeyManager {
|
||||||
// search if this session id is *somehow* found in another room
|
// search if this session id is *somehow* found in another room
|
||||||
for (final val in _inboundGroupSessions.values) {
|
for (final val in _inboundGroupSessions.values) {
|
||||||
if (val.containsKey(sessionId)) {
|
if (val.containsKey(sessionId)) {
|
||||||
return val[sessionId];
|
final sess = val[sessionId];
|
||||||
|
if (sess.senderKey != senderKey && sess.senderKey.isNotEmpty) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return sess;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -161,7 +186,11 @@ class KeyManager {
|
||||||
}
|
}
|
||||||
if (_inboundGroupSessions.containsKey(roomId) &&
|
if (_inboundGroupSessions.containsKey(roomId) &&
|
||||||
_inboundGroupSessions[roomId].containsKey(sessionId)) {
|
_inboundGroupSessions[roomId].containsKey(sessionId)) {
|
||||||
return _inboundGroupSessions[roomId][sessionId]; // nothing to do
|
final sess = _inboundGroupSessions[roomId][sessionId];
|
||||||
|
if (sess.senderKey != senderKey && sess.senderKey.isNotEmpty) {
|
||||||
|
return null; // sender keys do not match....better not do anything
|
||||||
|
}
|
||||||
|
return sess; // nothing to do
|
||||||
}
|
}
|
||||||
final session = await client.database
|
final session = await client.database
|
||||||
?.getDbInboundGroupSession(client.id, roomId, sessionId);
|
?.getDbInboundGroupSession(client.id, roomId, sessionId);
|
||||||
|
@ -181,7 +210,8 @@ class KeyManager {
|
||||||
_inboundGroupSessions[roomId] = <String, SessionKey>{};
|
_inboundGroupSessions[roomId] = <String, SessionKey>{};
|
||||||
}
|
}
|
||||||
final sess = SessionKey.fromDb(session, client.userID);
|
final sess = SessionKey.fromDb(session, client.userID);
|
||||||
if (!sess.isValid) {
|
if (!sess.isValid ||
|
||||||
|
(sess.senderKey.isNotEmpty && sess.senderKey != senderKey)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
_inboundGroupSessions[roomId][sessionId] = sess;
|
_inboundGroupSessions[roomId][sessionId] = sess;
|
||||||
|
@ -377,7 +407,10 @@ class KeyManager {
|
||||||
decrypted['room_id'] = roomId;
|
decrypted['room_id'] = roomId;
|
||||||
setInboundGroupSession(
|
setInboundGroupSession(
|
||||||
roomId, sessionId, decrypted['sender_key'], decrypted,
|
roomId, sessionId, decrypted['sender_key'], decrypted,
|
||||||
forwarded: true);
|
forwarded: true,
|
||||||
|
senderClaimedKeys: decrypted['sender_claimed_keys'] != null
|
||||||
|
? Map<String, String>.from(decrypted['sender_claimed_keys'])
|
||||||
|
: null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -556,11 +589,20 @@ class KeyManager {
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
return; // someone we didn't send our request to replied....better ignore this
|
return; // someone we didn't send our request to replied....better ignore this
|
||||||
}
|
}
|
||||||
|
// we add the sender key to the forwarded key chain
|
||||||
|
if (!(event.content['forwarding_curve25519_key_chain'] is List)) {
|
||||||
|
event.content['forwarding_curve25519_key_chain'] = <String>[];
|
||||||
|
}
|
||||||
|
event.content['forwarding_curve25519_key_chain']
|
||||||
|
.add(event.encryptedContent['sender_key']);
|
||||||
// TODO: verify that the keys work to decrypt a message
|
// TODO: verify that the keys work to decrypt a message
|
||||||
// alright, all checks out, let's go ahead and store this session
|
// alright, all checks out, let's go ahead and store this session
|
||||||
setInboundGroupSession(
|
setInboundGroupSession(
|
||||||
request.room.id, request.sessionId, request.senderKey, event.content,
|
request.room.id, request.sessionId, request.senderKey, event.content,
|
||||||
forwarded: true);
|
forwarded: true,
|
||||||
|
senderClaimedKeys: {
|
||||||
|
'ed25519': event.content['sender_claimed_ed25519_key'],
|
||||||
|
});
|
||||||
request.devices.removeWhere(
|
request.devices.removeWhere(
|
||||||
(k) => k.userId == device.userId && k.deviceId == device.deviceId);
|
(k) => k.userId == device.userId && k.deviceId == device.deviceId);
|
||||||
outgoingShareRequests.remove(request.requestId);
|
outgoingShareRequests.remove(request.requestId);
|
||||||
|
@ -659,28 +701,19 @@ class RoomKeyRequest extends ToDeviceEvent {
|
||||||
var room = this.room;
|
var room = this.room;
|
||||||
final session = await keyManager.loadInboundGroupSession(
|
final session = await keyManager.loadInboundGroupSession(
|
||||||
room.id, request.sessionId, request.senderKey);
|
room.id, request.sessionId, request.senderKey);
|
||||||
var forwardedKeys = <dynamic>[keyManager.encryption.identityKey];
|
|
||||||
for (final key in session.forwardingCurve25519KeyChain) {
|
|
||||||
forwardedKeys.add(key);
|
|
||||||
}
|
|
||||||
var message = session.content;
|
var message = session.content;
|
||||||
message['forwarding_curve25519_key_chain'] = forwardedKeys;
|
message['forwarding_curve25519_key_chain'] =
|
||||||
|
List<String>.from(session.forwardingCurve25519KeyChain);
|
||||||
|
|
||||||
message['sender_key'] = request.senderKey;
|
message['sender_key'] =
|
||||||
|
(session.senderKey != null && session.senderKey.isNotEmpty)
|
||||||
|
? session.senderKey
|
||||||
|
: request.senderKey;
|
||||||
message['sender_claimed_ed25519_key'] =
|
message['sender_claimed_ed25519_key'] =
|
||||||
forwardedKeys.isEmpty ? keyManager.encryption.fingerprintKey : null;
|
session.senderClaimedKeys['ed25519'] ??
|
||||||
if (message['sender_claimed_ed25519_key'] == null) {
|
(session.forwardingCurve25519KeyChain.isEmpty
|
||||||
for (final value in keyManager.client.userDeviceKeys.values) {
|
? keyManager.encryption.fingerprintKey
|
||||||
for (final key in value.deviceKeys.values) {
|
: null);
|
||||||
if (key.curve25519Key == forwardedKeys.first) {
|
|
||||||
message['sender_claimed_ed25519_key'] = key.ed25519Key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (message['sender_claimed_ed25519_key'] != null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
message['session_key'] = session.inboundGroupSession
|
message['session_key'] = session.inboundGroupSession
|
||||||
.export_session(session.inboundGroupSession.first_known_index());
|
.export_session(session.inboundGroupSession.first_known_index());
|
||||||
// send the actual reply of the key back to the requester
|
// send the actual reply of the key back to the requester
|
||||||
|
|
|
@ -29,23 +29,39 @@ class SessionKey {
|
||||||
Map<String, int> indexes;
|
Map<String, int> indexes;
|
||||||
olm.InboundGroupSession inboundGroupSession;
|
olm.InboundGroupSession inboundGroupSession;
|
||||||
final String key;
|
final String key;
|
||||||
List<dynamic> get forwardingCurve25519KeyChain =>
|
List<String> get forwardingCurve25519KeyChain =>
|
||||||
content['forwarding_curve25519_key_chain'] ?? [];
|
(content['forwarding_curve25519_key_chain'] != null
|
||||||
String get senderClaimedEd25519Key =>
|
? List<String>.from(content['forwarding_curve25519_key_chain'])
|
||||||
content['sender_claimed_ed25519_key'] ?? '';
|
: null) ??
|
||||||
String get senderKey => content['sender_key'] ?? '';
|
<String>[];
|
||||||
|
Map<String, String> senderClaimedKeys;
|
||||||
|
String senderKey;
|
||||||
bool get isValid => inboundGroupSession != null;
|
bool get isValid => inboundGroupSession != null;
|
||||||
|
|
||||||
SessionKey({this.content, this.inboundGroupSession, this.key, this.indexes});
|
SessionKey(
|
||||||
|
{this.content,
|
||||||
|
this.inboundGroupSession,
|
||||||
|
this.key,
|
||||||
|
this.indexes,
|
||||||
|
String senderKey,
|
||||||
|
Map<String, String> senderClaimedKeys}) {
|
||||||
|
_setSenderKey(senderKey);
|
||||||
|
_setSenderClaimedKeys(senderClaimedKeys);
|
||||||
|
}
|
||||||
|
|
||||||
SessionKey.fromDb(DbInboundGroupSession dbEntry, String key) : key = key {
|
SessionKey.fromDb(DbInboundGroupSession dbEntry, String key) : key = key {
|
||||||
final parsedContent = Event.getMapFromPayload(dbEntry.content);
|
final parsedContent = Event.getMapFromPayload(dbEntry.content);
|
||||||
final parsedIndexes = Event.getMapFromPayload(dbEntry.indexes);
|
final parsedIndexes = Event.getMapFromPayload(dbEntry.indexes);
|
||||||
|
final parsedSenderClaimedKeys =
|
||||||
|
Event.getMapFromPayload(dbEntry.senderClaimedKeys);
|
||||||
content =
|
content =
|
||||||
parsedContent != null ? Map<String, dynamic>.from(parsedContent) : null;
|
parsedContent != null ? Map<String, dynamic>.from(parsedContent) : null;
|
||||||
indexes = parsedIndexes != null
|
indexes = parsedIndexes != null
|
||||||
? Map<String, int>.from(parsedIndexes)
|
? Map<String, int>.from(parsedIndexes)
|
||||||
: <String, int>{};
|
: <String, int>{};
|
||||||
|
_setSenderKey(dbEntry.senderKey);
|
||||||
|
_setSenderClaimedKeys(Map<String, String>.from(parsedSenderClaimedKeys));
|
||||||
|
|
||||||
inboundGroupSession = olm.InboundGroupSession();
|
inboundGroupSession = olm.InboundGroupSession();
|
||||||
try {
|
try {
|
||||||
inboundGroupSession.unpickle(key, dbEntry.pickle);
|
inboundGroupSession.unpickle(key, dbEntry.pickle);
|
||||||
|
@ -57,6 +73,22 @@ class SessionKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _setSenderKey(String key) {
|
||||||
|
senderKey = key ?? content['sender_key'] ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setSenderClaimedKeys(Map<String, String> keys) {
|
||||||
|
senderClaimedKeys = (keys != null && keys.isNotEmpty)
|
||||||
|
? keys
|
||||||
|
: (content['sender_claimed_keys'] is Map
|
||||||
|
? Map<String, String>.from(content['sender_claimed_keys'])
|
||||||
|
: (content['sender_claimed_ed25519_key'] is String
|
||||||
|
? <String, String>{
|
||||||
|
'ed25519': content['sender_claimed_ed25519_key']
|
||||||
|
}
|
||||||
|
: <String, String>{}));
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final data = <String, dynamic>{};
|
final data = <String, dynamic>{};
|
||||||
if (content != null) {
|
if (content != null) {
|
||||||
|
|
|
@ -20,7 +20,7 @@ class Database extends _$Database {
|
||||||
Database.connect(DatabaseConnection connection) : super.connect(connection);
|
Database.connect(DatabaseConnection connection) : super.connect(connection);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 5;
|
int get schemaVersion => 6;
|
||||||
|
|
||||||
int get maxFileSize => 1 * 1024 * 1024;
|
int get maxFileSize => 1 * 1024 * 1024;
|
||||||
|
|
||||||
|
@ -62,6 +62,15 @@ class Database extends _$Database {
|
||||||
await m.addColumn(olmSessions, olmSessions.lastReceived);
|
await m.addColumn(olmSessions, olmSessions.lastReceived);
|
||||||
from++;
|
from++;
|
||||||
}
|
}
|
||||||
|
if (from == 5) {
|
||||||
|
await m.addColumn(
|
||||||
|
inboundGroupSessions, inboundGroupSessions.uploaded);
|
||||||
|
await m.addColumn(
|
||||||
|
inboundGroupSessions, inboundGroupSessions.senderKey);
|
||||||
|
await m.addColumn(
|
||||||
|
inboundGroupSessions, inboundGroupSessions.senderClaimedKeys);
|
||||||
|
from++;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
beforeOpen: (_) async {
|
beforeOpen: (_) async {
|
||||||
if (executor.dialect == SqlDialect.sqlite) {
|
if (executor.dialect == SqlDialect.sqlite) {
|
||||||
|
|
|
@ -2062,19 +2062,26 @@ class DbInboundGroupSession extends DataClass
|
||||||
final String pickle;
|
final String pickle;
|
||||||
final String content;
|
final String content;
|
||||||
final String indexes;
|
final String indexes;
|
||||||
|
final bool uploaded;
|
||||||
|
final String senderKey;
|
||||||
|
final String senderClaimedKeys;
|
||||||
DbInboundGroupSession(
|
DbInboundGroupSession(
|
||||||
{@required this.clientId,
|
{@required this.clientId,
|
||||||
@required this.roomId,
|
@required this.roomId,
|
||||||
@required this.sessionId,
|
@required this.sessionId,
|
||||||
@required this.pickle,
|
@required this.pickle,
|
||||||
this.content,
|
this.content,
|
||||||
this.indexes});
|
this.indexes,
|
||||||
|
this.uploaded,
|
||||||
|
this.senderKey,
|
||||||
|
this.senderClaimedKeys});
|
||||||
factory DbInboundGroupSession.fromData(
|
factory DbInboundGroupSession.fromData(
|
||||||
Map<String, dynamic> data, GeneratedDatabase db,
|
Map<String, dynamic> data, GeneratedDatabase db,
|
||||||
{String prefix}) {
|
{String prefix}) {
|
||||||
final effectivePrefix = prefix ?? '';
|
final effectivePrefix = prefix ?? '';
|
||||||
final intType = db.typeSystem.forDartType<int>();
|
final intType = db.typeSystem.forDartType<int>();
|
||||||
final stringType = db.typeSystem.forDartType<String>();
|
final stringType = db.typeSystem.forDartType<String>();
|
||||||
|
final boolType = db.typeSystem.forDartType<bool>();
|
||||||
return DbInboundGroupSession(
|
return DbInboundGroupSession(
|
||||||
clientId:
|
clientId:
|
||||||
intType.mapFromDatabaseResponse(data['${effectivePrefix}client_id']),
|
intType.mapFromDatabaseResponse(data['${effectivePrefix}client_id']),
|
||||||
|
@ -2088,6 +2095,12 @@ class DbInboundGroupSession extends DataClass
|
||||||
stringType.mapFromDatabaseResponse(data['${effectivePrefix}content']),
|
stringType.mapFromDatabaseResponse(data['${effectivePrefix}content']),
|
||||||
indexes:
|
indexes:
|
||||||
stringType.mapFromDatabaseResponse(data['${effectivePrefix}indexes']),
|
stringType.mapFromDatabaseResponse(data['${effectivePrefix}indexes']),
|
||||||
|
uploaded:
|
||||||
|
boolType.mapFromDatabaseResponse(data['${effectivePrefix}uploaded']),
|
||||||
|
senderKey: stringType
|
||||||
|
.mapFromDatabaseResponse(data['${effectivePrefix}sender_key']),
|
||||||
|
senderClaimedKeys: stringType.mapFromDatabaseResponse(
|
||||||
|
data['${effectivePrefix}sender_claimed_keys']),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@override
|
@override
|
||||||
|
@ -2111,6 +2124,15 @@ class DbInboundGroupSession extends DataClass
|
||||||
if (!nullToAbsent || indexes != null) {
|
if (!nullToAbsent || indexes != null) {
|
||||||
map['indexes'] = Variable<String>(indexes);
|
map['indexes'] = Variable<String>(indexes);
|
||||||
}
|
}
|
||||||
|
if (!nullToAbsent || uploaded != null) {
|
||||||
|
map['uploaded'] = Variable<bool>(uploaded);
|
||||||
|
}
|
||||||
|
if (!nullToAbsent || senderKey != null) {
|
||||||
|
map['sender_key'] = Variable<String>(senderKey);
|
||||||
|
}
|
||||||
|
if (!nullToAbsent || senderClaimedKeys != null) {
|
||||||
|
map['sender_claimed_keys'] = Variable<String>(senderClaimedKeys);
|
||||||
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2124,6 +2146,10 @@ class DbInboundGroupSession extends DataClass
|
||||||
pickle: serializer.fromJson<String>(json['pickle']),
|
pickle: serializer.fromJson<String>(json['pickle']),
|
||||||
content: serializer.fromJson<String>(json['content']),
|
content: serializer.fromJson<String>(json['content']),
|
||||||
indexes: serializer.fromJson<String>(json['indexes']),
|
indexes: serializer.fromJson<String>(json['indexes']),
|
||||||
|
uploaded: serializer.fromJson<bool>(json['uploaded']),
|
||||||
|
senderKey: serializer.fromJson<String>(json['sender_key']),
|
||||||
|
senderClaimedKeys:
|
||||||
|
serializer.fromJson<String>(json['sender_claimed_keys']),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@override
|
@override
|
||||||
|
@ -2136,6 +2162,9 @@ class DbInboundGroupSession extends DataClass
|
||||||
'pickle': serializer.toJson<String>(pickle),
|
'pickle': serializer.toJson<String>(pickle),
|
||||||
'content': serializer.toJson<String>(content),
|
'content': serializer.toJson<String>(content),
|
||||||
'indexes': serializer.toJson<String>(indexes),
|
'indexes': serializer.toJson<String>(indexes),
|
||||||
|
'uploaded': serializer.toJson<bool>(uploaded),
|
||||||
|
'sender_key': serializer.toJson<String>(senderKey),
|
||||||
|
'sender_claimed_keys': serializer.toJson<String>(senderClaimedKeys),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2145,7 +2174,10 @@ class DbInboundGroupSession extends DataClass
|
||||||
String sessionId,
|
String sessionId,
|
||||||
String pickle,
|
String pickle,
|
||||||
String content,
|
String content,
|
||||||
String indexes}) =>
|
String indexes,
|
||||||
|
bool uploaded,
|
||||||
|
String senderKey,
|
||||||
|
String senderClaimedKeys}) =>
|
||||||
DbInboundGroupSession(
|
DbInboundGroupSession(
|
||||||
clientId: clientId ?? this.clientId,
|
clientId: clientId ?? this.clientId,
|
||||||
roomId: roomId ?? this.roomId,
|
roomId: roomId ?? this.roomId,
|
||||||
|
@ -2153,6 +2185,9 @@ class DbInboundGroupSession extends DataClass
|
||||||
pickle: pickle ?? this.pickle,
|
pickle: pickle ?? this.pickle,
|
||||||
content: content ?? this.content,
|
content: content ?? this.content,
|
||||||
indexes: indexes ?? this.indexes,
|
indexes: indexes ?? this.indexes,
|
||||||
|
uploaded: uploaded ?? this.uploaded,
|
||||||
|
senderKey: senderKey ?? this.senderKey,
|
||||||
|
senderClaimedKeys: senderClaimedKeys ?? this.senderClaimedKeys,
|
||||||
);
|
);
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
|
@ -2162,7 +2197,10 @@ class DbInboundGroupSession extends DataClass
|
||||||
..write('sessionId: $sessionId, ')
|
..write('sessionId: $sessionId, ')
|
||||||
..write('pickle: $pickle, ')
|
..write('pickle: $pickle, ')
|
||||||
..write('content: $content, ')
|
..write('content: $content, ')
|
||||||
..write('indexes: $indexes')
|
..write('indexes: $indexes, ')
|
||||||
|
..write('uploaded: $uploaded, ')
|
||||||
|
..write('senderKey: $senderKey, ')
|
||||||
|
..write('senderClaimedKeys: $senderClaimedKeys')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
@ -2174,8 +2212,16 @@ class DbInboundGroupSession extends DataClass
|
||||||
roomId.hashCode,
|
roomId.hashCode,
|
||||||
$mrjc(
|
$mrjc(
|
||||||
sessionId.hashCode,
|
sessionId.hashCode,
|
||||||
$mrjc(pickle.hashCode,
|
$mrjc(
|
||||||
$mrjc(content.hashCode, indexes.hashCode))))));
|
pickle.hashCode,
|
||||||
|
$mrjc(
|
||||||
|
content.hashCode,
|
||||||
|
$mrjc(
|
||||||
|
indexes.hashCode,
|
||||||
|
$mrjc(
|
||||||
|
uploaded.hashCode,
|
||||||
|
$mrjc(senderKey.hashCode,
|
||||||
|
senderClaimedKeys.hashCode)))))))));
|
||||||
@override
|
@override
|
||||||
bool operator ==(dynamic other) =>
|
bool operator ==(dynamic other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
|
@ -2185,7 +2231,10 @@ class DbInboundGroupSession extends DataClass
|
||||||
other.sessionId == this.sessionId &&
|
other.sessionId == this.sessionId &&
|
||||||
other.pickle == this.pickle &&
|
other.pickle == this.pickle &&
|
||||||
other.content == this.content &&
|
other.content == this.content &&
|
||||||
other.indexes == this.indexes);
|
other.indexes == this.indexes &&
|
||||||
|
other.uploaded == this.uploaded &&
|
||||||
|
other.senderKey == this.senderKey &&
|
||||||
|
other.senderClaimedKeys == this.senderClaimedKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
class InboundGroupSessionsCompanion
|
class InboundGroupSessionsCompanion
|
||||||
|
@ -2196,6 +2245,9 @@ class InboundGroupSessionsCompanion
|
||||||
final Value<String> pickle;
|
final Value<String> pickle;
|
||||||
final Value<String> content;
|
final Value<String> content;
|
||||||
final Value<String> indexes;
|
final Value<String> indexes;
|
||||||
|
final Value<bool> uploaded;
|
||||||
|
final Value<String> senderKey;
|
||||||
|
final Value<String> senderClaimedKeys;
|
||||||
const InboundGroupSessionsCompanion({
|
const InboundGroupSessionsCompanion({
|
||||||
this.clientId = const Value.absent(),
|
this.clientId = const Value.absent(),
|
||||||
this.roomId = const Value.absent(),
|
this.roomId = const Value.absent(),
|
||||||
|
@ -2203,6 +2255,9 @@ class InboundGroupSessionsCompanion
|
||||||
this.pickle = const Value.absent(),
|
this.pickle = const Value.absent(),
|
||||||
this.content = const Value.absent(),
|
this.content = const Value.absent(),
|
||||||
this.indexes = const Value.absent(),
|
this.indexes = const Value.absent(),
|
||||||
|
this.uploaded = const Value.absent(),
|
||||||
|
this.senderKey = const Value.absent(),
|
||||||
|
this.senderClaimedKeys = const Value.absent(),
|
||||||
});
|
});
|
||||||
InboundGroupSessionsCompanion.insert({
|
InboundGroupSessionsCompanion.insert({
|
||||||
@required int clientId,
|
@required int clientId,
|
||||||
|
@ -2211,6 +2266,9 @@ class InboundGroupSessionsCompanion
|
||||||
@required String pickle,
|
@required String pickle,
|
||||||
this.content = const Value.absent(),
|
this.content = const Value.absent(),
|
||||||
this.indexes = const Value.absent(),
|
this.indexes = const Value.absent(),
|
||||||
|
this.uploaded = const Value.absent(),
|
||||||
|
this.senderKey = const Value.absent(),
|
||||||
|
this.senderClaimedKeys = const Value.absent(),
|
||||||
}) : clientId = Value(clientId),
|
}) : clientId = Value(clientId),
|
||||||
roomId = Value(roomId),
|
roomId = Value(roomId),
|
||||||
sessionId = Value(sessionId),
|
sessionId = Value(sessionId),
|
||||||
|
@ -2222,6 +2280,9 @@ class InboundGroupSessionsCompanion
|
||||||
Expression<String> pickle,
|
Expression<String> pickle,
|
||||||
Expression<String> content,
|
Expression<String> content,
|
||||||
Expression<String> indexes,
|
Expression<String> indexes,
|
||||||
|
Expression<bool> uploaded,
|
||||||
|
Expression<String> senderKey,
|
||||||
|
Expression<String> senderClaimedKeys,
|
||||||
}) {
|
}) {
|
||||||
return RawValuesInsertable({
|
return RawValuesInsertable({
|
||||||
if (clientId != null) 'client_id': clientId,
|
if (clientId != null) 'client_id': clientId,
|
||||||
|
@ -2230,6 +2291,9 @@ class InboundGroupSessionsCompanion
|
||||||
if (pickle != null) 'pickle': pickle,
|
if (pickle != null) 'pickle': pickle,
|
||||||
if (content != null) 'content': content,
|
if (content != null) 'content': content,
|
||||||
if (indexes != null) 'indexes': indexes,
|
if (indexes != null) 'indexes': indexes,
|
||||||
|
if (uploaded != null) 'uploaded': uploaded,
|
||||||
|
if (senderKey != null) 'sender_key': senderKey,
|
||||||
|
if (senderClaimedKeys != null) 'sender_claimed_keys': senderClaimedKeys,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2239,7 +2303,10 @@ class InboundGroupSessionsCompanion
|
||||||
Value<String> sessionId,
|
Value<String> sessionId,
|
||||||
Value<String> pickle,
|
Value<String> pickle,
|
||||||
Value<String> content,
|
Value<String> content,
|
||||||
Value<String> indexes}) {
|
Value<String> indexes,
|
||||||
|
Value<bool> uploaded,
|
||||||
|
Value<String> senderKey,
|
||||||
|
Value<String> senderClaimedKeys}) {
|
||||||
return InboundGroupSessionsCompanion(
|
return InboundGroupSessionsCompanion(
|
||||||
clientId: clientId ?? this.clientId,
|
clientId: clientId ?? this.clientId,
|
||||||
roomId: roomId ?? this.roomId,
|
roomId: roomId ?? this.roomId,
|
||||||
|
@ -2247,6 +2314,9 @@ class InboundGroupSessionsCompanion
|
||||||
pickle: pickle ?? this.pickle,
|
pickle: pickle ?? this.pickle,
|
||||||
content: content ?? this.content,
|
content: content ?? this.content,
|
||||||
indexes: indexes ?? this.indexes,
|
indexes: indexes ?? this.indexes,
|
||||||
|
uploaded: uploaded ?? this.uploaded,
|
||||||
|
senderKey: senderKey ?? this.senderKey,
|
||||||
|
senderClaimedKeys: senderClaimedKeys ?? this.senderClaimedKeys,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2271,6 +2341,15 @@ class InboundGroupSessionsCompanion
|
||||||
if (indexes.present) {
|
if (indexes.present) {
|
||||||
map['indexes'] = Variable<String>(indexes.value);
|
map['indexes'] = Variable<String>(indexes.value);
|
||||||
}
|
}
|
||||||
|
if (uploaded.present) {
|
||||||
|
map['uploaded'] = Variable<bool>(uploaded.value);
|
||||||
|
}
|
||||||
|
if (senderKey.present) {
|
||||||
|
map['sender_key'] = Variable<String>(senderKey.value);
|
||||||
|
}
|
||||||
|
if (senderClaimedKeys.present) {
|
||||||
|
map['sender_claimed_keys'] = Variable<String>(senderClaimedKeys.value);
|
||||||
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2328,9 +2407,45 @@ class InboundGroupSessions extends Table
|
||||||
$customConstraints: '');
|
$customConstraints: '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _uploadedMeta = const VerificationMeta('uploaded');
|
||||||
|
GeneratedBoolColumn _uploaded;
|
||||||
|
GeneratedBoolColumn get uploaded => _uploaded ??= _constructUploaded();
|
||||||
|
GeneratedBoolColumn _constructUploaded() {
|
||||||
|
return GeneratedBoolColumn('uploaded', $tableName, true,
|
||||||
|
$customConstraints: 'DEFAULT false',
|
||||||
|
defaultValue: const CustomExpression<bool>('false'));
|
||||||
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _senderKeyMeta = const VerificationMeta('senderKey');
|
||||||
|
GeneratedTextColumn _senderKey;
|
||||||
|
GeneratedTextColumn get senderKey => _senderKey ??= _constructSenderKey();
|
||||||
|
GeneratedTextColumn _constructSenderKey() {
|
||||||
|
return GeneratedTextColumn('sender_key', $tableName, true,
|
||||||
|
$customConstraints: '');
|
||||||
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _senderClaimedKeysMeta =
|
||||||
|
const VerificationMeta('senderClaimedKeys');
|
||||||
|
GeneratedTextColumn _senderClaimedKeys;
|
||||||
|
GeneratedTextColumn get senderClaimedKeys =>
|
||||||
|
_senderClaimedKeys ??= _constructSenderClaimedKeys();
|
||||||
|
GeneratedTextColumn _constructSenderClaimedKeys() {
|
||||||
|
return GeneratedTextColumn('sender_claimed_keys', $tableName, true,
|
||||||
|
$customConstraints: '');
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<GeneratedColumn> get $columns =>
|
List<GeneratedColumn> get $columns => [
|
||||||
[clientId, roomId, sessionId, pickle, content, indexes];
|
clientId,
|
||||||
|
roomId,
|
||||||
|
sessionId,
|
||||||
|
pickle,
|
||||||
|
content,
|
||||||
|
indexes,
|
||||||
|
uploaded,
|
||||||
|
senderKey,
|
||||||
|
senderClaimedKeys
|
||||||
|
];
|
||||||
@override
|
@override
|
||||||
InboundGroupSessions get asDslTable => this;
|
InboundGroupSessions get asDslTable => this;
|
||||||
@override
|
@override
|
||||||
|
@ -2375,6 +2490,20 @@ class InboundGroupSessions extends Table
|
||||||
context.handle(_indexesMeta,
|
context.handle(_indexesMeta,
|
||||||
indexes.isAcceptableOrUnknown(data['indexes'], _indexesMeta));
|
indexes.isAcceptableOrUnknown(data['indexes'], _indexesMeta));
|
||||||
}
|
}
|
||||||
|
if (data.containsKey('uploaded')) {
|
||||||
|
context.handle(_uploadedMeta,
|
||||||
|
uploaded.isAcceptableOrUnknown(data['uploaded'], _uploadedMeta));
|
||||||
|
}
|
||||||
|
if (data.containsKey('sender_key')) {
|
||||||
|
context.handle(_senderKeyMeta,
|
||||||
|
senderKey.isAcceptableOrUnknown(data['sender_key'], _senderKeyMeta));
|
||||||
|
}
|
||||||
|
if (data.containsKey('sender_claimed_keys')) {
|
||||||
|
context.handle(
|
||||||
|
_senderClaimedKeysMeta,
|
||||||
|
senderClaimedKeys.isAcceptableOrUnknown(
|
||||||
|
data['sender_claimed_keys'], _senderClaimedKeysMeta));
|
||||||
|
}
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5669,6 +5798,9 @@ abstract class _$Database extends GeneratedDatabase {
|
||||||
pickle: row.readString('pickle'),
|
pickle: row.readString('pickle'),
|
||||||
content: row.readString('content'),
|
content: row.readString('content'),
|
||||||
indexes: row.readString('indexes'),
|
indexes: row.readString('indexes'),
|
||||||
|
uploaded: row.readBool('uploaded'),
|
||||||
|
senderKey: row.readString('sender_key'),
|
||||||
|
senderClaimedKeys: row.readString('sender_claimed_keys'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5701,17 +5833,26 @@ abstract class _$Database extends GeneratedDatabase {
|
||||||
readsFrom: {inboundGroupSessions}).map(_rowToDbInboundGroupSession);
|
readsFrom: {inboundGroupSessions}).map(_rowToDbInboundGroupSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> storeInboundGroupSession(int client_id, String room_id,
|
Future<int> storeInboundGroupSession(
|
||||||
String session_id, String pickle, String content, String indexes) {
|
int client_id,
|
||||||
|
String room_id,
|
||||||
|
String session_id,
|
||||||
|
String pickle,
|
||||||
|
String content,
|
||||||
|
String indexes,
|
||||||
|
String sender_key,
|
||||||
|
String sender_claimed_keys) {
|
||||||
return customInsert(
|
return customInsert(
|
||||||
'INSERT OR REPLACE INTO inbound_group_sessions (client_id, room_id, session_id, pickle, content, indexes) VALUES (:client_id, :room_id, :session_id, :pickle, :content, :indexes)',
|
'INSERT OR REPLACE INTO inbound_group_sessions (client_id, room_id, session_id, pickle, content, indexes, sender_key, sender_claimed_keys) VALUES (:client_id, :room_id, :session_id, :pickle, :content, :indexes, :sender_key, :sender_claimed_keys)',
|
||||||
variables: [
|
variables: [
|
||||||
Variable.withInt(client_id),
|
Variable.withInt(client_id),
|
||||||
Variable.withString(room_id),
|
Variable.withString(room_id),
|
||||||
Variable.withString(session_id),
|
Variable.withString(session_id),
|
||||||
Variable.withString(pickle),
|
Variable.withString(pickle),
|
||||||
Variable.withString(content),
|
Variable.withString(content),
|
||||||
Variable.withString(indexes)
|
Variable.withString(indexes),
|
||||||
|
Variable.withString(sender_key),
|
||||||
|
Variable.withString(sender_claimed_keys)
|
||||||
],
|
],
|
||||||
updates: {inboundGroupSessions},
|
updates: {inboundGroupSessions},
|
||||||
);
|
);
|
||||||
|
|
|
@ -71,6 +71,9 @@ CREATE TABLE inbound_group_sessions (
|
||||||
pickle TEXT NOT NULL,
|
pickle TEXT NOT NULL,
|
||||||
content TEXT,
|
content TEXT,
|
||||||
indexes TEXT,
|
indexes TEXT,
|
||||||
|
uploaded BOOLEAN DEFAULT false,
|
||||||
|
sender_key TEXT,
|
||||||
|
sender_claimed_keys TEXT,
|
||||||
UNIQUE(client_id, room_id, session_id)
|
UNIQUE(client_id, room_id, session_id)
|
||||||
) AS DbInboundGroupSession;
|
) AS DbInboundGroupSession;
|
||||||
CREATE INDEX inbound_group_sessions_index ON inbound_group_sessions(client_id);
|
CREATE INDEX inbound_group_sessions_index ON inbound_group_sessions(client_id);
|
||||||
|
@ -186,7 +189,7 @@ removeOutboundGroupSession: DELETE FROM outbound_group_sessions WHERE client_id
|
||||||
dbGetInboundGroupSessionKey: SELECT * FROM inbound_group_sessions WHERE client_id = :client_id AND room_id = :room_id AND session_id = :session_id;
|
dbGetInboundGroupSessionKey: SELECT * FROM inbound_group_sessions WHERE client_id = :client_id AND room_id = :room_id AND session_id = :session_id;
|
||||||
dbGetInboundGroupSessionKeys: SELECT * FROM inbound_group_sessions WHERE client_id = :client_id AND room_id = :room_id;
|
dbGetInboundGroupSessionKeys: SELECT * FROM inbound_group_sessions WHERE client_id = :client_id AND room_id = :room_id;
|
||||||
getAllInboundGroupSessions: SELECT * FROM inbound_group_sessions WHERE client_id = :client_id;
|
getAllInboundGroupSessions: SELECT * FROM inbound_group_sessions WHERE client_id = :client_id;
|
||||||
storeInboundGroupSession: INSERT OR REPLACE INTO inbound_group_sessions (client_id, room_id, session_id, pickle, content, indexes) VALUES (:client_id, :room_id, :session_id, :pickle, :content, :indexes);
|
storeInboundGroupSession: INSERT OR REPLACE INTO inbound_group_sessions (client_id, room_id, session_id, pickle, content, indexes, sender_key, sender_claimed_keys) VALUES (:client_id, :room_id, :session_id, :pickle, :content, :indexes, :sender_key, :sender_claimed_keys);
|
||||||
updateInboundGroupSessionIndexes: UPDATE inbound_group_sessions SET indexes = :indexes WHERE client_id = :client_id AND room_id = :room_id AND session_id = :session_id;
|
updateInboundGroupSessionIndexes: UPDATE inbound_group_sessions SET indexes = :indexes WHERE client_id = :client_id AND room_id = :room_id AND session_id = :session_id;
|
||||||
storeUserDeviceKeysInfo: INSERT OR REPLACE INTO user_device_keys (client_id, user_id, outdated) VALUES (:client_id, :user_id, :outdated);
|
storeUserDeviceKeysInfo: INSERT OR REPLACE INTO user_device_keys (client_id, user_id, outdated) VALUES (:client_id, :user_id, :outdated);
|
||||||
setVerifiedUserDeviceKey: UPDATE user_device_keys_key SET verified = :verified WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id;
|
setVerifiedUserDeviceKey: UPDATE user_device_keys_key SET verified = :verified WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id;
|
||||||
|
|
|
@ -60,7 +60,7 @@ void main() {
|
||||||
'session_key': sessionKey,
|
'session_key': sessionKey,
|
||||||
},
|
},
|
||||||
encryptedContent: {
|
encryptedContent: {
|
||||||
'sender_key': validSessionId,
|
'sender_key': validSenderKey,
|
||||||
});
|
});
|
||||||
await client.encryption.keyManager.handleToDeviceEvent(event);
|
await client.encryption.keyManager.handleToDeviceEvent(event);
|
||||||
expect(
|
expect(
|
||||||
|
@ -185,6 +185,11 @@ void main() {
|
||||||
.getInboundGroupSession(roomId, sessionId, senderKey) !=
|
.getInboundGroupSession(roomId, sessionId, senderKey) !=
|
||||||
null,
|
null,
|
||||||
true);
|
true);
|
||||||
|
expect(
|
||||||
|
client.encryption.keyManager
|
||||||
|
.getInboundGroupSession(roomId, sessionId, 'invalid') !=
|
||||||
|
null,
|
||||||
|
false);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
client.encryption.keyManager
|
client.encryption.keyManager
|
||||||
|
@ -196,6 +201,11 @@ void main() {
|
||||||
.getInboundGroupSession('otherroom', sessionId, senderKey) !=
|
.getInboundGroupSession('otherroom', sessionId, senderKey) !=
|
||||||
null,
|
null,
|
||||||
true);
|
true);
|
||||||
|
expect(
|
||||||
|
client.encryption.keyManager
|
||||||
|
.getInboundGroupSession('otherroom', sessionId, 'invalid') !=
|
||||||
|
null,
|
||||||
|
false);
|
||||||
expect(
|
expect(
|
||||||
client.encryption.keyManager
|
client.encryption.keyManager
|
||||||
.getInboundGroupSession('otherroom', 'invalid', senderKey) !=
|
.getInboundGroupSession('otherroom', 'invalid', senderKey) !=
|
||||||
|
@ -215,6 +225,20 @@ void main() {
|
||||||
.getInboundGroupSession(roomId, sessionId, senderKey) !=
|
.getInboundGroupSession(roomId, sessionId, senderKey) !=
|
||||||
null,
|
null,
|
||||||
true);
|
true);
|
||||||
|
|
||||||
|
client.encryption.keyManager.clearInboundGroupSessions();
|
||||||
|
expect(
|
||||||
|
client.encryption.keyManager
|
||||||
|
.getInboundGroupSession(roomId, sessionId, senderKey) !=
|
||||||
|
null,
|
||||||
|
false);
|
||||||
|
await client.encryption.keyManager
|
||||||
|
.loadInboundGroupSession(roomId, sessionId, 'invalid');
|
||||||
|
expect(
|
||||||
|
client.encryption.keyManager
|
||||||
|
.getInboundGroupSession(roomId, sessionId, 'invalid') !=
|
||||||
|
null,
|
||||||
|
false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('setInboundGroupSession', () async {
|
test('setInboundGroupSession', () async {
|
||||||
|
|
|
@ -53,7 +53,7 @@ void main() {
|
||||||
if (!olmEnabled) return;
|
if (!olmEnabled) return;
|
||||||
|
|
||||||
final validSessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU';
|
final validSessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU';
|
||||||
final validSenderKey = '3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI';
|
final validSenderKey = 'JBG7ZaPn54OBC7TuIEiylW3BZ+7WcGQhFBPB9pogbAg';
|
||||||
test('Create Request', () async {
|
test('Create Request', () async {
|
||||||
var matrix = await getClient();
|
var matrix = await getClient();
|
||||||
final requestRoom = matrix.getRoomById('!726s6s6q:example.com');
|
final requestRoom = matrix.getRoomById('!726s6s6q:example.com');
|
||||||
|
|
Loading…
Reference in a new issue