From fc6c82838f624050bb0fdd29308ae9fe3e558e26 Mon Sep 17 00:00:00 2001 From: Vitaliy Zarubin Date: Thu, 29 Jun 2023 16:56:10 +0300 Subject: [PATCH] [flutter_example_packages] Add crypto, flutter_secure_storage --- example/lib/l10n/app_en.arb | 10 +- example/lib/l10n/app_ru.arb | 10 +- example/lib/packages/crypto/package.dart | 22 +++ .../flutter_local_notifications/page.dart | 2 +- .../flutter_secure_storage/model.dart | 92 ++++++++++++- .../packages/flutter_secure_storage/page.dart | 130 +++++++++++++++++- example/lib/packages/packages.dart | 3 + .../pages/home/widgets/package_list_item.dart | 2 +- example/pubspec.lock | 72 +++++++++- example/pubspec.yaml | 12 +- .../lib/flutter_secure_storage_aurora.dart | 3 +- 11 files changed, 337 insertions(+), 21 deletions(-) create mode 100644 example/lib/packages/crypto/package.dart diff --git a/example/lib/l10n/app_en.arb b/example/lib/l10n/app_en.arb index e9a9886..dbcc42f 100644 --- a/example/lib/l10n/app_en.arb +++ b/example/lib/l10n/app_en.arb @@ -61,8 +61,14 @@ "flutterLocalNotificationsBtn": "Send", "@_FLUTTER_SECURE_STORAGE": {}, - "flutterSecureStorageTitle": "Title", - "flutterSecureStorageDesc": "Desc", + "flutterSecureStorageSuccess": "Data saved successfully", + "flutterSecureStorageTitleSave": "Save value", + "flutterSecureStorageTitleGet": "Get value", + "flutterSecureStorageFieldPass": "Password", + "flutterSecureStorageFieldKey": "Key", + "flutterSecureStorageFieldValue": "Value", + "flutterSecureStorageBtnSave": "Save value", + "flutterSecureStorageBtnGet": "Get value", "@_PACKAGE_INFO_PLUS": {}, "packageInfoPlusTitlePackageName": "Package", diff --git a/example/lib/l10n/app_ru.arb b/example/lib/l10n/app_ru.arb index 8e1284e..6f795c4 100644 --- a/example/lib/l10n/app_ru.arb +++ b/example/lib/l10n/app_ru.arb @@ -61,8 +61,14 @@ "flutterLocalNotificationsBtn": "Отправить", "@_FLUTTER_SECURE_STORAGE": {}, - "flutterSecureStorageTitle": "Заголовок", - "flutterSecureStorageDesc": "Описание", + "flutterSecureStorageSuccess": "Данные успешно сохранены", + "flutterSecureStorageTitleSave": "Сохранить значение", + "flutterSecureStorageTitleGet": "Получить значение", + "flutterSecureStorageFieldPass": "Пароль", + "flutterSecureStorageFieldKey": "Ключ", + "flutterSecureStorageFieldValue": "Значение", + "flutterSecureStorageBtnSave": "Сохранить значение", + "flutterSecureStorageBtnGet": "Получить значение", "@_PACKAGE_INFO_PLUS": {}, "packageInfoPlusTitlePackageName": "Пакет", diff --git a/example/lib/packages/crypto/package.dart b/example/lib/packages/crypto/package.dart new file mode 100644 index 0000000..55499ef --- /dev/null +++ b/example/lib/packages/crypto/package.dart @@ -0,0 +1,22 @@ +import 'package:flutter_example_packages/base/package/package_dialog.dart'; + +/// Package values +final packageCrypto = PackageDialog( + key: 'crypto', + descEN: ''' + A set of cryptographic hashing functions for Dart. + ''', + descRU: ''' + Набор криптографических функций хеширования для Dart. + ''', + messageEN: ''' + This is a platform independent plugin used in this app, should work + for you too. + ''', + messageRU: ''' + Это плагин независимый от платформы, используется в этом приложении, + должен работать и у вас. + ''', + version: '3.0.2', + isPlatformDependent: false, +); diff --git a/example/lib/packages/flutter_local_notifications/page.dart b/example/lib/packages/flutter_local_notifications/page.dart index 5bd8707..bd5633d 100644 --- a/example/lib/packages/flutter_local_notifications/page.dart +++ b/example/lib/packages/flutter_local_notifications/page.dart @@ -53,7 +53,7 @@ class _FlutterLocalNotificationsPageState hintText: l10n.flutterLocalNotificationsHintTitle, ), ), - const SizedBox(height: 18), + const SizedBox(height: 16), TextField( controller: _bodyController, decoration: InputDecoration( diff --git a/example/lib/packages/flutter_secure_storage/model.dart b/example/lib/packages/flutter_secure_storage/model.dart index 13efa4a..6a12a56 100644 --- a/example/lib/packages/flutter_secure_storage/model.dart +++ b/example/lib/packages/flutter_secure_storage/model.dart @@ -1,10 +1,18 @@ +import 'dart:convert'; + +import 'package:crypto/crypto.dart'; import 'package:flutter/widgets.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:flutter_secure_storage_aurora/flutter_secure_storage_aurora.dart'; import 'package:scoped_model/scoped_model.dart'; /// Model for [FlutterSecureStoragePage] class FlutterSecureStorageModel extends Model { /// Get [ScopedModel] - static FlutterSecureStorageModel of(BuildContext context) => ScopedModel.of(context); + static FlutterSecureStorageModel of(BuildContext context) => + ScopedModel.of(context); + + final _secureStorage = const FlutterSecureStorage(); /// Error String? _error; @@ -14,4 +22,84 @@ class FlutterSecureStorageModel extends Model { /// Public is error bool get isError => _error != null; -} \ No newline at end of file + + /// Save success + bool _isSuccess = false; + + /// Public success + bool get isSuccess => _isSuccess; + + /// Value for read form secure storage + String _readValue = ""; + + /// Public read value + String get readValue => _readValue; + + // Get data from secure storage + Future read({ + required String key, + required String password, + }) async { + try { + // Update secret key + _updateByPassword(password); + // Read data + _readValue = await _secureStorage.read(key: key) ?? "Not found"; + } catch (e) { + _readValue = "Error password"; + } + notifyListeners(); + } + + // Write new data in secure storage + Future write({ + required String key, + required String value, + required String password, + }) async { + try { + // Update secret key + _updateByPassword(password); + // Clear old data + await _secureStorage.deleteAll(); + // Save new data + await _secureStorage.write(key: key, value: value); + // Show success + _isSuccess = true; + // Close success + Future.delayed(const Duration(milliseconds: 1500), () { + _isSuccess = false; + notifyListeners(); + }); + } catch (e) { + _error = e.toString(); + } + notifyListeners(); + } + + /// Update password + void _updateByPassword( + String password, + ) { + // https://pub.dev/packages/encrypt + // Encrypter(AES(key)) + // secure-random --length 16 --base 16 + // You can generate a secret key based on user data, as an example of a hash pin-code + FlutterSecureStorageAurora.setSecret( + _getPasswordFromString(password), + ); + } + + /// Generate secure key 32 length from string password + String _getPasswordFromString( + String password, + ) { + return md5.convert(utf8.encode(password)).toString(); + } + + /// Clear value if change values + void clearReadValue() { + _readValue = ""; + notifyListeners(); + } +} diff --git a/example/lib/packages/flutter_secure_storage/page.dart b/example/lib/packages/flutter_secure_storage/page.dart index 76f308e..d5bbd5f 100644 --- a/example/lib/packages/flutter_secure_storage/page.dart +++ b/example/lib/packages/flutter_secure_storage/page.dart @@ -5,8 +5,8 @@ import 'package:flutter_example_packages/packages/flutter_secure_storage/package import 'package:flutter_example_packages/widgets/base/export.dart'; import 'package:flutter_example_packages/widgets/blocks/block_alert.dart'; import 'package:flutter_example_packages/widgets/blocks/block_info_package.dart'; -import 'package:flutter_example_packages/widgets/blocks/block_item.dart'; import 'package:flutter_example_packages/widgets/layouts/block_layout.dart'; +import 'package:flutter_example_packages/widgets/texts/export.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class FlutterSecureStoragePage extends AppStatefulWidget { @@ -23,6 +23,31 @@ class FlutterSecureStoragePage extends AppStatefulWidget { class _FlutterSecureStoragePageState extends AppState { + bool _isValidSave = false; + final TextEditingController _passSaveController = TextEditingController(); + final TextEditingController _keySaveController = TextEditingController(); + final TextEditingController _valueSaveController = TextEditingController(); + + bool _isValidGet = false; + final TextEditingController _passGetController = TextEditingController(); + final TextEditingController _keyGetController = TextEditingController(); + final TextEditingController _valueGetController = TextEditingController(); + + void _validateSave() { + setState(() { + _isValidSave = _passSaveController.text.isNotEmpty && + _keySaveController.text.isNotEmpty && + _valueSaveController.text.isNotEmpty; + }); + } + + void _validateGet() { + setState(() { + _isValidGet = _passGetController.text.isNotEmpty && + _keyGetController.text.isNotEmpty; + }); + } + @override Widget buildWide( BuildContext context, @@ -32,6 +57,9 @@ class _FlutterSecureStoragePageState return BlockLayout( title: widget.package.key, builder: (context, child, model) { + // update read only value + _valueGetController.text = model.readValue; + // return widget return SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(20), @@ -44,10 +72,102 @@ class _FlutterSecureStoragePageState Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - BlockItem( - title: l10n.flutterSecureStorageTitle, - desc: l10n.flutterSecureStorageDesc, - value: null, + TextTitleLarge(l10n.flutterSecureStorageTitleSave), + const SizedBox(height: 14), + if (model.isSuccess) + BlockAlert( + l10n.flutterSecureStorageSuccess, + color: Colors.lightGreen, + ), + const SizedBox(height: 6), + TextField( + controller: _passSaveController, + decoration: InputDecoration( + labelText: l10n.flutterSecureStorageFieldPass, + ), + onChanged: (_) => _validateSave(), + ), + const SizedBox(height: 16), + TextField( + controller: _keySaveController, + decoration: InputDecoration( + labelText: l10n.flutterSecureStorageFieldKey, + ), + onChanged: (_) => _validateSave(), + ), + const SizedBox(height: 16), + TextField( + controller: _valueSaveController, + decoration: InputDecoration( + labelText: l10n.flutterSecureStorageFieldValue, + ), + onChanged: (_) => _validateSave(), + ), + const SizedBox(height: 20), + SizedBox( + width: double.infinity, + child: ElevatedButton( + onPressed: _isValidSave + ? () => model.write( + key: _keySaveController.text, + value: _valueSaveController.text, + password: _passSaveController.text, + ) + : null, + child: TextBodyLarge( + l10n.flutterSecureStorageBtnSave, + color: Colors.white, + ), + ), + ), + const SizedBox(height: 30), + TextTitleLarge(l10n.flutterSecureStorageTitleGet), + const SizedBox(height: 16), + TextField( + controller: _passGetController, + decoration: InputDecoration( + labelText: l10n.flutterSecureStorageFieldPass, + ), + onChanged: (_) { + _validateGet(); + model.clearReadValue(); + }, + ), + const SizedBox(height: 16), + TextField( + controller: _keyGetController, + decoration: InputDecoration( + labelText: l10n.flutterSecureStorageFieldKey, + ), + onChanged: (_) { + _validateGet(); + model.clearReadValue(); + } + ), + const SizedBox(height: 16), + TextField( + enabled: false, + readOnly: true, + controller: _valueGetController, + decoration: InputDecoration( + labelText: l10n.flutterSecureStorageFieldValue, + ), + ), + const SizedBox(height: 20), + SizedBox( + width: double.infinity, + child: ElevatedButton( + onPressed: _isValidGet + ? () => model.read( + key: _keyGetController.text, + password: _passGetController.text, + ) + : null, + child: TextBodyLarge( + l10n.flutterSecureStorageBtnGet, + color: Colors.white, + ), + ), ), ], ), diff --git a/example/lib/packages/packages.dart b/example/lib/packages/packages.dart index 299810c..4c50c71 100644 --- a/example/lib/packages/packages.dart +++ b/example/lib/packages/packages.dart @@ -18,10 +18,13 @@ import 'package:flutter_example_packages/packages/universal_io/package.dart'; import 'package:flutter_example_packages/packages/wakelock/package.dart'; import 'package:flutter_example_packages/packages/xdga_directories/package.dart'; +import 'crypto/package.dart'; + /// List app packages final packages = [ packageBatteryPlus, packageCachedNetworkImage, + packageCrypto, packageCupertinoIcons, packageDeviceInfoPlus, packageFlutterCacheManager, diff --git a/example/lib/pages/home/widgets/package_list_item.dart b/example/lib/pages/home/widgets/package_list_item.dart index 7250ca9..c4420b5 100644 --- a/example/lib/pages/home/widgets/package_list_item.dart +++ b/example/lib/pages/home/widgets/package_list_item.dart @@ -129,7 +129,7 @@ class PackageListItemWidget extends AppStatelessWidget { child: Padding( padding: const EdgeInsets.only( left: 6, - top: 3, + top: 6, right: 6, bottom: 6, ), diff --git a/example/pubspec.lock b/example/pubspec.lock index 6790108..a19cf96 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -22,6 +22,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.4.1" + asn1lib: + dependency: transitive + description: + name: asn1lib + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.1" async: dependency: transitive description: @@ -156,7 +163,7 @@ packages: source: hosted version: "3.1.1" crypto: - dependency: transitive + dependency: "direct main" description: name: crypto url: "https://pub.dartlang.org" @@ -204,6 +211,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "7.0.0" + encrypt: + dependency: transitive + description: + name: encrypt + url: "https://pub.dartlang.org" + source: hosted + version: "5.0.1" fake_async: dependency: transitive description: @@ -277,6 +291,55 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_secure_storage: + dependency: "direct main" + description: + name: flutter_secure_storage + url: "https://pub.dartlang.org" + source: hosted + version: "8.0.0" + flutter_secure_storage_aurora: + dependency: "direct main" + description: + path: "../packages/flutter_secure_storage/flutter_secure_storage_aurora" + relative: true + source: path + version: "0.0.1" + flutter_secure_storage_linux: + dependency: transitive + description: + name: flutter_secure_storage_linux + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.3" + flutter_secure_storage_macos: + dependency: transitive + description: + name: flutter_secure_storage_macos + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + flutter_secure_storage_platform_interface: + dependency: transitive + description: + name: flutter_secure_storage_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + flutter_secure_storage_web: + dependency: transitive + description: + name: flutter_secure_storage_web + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" + flutter_secure_storage_windows: + dependency: transitive + description: + name: flutter_secure_storage_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" flutter_test: dependency: "direct dev" description: flutter @@ -518,6 +581,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.4" + pointycastle: + dependency: transitive + description: + name: pointycastle + url: "https://pub.dartlang.org" + source: hosted + version: "3.7.3" pool: dependency: transitive description: diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 96c7d1e..fadc126 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -25,6 +25,8 @@ dependencies: intl: ^0.17.0 ## https://pub.dev/packages/universal_io universal_io: ^2.2.0 + ## https://pub.dev/packages/crypto + crypto: ^3.0.2 ## https://os-git.omprussia.ru/non-oss/flutter/flutter-plugins/-/tree/master/packages/xdga_directories xdga_directories: @@ -48,11 +50,11 @@ dependencies: flutter_local_notifications_aurora: path: ../packages/flutter_local_notifications/flutter_local_notifications_aurora -# ## https://pub.dev/packages/flutter_secure_storage -# flutter_secure_storage: ^8.0.0 -# ## https://os-git.omprussia.ru/non-oss/flutter/flutter-plugins/-/tree/master/packages/flutter_secure_storage/flutter_secure_storage_aurora -# flutter_secure_storage_aurora: -# path: ../packages/flutter_secure_storage/flutter_secure_storage_aurora + ## https://pub.dev/packages/flutter_secure_storage + flutter_secure_storage: ^8.0.0 + ## https://os-git.omprussia.ru/non-oss/flutter/flutter-plugins/-/tree/master/packages/flutter_secure_storage/flutter_secure_storage_aurora + flutter_secure_storage_aurora: + path: ../packages/flutter_secure_storage/flutter_secure_storage_aurora ## https://pub.dev/packages/package_info_plus package_info_plus: 4.0.2 diff --git a/packages/flutter_secure_storage/flutter_secure_storage_aurora/lib/flutter_secure_storage_aurora.dart b/packages/flutter_secure_storage/flutter_secure_storage_aurora/lib/flutter_secure_storage_aurora.dart index 7c22f90..a56ce05 100644 --- a/packages/flutter_secure_storage/flutter_secure_storage_aurora/lib/flutter_secure_storage_aurora.dart +++ b/packages/flutter_secure_storage/flutter_secure_storage_aurora/lib/flutter_secure_storage_aurora.dart @@ -22,8 +22,7 @@ class FlutterSecureStorageAurora extends FlutterSecureStoragePlatform { ); } - static void registerWith() async { - PathProviderAurora.registerWith(); + static void registerWith() { FlutterSecureStoragePlatform.instance = FlutterSecureStorageAurora(); }