refactor: Added type casts to match refactored matrix_api_lite

This commit is contained in:
Malin Errenst 2023-06-09 14:41:34 +02:00
parent 17df38b874
commit 5943576b1b
No known key found for this signature in database
13 changed files with 122 additions and 67 deletions

View File

@ -70,8 +70,8 @@ class KeyManager {
lastEvent.type == EventTypes.Encrypted &&
lastEvent.content['can_request_session'] == true) {
try {
maybeAutoRequest(room.id, lastEvent.content['session_id'],
lastEvent.content['sender_key']);
maybeAutoRequest(room.id, lastEvent.content['session_id'] as String,
lastEvent.content['sender_key'] as String?);
} catch (_) {
// dispose
}
@ -638,7 +638,7 @@ class KeyManager {
final sessionId = sessionEntry.key;
final session = sessionEntry.value;
final sessionData = session.sessionData;
Map<String, dynamic>? decrypted;
Map<String, Object?>? decrypted;
try {
decrypted = json.decode(decryption.decrypt(
sessionData['ephemeral'] as String,
@ -651,11 +651,11 @@ class KeyManager {
decrypted['session_id'] = sessionId;
decrypted['room_id'] = roomId;
await setInboundGroupSession(
roomId, sessionId, decrypted['sender_key'], decrypted,
roomId, sessionId, decrypted['sender_key'] as String, decrypted,
forwarded: true,
senderClaimedKeys: decrypted['sender_claimed_keys'] != null
? Map<String, String>.from(
decrypted['sender_claimed_keys']!)
senderClaimedKeys: decrypted['sender_claimed_keys']
is Map<String, String>
? (decrypted['sender_claimed_keys'] as Map<String, String>)
: <String, String>{},
uploaded: true);
}
@ -836,6 +836,7 @@ class KeyManager {
Logs().i('[KeyManager] No body, doing nothing');
return; // no body
}
final body = event.content['body'] as Map<String, Object?>;
final device = client.userDeviceKeys[event.sender]
?.deviceKeys[event.content['requesting_device_id']];
if (device == null) {
@ -847,20 +848,29 @@ class KeyManager {
Logs().i('[KeyManager] Request is by ourself, ignoring');
return; // ignore requests by ourself
}
final room = client.getRoomById(event.content['body']['room_id']);
if (body['room_id'] is! String) {
return; // wrong type for room_id
}
final room = client.getRoomById(body['room_id'] as String);
if (room == null) {
Logs().i('[KeyManager] Unknown room, ignoring');
return; // unknown room
}
final sessionId = event.content['body']['session_id'];
final sessionId = body['session_id'];
if (sessionId is! String) {
return; // wrong type for session_id
}
// okay, let's see if we have this session at all
final session = await loadInboundGroupSession(room.id, sessionId);
if (session == null) {
Logs().i('[KeyManager] Unknown session, ignoring');
return; // we don't have this session anyways
}
if (event.content['request_id'] is! String) {
return; // wrong type for request_id
}
final request = KeyManagerKeyShareRequest(
requestId: event.content['request_id'],
requestId: event.content['request_id'] as String,
devices: [device],
room: room,
sessionId: sessionId,
@ -933,15 +943,18 @@ class KeyManager {
if (event.content['forwarding_curve25519_key_chain'] is! List) {
event.content['forwarding_curve25519_key_chain'] = <String>[];
}
event.content['forwarding_curve25519_key_chain']
(event.content['forwarding_curve25519_key_chain'] as List)
.add(encryptedContent['sender_key']);
if (event.content['sender_claimed_ed25519_key'] is! String) {
return; // wrong type
}
// TODO: verify that the keys work to decrypt a message
// alright, all checks out, let's go ahead and store this session
await setInboundGroupSession(request.room.id, request.sessionId,
device.curve25519Key!, event.content,
forwarded: true,
senderClaimedKeys: {
'ed25519': event.content['sender_claimed_ed25519_key'],
'ed25519': event.content['sender_claimed_ed25519_key'] as String,
});
request.devices.removeWhere(
(k) => k.userId == device.userId && k.deviceId == device.deviceId);
@ -974,8 +987,8 @@ class KeyManager {
Logs().v('[KeyManager] not encrypted, ignoring...');
return; // the event wasn't encrypted, this is a security risk;
}
final String roomId = event.content['room_id'];
final String sessionId = event.content['session_id'];
final String roomId = event.content['room_id'] as String;
final String sessionId = event.content['session_id'] as String;
final sender_ed25519 = client.userDeviceKeys[event.sender]
?.deviceKeys[event.content['requesting_device_id']]?.ed25519Key;
if (sender_ed25519 != null) {

View File

@ -295,8 +295,9 @@ class SSSS {
bool isValid(SSSSCache dbEntry) =>
keys.contains(dbEntry.keyId) &&
dbEntry.ciphertext != null &&
client.accountData[type]?.content['encrypted'][dbEntry.keyId]
['ciphertext'] ==
((client.accountData[type]?.content['encrypted']
as Map<String, Object?>)[dbEntry.keyId]
as Map<String, Object?>)['ciphertext'] ==
dbEntry.ciphertext;
final fromCache = _cache[type];
@ -322,17 +323,22 @@ class SSSS {
if (secretInfo.content['encrypted'] is! Map) {
throw Exception('Content is not encrypted');
}
if (secretInfo.content['encrypted'][keyId] is! Map) {
if ((secretInfo.content['encrypted'] as Map<String, Object?>)[keyId]
is! Map) {
throw Exception('Wrong / unknown key');
}
final enc = secretInfo.content['encrypted'][keyId];
final enc = (secretInfo.content['encrypted'] as Map<String, Object?>)[keyId]
as Map<String, Object?>;
final encryptInfo = EncryptedContent(
iv: enc['iv'], ciphertext: enc['ciphertext'], mac: enc['mac']);
iv: enc['iv'] as String,
ciphertext: enc['ciphertext'] as String,
mac: enc['mac'] as String);
final decrypted = await decryptAes(encryptInfo, key, type);
final db = client.database;
if (cacheTypes.contains(type) && db != null) {
// cache the thing
await db.storeSSSSCache(type, keyId, enc['ciphertext'], decrypted);
await db.storeSSSSCache(
type, keyId, enc['ciphertext'] as String, decrypted);
onSecretStored.add(keyId);
if (_cacheCallbacks.containsKey(type) && await getCached(type) == null) {
_cacheCallbacks[type]!(decrypted);
@ -382,10 +388,11 @@ class SSSS {
if (content == null) {
throw InvalidPassphraseException('Key has no content!');
}
final contentEncrypted = content['encrypted'] as Map<String, Object?>;
final otherKeys =
Set<String>.from(content['encrypted'].keys.where((k) => k != keyId));
content['encrypted'].removeWhere((k, v) => otherKeys.contains(k));
Set<String>.from(contentEncrypted.keys.where((k) => k != keyId));
contentEncrypted.removeWhere((k, v) => otherKeys.contains(k));
// yes, we are paranoid...
if (await getStored(type, keyId, key) != secret) {
throw Exception('Secrets do not match up!');
@ -394,8 +401,9 @@ class SSSS {
await client.setAccountData(client.userID!, type, content);
if (cacheTypes.contains(type)) {
// cache the thing
await client.database?.storeSSSSCache(
type, keyId, content['encrypted'][keyId]['ciphertext'], secret);
final ciphertext = (contentEncrypted[keyId]
as Map<String, Object?>)['ciphertext'] as String;
await client.database?.storeSSSSCache(type, keyId, ciphertext, secret);
onSecretStored.add(keyId);
}
}
@ -502,7 +510,7 @@ class SSSS {
}
// alright, all seems fine...let's check if we actually have the secret they are asking for
final type = event.content['name'];
final secret = await getCached(type);
final secret = await getCached(type as String);
if (secret == null) {
Logs()
.i('[SSSS] We don\'t have the secret for $type ourself, ignoring');
@ -536,11 +544,11 @@ class SSSS {
Logs().i('[SSSS] Someone else replied?');
return; // someone replied whom we didn't send the share request to
}
final secret = event.content['secret'];
if (event.content['secret'] is! String) {
Logs().i('[SSSS] Secret wasn\'t a string');
return; // the secret wasn't a string....wut?
}
final secret = event.content['secret'] as String;
// let's validate if the secret is, well, valid
if (_validators.containsKey(request.type) &&
!(await _validators[request.type]!(secret))) {
@ -557,8 +565,9 @@ class SSSS {
if (db != null) {
final keyId = keyIdFromType(request.type);
if (keyId != null) {
final ciphertext = client.accountData[request.type]!
.content['encrypted'][keyId]['ciphertext'];
final ciphertext = ((client.accountData[request.type]!
.content['encrypted'] as Map<String, Object?>)[keyId]
as Map<String, Object?>)['ciphertext'] as String;
await db.storeSSSSCache(request.type, keyId, ciphertext, secret);
if (_cacheCallbacks.containsKey(request.type)) {
_cacheCallbacks[request.type]!(secret);
@ -575,7 +584,7 @@ class SSSS {
return null;
}
if (data.content['encrypted'] is Map) {
return data.content['encrypted'].keys.toSet();
return (data.content['encrypted'] as Map<String, Object?>).keys.toSet();
}
return null;
}

View File

@ -109,7 +109,8 @@ class Bootstrap {
}
final validKeys = <String>{};
final invalidKeys = <String>{};
for (final keyEntry in event.content['encrypted'].entries) {
for (final keyEntry
in (event.content['encrypted'] as Map<String, Object?>).entries) {
final key = keyEntry.key;
final value = keyEntry.value;
if (value is! Map) {

View File

@ -47,7 +47,8 @@ extension DehydratedDeviceMatrixApi on MatrixApi {
},
},
);
return Map<String, int>.from(response['one_time_key_counts']);
return Map<String, int>.from(
response['one_time_key_counts'] as Map<String, Object?>);
}
/// uploads a dehydrated device.

View File

@ -2731,12 +2731,16 @@ class Client extends MatrixApi {
/// Whether all push notifications are muted using the [.m.rule.master]
/// rule of the push rules: https://matrix.org/docs/spec/client_server/r0.6.0#m-rule-master
bool get allPushNotificationsMuted {
final Map<String, dynamic>? globalPushRules =
_accountData[EventTypes.PushRules]?.content['global'];
final Map<String, Object?>? globalPushRules =
_accountData[EventTypes.PushRules]?.content['global']
is Map<String, Object?>?
? _accountData[EventTypes.PushRules]?.content['global']
as Map<String, Object?>?
: null;
if (globalPushRules == null) return false;
if (globalPushRules['override'] is List) {
for (final pushRule in globalPushRules['override']) {
for (final pushRule in globalPushRules['override'] as List) {
if (pushRule['rule_id'] == '.m.rule.master') {
return pushRule['enabled'];
}
@ -2816,8 +2820,9 @@ class Client extends MatrixApi {
List<String> get ignoredUsers => (_accountData
.containsKey('m.ignored_user_list') &&
_accountData['m.ignored_user_list']?.content['ignored_users'] is Map)
? List<String>.from(
_accountData['m.ignored_user_list']?.content['ignored_users'].keys)
? List<String>.from((_accountData['m.ignored_user_list']
?.content['ignored_users'] as Map<String, Object?>)
.keys)
: [];
/// Ignore another user. This will clear the local cached messages to

View File

@ -259,7 +259,9 @@ class Event extends MatrixEvent {
String get messageType => type == EventTypes.Sticker
? MessageTypes.Sticker
: (content['msgtype'] is String ? content['msgtype'] : MessageTypes.Text);
: (content['msgtype'] is String
? content['msgtype'] as String
: MessageTypes.Text);
void setRedactionEvent(Event redactedBecause) {
unsigned = {
@ -301,11 +303,12 @@ class Event extends MatrixEvent {
}
/// Returns the body of this event if it has a body.
String get text => content['body'] is String ? content['body'] : '';
String get text => content['body'] is String ? content['body'] as String : '';
/// Returns the formatted boy of this event if it has a formatted body.
String get formattedText =>
content['formatted_body'] is String ? content['formatted_body'] : '';
String get formattedText => content['formatted_body'] is String
? content['formatted_body'] as String
: '';
/// Use this to get the body.
String get body {
@ -398,11 +401,16 @@ class Event extends MatrixEvent {
);
}
String transactionId = eventId;
if (unsigned?['transaction_id'] is String) {
transactionId = unsigned?['transaction_id'] as String;
}
// we do not remove the event here. It will automatically be updated
// in the `sendEvent` method to transition -1 -> 0 -> 1 -> 2
return await room.sendEvent(
content,
txid: txid ?? unsigned?['transaction_id'] ?? eventId,
txid: txid ?? transactionId,
);
}
@ -432,13 +440,15 @@ class Event extends MatrixEvent {
content['can_request_session'] != true) {
throw ('Session key not requestable');
}
await room.requestSessionKey(content['session_id'], content['sender_key']);
await room.requestSessionKey(
content['session_id'] as String, content['sender_key'] as String);
return;
}
/// Gets the info map of file events, or a blank map if none present
Map get infoMap =>
content['info'] is Map ? content['info'] : <String, dynamic>{};
Map get infoMap => content['info'] is Map
? content['info'] as Map<String, Object?>
: <String, Object?>{};
/// Gets the thumbnail info map of file events, or a blank map if nonepresent
Map get thumbnailInfoMap => infoMap['thumbnail_info'] is Map
@ -461,8 +471,9 @@ class Event extends MatrixEvent {
/// Gets the mimetype of the attachment of a file event, or a blank string if not present
String get attachmentMimetype => infoMap['mimetype'] is String
? infoMap['mimetype'].toLowerCase()
: (content['file'] is Map && content['file']['mimetype'] is String
? content['file']['mimetype']
: (content['file'] is Map &&
(content['file'] as Map<String, Object?>)['mimetype'] is String
? (content['file'] as Map<String, Object?>)['mimetype']
: '');
/// Gets the mimetype of the thumbnail of a file event, or a blank string if not present
@ -475,7 +486,9 @@ class Event extends MatrixEvent {
/// Gets the underlying mxc url of an attachment of a file event, or null if not present
Uri? get attachmentMxcUrl {
final url = isAttachmentEncrypted ? content['file']['url'] : content['url'];
final url = isAttachmentEncrypted
? (content['file'] as Map<String, Object?>)['url']
: content['url'];
return url is String ? Uri.tryParse(url) : null;
}
@ -763,7 +776,8 @@ class Event extends MatrixEvent {
relationshipType == RelationshipTypes.edit &&
content.tryGet<Map<String, dynamic>>('m.new_content') != null) {
if (plaintextBody &&
content['m.new_content']['format'] == 'org.matrix.custom.html') {
(content['m.new_content'] as Map<String, Object?>)['format'] ==
'org.matrix.custom.html') {
htmlMessage = true;
body = HtmlToText.convert(
(content['m.new_content'] as Map<String, dynamic>)
@ -818,7 +832,8 @@ class Event extends MatrixEvent {
if (content.tryGet<Map<String, dynamic>>('m.relates_to') == null) {
return null;
}
if (content['m.relates_to'].containsKey('rel_type')) {
if ((content['m.relates_to'] as Map<String, Object?>)
.containsKey('rel_type')) {
if (content
.tryGet<Map<String, dynamic>>('m.relates_to')
?.tryGet<String>('rel_type') ==
@ -826,7 +841,8 @@ class Event extends MatrixEvent {
return RelationshipTypes.thread;
}
}
if (content['m.relates_to'].containsKey('m.in_reply_to')) {
if ((content['m.relates_to'] as Map<String, Object?>)
.containsKey('m.in_reply_to')) {
return RelationshipTypes.reply;
}
return content

View File

@ -269,7 +269,7 @@ class Room {
final invitation = getState(EventTypes.RoomMember, client.userID!);
if (invitation != null && invitation.unsigned?['prev_sender'] != null) {
final name = unsafeGetUserFromMemoryOrFallback(
invitation.unsigned?['prev_sender'])
invitation.unsigned?['prev_sender'] as String)
.calcDisplayname(i18n: i18n);
return i18n.wasDirectChatDisplayName(name);
}
@ -1315,8 +1315,9 @@ class Room {
Future<void> removeFromDirectChat() async {
final directChats = client.directChats.copy();
for (final k in directChats.keys) {
if (directChats[k] is List && directChats[k].contains(id)) {
directChats[k].remove(id);
final directChat = directChats[k];
if (directChat is List && directChat.contains(id)) {
directChat.remove(id);
}
}
@ -1833,7 +1834,9 @@ class Room {
final currentPowerLevelsMap = getState(EventTypes.RoomPowerLevels)?.content;
if (currentPowerLevelsMap != null) {
final newPowerLevelMap = currentPowerLevelsMap;
final eventsMap = newPowerLevelMap['events'] ?? {};
final eventsMap = newPowerLevelMap['events'] is Map<String, Object?>
? newPowerLevelMap['events'] as Map<String, Object?>
: <String, Object?>{};
eventsMap.addAll({
EventTypes.GroupCallPrefix: getDefaultPowerLevel(currentPowerLevelsMap),
EventTypes.GroupCallMemberPrefix:

View File

@ -350,8 +350,8 @@ class Timeline {
try {
room.client.encryption?.keyManager.maybeAutoRequest(
room.id,
event.content['session_id'],
event.content['sender_key'],
event.content['session_id'] as String,
event.content['sender_key'] as String,
tryOnlineBackup: tryOnlineBackup,
onlineKeyBackupOnly: onlineKeyBackupOnly,
);
@ -389,7 +389,7 @@ class Timeline {
final txnid = events[i].unsigned?['transaction_id'];
if (txnid != null) {
searchHaystack.add(txnid);
searchHaystack.add(txnid as String);
}
if (searchNeedle.intersection(searchHaystack).isNotEmpty) {
break;
@ -402,7 +402,10 @@ class Timeline {
eventSet.removeWhere((e) =>
e.matchesEventOrTransactionId(event.eventId) ||
(event.unsigned != null &&
e.matchesEventOrTransactionId(event.unsigned?['transaction_id'])));
e.matchesEventOrTransactionId(
(event.unsigned?['transaction_id'] is String)
? (event.unsigned?['transaction_id'] as String)
: null)));
}
void addAggregatedEvent(Event event) {

View File

@ -426,7 +426,7 @@ class DeviceKeys extends SignableKey {
late DateTime lastActive;
String? get curve25519Key => keys['curve25519:$deviceId'];
String? get deviceDisplayName => unsigned?['device_display_name'];
String? get deviceDisplayName => unsigned?['device_display_name'] as String;
bool? _validSelfSignature;
bool get selfSigned =>

View File

@ -204,11 +204,11 @@ abstract class EventLocalizations {
event.senderFromMemoryOrFallback.calcDisplayname(i18n: i18n)),
EventTypes.RoomName: (event, i18n, body) => i18n.changedTheChatNameTo(
event.senderFromMemoryOrFallback.calcDisplayname(i18n: i18n),
event.content['name']),
event.content['name'] as String),
EventTypes.RoomTopic: (event, i18n, body) =>
i18n.changedTheChatDescriptionTo(
event.senderFromMemoryOrFallback.calcDisplayname(i18n: i18n),
event.content['topic']),
event.content['topic'] as String),
EventTypes.RoomAvatar: (event, i18n, body) => i18n.changedTheChatAvatar(
event.senderFromMemoryOrFallback.calcDisplayname(i18n: i18n)),
EventTypes.GuestAccess: (event, i18n, body) {

View File

@ -61,11 +61,13 @@ extension ImagePackRoomExtension on Room {
// next we add all the external image packs
final packRooms = client.accountData['im.ponies.emote_rooms'];
if (packRooms != null && packRooms.content['rooms'] is Map) {
for (final roomEntry in packRooms.content['rooms'].entries) {
for (final roomEntry
in (packRooms.content['rooms'] as Map<String, Object?>).entries) {
final roomId = roomEntry.key;
final room = client.getRoomById(roomId);
if (room != null && roomEntry.value is Map) {
for (final stateKeyEntry in roomEntry.value.entries) {
for (final stateKeyEntry
in (roomEntry.value as Map<String, Object?>).entries) {
final stateKey = stateKeyEntry.key;
final fallbackSlug =
'${room.getLocalizedDisplayname()}-${stateKey.isNotEmpty ? '$stateKey-' : ''}${room.id}';

View File

@ -726,8 +726,8 @@ class VoIP {
voip: this,
room: room,
groupCallId: groupCallId,
type: callType,
intent: callIntent,
type: callType as String,
intent: callIntent as String,
);
groupCalls[groupCallId!] = groupCall;

View File

@ -1042,8 +1042,10 @@ void main() {
test('pushRuleState', () async {
expect(room.pushRuleState, PushRuleState.mentionsOnly);
matrix.accountData['m.push_rules']?.content['global']['override'].add(
matrix.accountData['m.push_rules']?.content['global']['room'][0]);
((matrix.accountData['m.push_rules']?.content['global']
as Map<String, Object?>)['override'] as List)
.add(((matrix.accountData['m.push_rules']?.content['global']
as Map<String, Object?>)['room'] as List)[0]);
expect(room.pushRuleState, PushRuleState.dontNotify);
});