From 262e42407c810ec99b29dac941f4fe669a5fe0fd Mon Sep 17 00:00:00 2001 From: Krille Date: Thu, 20 Apr 2023 13:51:50 +0200 Subject: [PATCH] feat: Try out FluffyBox 2 database --- android/app/proguard-rules.pro | 1 + lib/utils/client_manager.dart | 4 +- .../fluffybox_database_builder.dart | 86 +++++++++++++++++++ .../flutter_hive_collections_database.dart | 4 +- macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 67 +++++++++++++-- pubspec.yaml | 8 ++ scripts/enable-android-google-services.patch | 20 +++-- 8 files changed, 171 insertions(+), 21 deletions(-) create mode 100644 android/app/proguard-rules.pro create mode 100644 lib/utils/matrix_sdk_extensions/fluffybox_database_builder.dart diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro new file mode 100644 index 00000000..d0e0fbc9 --- /dev/null +++ b/android/app/proguard-rules.pro @@ -0,0 +1 @@ +-keep class net.sqlcipher.** { *; } \ No newline at end of file diff --git a/lib/utils/client_manager.dart b/lib/utils/client_manager.dart index 1ee71d49..3b3b7c4f 100644 --- a/lib/utils/client_manager.dart +++ b/lib/utils/client_manager.dart @@ -12,6 +12,7 @@ import 'package:fluffychat/utils/custom_image_resizer.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'famedlysdk_store.dart'; +import 'matrix_sdk_extensions/fluffybox_database_builder.dart'; abstract class ClientManager { static const String clientNamespace = 'im.fluffychat.store.clients'; @@ -109,7 +110,8 @@ abstract class ClientManager { EventTypes.RoomPowerLevels, }, logLevel: kReleaseMode ? Level.warning : Level.verbose, - databaseBuilder: FlutterHiveCollectionsDatabase.databaseBuilder, + databaseBuilder: fluffyBoxDatabaseBuilder, + legacyDatabaseBuilder: FlutterHiveCollectionsDatabase.databaseBuilder, supportedLoginTypes: { AuthenticationTypes.password, AuthenticationTypes.sso, diff --git a/lib/utils/matrix_sdk_extensions/fluffybox_database_builder.dart b/lib/utils/matrix_sdk_extensions/fluffybox_database_builder.dart new file mode 100644 index 00000000..32531490 --- /dev/null +++ b/lib/utils/matrix_sdk_extensions/fluffybox_database_builder.dart @@ -0,0 +1,86 @@ +import 'dart:convert'; +import 'dart:math'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; + +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:matrix/matrix.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:sqflite_common_ffi/sqflite_ffi.dart' as ffi; +import 'package:sqflite_sqlcipher/sqflite.dart'; +import 'package:universal_html/html.dart' as html; + +import 'package:fluffychat/utils/platform_infos.dart'; + +Future fluffyBoxDatabaseBuilder(Client client) async { + final database = await _constructDatabase(client); + await database.open(); + return database; +} + +Future _constructDatabase(Client client) async { + if (kIsWeb) { + html.window.navigator.storage?.persist(); + return FluffyBoxDatabase(client.clientName); + } + if (PlatformInfos.isDesktop) { + final path = await getApplicationSupportDirectory(); + return FluffyBoxDatabase( + client.clientName, + database: await ffi.databaseFactoryFfi.openDatabase( + '$path/${client.clientName}', + ), + maxFileSize: 1024 * 1024 * 10, + fileStoragePath: path, + deleteFilesAfterDuration: const Duration(days: 30), + ); + } + + final path = await getDatabasesPath(); + const passwordStorageKey = 'database_password'; + String? password; + + try { + // Workaround for secure storage is calling Platform.operatingSystem on web + if (kIsWeb) throw MissingPluginException(); + + const secureStorage = FlutterSecureStorage(); + final containsEncryptionKey = + await secureStorage.read(key: passwordStorageKey) != null; + if (!containsEncryptionKey) { + final rng = Random.secure(); + final list = Uint8List(32); + list.setAll(0, Iterable.generate(list.length, (i) => rng.nextInt(256))); + final newPassword = base64UrlEncode(list); + await secureStorage.write( + key: passwordStorageKey, + value: newPassword, + ); + } + // workaround for if we just wrote to the key and it still doesn't exist + password = await secureStorage.read(key: passwordStorageKey); + if (password == null) throw MissingPluginException(); + } on MissingPluginException catch (_) { + const FlutterSecureStorage() + .delete(key: passwordStorageKey) + .catchError((_) {}); + Logs().i('Database encryption is not supported on this platform'); + } catch (e, s) { + const FlutterSecureStorage() + .delete(key: passwordStorageKey) + .catchError((_) {}); + Logs().w('Unable to init database encryption', e, s); + } + + return FluffyBoxDatabase( + client.clientName, + database: await openDatabase( + '$path/${client.clientName}', + password: password, + ), + maxFileSize: 1024 * 1024 * 10, + fileStoragePath: await getTemporaryDirectory(), + deleteFilesAfterDuration: const Duration(days: 30), + ); +} diff --git a/lib/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart b/lib/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart index 932763c5..56a2d2da 100644 --- a/lib/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart +++ b/lib/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart @@ -63,7 +63,7 @@ class FlutterHiveCollectionsDatabase extends HiveCollectionsDatabase { final db = FlutterHiveCollectionsDatabase( 'hive_collections_${client.clientName.replaceAll(' ', '_').toLowerCase()}', - await _findDatabasePath(client), + await findDatabasePath(client), key: hiverCipher, ); try { @@ -79,7 +79,7 @@ class FlutterHiveCollectionsDatabase extends HiveCollectionsDatabase { return db; } - static Future _findDatabasePath(Client client) async { + static Future findDatabasePath(Client client) async { String path = client.clientName; if (!kIsWeb) { Directory directory; diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 879986ff..7d6c7299 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -27,6 +27,7 @@ import record_macos import share_plus import shared_preferences_macos import sqflite +import sqflite_sqlcipher import url_launcher_macos import video_compress import wakelock_macos @@ -55,6 +56,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) + SqfliteSqlCipherPlugin.register(with: registry.registrar(forPlugin: "SqfliteSqlCipherPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) VideoCompressPlugin.register(with: registry.registrar(forPlugin: "VideoCompressPlugin")) WakelockMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockMacosPlugin")) diff --git a/pubspec.lock b/pubspec.lock index d66ecd27..cfb2463d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -417,6 +417,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.3.0" + fluffybox: + dependency: transitive + description: + name: fluffybox + sha256: "19560c2c8b3f06009a0fe8c2af2f96ee7c1e6a3b248ae79df90f57e51d8995ce" + url: "https://pub.dev" + source: hosted + version: "0.7.1" flutter: dependency: "direct main" description: flutter @@ -858,6 +866,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + idb_shim: + dependency: "direct main" + description: + name: idb_shim + sha256: "3ac9d6a90c29e2192d35c8386d7b20cb3865756f5b299d74a829d5b888776d26" + url: "https://pub.dev" + source: hosted + version: "2.3.0+2" image: dependency: transitive description: @@ -1068,10 +1084,11 @@ packages: matrix: dependency: "direct main" description: - name: matrix - sha256: "2b07709bce975d2be4dc4cd3cc1196fcd6c0397d4e250b42a498e35523fc28f3" - url: "https://pub.dev" - source: hosted + path: "." + ref: "krille/new-fluffybox" + resolved-ref: "0e54885bfcf7c8e6a295938714cb5a05836a5ee5" + url: "https://gitlab.com/famedly/company/frontend/famedlysdk.git" + source: git version: "0.20.1" matrix_api_lite: dependency: transitive @@ -1554,6 +1571,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.2" + sembast: + dependency: transitive + description: + name: sembast + sha256: "24829715d11c2c437e67b413f29ff91b5325daa9632f851d44deeea7a29bde9e" + url: "https://pub.dev" + source: hosted + version: "3.4.3+1" sentiment_dart: dependency: transitive description: @@ -1664,21 +1689,45 @@ packages: source: hosted version: "1.9.1" sqflite: - dependency: transitive + dependency: "direct main" description: name: sqflite - sha256: "500d6fec583d2c021f2d25a056d96654f910662c64f836cd2063167b8f1fa758" + sha256: "3a82c9a216b46b88617e3714dd74227eaca20c501c4abcc213e56db26b9caa00" url: "https://pub.dev" source: hosted - version: "2.2.6" + version: "2.2.8+2" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "963dad8c4aa2f814ce7d2d5b1da2f36f31bd1a439d8f27e3dc189bb9d26bc684" + sha256: e77abf6ff961d69dfef41daccbb66b51e9983cdd5cb35bf30733598057401555 url: "https://pub.dev" source: hosted - version: "2.4.3" + version: "2.4.5" + sqflite_common_ffi: + dependency: "direct main" + description: + name: sqflite_common_ffi + sha256: f86de82d37403af491b21920a696b19f01465b596f545d1acd4d29a0a72418ad + url: "https://pub.dev" + source: hosted + version: "2.2.5" + sqflite_sqlcipher: + dependency: "direct main" + description: + name: sqflite_sqlcipher + sha256: bcc02bfcc549895338558ba9acd0e3c54f808ef7095bb1294973751c521c9ba2 + url: "https://pub.dev" + source: hosted + version: "2.1.1+1" + sqlite3: + dependency: transitive + description: + name: sqlite3 + sha256: "2cef47b59d310e56f8275b13734ee80a9cf4a48a43172020cb55a620121fbf66" + url: "https://pub.dev" + source: hosted + version: "1.11.1" stack_trace: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 61e0e8cd..205d8c30 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -51,6 +51,7 @@ dependencies: hive: ^2.2.3 hive_flutter: ^1.1.0 http: ^0.13.4 + idb_shim: ^2.3.0+2 image_picker: ^0.8.4+8 intl: any just_audio: ^0.9.30 @@ -75,6 +76,9 @@ dependencies: share_plus: ^7.0.0 shared_preferences: 2.0.15 # Pinned because https://github.com/flutter/flutter/issues/118401 slugify: ^2.0.0 + sqflite: ^2.2.8+2 + sqflite_common_ffi: ^2.2.5 + sqflite_sqlcipher: ^2.1.1+1 swipe_to_action: ^0.2.0 tor_detector_web: ^1.1.0 uni_links: ^0.5.1 @@ -186,3 +190,7 @@ dependency_overrides: url: https://github.com/timsneath/wakelock.git ref: 2a9bca63a540771f241d688562351482b2cf234c path: wakelock_windows + matrix: + git: + url: https://gitlab.com/famedly/company/frontend/famedlysdk.git + ref: krille/new-fluffybox diff --git a/scripts/enable-android-google-services.patch b/scripts/enable-android-google-services.patch index ad9dc958..88dded80 100644 --- a/scripts/enable-android-google-services.patch +++ b/scripts/enable-android-google-services.patch @@ -1,5 +1,5 @@ diff --git a/android/app/build.gradle b/android/app/build.gradle -index 001fbd72..339b35af 100644 +index bf972f30..46cebdc6 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -68,6 +68,10 @@ android { @@ -28,13 +28,15 @@ index 001fbd72..339b35af 100644 -//apply plugin: 'com.google.gms.google-services' +apply plugin: 'com.google.gms.google-services' diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro -new file mode 100644 -index 00000000..40570865 ---- /dev/null +index d0e0fbc9..0a546da0 100644 +--- a/android/app/proguard-rules.pro +++ b/android/app/proguard-rules.pro -@@ -0,0 +1,41 @@ +@@ -1 +1,42 @@ +--keep class net.sqlcipher.** { *; } +\ No newline at end of file +-optimizationpasses 5 +## Flutter wrapper ++-keep class net.sqlcipher.** { *; } +-keep class io.flutter.app.** { *; } +-keep class io.flutter.plugin.** { *; } +-keep class io.flutter.util.** { *; } @@ -110,7 +112,7 @@ index 1afc4606..894d1571 100644 return provideEngine(this) } diff --git a/android/build.gradle b/android/build.gradle -index 85aa8647..3b7e09e7 100644 +index bd394967..2e9d54de 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,7 +8,7 @@ buildscript { @@ -123,7 +125,7 @@ index 85aa8647..3b7e09e7 100644 } diff --git a/lib/utils/background_push.dart b/lib/utils/background_push.dart -index cd79b0ab..c2db0f1e 100644 +index 5f5b7618..35928203 100644 --- a/lib/utils/background_push.dart +++ b/lib/utils/background_push.dart @@ -39,7 +39,7 @@ import '../config/setting_keys.dart'; @@ -145,10 +147,10 @@ index cd79b0ab..c2db0f1e 100644 DateTime? lastReceivedPush; diff --git a/pubspec.yaml b/pubspec.yaml -index 6999d0b8..b2c9144f 100644 +index 193e6ed6..f70e48d4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml -@@ -26,7 +26,7 @@ dependencies: +@@ -24,7 +24,7 @@ dependencies: emoji_picker_flutter: ^1.5.1 emoji_proposal: ^0.0.1 emojis: ^0.9.9