refactor: Create a clean database API
This commit is contained in:
parent
6fae2e1426
commit
c66e35c16c
|
|
@ -136,7 +136,6 @@ pages:
|
||||||
- public
|
- public
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||||
|
|
||||||
# Adds license-scanning job. Because Gitlab does not support pub.dev
|
# Adds license-scanning job. Because Gitlab does not support pub.dev
|
||||||
# we added https://github.com/oss-review-toolkit/ort
|
# we added https://github.com/oss-review-toolkit/ort
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,13 @@
|
||||||
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:famedlysdk/encryption/utils/stored_inbound_group_session.dart';
|
||||||
import 'package:olm/olm.dart' as olm;
|
import 'package:olm/olm.dart' as olm;
|
||||||
|
|
||||||
import './encryption.dart';
|
import './encryption.dart';
|
||||||
import './utils/outbound_group_session.dart';
|
import './utils/outbound_group_session.dart';
|
||||||
import './utils/session_key.dart';
|
import './utils/session_key.dart';
|
||||||
import '../famedlysdk.dart';
|
import '../famedlysdk.dart';
|
||||||
import '../src/database/database.dart';
|
|
||||||
import '../src/utils/run_in_background.dart';
|
import '../src/utils/run_in_background.dart';
|
||||||
import '../src/utils/run_in_root.dart';
|
import '../src/utils/run_in_root.dart';
|
||||||
|
|
||||||
|
|
@ -231,15 +231,14 @@ class KeyManager {
|
||||||
}
|
}
|
||||||
return sess; // nothing to do
|
return sess; // nothing to do
|
||||||
}
|
}
|
||||||
final session = await client.database
|
final sess = await client.database
|
||||||
?.getDbInboundGroupSession(client.id, roomId, sessionId);
|
?.getInboundGroupSession(client.id, roomId, sessionId, client.userID);
|
||||||
if (session == null) {
|
if (sess == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!_inboundGroupSessions.containsKey(roomId)) {
|
if (!_inboundGroupSessions.containsKey(roomId)) {
|
||||||
_inboundGroupSessions[roomId] = <String, SessionKey>{};
|
_inboundGroupSessions[roomId] = <String, SessionKey>{};
|
||||||
}
|
}
|
||||||
final sess = SessionKey.fromDb(session, client.userID);
|
|
||||||
if (!sess.isValid ||
|
if (!sess.isValid ||
|
||||||
(sess.senderKey.isNotEmpty && sess.senderKey != senderKey)) {
|
(sess.senderKey.isNotEmpty && sess.senderKey != senderKey)) {
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -506,13 +505,12 @@ class KeyManager {
|
||||||
return; // nothing to do
|
return; // nothing to do
|
||||||
}
|
}
|
||||||
_loadedOutboundGroupSessions.add(roomId);
|
_loadedOutboundGroupSessions.add(roomId);
|
||||||
final session =
|
final sess = await client.database.getOutboundGroupSession(
|
||||||
await client.database.getDbOutboundGroupSession(client.id, roomId);
|
client.id,
|
||||||
if (session == null) {
|
roomId,
|
||||||
return;
|
client.userID,
|
||||||
}
|
);
|
||||||
final sess = OutboundGroupSession.fromDb(session, client.userID);
|
if (sess == null || !sess.isValid) {
|
||||||
if (!sess.isValid) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_outboundGroupSessions[roomId] = sess;
|
_outboundGroupSessions[roomId] = sess;
|
||||||
|
|
@ -693,7 +691,7 @@ class KeyManager {
|
||||||
return; // we can't backup anyways
|
return; // we can't backup anyways
|
||||||
}
|
}
|
||||||
final dbSessions =
|
final dbSessions =
|
||||||
await client.database.getInboundGroupSessionsToUpload().get();
|
await client.database.getInboundGroupSessionsToUpload();
|
||||||
if (dbSessions.isEmpty) {
|
if (dbSessions.isEmpty) {
|
||||||
_haveKeysToUpload = false;
|
_haveKeysToUpload = false;
|
||||||
return; // nothing to do
|
return; // nothing to do
|
||||||
|
|
@ -1060,7 +1058,7 @@ RoomKeys _generateUploadKeys(_GenerateUploadKeysArgs args) {
|
||||||
class _DbInboundGroupSessionBundle {
|
class _DbInboundGroupSessionBundle {
|
||||||
_DbInboundGroupSessionBundle({this.dbSession, this.verified});
|
_DbInboundGroupSessionBundle({this.dbSession, this.verified});
|
||||||
|
|
||||||
DbInboundGroupSession dbSession;
|
StoredInboundGroupSession dbSession;
|
||||||
bool verified;
|
bool verified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -410,16 +410,9 @@ class OlmManager {
|
||||||
if (client.database == null) {
|
if (client.database == null) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
final rows =
|
final olmSessions = await client.database
|
||||||
await client.database.dbGetOlmSessions(client.id, senderKey).get();
|
.getOlmSessions(client.id, senderKey, client.userID);
|
||||||
final res = <OlmSession>[];
|
return olmSessions.where((sess) => sess.isValid).toList();
|
||||||
for (final row in rows) {
|
|
||||||
final sess = OlmSession.fromDb(row, client.userID);
|
|
||||||
if (sess.isValid) {
|
|
||||||
res.add(sess);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> getOlmSessionsForDevicesFromDatabase(
|
Future<void> getOlmSessionsForDevicesFromDatabase(
|
||||||
|
|
@ -427,15 +420,16 @@ class OlmManager {
|
||||||
if (client.database == null) {
|
if (client.database == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final rows = await client.database
|
final rows = await client.database.getOlmSessionsForDevices(
|
||||||
.dbGetOlmSessionsForDevices(client.id, senderKeys)
|
client.id,
|
||||||
.get();
|
senderKeys,
|
||||||
|
client.userID,
|
||||||
|
);
|
||||||
final res = <String, List<OlmSession>>{};
|
final res = <String, List<OlmSession>>{};
|
||||||
for (final row in rows) {
|
for (final sess in rows) {
|
||||||
res[row.identityKey] ??= <OlmSession>[];
|
res[sess.identityKey] ??= <OlmSession>[];
|
||||||
final sess = OlmSession.fromDb(row, client.userID);
|
|
||||||
if (sess.isValid) {
|
if (sess.isValid) {
|
||||||
res[row.identityKey].add(sess);
|
res[sess.identityKey].add(sess);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (final entry in res.entries) {
|
for (final entry in res.entries) {
|
||||||
|
|
@ -653,8 +647,7 @@ class OlmManager {
|
||||||
'[OlmManager] Device ${device.userId}:${device.deviceId} generated a new olm session, replaying last sent message...');
|
'[OlmManager] Device ${device.userId}:${device.deviceId} generated a new olm session, replaying last sent message...');
|
||||||
final lastSentMessageRes = await client.database
|
final lastSentMessageRes = await client.database
|
||||||
.getLastSentMessageUserDeviceKey(
|
.getLastSentMessageUserDeviceKey(
|
||||||
client.id, device.userId, device.deviceId)
|
client.id, device.userId, device.deviceId);
|
||||||
.get();
|
|
||||||
if (lastSentMessageRes.isEmpty ||
|
if (lastSentMessageRes.isEmpty ||
|
||||||
(lastSentMessageRes.first?.isEmpty ?? true)) {
|
(lastSentMessageRes.first?.isEmpty ?? true)) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -25,11 +25,11 @@ import 'package:base58check/base58.dart';
|
||||||
import 'package:crypto/crypto.dart';
|
import 'package:crypto/crypto.dart';
|
||||||
|
|
||||||
import '../famedlysdk.dart';
|
import '../famedlysdk.dart';
|
||||||
import '../src/database/database.dart';
|
|
||||||
import '../src/utils/crypto/crypto.dart' as uc;
|
import '../src/utils/crypto/crypto.dart' as uc;
|
||||||
import '../src/utils/run_in_background.dart';
|
import '../src/utils/run_in_background.dart';
|
||||||
import '../src/utils/run_in_root.dart';
|
import '../src/utils/run_in_root.dart';
|
||||||
import 'encryption.dart';
|
import 'encryption.dart';
|
||||||
|
import 'utils/ssss_cache.dart';
|
||||||
|
|
||||||
const cacheTypes = <String>{
|
const cacheTypes = <String>{
|
||||||
EventTypes.CrossSigningSelfSigning,
|
EventTypes.CrossSigningSelfSigning,
|
||||||
|
|
@ -56,7 +56,7 @@ class SSSS {
|
||||||
final pendingShareRequests = <String, _ShareRequest>{};
|
final pendingShareRequests = <String, _ShareRequest>{};
|
||||||
final _validators = <String, FutureOr<bool> Function(String)>{};
|
final _validators = <String, FutureOr<bool> Function(String)>{};
|
||||||
final _cacheCallbacks = <String, FutureOr<void> Function(String)>{};
|
final _cacheCallbacks = <String, FutureOr<void> Function(String)>{};
|
||||||
final Map<String, DbSSSSCache> _cache = <String, DbSSSSCache>{};
|
final Map<String, SSSSCache> _cache = <String, SSSSCache>{};
|
||||||
SSSS(this.encryption);
|
SSSS(this.encryption);
|
||||||
|
|
||||||
// for testing
|
// for testing
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,10 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import 'package:famedlysdk/encryption/utils/stored_inbound_group_session.dart';
|
||||||
import 'package:olm/olm.dart' as olm;
|
import 'package:olm/olm.dart' as olm;
|
||||||
|
|
||||||
import '../../famedlysdk.dart';
|
import '../../famedlysdk.dart';
|
||||||
import '../../src/database/database.dart' show DbInboundGroupSession;
|
|
||||||
|
|
||||||
class SessionKey {
|
class SessionKey {
|
||||||
/// The raw json content of the key
|
/// The raw json content of the key
|
||||||
|
|
@ -76,7 +76,7 @@ class SessionKey {
|
||||||
allowedAtIndex ??= <String, Map<String, int>>{};
|
allowedAtIndex ??= <String, Map<String, int>>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionKey.fromDb(DbInboundGroupSession dbEntry, String key) : key = key {
|
SessionKey.fromDb(StoredInboundGroupSession 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 parsedAllowedAtIndex =
|
final parsedAllowedAtIndex =
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Famedly Matrix SDK
|
||||||
|
* Copyright (C) 2021 Famedly GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* 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 SSSSCache {
|
||||||
|
final int clientId;
|
||||||
|
final String type;
|
||||||
|
final String keyId;
|
||||||
|
final String ciphertext;
|
||||||
|
final String content;
|
||||||
|
|
||||||
|
const SSSSCache(
|
||||||
|
{this.clientId, this.type, this.keyId, this.ciphertext, this.content});
|
||||||
|
|
||||||
|
factory SSSSCache.fromJson(Map<String, dynamic> json) => SSSSCache(
|
||||||
|
clientId: json['client_id'],
|
||||||
|
type: json['type'],
|
||||||
|
keyId: json['key_id'],
|
||||||
|
ciphertext: json['ciphertext'],
|
||||||
|
content: json['content'],
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
'client_id': clientId,
|
||||||
|
'type': type,
|
||||||
|
'key_id': keyId,
|
||||||
|
'ciphertext': ciphertext,
|
||||||
|
'content': content,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Famedly Matrix SDK
|
||||||
|
* Copyright (C) 2021 Famedly GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* 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 StoredInboundGroupSession {
|
||||||
|
final int clientId;
|
||||||
|
final String roomId;
|
||||||
|
final String sessionId;
|
||||||
|
final String pickle;
|
||||||
|
final String content;
|
||||||
|
final String indexes;
|
||||||
|
final String allowedAtIndex;
|
||||||
|
final bool uploaded;
|
||||||
|
final String senderKey;
|
||||||
|
final String senderClaimedKeys;
|
||||||
|
|
||||||
|
StoredInboundGroupSession({
|
||||||
|
this.clientId,
|
||||||
|
this.roomId,
|
||||||
|
this.sessionId,
|
||||||
|
this.pickle,
|
||||||
|
this.content,
|
||||||
|
this.indexes,
|
||||||
|
this.allowedAtIndex,
|
||||||
|
this.uploaded,
|
||||||
|
this.senderKey,
|
||||||
|
this.senderClaimedKeys,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory StoredInboundGroupSession.fromJson(Map<String, dynamic> json) =>
|
||||||
|
StoredInboundGroupSession(
|
||||||
|
clientId: json['client_id'],
|
||||||
|
roomId: json['room_id'],
|
||||||
|
sessionId: json['session_id'],
|
||||||
|
pickle: json['pickle'],
|
||||||
|
content: json['content'],
|
||||||
|
indexes: json['indexes'],
|
||||||
|
allowedAtIndex: json['allowed_at_index'],
|
||||||
|
uploaded: json['uploaded'],
|
||||||
|
senderKey: json['sender_key'],
|
||||||
|
senderClaimedKeys: json['sender_claimed_keys'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -28,7 +28,7 @@ import 'package:pedantic/pedantic.dart';
|
||||||
|
|
||||||
import '../encryption.dart';
|
import '../encryption.dart';
|
||||||
import '../famedlysdk.dart';
|
import '../famedlysdk.dart';
|
||||||
import 'database/database.dart' show Database;
|
import 'database/database_api.dart';
|
||||||
import 'event.dart';
|
import 'event.dart';
|
||||||
import 'room.dart';
|
import 'room.dart';
|
||||||
import 'user.dart';
|
import 'user.dart';
|
||||||
|
|
@ -56,11 +56,11 @@ class Client extends MatrixApi {
|
||||||
|
|
||||||
int get id => _id;
|
int get id => _id;
|
||||||
|
|
||||||
final FutureOr<Database> Function(Client) databaseBuilder;
|
final FutureOr<DatabaseApi> Function(Client) databaseBuilder;
|
||||||
final FutureOr<void> Function(Client) databaseDestroyer;
|
final FutureOr<void> Function(Client) databaseDestroyer;
|
||||||
Database _database;
|
DatabaseApi _database;
|
||||||
|
|
||||||
Database get database => _database;
|
DatabaseApi get database => _database;
|
||||||
|
|
||||||
bool enableE2eeRecovery;
|
bool enableE2eeRecovery;
|
||||||
|
|
||||||
|
|
@ -919,7 +919,7 @@ class Client extends MatrixApi {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_userDeviceKeys = await database.getUserDeviceKeys(this);
|
_userDeviceKeys = await database.getUserDeviceKeys(this);
|
||||||
_rooms = await database.getRoomList(this, onlyLeft: false);
|
_rooms = await database.getRoomList(this);
|
||||||
_sortRooms();
|
_sortRooms();
|
||||||
accountData = await database.getAccountData(id);
|
accountData = await database.getAccountData(id);
|
||||||
presences.clear();
|
presences.clear();
|
||||||
|
|
@ -1753,18 +1753,20 @@ sort order of ${prevState.sortOrder}. This should never happen...''');
|
||||||
if (database == null || !_toDeviceQueueNeedsProcessing) {
|
if (database == null || !_toDeviceQueueNeedsProcessing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final entries = await database.getToDeviceQueue(id).get();
|
final entries = await database.getToDeviceEventQueue(id);
|
||||||
if (entries.isEmpty) {
|
if (entries.isEmpty) {
|
||||||
_toDeviceQueueNeedsProcessing = false;
|
_toDeviceQueueNeedsProcessing = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (final entry in entries) {
|
for (final entry in entries) {
|
||||||
// ohgod what is this...
|
// Convert the Json Map to the correct format regarding
|
||||||
final data = (json.decode(entry.content) as Map).map((k, v) =>
|
// https: //matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-sendtodevice-eventtype-txnid
|
||||||
|
final data = entry.content.map((k, v) =>
|
||||||
MapEntry<String, Map<String, Map<String, dynamic>>>(
|
MapEntry<String, Map<String, Map<String, dynamic>>>(
|
||||||
k,
|
k,
|
||||||
(v as Map).map((k, v) => MapEntry<String, Map<String, dynamic>>(
|
(v as Map).map((k, v) => MapEntry<String, Map<String, dynamic>>(
|
||||||
k, Map<String, dynamic>.from(v)))));
|
k, Map<String, dynamic>.from(v)))));
|
||||||
|
|
||||||
await super.sendToDevice(entry.type, entry.txnId, data);
|
await super.sendToDevice(entry.type, entry.txnId, data);
|
||||||
await database.deleteFromToDeviceQueue(id, entry.id);
|
await database.deleteFromToDeviceQueue(id, entry.id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,19 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
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';
|
||||||
import 'package:moor/moor.dart';
|
import 'package:moor/moor.dart';
|
||||||
|
|
||||||
import '../../famedlysdk.dart' as sdk;
|
import '../../famedlysdk.dart' as sdk;
|
||||||
import 'package:matrix_api_lite/matrix_api_lite.dart' as api;
|
import 'package:matrix_api_lite/matrix_api_lite.dart' as api;
|
||||||
import '../client.dart';
|
import '../client.dart';
|
||||||
import '../room.dart';
|
import '../room.dart';
|
||||||
|
import 'database_api.dart';
|
||||||
|
|
||||||
part 'database.g.dart';
|
part 'database.g.dart';
|
||||||
|
|
||||||
|
|
@ -64,7 +71,7 @@ extension MigratorExtension on Migrator {
|
||||||
@UseMoor(
|
@UseMoor(
|
||||||
include: {'database.moor'},
|
include: {'database.moor'},
|
||||||
)
|
)
|
||||||
class Database extends _$Database {
|
class Database extends _$Database implements DatabaseApi {
|
||||||
Database(QueryExecutor e) : super(e);
|
Database(QueryExecutor e) : super(e);
|
||||||
|
|
||||||
Database.connect(DatabaseConnection connection) : super.connect(connection);
|
Database.connect(DatabaseConnection connection) : super.connect(connection);
|
||||||
|
|
@ -72,6 +79,7 @@ class Database extends _$Database {
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 12;
|
int get schemaVersion => 12;
|
||||||
|
|
||||||
|
@override
|
||||||
int get maxFileSize => 1 * 1024 * 1024;
|
int get maxFileSize => 1 * 1024 * 1024;
|
||||||
|
|
||||||
/// Update errors are coming here.
|
/// Update errors are coming here.
|
||||||
|
|
@ -202,6 +210,7 @@ class Database extends _$Database {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
Future<DbClient> getClient(String name) async {
|
Future<DbClient> getClient(String name) async {
|
||||||
final res = await dbGetClient(name).get();
|
final res = await dbGetClient(name).get();
|
||||||
if (res.isEmpty) return null;
|
if (res.isEmpty) return null;
|
||||||
|
|
@ -209,6 +218,7 @@ class Database extends _$Database {
|
||||||
return res.single;
|
return res.single;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<Map<String, sdk.DeviceKeysList>> getUserDeviceKeys(
|
Future<Map<String, sdk.DeviceKeysList>> getUserDeviceKeys(
|
||||||
sdk.Client client) async {
|
sdk.Client client) async {
|
||||||
final deviceKeys = await getAllUserDeviceKeys(client.id).get();
|
final deviceKeys = await getAllUserDeviceKeys(client.id).get();
|
||||||
|
|
@ -228,45 +238,51 @@ class Database extends _$Database {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<DbOutboundGroupSession> getDbOutboundGroupSession(
|
@override
|
||||||
int clientId, String roomId) async {
|
Future<OutboundGroupSession> getOutboundGroupSession(
|
||||||
|
int clientId, String roomId, String userId) async {
|
||||||
final res = await dbGetOutboundGroupSession(clientId, roomId).get();
|
final res = await dbGetOutboundGroupSession(clientId, roomId).get();
|
||||||
if (res.isEmpty) {
|
if (res.isEmpty) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return res.single;
|
return OutboundGroupSession.fromDb(res.single, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<DbInboundGroupSession>> getDbInboundGroupSessions(
|
@override
|
||||||
int clientId, String roomId) async {
|
Future<SessionKey> getInboundGroupSession(
|
||||||
return await dbGetInboundGroupSessionKeys(clientId, roomId).get();
|
int clientId,
|
||||||
}
|
String roomId,
|
||||||
|
String sessionId,
|
||||||
Future<DbInboundGroupSession> getDbInboundGroupSession(
|
String userId,
|
||||||
int clientId, String roomId, String sessionId) async {
|
) async {
|
||||||
final res =
|
final res =
|
||||||
await dbGetInboundGroupSessionKey(clientId, roomId, sessionId).get();
|
await dbGetInboundGroupSessionKey(clientId, roomId, sessionId).get();
|
||||||
if (res.isEmpty) {
|
if (res.isEmpty) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return res.single;
|
return SessionKey.fromDb(
|
||||||
|
StoredInboundGroupSession.fromJson(res.single.toJson()), userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<DbSSSSCache> getSSSSCache(int clientId, String type) async {
|
@override
|
||||||
|
Future<SSSSCache> getSSSSCache(int clientId, String type) async {
|
||||||
final res = await dbGetSSSSCache(clientId, type).get();
|
final res = await dbGetSSSSCache(clientId, type).get();
|
||||||
if (res.isEmpty) {
|
if (res.isEmpty) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return res.single;
|
final dbCache = res.single;
|
||||||
|
return SSSSCache(
|
||||||
|
ciphertext: dbCache.ciphertext,
|
||||||
|
clientId: dbCache.clientId,
|
||||||
|
type: dbCache.type,
|
||||||
|
keyId: dbCache.keyId,
|
||||||
|
content: dbCache.content,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<sdk.Room>> getRoomList(sdk.Client client,
|
@override
|
||||||
{bool onlyLeft = false}) async {
|
Future<List<sdk.Room>> getRoomList(sdk.Client client) async {
|
||||||
final res = await (select(rooms)
|
final res = await select(rooms).get();
|
||||||
..where((t) => onlyLeft
|
|
||||||
? t.membership.equals('leave')
|
|
||||||
: t.membership.equals('leave').not()))
|
|
||||||
.get();
|
|
||||||
final resStates = await getImportantRoomStates(
|
final resStates = await getImportantRoomStates(
|
||||||
client.id, client.importantStateEvents.toList())
|
client.id, client.importantStateEvents.toList())
|
||||||
.get();
|
.get();
|
||||||
|
|
@ -358,6 +374,7 @@ class Database extends _$Database {
|
||||||
return roomList;
|
return roomList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<Map<String, api.BasicEvent>> getAccountData(int clientId) async {
|
Future<Map<String, api.BasicEvent>> getAccountData(int clientId) async {
|
||||||
final newAccountData = <String, api.BasicEvent>{};
|
final newAccountData = <String, api.BasicEvent>{};
|
||||||
final rawAccountData = await getAllAccountData(clientId).get();
|
final rawAccountData = await getAllAccountData(clientId).get();
|
||||||
|
|
@ -381,6 +398,7 @@ class Database extends _$Database {
|
||||||
/// Stores a RoomUpdate object in the database. Must be called inside of
|
/// Stores a RoomUpdate object in the database. Must be called inside of
|
||||||
/// [transaction].
|
/// [transaction].
|
||||||
final Set<String> _ensuredRooms = {};
|
final Set<String> _ensuredRooms = {};
|
||||||
|
@override
|
||||||
Future<void> storeRoomUpdate(int clientId, sdk.RoomUpdate roomUpdate,
|
Future<void> storeRoomUpdate(int clientId, sdk.RoomUpdate roomUpdate,
|
||||||
[sdk.Room oldRoom]) async {
|
[sdk.Room oldRoom]) async {
|
||||||
final setKey = '$clientId;${roomUpdate.id}';
|
final setKey = '$clientId;${roomUpdate.id}';
|
||||||
|
|
@ -446,6 +464,7 @@ class Database extends _$Database {
|
||||||
|
|
||||||
/// Stores an EventUpdate object in the database. Must be called inside of
|
/// Stores an EventUpdate object in the database. Must be called inside of
|
||||||
/// [transaction].
|
/// [transaction].
|
||||||
|
@override
|
||||||
Future<void> storeEventUpdate(
|
Future<void> storeEventUpdate(
|
||||||
int clientId, sdk.EventUpdate eventUpdate) async {
|
int clientId, sdk.EventUpdate eventUpdate) async {
|
||||||
if (eventUpdate.type == sdk.EventUpdateType.ephemeral) return;
|
if (eventUpdate.type == sdk.EventUpdateType.ephemeral) return;
|
||||||
|
|
@ -579,6 +598,7 @@ class Database extends _$Database {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<sdk.Event> getEventById(
|
Future<sdk.Event> getEventById(
|
||||||
int clientId, String eventId, sdk.Room room) async {
|
int clientId, String eventId, sdk.Room room) async {
|
||||||
final event = await getEvent(clientId, eventId, room.id).get();
|
final event = await getEvent(clientId, eventId, room.id).get();
|
||||||
|
|
@ -617,6 +637,7 @@ class Database extends _$Database {
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<void> forgetRoom(int clientId, String roomId) async {
|
Future<void> forgetRoom(int clientId, String roomId) async {
|
||||||
final setKey = '$clientId;$roomId';
|
final setKey = '$clientId;$roomId';
|
||||||
_ensuredRooms.remove(setKey);
|
_ensuredRooms.remove(setKey);
|
||||||
|
|
@ -634,6 +655,7 @@ class Database extends _$Database {
|
||||||
.go();
|
.go();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<void> clearCache(int clientId) async {
|
Future<void> clearCache(int clientId) async {
|
||||||
await (delete(presences)..where((r) => r.clientId.equals(clientId))).go();
|
await (delete(presences)..where((r) => r.clientId.equals(clientId))).go();
|
||||||
await (delete(roomAccountData)..where((r) => r.clientId.equals(clientId)))
|
await (delete(roomAccountData)..where((r) => r.clientId.equals(clientId)))
|
||||||
|
|
@ -649,6 +671,7 @@ class Database extends _$Database {
|
||||||
await storePrevBatch(null, clientId);
|
await storePrevBatch(null, clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<void> clear(int clientId) async {
|
Future<void> clear(int clientId) async {
|
||||||
await clearCache(clientId);
|
await clearCache(clientId);
|
||||||
await (delete(inboundGroupSessions)
|
await (delete(inboundGroupSessions)
|
||||||
|
|
@ -669,6 +692,7 @@ class Database extends _$Database {
|
||||||
.go();
|
.go();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<sdk.User> getUser(int clientId, String userId, sdk.Room room) async {
|
Future<sdk.User> getUser(int clientId, String userId, sdk.Room room) async {
|
||||||
final res = await dbGetUser(clientId, userId, room.id).get();
|
final res = await dbGetUser(clientId, userId, room.id).get();
|
||||||
if (res.isEmpty) {
|
if (res.isEmpty) {
|
||||||
|
|
@ -677,19 +701,88 @@ class Database extends _$Database {
|
||||||
return sdk.Event.fromDb(res.single, room).asUser;
|
return sdk.Event.fromDb(res.single, room).asUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<List<sdk.User>> getUsers(int clientId, sdk.Room room) async {
|
Future<List<sdk.User>> getUsers(int clientId, sdk.Room room) async {
|
||||||
final res = await dbGetUsers(clientId, room.id).get();
|
final res = await dbGetUsers(clientId, room.id).get();
|
||||||
return res.map((r) => sdk.Event.fromDb(r, room).asUser).toList();
|
return res.map((r) => sdk.Event.fromDb(r, room).asUser).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<List<sdk.Event>> getEventList(int clientId, sdk.Room room) async {
|
Future<List<sdk.Event>> getEventList(int clientId, sdk.Room room) async {
|
||||||
final res = await dbGetEventList(clientId, room.id).get();
|
final res = await dbGetEventList(clientId, room.id).get();
|
||||||
return res.map((r) => sdk.Event.fromDb(r, room)).toList();
|
return res.map((r) => sdk.Event.fromDb(r, room)).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<Uint8List> getFile(String mxcUri) async {
|
Future<Uint8List> getFile(String mxcUri) async {
|
||||||
final res = await dbGetFile(mxcUri).get();
|
final res = await dbGetFile(mxcUri).get();
|
||||||
if (res.isEmpty) return null;
|
if (res.isEmpty) return null;
|
||||||
return res.single.bytes;
|
return res.single.bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<sdk.Event>> getUnimportantRoomEventStatesForRoom(
|
||||||
|
int client_id,
|
||||||
|
List<String> events,
|
||||||
|
Room room,
|
||||||
|
) async {
|
||||||
|
final entries = await getUnimportantRoomStatesForRoom(
|
||||||
|
client_id,
|
||||||
|
room.id,
|
||||||
|
events,
|
||||||
|
).get();
|
||||||
|
return entries.map((dbEvent) => sdk.Event.fromDb(dbEvent, room)).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<OlmSession>> getOlmSessions(
|
||||||
|
int client_id,
|
||||||
|
String identity_key,
|
||||||
|
String userId,
|
||||||
|
) async {
|
||||||
|
final rows = await dbGetOlmSessions(client_id, identity_key).get();
|
||||||
|
return rows.map((row) => OlmSession.fromDb(row, userId)).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<OlmSession>> getOlmSessionsForDevices(
|
||||||
|
int client_id,
|
||||||
|
List<String> identity_keys,
|
||||||
|
String userId,
|
||||||
|
) async {
|
||||||
|
final rows =
|
||||||
|
await dbGetOlmSessionsForDevices(client_id, identity_keys).get();
|
||||||
|
return rows.map((row) => OlmSession.fromDb(row, userId)).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<QueuedToDeviceEvent>> getToDeviceEventQueue(int client_id) async {
|
||||||
|
final rows = await getToDeviceQueue(client_id).get();
|
||||||
|
return rows
|
||||||
|
.map((row) => QueuedToDeviceEvent(
|
||||||
|
id: row.id,
|
||||||
|
type: row.type,
|
||||||
|
txnId: row.txnId,
|
||||||
|
content:
|
||||||
|
(json.decode(row.content) as Map<String, dynamic>).copy(),
|
||||||
|
))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<String>> getLastSentMessageUserDeviceKey(
|
||||||
|
int client_id,
|
||||||
|
String user_id,
|
||||||
|
String device_id,
|
||||||
|
) =>
|
||||||
|
dbGetLastSentMessageUserDeviceKey(client_id, user_id, device_id).get();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<StoredInboundGroupSession>>
|
||||||
|
getInboundGroupSessionsToUpload() async {
|
||||||
|
final rows = await dbGetInboundGroupSessionsToUpload().get();
|
||||||
|
return rows
|
||||||
|
.map((row) => StoredInboundGroupSession.fromJson(row.toJson()))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6881,7 +6881,7 @@ abstract class _$Database extends GeneratedDatabase {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selectable<DbInboundGroupSession> getInboundGroupSessionsToUpload() {
|
Selectable<DbInboundGroupSession> dbGetInboundGroupSessionsToUpload() {
|
||||||
return customSelect(
|
return customSelect(
|
||||||
'SELECT * FROM inbound_group_sessions WHERE uploaded = false LIMIT 500',
|
'SELECT * FROM inbound_group_sessions WHERE uploaded = false LIMIT 500',
|
||||||
variables: [],
|
variables: [],
|
||||||
|
|
@ -7021,7 +7021,7 @@ abstract class _$Database extends GeneratedDatabase {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selectable<String> getLastSentMessageUserDeviceKey(
|
Selectable<String> dbGetLastSentMessageUserDeviceKey(
|
||||||
int client_id, String user_id, String device_id) {
|
int client_id, String user_id, String device_id) {
|
||||||
return customSelect(
|
return customSelect(
|
||||||
'SELECT last_sent_message FROM user_device_keys_key WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id',
|
'SELECT last_sent_message FROM user_device_keys_key WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id',
|
||||||
|
|
|
||||||
|
|
@ -208,7 +208,7 @@ getAllInboundGroupSessions: SELECT * FROM inbound_group_sessions WHERE client_id
|
||||||
storeInboundGroupSession: INSERT OR REPLACE INTO inbound_group_sessions (client_id, room_id, session_id, pickle, content, indexes, allowed_at_index, sender_key, sender_claimed_keys) VALUES (:client_id, :room_id, :session_id, :pickle, :content, :indexes, :allowed_at_index, :sender_key, :sender_claimed_keys);
|
storeInboundGroupSession: INSERT OR REPLACE INTO inbound_group_sessions (client_id, room_id, session_id, pickle, content, indexes, allowed_at_index, sender_key, sender_claimed_keys) VALUES (:client_id, :room_id, :session_id, :pickle, :content, :indexes, :allowed_at_index, :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;
|
||||||
updateInboundGroupSessionAllowedAtIndex: UPDATE inbound_group_sessions SET allowed_at_index = :allowed_at_index WHERE client_id = :client_id AND room_id = :room_id AND session_id = :session_id;
|
updateInboundGroupSessionAllowedAtIndex: UPDATE inbound_group_sessions SET allowed_at_index = :allowed_at_index WHERE client_id = :client_id AND room_id = :room_id AND session_id = :session_id;
|
||||||
getInboundGroupSessionsToUpload: SELECT * FROM inbound_group_sessions WHERE uploaded = false LIMIT 500;
|
dbGetInboundGroupSessionsToUpload: SELECT * FROM inbound_group_sessions WHERE uploaded = false LIMIT 500;
|
||||||
markInboundGroupSessionAsUploaded: UPDATE inbound_group_sessions SET uploaded = true WHERE client_id = :client_id AND room_id = :room_id AND session_id = :session_id;
|
markInboundGroupSessionAsUploaded: UPDATE inbound_group_sessions SET uploaded = true WHERE client_id = :client_id AND room_id = :room_id AND session_id = :session_id;
|
||||||
markInboundGroupSessionsAsNeedingUpload: UPDATE inbound_group_sessions SET uploaded = false WHERE client_id = :client_id;
|
markInboundGroupSessionsAsNeedingUpload: UPDATE inbound_group_sessions SET uploaded = false WHERE client_id = :client_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);
|
||||||
|
|
@ -218,7 +218,7 @@ storeUserDeviceKey: INSERT OR REPLACE INTO user_device_keys_key (client_id, user
|
||||||
removeUserDeviceKey: DELETE FROM user_device_keys_key WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id;
|
removeUserDeviceKey: DELETE FROM user_device_keys_key WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id;
|
||||||
setLastActiveUserDeviceKey: UPDATE user_device_keys_key SET last_active = :last_active WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id;
|
setLastActiveUserDeviceKey: UPDATE user_device_keys_key SET last_active = :last_active WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id;
|
||||||
setLastSentMessageUserDeviceKey: UPDATE user_device_keys_key SET last_sent_message = :last_sent_message WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id;
|
setLastSentMessageUserDeviceKey: UPDATE user_device_keys_key SET last_sent_message = :last_sent_message WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id;
|
||||||
getLastSentMessageUserDeviceKey: SELECT last_sent_message FROM user_device_keys_key WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id;
|
dbGetLastSentMessageUserDeviceKey: SELECT last_sent_message FROM user_device_keys_key WHERE client_id = :client_id AND user_id = :user_id AND device_id = :device_id;
|
||||||
setVerifiedUserCrossSigningKey: UPDATE user_cross_signing_keys SET verified = :verified WHERE client_id = :client_id AND user_id = :user_id AND public_key = :public_key;
|
setVerifiedUserCrossSigningKey: UPDATE user_cross_signing_keys SET verified = :verified WHERE client_id = :client_id AND user_id = :user_id AND public_key = :public_key;
|
||||||
setBlockedUserCrossSigningKey: UPDATE user_cross_signing_keys SET blocked = :blocked WHERE client_id = :client_id AND user_id = :user_id AND public_key = :public_key;
|
setBlockedUserCrossSigningKey: UPDATE user_cross_signing_keys SET blocked = :blocked WHERE client_id = :client_id AND user_id = :user_id AND public_key = :public_key;
|
||||||
storeUserCrossSigningKey: INSERT OR REPLACE INTO user_cross_signing_keys (client_id, user_id, public_key, content, verified, blocked) VALUES (:client_id, :user_id, :public_key, :content, :verified, :blocked);
|
storeUserCrossSigningKey: INSERT OR REPLACE INTO user_cross_signing_keys (client_id, user_id, public_key, content, verified, blocked) VALUES (:client_id, :user_id, :public_key, :content, :verified, :blocked);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,315 @@
|
||||||
|
/*
|
||||||
|
* Famedly Matrix SDK
|
||||||
|
* Copyright (C) 2021 Famedly GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* 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: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';
|
||||||
|
|
||||||
|
import '../../famedlysdk.dart';
|
||||||
|
|
||||||
|
abstract class DatabaseApi {
|
||||||
|
int get maxFileSize => 1 * 1024 * 1024;
|
||||||
|
Future<dynamic> getClient(String name);
|
||||||
|
|
||||||
|
Future<Map<String, DeviceKeysList>> getUserDeviceKeys(Client client);
|
||||||
|
|
||||||
|
Future<OutboundGroupSession> getOutboundGroupSession(
|
||||||
|
int clientId,
|
||||||
|
String roomId,
|
||||||
|
String userId,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<SessionKey> getInboundGroupSession(
|
||||||
|
int clientId,
|
||||||
|
String roomId,
|
||||||
|
String sessionId,
|
||||||
|
String userId,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<SSSSCache> getSSSSCache(int clientId, String type);
|
||||||
|
|
||||||
|
Future<List<Room>> getRoomList(Client client);
|
||||||
|
|
||||||
|
Future<Map<String, BasicEvent>> getAccountData(int clientId);
|
||||||
|
|
||||||
|
/// Stores a RoomUpdate object in the database. Must be called inside of
|
||||||
|
/// [transaction].
|
||||||
|
Future<void> storeRoomUpdate(int clientId, RoomUpdate roomUpdate,
|
||||||
|
[Room oldRoom]);
|
||||||
|
|
||||||
|
/// Stores an EventUpdate object in the database. Must be called inside of
|
||||||
|
/// [transaction].
|
||||||
|
Future<void> storeEventUpdate(int clientId, EventUpdate eventUpdate);
|
||||||
|
|
||||||
|
Future<Event> getEventById(int clientId, String eventId, Room room);
|
||||||
|
|
||||||
|
Future<void> forgetRoom(int clientId, String roomId);
|
||||||
|
|
||||||
|
Future<void> clearCache(int clientId);
|
||||||
|
|
||||||
|
Future<void> clear(int clientId);
|
||||||
|
|
||||||
|
Future<User> getUser(int clientId, String userId, Room room);
|
||||||
|
|
||||||
|
Future<List<User>> getUsers(int clientId, Room room);
|
||||||
|
|
||||||
|
Future<List<Event>> getEventList(int clientId, Room room);
|
||||||
|
|
||||||
|
Future<Uint8List> getFile(String mxcUri);
|
||||||
|
|
||||||
|
Future<int> updateInboundGroupSessionIndexes(
|
||||||
|
String indexes,
|
||||||
|
int clientId,
|
||||||
|
String roomId,
|
||||||
|
String sessionId,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> storeInboundGroupSession(
|
||||||
|
int clientId,
|
||||||
|
String roomId,
|
||||||
|
String sessionId,
|
||||||
|
String pickle,
|
||||||
|
String content,
|
||||||
|
String indexes,
|
||||||
|
String allowedAtIndex,
|
||||||
|
String senderKey,
|
||||||
|
String senderClaimedKey,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> markInboundGroupSessionAsUploaded(
|
||||||
|
int clientId,
|
||||||
|
String roomId,
|
||||||
|
String sessionId,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> updateInboundGroupSessionAllowedAtIndex(
|
||||||
|
String allowedAtIndex,
|
||||||
|
int clientId,
|
||||||
|
String roomId,
|
||||||
|
String sessionId,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> 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(
|
||||||
|
int clientId,
|
||||||
|
String roomId,
|
||||||
|
String pickle,
|
||||||
|
String deviceIds,
|
||||||
|
int creationTime,
|
||||||
|
int sentMessages,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> updateClientKeys(String olmAccount, int clientId);
|
||||||
|
|
||||||
|
Future<int> storeOlmSession(
|
||||||
|
int clientId,
|
||||||
|
String identitiyKey,
|
||||||
|
String sessionId,
|
||||||
|
String pickle,
|
||||||
|
int lastReceived,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> setLastActiveUserDeviceKey(
|
||||||
|
int lastActive,
|
||||||
|
int clientId,
|
||||||
|
String userId,
|
||||||
|
String deviceId,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> setLastSentMessageUserDeviceKey(
|
||||||
|
String lastSentMessage,
|
||||||
|
int clientId,
|
||||||
|
String userId,
|
||||||
|
String deviceId,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> clearSSSSCache(int clientId);
|
||||||
|
|
||||||
|
Future<int> storeSSSSCache(
|
||||||
|
int clientId,
|
||||||
|
String type,
|
||||||
|
String keyId,
|
||||||
|
String ciphertext,
|
||||||
|
String content,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> markInboundGroupSessionsAsNeedingUpload(int clientId);
|
||||||
|
|
||||||
|
Future<int> storePrevBatch(String prevBatch, int clientId);
|
||||||
|
|
||||||
|
Future<int> deleteOldFiles(int savedAt);
|
||||||
|
|
||||||
|
Future<int> storeUserDeviceKeysInfo(
|
||||||
|
int clientId,
|
||||||
|
String userId,
|
||||||
|
bool outdated,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> storeUserDeviceKey(
|
||||||
|
int clientId,
|
||||||
|
String userId,
|
||||||
|
String deviceId,
|
||||||
|
String content,
|
||||||
|
bool verified,
|
||||||
|
bool blocked,
|
||||||
|
int lastActive,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> removeUserDeviceKey(
|
||||||
|
int clientId,
|
||||||
|
String userId,
|
||||||
|
String deviceId,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> removeUserCrossSigningKey(
|
||||||
|
int clientId,
|
||||||
|
String userId,
|
||||||
|
String publicKey,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> storeUserCrossSigningKey(
|
||||||
|
int clientId,
|
||||||
|
String userId,
|
||||||
|
String publicKey,
|
||||||
|
String content,
|
||||||
|
bool verified,
|
||||||
|
bool blocked,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> deleteFromToDeviceQueue(int clientId, int id);
|
||||||
|
|
||||||
|
Future<int> removeEvent(int clientId, String eventId, String roomId);
|
||||||
|
|
||||||
|
Future<int> updateRoomSortOrder(
|
||||||
|
double oldestSortOrder,
|
||||||
|
double newestSortOrder,
|
||||||
|
int clientId,
|
||||||
|
String roomId,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> setRoomPrevBatch(
|
||||||
|
String prevBatch,
|
||||||
|
int clientId,
|
||||||
|
String roomId,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> resetNotificationCount(int clientId, String roomId);
|
||||||
|
|
||||||
|
Future<int> setVerifiedUserCrossSigningKey(
|
||||||
|
bool verified,
|
||||||
|
int clientId,
|
||||||
|
String userId,
|
||||||
|
String publicKey,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> setBlockedUserCrossSigningKey(
|
||||||
|
bool blocked,
|
||||||
|
int clientId,
|
||||||
|
String userId,
|
||||||
|
String publicKey,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> setVerifiedUserDeviceKey(
|
||||||
|
bool verified,
|
||||||
|
int clientId,
|
||||||
|
String userId,
|
||||||
|
String deviceId,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int> setBlockedUserDeviceKey(
|
||||||
|
bool blocked,
|
||||||
|
int clientId,
|
||||||
|
String userId,
|
||||||
|
String deviceId,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<List<Event>> getUnimportantRoomEventStatesForRoom(
|
||||||
|
int clientId,
|
||||||
|
List<String> events,
|
||||||
|
Room room,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<List<OlmSession>> getOlmSessions(
|
||||||
|
int clientId,
|
||||||
|
String identityKey,
|
||||||
|
String userId,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<List<OlmSession>> getOlmSessionsForDevices(
|
||||||
|
int clientId,
|
||||||
|
List<String> identityKeys,
|
||||||
|
String userId,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<List<QueuedToDeviceEvent>> getToDeviceEventQueue(int clientId);
|
||||||
|
|
||||||
|
/// Please do `jsonEncode(content)` in your code to stay compatible with
|
||||||
|
/// auto generated methods here.
|
||||||
|
Future<int> insertIntoToDeviceQueue(
|
||||||
|
int clientId,
|
||||||
|
String type,
|
||||||
|
String txnId,
|
||||||
|
String content,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<List<String>> getLastSentMessageUserDeviceKey(
|
||||||
|
int clientId,
|
||||||
|
String userId,
|
||||||
|
String deviceId,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<List<StoredInboundGroupSession>> getInboundGroupSessionsToUpload();
|
||||||
|
|
||||||
|
Future<dynamic> close();
|
||||||
|
|
||||||
|
Future<T> transaction<T>(Future<T> Function() action);
|
||||||
|
}
|
||||||
|
|
@ -130,12 +130,11 @@ class Room {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final allStates = await client.database
|
final allStates = await client.database
|
||||||
.getUnimportantRoomStatesForRoom(
|
.getUnimportantRoomEventStatesForRoom(
|
||||||
client.id, id, client.importantStateEvents.toList())
|
client.id, client.importantStateEvents.toList(), this);
|
||||||
.get();
|
|
||||||
for (final state in allStates) {
|
for (final state in allStates) {
|
||||||
final newState = Event.fromDb(state, this);
|
setState(state);
|
||||||
setState(newState);
|
|
||||||
}
|
}
|
||||||
partial = false;
|
partial = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
class QueuedToDeviceEvent {
|
||||||
|
final int id;
|
||||||
|
final String type;
|
||||||
|
final String txnId;
|
||||||
|
final Map<String, dynamic> content;
|
||||||
|
|
||||||
|
QueuedToDeviceEvent({this.id, this.type, this.txnId, this.content});
|
||||||
|
|
||||||
|
factory QueuedToDeviceEvent.fromJson(Map<String, dynamic> json) =>
|
||||||
|
QueuedToDeviceEvent(
|
||||||
|
id: json['id'],
|
||||||
|
type: json['type'],
|
||||||
|
txnId: json['txn_id'],
|
||||||
|
content: json['content'],
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
'id': id,
|
||||||
|
'type': type,
|
||||||
|
'txn_id': txnId,
|
||||||
|
'content': content,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -96,14 +96,12 @@ void main() {
|
||||||
client.encryption.keyManager.setInboundGroupSession(
|
client.encryption.keyManager.setInboundGroupSession(
|
||||||
roomId, sessionId, senderKey, sessionPayload,
|
roomId, sessionId, senderKey, sessionPayload,
|
||||||
forwarded: true);
|
forwarded: true);
|
||||||
var dbSessions =
|
var dbSessions = await client.database.getInboundGroupSessionsToUpload();
|
||||||
await client.database.getInboundGroupSessionsToUpload().get();
|
|
||||||
expect(dbSessions.isNotEmpty, true);
|
expect(dbSessions.isNotEmpty, true);
|
||||||
await client.encryption.keyManager.backgroundTasks();
|
await client.encryption.keyManager.backgroundTasks();
|
||||||
final payload = FakeMatrixApi
|
final payload = FakeMatrixApi
|
||||||
.calledEndpoints['/client/unstable/room_keys/keys?version=5'].first;
|
.calledEndpoints['/client/unstable/room_keys/keys?version=5'].first;
|
||||||
dbSessions =
|
dbSessions = await client.database.getInboundGroupSessionsToUpload();
|
||||||
await client.database.getInboundGroupSessionsToUpload().get();
|
|
||||||
expect(dbSessions.isEmpty, true);
|
expect(dbSessions.isEmpty, true);
|
||||||
|
|
||||||
final onlineKeys = RoomKeys.fromJson(json.decode(payload));
|
final onlineKeys = RoomKeys.fromJson(json.decode(payload));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue