Skip to content

Commit

Permalink
feat: Send state event to timeline when sharing megolm session
Browse files Browse the repository at this point in the history
  • Loading branch information
krille-chan committed Feb 4, 2025
1 parent 0874488 commit d7c4ce8
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 24 deletions.
96 changes: 72 additions & 24 deletions lib/encryption/key_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,43 @@ class KeyManager {
return sess;
}

void _sendEncryptionInfoEvent({
required String roomId,
required List<String> userIds,
List<String>? deviceIds,
}) async {
await client.database?.transaction(() async {
await client.handleSync(
SyncUpdate(
nextBatch: '',
rooms: RoomsUpdate(
join: {
roomId: JoinedRoomUpdate(
timeline: TimelineUpdate(
events: [
MatrixEvent(
eventId:
'fake_event_${client.generateUniqueTransactionId()}',
content: {
'body':
'${userIds.join(', ')} can now read along${deviceIds != null ? ' on a new device' : ''}',
if (deviceIds != null) 'devices': deviceIds,
'users': userIds,
},
type: 'sdk.dart.matrix.new_megolm_session',
senderId: client.userID!,
originServerTs: DateTime.now(),
),
],
),
),
},
),
),
);
});
}

Map<String, Map<String, bool>> _getDeviceKeyIdMap(
List<DeviceKeys> deviceKeys,
) {
Expand Down Expand Up @@ -328,21 +365,6 @@ class KeyManager {
return true;
}

if (!wipe) {
// first check if it needs to be rotated
final encryptionContent =
room.getState(EventTypes.Encryption)?.parsedRoomEncryptionContent;
final maxMessages = encryptionContent?.rotationPeriodMsgs ?? 100;
final maxAge = encryptionContent?.rotationPeriodMs ??
604800000; // default of one week
if ((sess.sentMessages ?? maxMessages) >= maxMessages ||
sess.creationTime
.add(Duration(milliseconds: maxAge))
.isBefore(DateTime.now())) {
wipe = true;
}
}

final inboundSess = await loadInboundGroupSession(
room.id,
sess.outboundGroupSession!.session_id(),
Expand All @@ -368,6 +390,7 @@ class KeyManager {
// new user! Gotta send the megolm session to them
devicesToReceive
.addAll(newDeviceKeys.where((d) => newUsers.contains(d.userId)));
_sendEncryptionInfoEvent(roomId: roomId, userIds: newUsers.toList());
}
// okay, now we must test all the individual user devices, if anything new got blocked
// or if we need to send to any new devices.
Expand All @@ -387,12 +410,6 @@ class KeyManager {
.map((e) => e.key)
.toSet()
: <String>{};
// we don't really care about old devices that got dropped (deleted), we only care if new ones got added and if new ones got blocked
// check if new devices got blocked
if (newBlockedDevices.difference(oldBlockedDevices).isNotEmpty) {
wipe = true;
break;
}
// and now add all the new devices!
final oldDeviceIds = sess.devices.containsKey(userId)
? sess.devices[userId]!.entries
Expand All @@ -408,14 +425,30 @@ class KeyManager {
.toSet()
: <String>{};

// check if any new devices need keys
final newDevices = newDeviceIds.difference(oldDeviceIds);

if (userId != client.userID && newDevices.isNotEmpty) {
_sendEncryptionInfoEvent(
roomId: roomId,
userIds: [userId],
deviceIds: newDevices.toList(),
);
}

// we don't really care about old devices that got dropped (deleted), we only care if new ones got added and if new ones got blocked
// check if new devices got blocked
if (newBlockedDevices.difference(oldBlockedDevices).isNotEmpty) {
wipe = true;
continue;
}

// check if a device got removed
if (oldDeviceIds.difference(newDeviceIds).isNotEmpty) {
wipe = true;
break;
continue;
}

// check if any new devices need keys
final newDevices = newDeviceIds.difference(oldDeviceIds);
if (newDeviceIds.isNotEmpty) {
devicesToReceive.addAll(
newDeviceKeys.where(
Expand All @@ -426,6 +459,21 @@ class KeyManager {
}
}

if (!wipe) {
// first check if it needs to be rotated
final encryptionContent =
room.getState(EventTypes.Encryption)?.parsedRoomEncryptionContent;
final maxMessages = encryptionContent?.rotationPeriodMsgs ?? 100;
final maxAge = encryptionContent?.rotationPeriodMs ??
604800000; // default of one week
if ((sess.sentMessages ?? maxMessages) >= maxMessages ||
sess.creationTime
.add(Duration(milliseconds: maxAge))
.isBefore(DateTime.now())) {
wipe = true;
}
}

if (!wipe) {
if (!use) {
return false;
Expand Down
1 change: 1 addition & 0 deletions lib/src/utils/event_localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ abstract class EventLocalizations {
EventTypes.Sticker: (event, i18n, body) => i18n.sentASticker(
event.senderFromMemoryOrFallback.calcDisplayname(i18n: i18n),
),
'sdk.dart.matrix.new_megolm_session': (event, i18n, body) => body,
EventTypes.Redaction: (event, i18n, body) => i18n.redactedAnEvent(event),
EventTypes.RoomAliases: (event, i18n, body) => i18n.changedTheRoomAliases(
event.senderFromMemoryOrFallback.calcDisplayname(i18n: i18n),
Expand Down

0 comments on commit d7c4ce8

Please sign in to comment.