CI: Use correct image

This commit is contained in:
Christian Pauly 2021-05-20 09:21:37 +02:00
parent c66e35c16c
commit c3d47b16c6
14 changed files with 674 additions and 222 deletions

View File

@ -85,7 +85,7 @@ code_analyze:
tags:
- docker
stage: coverage
image: cirrusci/flutter
image: registry.gitlab.com/famedly/containers/flutter-dockerimages:stable
dependencies: []
script:
- flutter format lib/ test/ test_driver/ --set-exit-if-changed

View File

@ -231,11 +231,12 @@ class KeyManager {
}
return sess; // nothing to do
}
final sess = await client.database
?.getInboundGroupSession(client.id, roomId, sessionId, client.userID);
if (sess == null) {
final session = await client.database
?.getInboundGroupSession(client.id, roomId, sessionId);
if (session == null) {
return null;
}
final sess = SessionKey.fromDb(session, client.userID);
if (!_inboundGroupSessions.containsKey(roomId)) {
_inboundGroupSessions[roomId] = <String, SessionKey>{};
}

View File

@ -19,7 +19,6 @@
import 'package:olm/olm.dart' as olm;
import '../../famedlysdk.dart';
import '../../src/database/database.dart' show DbOlmSessions;
class OlmSession {
String identityKey;
@ -39,14 +38,14 @@ class OlmSession {
this.lastReceived,
});
OlmSession.fromDb(DbOlmSessions dbEntry, String key) : key = key {
OlmSession.fromJson(Map<String, dynamic> dbEntry, String key) : key = key {
session = olm.Session();
try {
session.unpickle(key, dbEntry.pickle);
identityKey = dbEntry.identityKey;
sessionId = dbEntry.sessionId;
session.unpickle(key, dbEntry['pickle']);
identityKey = dbEntry['identity_key'];
sessionId = dbEntry['session_id'];
lastReceived =
DateTime.fromMillisecondsSinceEpoch(dbEntry.lastReceived ?? 0);
DateTime.fromMillisecondsSinceEpoch(dbEntry['last_received'] ?? 0);
assert(sessionId == session.session_id());
} catch (e, s) {
Logs().e('[LibOlm] Could not unpickle olm session', e, s);

View File

@ -21,7 +21,6 @@ import 'dart:convert';
import 'package:olm/olm.dart' as olm;
import '../../famedlysdk.dart';
import '../../src/database/database.dart' show DbOutboundGroupSession;
class OutboundGroupSession {
/// The devices is a map from user id to device id to if the device is blocked.
@ -42,11 +41,11 @@ class OutboundGroupSession {
this.sentMessages,
this.key});
OutboundGroupSession.fromDb(DbOutboundGroupSession dbEntry, String key)
OutboundGroupSession.fromJson(Map<String, dynamic> dbEntry, String key)
: key = key {
try {
devices = {};
for (final entry in json.decode(dbEntry.deviceIds).entries) {
for (final entry in json.decode(dbEntry['device_ids']).entries) {
devices[entry.key] = Map<String, bool>.from(entry.value);
}
} catch (e) {
@ -58,9 +57,10 @@ class OutboundGroupSession {
}
outboundGroupSession = olm.OutboundGroupSession();
try {
outboundGroupSession.unpickle(key, dbEntry.pickle);
creationTime = DateTime.fromMillisecondsSinceEpoch(dbEntry.creationTime);
sentMessages = dbEntry.sentMessages;
outboundGroupSession.unpickle(key, dbEntry['pickle']);
creationTime =
DateTime.fromMillisecondsSinceEpoch(dbEntry['creation_time']);
sentMessages = dbEntry['sent_messages'];
} catch (e, s) {
dispose();
Logs().e('[LibOlm] Unable to unpickle outboundGroupSession', e, s);

View File

@ -38,3 +38,4 @@ export 'src/room.dart';
export 'src/timeline.dart';
export 'src/user.dart';
export 'src/database/database.dart' show Database;
export 'src/database/database_api.dart';

View File

@ -843,15 +843,15 @@ class Client extends MatrixApi {
if (database != null) {
final account = await database.getClient(clientName);
if (account != null) {
_id = account.clientId;
homeserver = Uri.parse(account.homeserverUrl);
accessToken = account.token;
_userID = account.userId;
_deviceID = account.deviceId;
_deviceName = account.deviceName;
syncFilterId = account.syncFilterId;
prevBatch = account.prevBatch;
olmAccount = account.olmAccount;
_id = account['client_id'];
homeserver = Uri.parse(account['homeserver_url']);
accessToken = account['token'];
_userID = account['user_id'];
_deviceID = account['device_id'];
_deviceName = account['device_name'];
syncFilterId = account['sync_filter_id'];
prevBatch = account['prev_batch'];
olmAccount = account['olm_account'];
}
}
if (newToken != null) {

View File

@ -21,7 +21,6 @@ import 'dart:convert';
import 'package:famedlysdk/encryption/utils/olm_session.dart';
import 'package:famedlysdk/encryption/utils/outbound_group_session.dart';
import 'package:famedlysdk/encryption/utils/session_key.dart';
import 'package:famedlysdk/encryption/utils/ssss_cache.dart';
import 'package:famedlysdk/encryption/utils/stored_inbound_group_session.dart';
import 'package:famedlysdk/src/utils/QueuedToDeviceEvent.dart';
@ -211,11 +210,11 @@ class Database extends _$Database implements DatabaseApi {
);
@override
Future<DbClient> getClient(String name) async {
Future<Map<String, dynamic>> getClient(String name) async {
final res = await dbGetClient(name).get();
if (res.isEmpty) return null;
await markPendingEventsAsError(res.single.clientId);
return res.single;
return res.single.toJson();
}
@override
@ -229,10 +228,16 @@ class Database extends _$Database implements DatabaseApi {
final crossSigningKeys = await getAllUserCrossSigningKeys(client.id).get();
final res = <String, sdk.DeviceKeysList>{};
for (final entry in deviceKeys) {
res[entry.userId] = sdk.DeviceKeysList.fromDb(
entry,
deviceKeysKeys.where((k) => k.userId == entry.userId).toList(),
crossSigningKeys.where((k) => k.userId == entry.userId).toList(),
res[entry.userId] = sdk.DeviceKeysList.fromDbJson(
entry.toJson(),
deviceKeysKeys
.where((k) => k.userId == entry.userId)
.map((d) => d.toJson())
.toList(),
crossSigningKeys
.where((k) => k.userId == entry.userId)
.map((d) => d.toJson())
.toList(),
client);
}
return res;
@ -245,23 +250,21 @@ class Database extends _$Database implements DatabaseApi {
if (res.isEmpty) {
return null;
}
return OutboundGroupSession.fromDb(res.single, userId);
return OutboundGroupSession.fromJson(res.single.toJson(), userId);
}
@override
Future<SessionKey> getInboundGroupSession(
Future<StoredInboundGroupSession> getInboundGroupSession(
int clientId,
String roomId,
String sessionId,
String userId,
) async {
final res =
await dbGetInboundGroupSessionKey(clientId, roomId, sessionId).get();
if (res.isEmpty) {
return null;
}
return SessionKey.fromDb(
StoredInboundGroupSession.fromJson(res.single.toJson()), userId);
return StoredInboundGroupSession.fromJson(res.single.toJson());
}
@override
@ -290,7 +293,7 @@ class Database extends _$Database implements DatabaseApi {
final roomList = <sdk.Room>[];
final allMembersToPostload = <String, Set<String>>{};
for (final r in res) {
final room = await sdk.Room.getRoomFromTableRow(
final room = await getRoomFromTableRow(
r,
client,
states: resStates.where((rs) => rs.roomId == r.roomId),
@ -366,7 +369,7 @@ class Database extends _$Database implements DatabaseApi {
// now that we got all the entries from the database, set them as room states
for (final dbMember in membersRes) {
final room = roomList.firstWhere((r) => r.id == dbMember.roomId);
final event = sdk.Event.fromDb(dbMember, room);
final event = getEventFromDb(dbMember, room);
room.setState(event);
}
}
@ -605,7 +608,7 @@ class Database extends _$Database implements DatabaseApi {
if (event.isEmpty) {
return null;
}
return sdk.Event.fromDb(event.single, room);
return getEventFromDb(event.single, room);
}
Future<bool> redactMessage(int clientId, sdk.EventUpdate eventUpdate) async {
@ -614,7 +617,7 @@ class Database extends _$Database implements DatabaseApi {
.get();
var success = false;
for (final dbEvent in events) {
final event = sdk.Event.fromDb(dbEvent, null);
final event = getEventFromDb(dbEvent, null);
event.setRedactionEvent(sdk.Event.fromJson(eventUpdate.content, null));
final changes1 = await updateEvent(
json.encode(event.unsigned ?? ''),
@ -698,19 +701,19 @@ class Database extends _$Database implements DatabaseApi {
if (res.isEmpty) {
return null;
}
return sdk.Event.fromDb(res.single, room).asUser;
return getEventFromDb(res.single, room).asUser;
}
@override
Future<List<sdk.User>> getUsers(int clientId, sdk.Room room) async {
final res = await dbGetUsers(clientId, room.id).get();
return res.map((r) => sdk.Event.fromDb(r, room).asUser).toList();
return res.map((r) => getEventFromDb(r, room).asUser).toList();
}
@override
Future<List<sdk.Event>> getEventList(int clientId, sdk.Room room) async {
final res = await dbGetEventList(clientId, room.id).get();
return res.map((r) => sdk.Event.fromDb(r, room)).toList();
return res.map((r) => getEventFromDb(r, room)).toList();
}
@override
@ -731,7 +734,7 @@ class Database extends _$Database implements DatabaseApi {
room.id,
events,
).get();
return entries.map((dbEvent) => sdk.Event.fromDb(dbEvent, room)).toList();
return entries.map((dbEvent) => getEventFromDb(dbEvent, room)).toList();
}
@override
@ -741,7 +744,9 @@ class Database extends _$Database implements DatabaseApi {
String userId,
) async {
final rows = await dbGetOlmSessions(client_id, identity_key).get();
return rows.map((row) => OlmSession.fromDb(row, userId)).toList();
return rows
.map((row) => OlmSession.fromJson(row.toJson(), userId))
.toList();
}
@override
@ -752,7 +757,9 @@ class Database extends _$Database implements DatabaseApi {
) async {
final rows =
await dbGetOlmSessionsForDevices(client_id, identity_keys).get();
return rows.map((row) => OlmSession.fromDb(row, userId)).toList();
return rows
.map((row) => OlmSession.fromJson(row.toJson(), userId))
.toList();
}
@override
@ -786,3 +793,82 @@ class Database extends _$Database implements DatabaseApi {
.toList();
}
}
/// Get an event from either DbRoomState or DbEvent
sdk.Event getEventFromDb(dynamic dbEntry, sdk.Room room) {
if (!(dbEntry is DbRoomState || dbEntry is DbEvent)) {
throw ('Unknown db type');
}
final content = sdk.Event.getMapFromPayload(dbEntry.content);
final unsigned = sdk.Event.getMapFromPayload(dbEntry.unsigned);
final prevContent = sdk.Event.getMapFromPayload(dbEntry.prevContent);
return sdk.Event(
status:
(dbEntry is DbEvent ? dbEntry.status : null) ?? sdk.Event.defaultStatus,
stateKey: dbEntry.stateKey,
prevContent: prevContent,
content: content,
type: dbEntry.type,
eventId: dbEntry.eventId,
roomId: dbEntry.roomId,
senderId: dbEntry.sender,
originServerTs: dbEntry.originServerTs != null
? DateTime.fromMillisecondsSinceEpoch(dbEntry.originServerTs)
: DateTime.now(),
unsigned: unsigned,
room: room,
sortOrder: dbEntry.sortOrder ?? 0.0,
);
}
/// Returns a Room from a json String which comes normally from the store. If the
/// state are also given, the method will await them.
Future<Room> getRoomFromTableRow(
// either Map<String, dynamic> or DbRoom
DbRoom row,
Client matrix, {
dynamic states, // DbRoomState, as iterator and optionally as future
dynamic
roomAccountData, // DbRoomAccountData, as iterator and optionally as future
}) async {
final newRoom = Room(
id: row.roomId,
membership: sdk.Membership.values
.firstWhere((e) => e.toString() == 'Membership.' + row.membership),
notificationCount: row.notificationCount,
highlightCount: row.highlightCount,
// TODO: do proper things
notificationSettings: 'mention',
prev_batch: row.prevBatch,
mInvitedMemberCount: row.invitedMemberCount,
mJoinedMemberCount: row.joinedMemberCount,
mHeroes: row.heroes?.split(',') ?? [],
client: matrix,
roomAccountData: {},
newestSortOrder: row.newestSortOrder,
oldestSortOrder: row.oldestSortOrder,
);
if (states != null) {
for (final rawState in await states) {
final newState = getEventFromDb(rawState, newRoom);
newRoom.setState(newState);
}
}
final newRoomAccountData = <String, sdk.BasicRoomEvent>{};
if (roomAccountData != null) {
for (final singleAccountData in await roomAccountData) {
final content = sdk.Event.getMapFromPayload(singleAccountData.content);
final newData = sdk.BasicRoomEvent(
content: content,
type: singleAccountData.type,
roomId: singleAccountData.roomId,
);
newRoomAccountData[newData.type] = newData;
}
}
newRoom.roomAccountData = newRoomAccountData;
return newRoom;
}

View File

@ -20,7 +20,6 @@ import 'dart:typed_data';
import 'package:famedlysdk/encryption/utils/olm_session.dart';
import 'package:famedlysdk/encryption/utils/outbound_group_session.dart';
import 'package:famedlysdk/encryption/utils/session_key.dart';
import 'package:famedlysdk/encryption/utils/ssss_cache.dart';
import 'package:famedlysdk/encryption/utils/stored_inbound_group_session.dart';
import 'package:famedlysdk/src/utils/QueuedToDeviceEvent.dart';
@ -29,25 +28,30 @@ import '../../famedlysdk.dart';
abstract class DatabaseApi {
int get maxFileSize => 1 * 1024 * 1024;
Future<dynamic> getClient(String name);
Future<Map<String, dynamic>> getClient(String name);
Future<Map<String, DeviceKeysList>> getUserDeviceKeys(Client client);
Future<OutboundGroupSession> getOutboundGroupSession(
int clientId,
String roomId,
Future updateClient(
String homeserverUrl,
String token,
String userId,
String deviceId,
String deviceName,
String prevBatch,
String olmAccount,
int clientId,
);
Future<SessionKey> getInboundGroupSession(
int clientId,
String roomId,
String sessionId,
Future insertClient(
String name,
String homeserverUrl,
String token,
String userId,
String deviceId,
String deviceName,
String prevBatch,
String olmAccount,
);
Future<SSSSCache> getSSSSCache(int clientId, String type);
Future<List<Room>> getRoomList(Client client);
Future<Map<String, BasicEvent>> getAccountData(int clientId);
@ -77,14 +81,36 @@ abstract class DatabaseApi {
Future<Uint8List> getFile(String mxcUri);
Future<int> updateInboundGroupSessionIndexes(
Future storeFile(String mxcUri, Uint8List bytes, int time);
Future storeSyncFilterId(String syncFilterId, int clientId);
Future storeAccountData(int clientId, String type, String content);
Future<Map<String, DeviceKeysList>> getUserDeviceKeys(Client client);
Future<SSSSCache> getSSSSCache(int clientId, String type);
Future<OutboundGroupSession> getOutboundGroupSession(
int clientId,
String roomId,
String userId,
);
Future<StoredInboundGroupSession> getInboundGroupSession(
int clientId,
String roomId,
String sessionId,
);
Future updateInboundGroupSessionIndexes(
String indexes,
int clientId,
String roomId,
String sessionId,
);
Future<int> storeInboundGroupSession(
Future storeInboundGroupSession(
int clientId,
String roomId,
String sessionId,
@ -96,50 +122,22 @@ abstract class DatabaseApi {
String senderClaimedKey,
);
Future<int> markInboundGroupSessionAsUploaded(
Future markInboundGroupSessionAsUploaded(
int clientId,
String roomId,
String sessionId,
);
Future<int> updateInboundGroupSessionAllowedAtIndex(
Future updateInboundGroupSessionAllowedAtIndex(
String allowedAtIndex,
int clientId,
String roomId,
String sessionId,
);
Future<int> removeOutboundGroupSession(int clientId, String roomId);
Future removeOutboundGroupSession(int clientId, String roomId);
Future<int> storeFile(String mxcUri, Uint8List bytes, int time);
Future<int> updateClient(
String homeserverUrl,
String token,
String userId,
String deviceId,
String deviceName,
String prevBatch,
String olmAccount,
int clientId,
);
Future<int> insertClient(
String name,
String homeserverUrl,
String token,
String userId,
String deviceId,
String deviceName,
String prevBatch,
String olmAccount,
);
Future<int> storeSyncFilterId(String syncFilterId, int clientId);
Future<int> storeAccountData(int clientId, String type, String content);
Future<int> storeOutboundGroupSession(
Future storeOutboundGroupSession(
int clientId,
String roomId,
String pickle,
@ -148,9 +146,9 @@ abstract class DatabaseApi {
int sentMessages,
);
Future<int> updateClientKeys(String olmAccount, int clientId);
Future updateClientKeys(String olmAccount, int clientId);
Future<int> storeOlmSession(
Future storeOlmSession(
int clientId,
String identitiyKey,
String sessionId,
@ -158,23 +156,23 @@ abstract class DatabaseApi {
int lastReceived,
);
Future<int> setLastActiveUserDeviceKey(
Future setLastActiveUserDeviceKey(
int lastActive,
int clientId,
String userId,
String deviceId,
);
Future<int> setLastSentMessageUserDeviceKey(
Future setLastSentMessageUserDeviceKey(
String lastSentMessage,
int clientId,
String userId,
String deviceId,
);
Future<int> clearSSSSCache(int clientId);
Future clearSSSSCache(int clientId);
Future<int> storeSSSSCache(
Future storeSSSSCache(
int clientId,
String type,
String keyId,
@ -182,19 +180,19 @@ abstract class DatabaseApi {
String content,
);
Future<int> markInboundGroupSessionsAsNeedingUpload(int clientId);
Future markInboundGroupSessionsAsNeedingUpload(int clientId);
Future<int> storePrevBatch(String prevBatch, int clientId);
Future storePrevBatch(String prevBatch, int clientId);
Future<int> deleteOldFiles(int savedAt);
Future deleteOldFiles(int savedAt);
Future<int> storeUserDeviceKeysInfo(
Future storeUserDeviceKeysInfo(
int clientId,
String userId,
bool outdated,
);
Future<int> storeUserDeviceKey(
Future storeUserDeviceKey(
int clientId,
String userId,
String deviceId,
@ -204,19 +202,19 @@ abstract class DatabaseApi {
int lastActive,
);
Future<int> removeUserDeviceKey(
Future removeUserDeviceKey(
int clientId,
String userId,
String deviceId,
);
Future<int> removeUserCrossSigningKey(
Future removeUserCrossSigningKey(
int clientId,
String userId,
String publicKey,
);
Future<int> storeUserCrossSigningKey(
Future storeUserCrossSigningKey(
int clientId,
String userId,
String publicKey,
@ -225,47 +223,47 @@ abstract class DatabaseApi {
bool blocked,
);
Future<int> deleteFromToDeviceQueue(int clientId, int id);
Future deleteFromToDeviceQueue(int clientId, int id);
Future<int> removeEvent(int clientId, String eventId, String roomId);
Future removeEvent(int clientId, String eventId, String roomId);
Future<int> updateRoomSortOrder(
Future updateRoomSortOrder(
double oldestSortOrder,
double newestSortOrder,
int clientId,
String roomId,
);
Future<int> setRoomPrevBatch(
Future setRoomPrevBatch(
String prevBatch,
int clientId,
String roomId,
);
Future<int> resetNotificationCount(int clientId, String roomId);
Future resetNotificationCount(int clientId, String roomId);
Future<int> setVerifiedUserCrossSigningKey(
Future setVerifiedUserCrossSigningKey(
bool verified,
int clientId,
String userId,
String publicKey,
);
Future<int> setBlockedUserCrossSigningKey(
Future setBlockedUserCrossSigningKey(
bool blocked,
int clientId,
String userId,
String publicKey,
);
Future<int> setVerifiedUserDeviceKey(
Future setVerifiedUserDeviceKey(
bool verified,
int clientId,
String userId,
String deviceId,
);
Future<int> setBlockedUserDeviceKey(
Future setBlockedUserDeviceKey(
bool blocked,
int clientId,
String userId,
@ -294,7 +292,7 @@ abstract class DatabaseApi {
/// Please do `jsonEncode(content)` in your code to stay compatible with
/// auto generated methods here.
Future<int> insertIntoToDeviceQueue(
Future insertIntoToDeviceQueue(
int clientId,
String type,
String txnId,

View File

@ -22,7 +22,6 @@ import 'dart:typed_data';
import 'package:http/http.dart' as http;
import '../famedlysdk.dart';
import 'database/database.dart' show DbRoomState, DbEvent;
import 'room.dart';
import 'utils/matrix_localizations.dart';
import 'utils/receipt.dart';
@ -178,32 +177,6 @@ class Event extends MatrixEvent {
);
}
/// Get an event from either DbRoomState or DbEvent
factory Event.fromDb(dynamic dbEntry, Room room) {
if (!(dbEntry is DbRoomState || dbEntry is DbEvent)) {
throw ('Unknown db type');
}
final content = Event.getMapFromPayload(dbEntry.content);
final unsigned = Event.getMapFromPayload(dbEntry.unsigned);
final prevContent = Event.getMapFromPayload(dbEntry.prevContent);
return Event(
status: (dbEntry is DbEvent ? dbEntry.status : null) ?? defaultStatus,
stateKey: dbEntry.stateKey,
prevContent: prevContent,
content: content,
type: dbEntry.type,
eventId: dbEntry.eventId,
roomId: dbEntry.roomId,
senderId: dbEntry.sender,
originServerTs: dbEntry.originServerTs != null
? DateTime.fromMillisecondsSinceEpoch(dbEntry.originServerTs)
: DateTime.now(),
unsigned: unsigned,
room: room,
sortOrder: dbEntry.sortOrder ?? 0.0,
);
}
@override
Map<String, dynamic> toJson() {
final data = <String, dynamic>{};

View File

@ -24,7 +24,6 @@ import 'package:html_unescape/html_unescape.dart';
import '../famedlysdk.dart';
import 'client.dart';
import 'database/database.dart' show DbRoom;
import 'event.dart';
import 'timeline.dart';
import 'user.dart';
@ -1079,58 +1078,6 @@ class Room {
return;
}
/// Returns a Room from a json String which comes normally from the store. If the
/// state are also given, the method will await them.
static Future<Room> getRoomFromTableRow(
// either Map<String, dynamic> or DbRoom
DbRoom row,
Client matrix, {
dynamic states, // DbRoomState, as iterator and optionally as future
dynamic
roomAccountData, // DbRoomAccountData, as iterator and optionally as future
}) async {
final newRoom = Room(
id: row.roomId,
membership: Membership.values
.firstWhere((e) => e.toString() == 'Membership.' + row.membership),
notificationCount: row.notificationCount,
highlightCount: row.highlightCount,
// TODO: do proper things
notificationSettings: 'mention',
prev_batch: row.prevBatch,
mInvitedMemberCount: row.invitedMemberCount,
mJoinedMemberCount: row.joinedMemberCount,
mHeroes: row.heroes?.split(',') ?? [],
client: matrix,
roomAccountData: {},
newestSortOrder: row.newestSortOrder,
oldestSortOrder: row.oldestSortOrder,
);
if (states != null) {
for (final rawState in await states) {
final newState = Event.fromDb(rawState, newRoom);
newRoom.setState(newState);
}
}
final newRoomAccountData = <String, BasicRoomEvent>{};
if (roomAccountData != null) {
for (final singleAccountData in await roomAccountData) {
final content = Event.getMapFromPayload(singleAccountData.content);
final newData = BasicRoomEvent(
content: content,
type: singleAccountData.type,
roomId: singleAccountData.roomId,
);
newRoomAccountData[newData.type] = newData;
}
}
newRoom.roomAccountData = newRoomAccountData;
return newRoom;
}
/// Creates a timeline from the store. Returns a [Timeline] object.
Future<Timeline> getTimeline(
{onTimelineUpdateCallback onUpdate,

View File

@ -1,3 +1,20 @@
/*
* Famedly Matrix SDK
* Copyright (C) 2019, 2020 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
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
class QueuedToDeviceEvent {
final int id;
final String type;

View File

@ -25,8 +25,6 @@ import 'package:olm/olm.dart' as olm;
import '../../encryption.dart';
import '../client.dart';
import '../database/database.dart'
show DbUserDeviceKey, DbUserDeviceKeysKey, DbUserCrossSigningKey;
import '../event.dart';
import '../room.dart';
import '../user.dart';
@ -104,27 +102,27 @@ class DeviceKeysList {
}
}
DeviceKeysList.fromDb(
DbUserDeviceKey dbEntry,
List<DbUserDeviceKeysKey> childEntries,
List<DbUserCrossSigningKey> crossSigningEntries,
DeviceKeysList.fromDbJson(
Map<String, dynamic> dbEntry,
List<Map<String, dynamic>> childEntries,
List<Map<String, dynamic>> crossSigningEntries,
Client cl) {
client = cl;
userId = dbEntry.userId;
outdated = dbEntry.outdated;
userId = dbEntry['user_id'];
outdated = dbEntry['outdated'];
deviceKeys = {};
for (final childEntry in childEntries) {
final entry = DeviceKeys.fromDb(childEntry, client);
if (entry.isValid) {
deviceKeys[childEntry.deviceId] = entry;
deviceKeys[childEntry['device_id']] = entry;
} else {
outdated = true;
}
}
for (final crossSigningEntry in crossSigningEntries) {
final entry = CrossSigningKey.fromDb(crossSigningEntry, client);
final entry = CrossSigningKey.fromDbJson(crossSigningEntry, client);
if (entry.isValid) {
crossSigningKeys[crossSigningEntry.publicKey] = entry;
crossSigningKeys[crossSigningEntry['public_key']] = entry;
} else {
outdated = true;
}
@ -365,13 +363,13 @@ class CrossSigningKey extends SignableKey {
usage = json['usage'].cast<String>();
}
CrossSigningKey.fromDb(DbUserCrossSigningKey dbEntry, Client cl)
: super.fromJson(Event.getMapFromPayload(dbEntry.content), cl) {
CrossSigningKey.fromDbJson(Map<String, dynamic> dbEntry, Client cl)
: super.fromJson(Event.getMapFromPayload(dbEntry['content']), cl) {
final json = toJson();
identifier = dbEntry.publicKey;
identifier = dbEntry['public_key'];
usage = json['usage'].cast<String>();
_verified = dbEntry.verified;
blocked = dbEntry.blocked;
_verified = dbEntry['verified'];
blocked = dbEntry['blocked'];
}
CrossSigningKey.fromJson(Map<String, dynamic> json, Client cl)
@ -441,14 +439,15 @@ class DeviceKeys extends SignableKey {
lastActive = lastActiveTs ?? DateTime.now();
}
DeviceKeys.fromDb(DbUserDeviceKeysKey dbEntry, Client cl)
: super.fromJson(Event.getMapFromPayload(dbEntry.content), cl) {
DeviceKeys.fromDb(Map<String, dynamic> dbEntry, Client cl)
: super.fromJson(Event.getMapFromPayload(dbEntry['content']), cl) {
final json = toJson();
identifier = dbEntry.deviceId;
identifier = dbEntry['device_id'];
algorithms = json['algorithms'].cast<String>();
_verified = dbEntry.verified;
blocked = dbEntry.blocked;
lastActive = DateTime.fromMillisecondsSinceEpoch(dbEntry.lastActive ?? 0);
_verified = dbEntry['verified'];
blocked = dbEntry['blocked'];
lastActive =
DateTime.fromMillisecondsSinceEpoch(dbEntry['last_active'] ?? 0);
}
DeviceKeys.fromJson(Map<String, dynamic> json, Client cl)

431
test/database_api_test.dart Normal file
View File

@ -0,0 +1,431 @@
/*
* Famedly Matrix SDK
* Copyright (C) 2019, 2020 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
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import 'dart:convert';
import 'package:famedlysdk/famedlysdk.dart';
import 'package:moor/moor.dart';
import 'package:test/test.dart';
import 'package:olm/olm.dart' as olm;
import 'fake_database_native.dart';
void main() {
/// All Tests related to the ChatTime
group('Moor Database Test', () {
testDatabase(getDatabase(null), 0);
});
}
Future<bool> olmEnabled() async {
var olmEnabled = true;
try {
await olm.init();
olm.get_library_version();
} catch (e) {
olmEnabled = false;
}
return olmEnabled;
}
void testDatabase(Future<DatabaseApi> futureDatabase, int clientId) {
DatabaseApi database;
int toDeviceQueueIndex;
test('Open', () async {
database = await futureDatabase;
});
test('insertIntoToDeviceQueue', () async {
toDeviceQueueIndex = await database.insertIntoToDeviceQueue(
clientId,
'm.test',
'txnId',
'{"foo":"bar"}',
);
});
test('getToDeviceEventQueue', () async {
final toDeviceQueue = await database.getToDeviceEventQueue(clientId);
expect(toDeviceQueue.single.type, 'm.test');
});
test('deleteFromToDeviceQueue', () async {
await database.deleteFromToDeviceQueue(clientId, toDeviceQueueIndex);
final toDeviceQueue = await database.getToDeviceEventQueue(clientId);
expect(toDeviceQueue.isEmpty, true);
});
test('storeFile', () async {
await database.storeFile('mxc://test', Uint8List.fromList([0]), 0);
final file = await database.getFile('mxc://test');
expect(file != null, true);
});
test('getFile', () async {
await database.getFile('mxc://test');
});
test('deleteOldFiles', () async {
await database.deleteOldFiles(1);
final file = await database.getFile('mxc://test');
expect(file == null, true);
});
test('storeRoomUpdate', () async {
await database.storeRoomUpdate(
clientId,
RoomUpdate(
id: '!testroom',
highlight_count: 0,
notification_count: 0,
limitedTimeline: false,
membership: Membership.join,
));
final rooms = await database.getRoomList(Client('testclient'));
expect(rooms.single.id, '!testroom');
});
test('getRoomList', () async {
final list = await database.getRoomList(Client('testclient'));
expect(list.single.id, '!testroom');
});
test('setRoomPrevBatch', () async {
await database.setRoomPrevBatch('1234', clientId, '!testroom');
final rooms = await database.getRoomList(Client('testclient'));
expect(rooms.single.prev_batch, '1234');
});
test('forgetRoom', () async {
await database.forgetRoom(clientId, '!testroom');
final rooms = await database.getRoomList(Client('testclient'));
expect(rooms.isEmpty, true);
});
test('getClient', () async {
await database.getClient('name');
});
test('insertClient', () async {
clientId = await database.insertClient(
'name',
'homeserverUrl',
'token',
'userId',
'deviceId',
'deviceName',
'prevBatch',
'olmAccount',
);
final client = await database.getClient('name');
expect(client['token'], 'token');
});
test('updateClient', () async {
await database.updateClient(
'homeserverUrl',
'token_different',
'userId',
'deviceId',
'deviceName',
'prevBatch',
'olmAccount',
clientId,
);
final client = await database.getClient('name');
expect(client['token'], 'token_different');
});
test('updateClientKeys', () async {
await database.updateClientKeys('olmAccount2', clientId);
final client = await database.getClient('name');
expect(client['olm_account'], 'olmAccount2');
});
test('storeSyncFilterId', () async {
await database.storeSyncFilterId('1234', clientId);
final client = await database.getClient('name');
expect(client['sync_filter_id'], '1234');
});
test('getAccountData', () async {
await database.getAccountData(clientId);
});
test('storeAccountData', () async {
await database.storeAccountData(clientId, 'm.test', '{}');
final events = await database.getAccountData(clientId);
expect(events.values.single.type, 'm.test');
});
test('storeEventUpdate', () async {
await database.storeEventUpdate(
clientId,
EventUpdate(
roomID: '!testroom:example.com',
type: EventUpdateType.timeline,
sortOrder: DateTime.now().millisecondsSinceEpoch.toDouble(),
content: {
'type': EventTypes.Message,
'content': {
'body': '* edit 3',
'msgtype': 'm.text',
'm.new_content': {
'body': 'edit 3',
'msgtype': 'm.text',
},
'm.relates_to': {
'event_id': '\$source',
'rel_type': RelationshipTypes.edit,
},
},
'event_id': '\$event:example.com',
'sender': '@bob:example.org',
},
),
);
});
test('getEventById', () async {
final event = await database.getEventById(
clientId, '\$event:example.com', Room(id: '!testroom:example.com'));
expect(event.type, EventTypes.Message);
});
test('getEventList', () async {
final events = await database.getEventList(
clientId, Room(id: '!testroom:example.com'));
expect(events.single.type, EventTypes.Message);
});
test('getUser', () async {
final user = await database.getUser(
clientId, '@bob:example.org', Room(id: '!testroom:example.com'));
expect(user, null);
});
test('getUsers', () async {
final users =
await database.getUsers(clientId, Room(id: '!testroom:example.com'));
expect(users.isEmpty, true);
});
test('removeEvent', () async {
await database.removeEvent(
clientId, '\$event:example.com', '!testroom:example.com');
final event = await database.getEventById(
clientId, '\$event:example.com', Room(id: '!testroom:example.com'));
expect(event, null);
});
test('getInboundGroupSession', () async {
await database.getInboundGroupSession(
clientId, '!testroom:example.com', 'sessionId');
});
test('getInboundGroupSessionsToUpload', () async {
await database.getInboundGroupSessionsToUpload();
});
test('getInboundGroupSessionsToUpload', () async {
await database.storeInboundGroupSession(
clientId,
'!testroom:example.com',
'sessionId',
'pickle',
'{"foo":"bar"}',
'{}',
'{}',
'senderKey',
'{}',
);
final session = await database.getInboundGroupSession(
clientId,
'!testroom:example.com',
'sessionId',
);
expect(jsonDecode(session.content)['foo'], 'bar');
});
test('markInboundGroupSessionAsUploaded', () async {
await database.markInboundGroupSessionAsUploaded(
clientId, '!testroom:example.com', 'sessionId');
});
test('markInboundGroupSessionsAsNeedingUpload', () async {
await database.markInboundGroupSessionsAsNeedingUpload(clientId);
});
test('updateInboundGroupSessionAllowedAtIndex', () async {
await database.updateInboundGroupSessionAllowedAtIndex(
'{}',
clientId,
'!testroom:example.com',
'sessionId',
);
});
test('updateInboundGroupSessionIndexes', () async {
await database.updateInboundGroupSessionIndexes(
'{}',
clientId,
'!testroom:example.com',
'sessionId',
);
});
test('getSSSSCache', () async {
final cache = await database.getSSSSCache(clientId, 'type');
expect(cache, null);
});
test('storeSSSSCache', () async {
await database.storeSSSSCache(
clientId, 'type', 'keyId', 'ciphertext', '{}');
final cache = await database.getSSSSCache(clientId, 'type');
expect(cache.type, 'type');
expect(cache.keyId, 'keyId');
expect(cache.ciphertext, 'ciphertext');
expect(cache.content, '{}');
});
test('getOlmSessions', () async {
final olm = await database.getOlmSessions(
clientId,
'identityKey',
'userId',
);
expect(olm.isEmpty, true);
});
test('getOlmSessionsForDevices', () async {
final olm = await database.getOlmSessionsForDevices(
clientId,
['identityKeys'],
'userId',
);
expect(olm.isEmpty, true);
});
test('storeOlmSession', () async {
if (!(await olmEnabled())) return;
await database.storeOlmSession(
clientId,
'identityKey',
'sessionId',
'pickle',
0,
);
final olm = await database.getOlmSessions(
clientId,
'identityKey',
'userId',
);
expect(olm.isNotEmpty, true);
});
test('getOutboundGroupSession', () async {
final session = await database.getOutboundGroupSession(
clientId,
'!testroom:example.com',
'@alice:example.com',
);
expect(session, null);
});
test('storeOutboundGroupSession', () async {
if (!(await olmEnabled())) return;
await database.storeOutboundGroupSession(
clientId,
'!testroom:example.com',
'pickle',
'{}',
0,
0,
);
final session = await database.getOutboundGroupSession(
clientId,
'!testroom:example.com',
'@alice:example.com',
);
expect(session.devices.isEmpty, true);
});
test('getLastSentMessageUserDeviceKey', () async {
final list = await database.getLastSentMessageUserDeviceKey(
clientId,
'userId',
'deviceId',
);
expect(list.isEmpty, true);
});
test('getUnimportantRoomEventStatesForRoom', () async {
final events = await database.getUnimportantRoomEventStatesForRoom(
clientId,
['events'],
Room(id: '!mep'),
);
expect(events.isEmpty, true);
});
test('getUserDeviceKeys', () async {
await database.getUserDeviceKeys(Client('testclient'));
});
test('storeUserCrossSigningKey', () async {
await database.storeUserCrossSigningKey(
clientId,
'@alice:example.com',
'publicKey',
'{}',
false,
false,
);
});
test('setVerifiedUserCrossSigningKey', () async {
await database.setVerifiedUserCrossSigningKey(
true,
clientId,
'@alice:example.com',
'publicKey',
);
});
test('setBlockedUserCrossSigningKey', () async {
await database.setBlockedUserCrossSigningKey(
true,
clientId,
'@alice:example.com',
'publicKey',
);
});
test('removeUserCrossSigningKey', () async {
await database.removeUserCrossSigningKey(
clientId,
'@alice:example.com',
'publicKey',
);
});
test('storeUserDeviceKeysInfo', () async {
await database.storeUserDeviceKeysInfo(
clientId,
'@alice:example.com',
true,
);
});
test('storeUserDeviceKey', () async {
await database.storeUserDeviceKey(
clientId,
'@alice:example.com',
'deviceId',
'{}',
false,
false,
0,
);
});
test('setVerifiedUserDeviceKey', () async {
await database.setVerifiedUserDeviceKey(
true,
clientId,
'@alice:example.com',
'deviceId',
);
});
test('setBlockedUserDeviceKey', () async {
await database.setBlockedUserDeviceKey(
true,
clientId,
'@alice:example.com',
'deviceId',
);
});
// Clearing up from here
test('clearSSSSCache', () async {
await database.clearSSSSCache(clientId);
});
test('clearCache', () async {
await database.clearCache(clientId);
});
test('clear', () async {
await database.clear(clientId);
});
test('Close', () async {
await database.close();
});
return;
}

View File

@ -22,7 +22,7 @@ import 'dart:typed_data';
import 'package:famedlysdk/famedlysdk.dart';
import 'package:famedlysdk/src/client.dart';
import 'package:famedlysdk/src/database/database.dart'
show DbRoom, DbRoomState, DbRoomAccountData;
show DbRoom, DbRoomAccountData, DbRoomState, getRoomFromTableRow;
import 'package:famedlysdk/src/event.dart';
import 'package:famedlysdk/src/room.dart';
import 'package:famedlysdk/src/user.dart';
@ -94,7 +94,7 @@ void main() {
),
];
room = await Room.getRoomFromTableRow(
room = await getRoomFromTableRow(
dbRoom,
matrix,
states: states,