diff --git a/sqflite/example/assets/example_pass_1234.db b/sqflite/example/assets/example_pass_1234.db new file mode 100644 index 00000000..557ada3b Binary files /dev/null and b/sqflite/example/assets/example_pass_1234.db differ diff --git a/sqflite/example/lib/main.dart b/sqflite/example/lib/main.dart index 6131f8ba..c35fc77b 100644 --- a/sqflite/example/lib/main.dart +++ b/sqflite/example/lib/main.dart @@ -8,6 +8,7 @@ import 'package:sqflite_example/deprecated_test_page.dart'; import 'package:sqflite_example/exception_test_page.dart'; import 'package:sqflite_example/exp_test_page.dart'; import 'package:sqflite_example/manual_test_page.dart'; +import 'package:sqflite_example/sqlcipher_test_page.dart'; import 'package:sqflite_example/src/dev_utils.dart'; import 'model/main_item.dart'; @@ -29,6 +30,7 @@ class MyApp extends StatefulWidget { _MyAppState createState() => _MyAppState(); } +const String testSqlCipherRoute = "/test/sqlcipher"; const String testRawRoute = "/test/simple"; const String testOpenRoute = "/test/open"; const String testSlowRoute = "/test/slow"; @@ -43,6 +45,7 @@ const String testDeprecatedRoute = "/test/deprecated"; class _MyAppState extends State { var routes = { '/test': (BuildContext context) => MyHomePage(), + testSqlCipherRoute: (BuildContext context) => SqlCipherTestPage(), testRawRoute: (BuildContext context) => RawTestPage(), testOpenRoute: (BuildContext context) => OpenTestPage(), testSlowRoute: (BuildContext context) => SlowTestPage(), @@ -78,6 +81,8 @@ class _MyAppState extends State { class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key) { + items.add( + MainItem("Sqlcipher tests", "Simple tests with an encrypted database", route: testSqlCipherRoute)); items.add( MainItem("Raw tests", "Raw SQLite operations", route: testRawRoute)); items.add(MainItem("Open tests", "Open onCreate/onUpgrade/onDowngrade", diff --git a/sqflite/example/lib/open_test_page.dart b/sqflite/example/lib/open_test_page.dart index a9c3e3ac..c7448573 100644 --- a/sqflite/example/lib/open_test_page.dart +++ b/sqflite/example/lib/open_test_page.dart @@ -91,11 +91,11 @@ class OpenCallbacks { /// Check if a file is a valid database file /// /// An empty file is a valid empty sqlite file -Future isDatabase(String path) async { +Future isDatabase(String path, {String password}) async { Database db; bool isDatabase = false; try { - db = await openReadOnlyDatabase(path); + db = await openReadOnlyDatabase(path, password: password); int version = await db.getVersion(); if (version != null) { isDatabase = true; diff --git a/sqflite/example/lib/sqlcipher_test_page.dart b/sqflite/example/lib/sqlcipher_test_page.dart new file mode 100644 index 00000000..f7a39528 --- /dev/null +++ b/sqflite/example/lib/sqlcipher_test_page.dart @@ -0,0 +1,79 @@ +import 'dart:io'; + +import 'package:flutter/services.dart'; +import 'package:path/path.dart'; +import 'package:sqflite/sqflite.dart'; +import 'package:sqflite_example/open_test_page.dart'; + +import 'test_page.dart'; + +class SqlCipherTestPage extends TestPage { + SqlCipherTestPage() : super("SqlCipher tests") { + test('Open and query database', () async { + String path = await initDeleteDb("encrypted.db"); + + expect(await isDatabase(path), isFalse); + + const String password = "1234"; + + Database db = await openDatabase( + path, + password: password, + version: 1, + onCreate: (db, version) async { + Batch batch = db.batch(); + + batch + .execute("CREATE TABLE Test (id INTEGER PRIMARY KEY, text NAME)"); + await batch.commit(); + }, + ); + + try { + expect( + await db.rawInsert("INSERT INTO Test (text) VALUES (?)", ['test']), + 1); + var result = await db.query("Test"); + List expected = [ + {'id': 1, 'text': 'test'} + ]; + expect(result, expected); + + expect(await isDatabase(path, password: password), isTrue); + } finally { + await db?.close(); + } + expect(await isDatabase(path, password: password), isTrue); + }); + + test("Open asset database", () async { + var databasesPath = await getDatabasesPath(); + String path = join(databasesPath, "asset_example.db"); + + // delete existing if any + await deleteDatabase(path); + + // Make sure the parent directory exists + try { + await Directory(dirname(path)).create(recursive: true); + } catch (_) {} + + // Copy from asset + ByteData data = await rootBundle.load(join("assets", "example_pass_1234.db")); + List bytes = + data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); + // Write and flush the bytes written + await File(path).writeAsBytes(bytes, flush: true); + + // open the database + Database db = await openDatabase(path, password: "1234"); + + // Our database as a single table with a single element + List> list = await db.rawQuery("SELECT * FROM Test"); + print("list $list"); + expect(list.first["name"], "simple value"); + + await db.close(); + }); + } +} diff --git a/sqflite/example/pubspec.yaml b/sqflite/example/pubspec.yaml index 62bcb870..32613767 100644 --- a/sqflite/example/pubspec.yaml +++ b/sqflite/example/pubspec.yaml @@ -3,7 +3,7 @@ description: Demonstrates how to use the sqflite plugin. publish_to: none environment: - sdk: ">=2.1.0-dev <3.0.0" + sdk: '>=2.5.0 <3.0.0' dependencies: path: any @@ -11,9 +11,7 @@ dependencies: flutter: sdk: flutter sqflite: - git: - url: git://github.com/tekartik/sqflite - path: sqflite + path: ../ dev_dependencies: @@ -44,6 +42,7 @@ flutter: # - images/a_dot_ham.jpeg assets: - assets/example.db + - assets/example_pass_1234.db - assets/issue_64.db dependency_overrides: diff --git a/sqflite/lib/sqlite_api.dart b/sqflite/lib/sqlite_api.dart index 492222b0..2f6bd68a 100644 --- a/sqflite/lib/sqlite_api.dart +++ b/sqflite/lib/sqlite_api.dart @@ -294,6 +294,7 @@ abstract class OpenDatabaseOptions { /// Called after all other callbacks have been called. OnDatabaseOpenFn onOpen; + /// Database password (optional) String password; /// Open the database in read-only mode (no callback called). diff --git a/sqflite/lib/src/constant.dart b/sqflite/lib/src/constant.dart index 180ff073..9cd70c3e 100644 --- a/sqflite/lib/src/constant.dart +++ b/sqflite/lib/src/constant.dart @@ -92,7 +92,7 @@ const String paramVersion = "version"; /// The database id (int) const String paramId = "id"; -// When opening the database (String) (optional) +/// When opening the database (String) (optional) const String paramPassword = "password"; /// True if the database is in a transaction