davidmartos96 / sqflite_sqlcipher

SQLite flutter plugin
BSD 2-Clause "Simplified" License
99 stars 44 forks source link

usage with the sqflite_common api? #43

Closed ramsestom closed 3 years ago

ramsestom commented 3 years ago

Trying to use sqflite_sqlcipheras a replacment of sqflitein a third party library that uses the sqflite_common api to open a databse It uses the DatabaseFactory.openDatabase(String path, {OpenDatabaseOptions? options}); method to open the database. So is it possible to pass the password field to this function as an option?

Here is the code of the function used to open a database:

Future<sqflite.Database> open(String path, List<Migration> migrations, [Callback? callback, String? password]) async {
    final databaseOptions = sqflite.OpenDatabaseOptions(
      version: 1,
      onConfigure: (database) async {
        await database.execute('PRAGMA foreign_keys = ON');
        await callback?.onConfigure?.call(database);
      },
      onOpen: (database) async {
        await callback?.onOpen?.call(database);
      },
      onUpgrade: (database, startVersion, endVersion) async {
        await MigrationAdapter.runMigrations(
            database, startVersion, endVersion, migrations);

        await callback?.onUpgrade?.call(database, startVersion, endVersion);
      },
      onCreate: (database, version) async {
        await database.execute(
            'CREATE TABLE IF NOT EXISTS `Task` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `message` TEXT NOT NULL)');

        await callback?.onCreate?.call(database, version);
      },
    );
    return sqfliteDatabaseFactory.openDatabase(path, options: databaseOptions);
  }

I added it the optional String? password parameter but now I would like to pass it along to the DatabaseFactory.openDatabase() sqflite_common API function

davidmartos96 commented 3 years ago

@ramsestom What do you mean? Could you give an example? You can use the sqflite functionality API after having opened the encrypted database.

ramsestom commented 3 years ago

@davidmartos96 Sorry I miss-pressed the enter key before typing my first comment ;) I edited it

davidmartos96 commented 3 years ago

@ramsestom Doing that you are basically reimplementing the Dart side of sqflite_sqlcipher. Under the hood this package uses sqflite_common and has a databaseFactory that returns an encrypted Database. Any reason for not using the openDatabase method from sqflite_sqlcipher directly?

davidmartos96 commented 3 years ago

Take a look at this file: https://www.github.com/davidmartos96/sqflite_sqlcipher/tree/master/sqflite%2Flib%2Fsrc%2Fdatabase_sql_cipher_impl.dart

As you can see, the password is injected in the openDatabase platform channel method.

ramsestom commented 3 years ago

Does the openDatabasemethod from sqflite_sqlcipher have an OpenDatabaseOptions options optional parameter?

davidmartos96 commented 3 years ago

@ramsestom No, that would be the factory. This is what gets called underneath openDatabase:

image

In any case, note that even if you used the sqflite_common API for SQLCipher, you would be missing the native implementation (android, ios and macos). Also, SQLCipher is a superset of SQLite, so you can open normal databases (without encryption) with SQLCipher. I don't yet quite understand the situation. I think you can simply swap the sqflite dependency.

davidmartos96 commented 3 years ago

@ramsestom Sorry, I didn't see the code above, now I understand better. I think you could use the sqfliteSqlCipherDatabase factory (https://pub.dev/documentation/sqflite_sqlcipher/latest/sqflite/databaseFactory.html) and the SqlCipherOpenDatabaseOptions which is a subclass of the regular Options (https://pub.dev/documentation/sqflite_sqlcipher/latest/sqlite_api/SqlCipherOpenDatabaseOptions-class.html)

But, note that if you are building a general solution for migrations, you need the SqlCipher native library. Importing sqflite_sqlcipher would be enough for it to work

ramsestom commented 3 years ago

OK the factory use a String? password option field so writting it in my databaseOptions object should just work fine ;)

to clarify the situation: I already swaped the sqflite dependency in the third part library (https://github.com/vitusortner/floor) I want to migrate to sqflite_sqlcipher. But the code of this lib is relying on calling the sqflite_common api to connect to the database (because it uses as DatabaseFactory the SqfliteDatabaseFactory from sqflite for Android and iOS and another one for desktop platforms. So my problem was just to know how to pass the password option field to the SqfliteDatabaseFactory from sqflite_sqlcipher that would replace the SqfliteDatabaseFactory from sqflite. But you gave me the solution with the code you pasted

ramsestom commented 3 years ago

Is there a way to declare sqflite_sqlcipher as if it where a packaged name sqflite in my pubspec.yaml so I don't have to modify every sqflite import to sqflite_sqlcipher in my third party library code?

davidmartos96 commented 3 years ago

@ramsestom I don't think there is, but you can do a good old find and replace :sweat_smile:

davidmartos96 commented 3 years ago

On a side note, if you are looking for desktop support check out the following post. https://github.com/davidmartos96/sqflite_sqlcipher/issues/42

Maybe you don't need this library at all.