From dae65b645c8ee44d0eff11d27037bc7e90445fb7 Mon Sep 17 00:00:00 2001 From: Krille Date: Fri, 12 May 2023 11:05:50 +0200 Subject: [PATCH] feat: Experimental sqflite database --- .gitignore | 4 + android/app/proguard-rules.pro | 1 + lib/pages/chat_list/chat_list_item.dart | 5 +- lib/utils/client_manager.dart | 4 +- lib/utils/sqflite_database_builder.dart | 78 +++++++ macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 201 +++++++++++++++++- pubspec.yaml | 5 + scripts/enable-android-google-services.patch | 20 +- scripts/prepare-web.sh | 1 + 10 files changed, 299 insertions(+), 22 deletions(-) create mode 100644 android/app/proguard-rules.pro create mode 100644 lib/utils/sqflite_database_builder.dart diff --git a/.gitignore b/.gitignore index 1245e194..f0c49e12 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,10 @@ prime # libolm package /assets/js/package +# sqflite web +web/sqflite_sw.js +web/sqlite3.wasm + # IntelliJ related *.iml *.ipr 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/pages/chat_list/chat_list_item.dart b/lib/pages/chat_list/chat_list_item.dart index a53c2927..d1002d55 100644 --- a/lib/pages/chat_list/chat_list_item.dart +++ b/lib/pages/chat_list/chat_list_item.dart @@ -127,9 +127,8 @@ class ChatListItem extends StatelessWidget { ? 20.0 : 14.0 : 0.0; - final displayname = room.getLocalizedDisplayname( - MatrixLocals(L10n.of(context)!), - ); + final displayname = + room.getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)); return Padding( padding: const EdgeInsets.symmetric( horizontal: 8, diff --git a/lib/utils/client_manager.dart b/lib/utils/client_manager.dart index 1ee71d49..af1e4723 100644 --- a/lib/utils/client_manager.dart +++ b/lib/utils/client_manager.dart @@ -11,6 +11,7 @@ import 'package:fluffychat/utils/custom_http_client.dart'; 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 'package:fluffychat/utils/sqflite_database_builder.dart'; import 'famedlysdk_store.dart'; abstract class ClientManager { @@ -109,7 +110,8 @@ abstract class ClientManager { EventTypes.RoomPowerLevels, }, logLevel: kReleaseMode ? Level.warning : Level.verbose, - databaseBuilder: FlutterHiveCollectionsDatabase.databaseBuilder, + databaseBuilder: sqfliteDatabaseBuilder, + legacyDatabaseBuilder: FlutterHiveCollectionsDatabase.databaseBuilder, supportedLoginTypes: { AuthenticationTypes.password, AuthenticationTypes.sso, diff --git a/lib/utils/sqflite_database_builder.dart b/lib/utils/sqflite_database_builder.dart new file mode 100644 index 00000000..2bb00455 --- /dev/null +++ b/lib/utils/sqflite_database_builder.dart @@ -0,0 +1,78 @@ +import 'dart:convert'; +import 'dart:io'; +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_web/sqflite_ffi_web.dart'; +import 'package:sqflite_sqlcipher/sqflite.dart'; +import 'package:universal_html/html.dart' as html; + +Future sqfliteDatabaseBuilder(Client client) async { + if (kIsWeb) { + html.window.navigator.storage?.persist(); + return SqfliteDatabase( + await databaseFactoryFfiWeb.openDatabase( + client.clientName, + options: OpenDatabaseOptions( + version: 1, + onCreate: DbTablesExtension.create, + ), + ), + fileStoragePath: null, + maxFileSize: 0, + ); + } + 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) { + // do not try to create a buggy secure storage for new Linux users + if (Platform.isLinux) throw MissingPluginException(); + 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('Hive encryption is not supported on this platform'); + } catch (e, s) { + const FlutterSecureStorage() + .delete(key: passwordStorageKey) + .catchError((_) {}); + Logs().w('Unable to init Hive encryption', e, s); + } + + return SqfliteDatabase( + await openDatabase( + '$path/${client.clientName}', + version: 1, + onCreate: DbTablesExtension.create, + password: password, + ), + fileStoragePath: await getTemporaryDirectory(), + maxFileSize: 10 * 1024 * 1024, + ); +} diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 268d92fb..1a56ee96 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -26,6 +26,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 @@ -53,6 +54,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 2c861904..450cd8ed 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -233,6 +233,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.1" + coverage: + dependency: transitive + description: + name: coverage + sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097" + url: "https://pub.dev" + source: hosted + version: "1.6.3" cross_file: dependency: transitive description: @@ -321,6 +329,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.3" + dev_test: + dependency: transitive + description: + name: dev_test + sha256: f03d3778ae90a00dce805b74fb7e68c7d8c71e0d8fe45feefdfb0ac6fb2050f2 + url: "https://pub.dev" + source: hosted + version: "0.16.1+1" device_info_plus: dependency: "direct main" description: @@ -725,6 +741,14 @@ packages: url: "https://github.com/radzio-it/flutter-webrtc.git" source: git version: "0.9.29+hotfix.1" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" + source: hosted + version: "3.2.0" fuchsia_remote_debug_protocol: dependency: transitive description: flutter @@ -850,6 +874,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.13.5" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" http_parser: dependency: transitive description: @@ -935,6 +967,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.17.0" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" isolate: dependency: transitive description: @@ -1024,6 +1064,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + logging: + dependency: transitive + description: + name: logging + sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + url: "https://pub.dev" + source: hosted + version: "1.1.1" macos_ui: dependency: transitive description: @@ -1059,10 +1107,9 @@ packages: matrix: dependency: "direct main" description: - name: matrix - sha256: "2b07709bce975d2be4dc4cd3cc1196fcd6c0397d4e250b42a498e35523fc28f3" - url: "https://pub.dev" - source: hosted + path: "../famedlysdk" + relative: true + source: path version: "0.20.1" matrix_api_lite: dependency: transitive @@ -1160,6 +1207,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.0" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" octo_image: dependency: transitive description: @@ -1400,6 +1455,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" positioned_tap_detector_2: dependency: transitive description: @@ -1416,6 +1479,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.2.4" + process_run: + dependency: transitive + description: + name: process_run + sha256: "0071cece7ca0fdf4aaf2cf84ee3082f3043f18afc7fcfd51f53f9424a8072c04" + url: "https://pub.dev" + source: hosted + version: "0.13.0" proj4dart: dependency: transitive description: @@ -1664,6 +1735,38 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.5" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e + url: "https://pub.dev" + source: hosted + version: "1.1.2" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + url: "https://pub.dev" + source: hosted + version: "1.0.4" sky_engine: dependency: transitive description: flutter @@ -1677,6 +1780,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" + url: "https://pub.dev" + source: hosted + version: "0.10.12" source_span: dependency: transitive description: @@ -1686,21 +1805,53 @@ 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: transitive + description: + name: sqflite_common_ffi + sha256: f86de82d37403af491b21920a696b19f01465b596f545d1acd4d29a0a72418ad + url: "https://pub.dev" + source: hosted + version: "2.2.5" + sqflite_common_ffi_web: + dependency: "direct main" + description: + name: sqflite_common_ffi_web + sha256: "59885fbdd4ed51b9515061c14f4790458b62b08660deab9804b87ff6d4f7fff2" + url: "https://pub.dev" + source: hosted + version: "0.3.5+1" + 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: @@ -1757,6 +1908,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.1" + test: + dependency: transitive + description: + name: test + sha256: a5fcd2d25eeadbb6589e80198a47d6a464ba3e2049da473943b8af9797900c2d + url: "https://pub.dev" + source: hosted + version: "1.22.0" test_api: dependency: transitive description: @@ -1765,6 +1924,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.4.16" + test_core: + dependency: transitive + description: + name: test_core + sha256: "0ef9755ec6d746951ba0aabe62f874b707690b5ede0fecc818b138fcc9b14888" + url: "https://pub.dev" + source: hosted + version: "0.4.20" timezone: dependency: transitive description: @@ -2109,6 +2276,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.2" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + url: "https://pub.dev" + source: hosted + version: "2.4.0" webdriver: dependency: transitive description: @@ -2117,6 +2292,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.1" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d" + url: "https://pub.dev" + source: hosted + version: "1.2.0" webrtc_interface: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 2c8e5002..193e6ed6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -75,6 +75,9 @@ dependencies: share_plus: ^6.3.1 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_web: ^0.3.5+1 + sqflite_sqlcipher: ^2.1.1+1 swipe_to_action: ^0.2.0 tor_detector_web: ^1.1.0 uni_links: ^0.5.1 @@ -166,3 +169,5 @@ dependency_overrides: git: url: https://github.com/TheOneWithTheBraid/keyboard_shortcuts.git ref: null-safety + matrix: + path: ../famedlysdk/ diff --git a/scripts/enable-android-google-services.patch b/scripts/enable-android-google-services.patch index 00197e20..a96a830c 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 @@ -44,7 +44,7 @@ android { @@ -37,13 +37,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.** { *; } @@ -119,7 +121,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 { @@ -132,7 +134,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'; @@ -154,10 +156,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 diff --git a/scripts/prepare-web.sh b/scripts/prepare-web.sh index 2c05a203..48f1ba91 100755 --- a/scripts/prepare-web.sh +++ b/scripts/prepare-web.sh @@ -4,3 +4,4 @@ cd assets/js/ && curl -L 'https://gitlab.com/famedly/company/frontend/libraries/ cd assets/js/ && unzip olm.zip && cd ../../ cd assets/js/ && rm olm.zip && cd ../../ cd assets/js/ && mv javascript package && cd ../../ +dart run sqflite_common_ffi_web:setup --force \ No newline at end of file