From d0b93581b214de88c5a344a1a153992e45634460 Mon Sep 17 00:00:00 2001 From: itsscb Date: Sat, 11 Nov 2023 01:10:45 +0100 Subject: [PATCH] ft/adds registration and secure_storage [alpha] --- frontend/app/android/app/build.gradle | 2 +- frontend/app/lib/main.dart | 80 ++++++- .../lib/model/services/backend_service.dart | 2 +- .../lib/model/services/storage_service.dart | 84 +++++++ .../app/lib/pages/notifications_page.dart | 19 +- frontend/app/lib/pages/password_page.dart | 219 ++++++++++++++++++ frontend/app/lib/pages/registration_page.dart | 146 ++++++++---- frontend/app/lib/pages/verify_email_page.dart | 110 +++++++++ frontend/app/lib/util/colors.dart | 2 +- frontend/app/lib/util/enums.dart | 0 frontend/app/lib/util/validation.dart | 2 +- .../flutter/generated_plugin_registrant.cc | 4 + .../app/linux/flutter/generated_plugins.cmake | 1 + frontend/app/pubspec.lock | 133 +++++++++++ frontend/app/pubspec.yaml | 1 + .../flutter/generated_plugin_registrant.cc | 3 + .../windows/flutter/generated_plugins.cmake | 1 + 17 files changed, 757 insertions(+), 52 deletions(-) create mode 100644 frontend/app/lib/model/services/storage_service.dart create mode 100644 frontend/app/lib/pages/password_page.dart create mode 100644 frontend/app/lib/pages/verify_email_page.dart create mode 100644 frontend/app/lib/util/enums.dart diff --git a/frontend/app/android/app/build.gradle b/frontend/app/android/app/build.gradle index d6f6037..98ea8be 100644 --- a/frontend/app/android/app/build.gradle +++ b/frontend/app/android/app/build.gradle @@ -45,7 +45,7 @@ android { applicationId "com.example.app" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdkVersion flutter.minSdkVersion + minSdkVersion 18 targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/frontend/app/lib/main.dart b/frontend/app/lib/main.dart index 47be75a..a8e16d2 100644 --- a/frontend/app/lib/main.dart +++ b/frontend/app/lib/main.dart @@ -1,5 +1,10 @@ +import 'package:app/model/services/auth_service.dart'; +import 'package:app/model/services/storage_service.dart'; +import 'package:app/pages/notifications_page.dart'; import 'package:app/pages/start_page.dart'; -import 'package:app/pages_draft/home_page.dart'; +import 'package:app/pages/verify_email_page.dart'; +import 'package:app/pages/registration_page.dart'; +import 'package:app/util/colors.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart' show GlobalMaterialLocalizations; @@ -47,7 +52,78 @@ void main() async { backgroundColor: Colors.black, foregroundColor: Colors.white, )), - home: StartPage(), + home: const DigitalerFrieden(), ), ); } + +class DigitalerFrieden extends StatefulWidget { + const DigitalerFrieden({super.key}); + + @override + State createState() => _DigitalerFriedenState(); +} + +class _DigitalerFriedenState extends State { + final StorageService _storageService = StorageService(); + int? accountLevel; + bool? authenticated; + bool _loading = true; + @override + void initState() { + _init(); + super.initState(); + } + + void _init() async { + accountLevel = await _storageService.accountLevel; + print(accountLevel!); + if (accountLevel! > 0) { + authenticated = await AuthService.authenticateWithBiometrics(); + } + _loading = false; + setState(() {}); + } + + @override + Widget build(BuildContext context) { + if (_loading) { + return Center( + child: Column( + children: [ + Image.asset( + 'assets/JPEG.jpg', + height: 180, + ), + CircularProgressIndicator( + color: CustomColors.primary, + ), + ], + ), + ); + } + if (accountLevel == null || accountLevel == 0) { + return const StartPage(); + } + // else if (authenticated == null) { + // AuthService.authenticateWithBiometrics().then((value) { + // setState(() { + // authenticated = value; + // }); + // }); + // } + + switch (accountLevel) { + case null: + return const StartPage(); + case < 1: + return NotificationsPage(); + case 1: + return const RegistrationPage(); + case 2: + return VerifyEmailPage(); + default: + return const StartPage(); + } + } +} diff --git a/frontend/app/lib/model/services/backend_service.dart b/frontend/app/lib/model/services/backend_service.dart index a0c8cb8..8cec418 100644 --- a/frontend/app/lib/model/services/backend_service.dart +++ b/frontend/app/lib/model/services/backend_service.dart @@ -131,7 +131,7 @@ class BackendService { } on SocketException { throw FetchDataException('Keine Internet Verbindung'); } on GrpcError catch (err) { - throw FetchDataException(err.message); + throw FetchDataException('${err.message}'); } catch (err) { throw InternalException(err.toString()); } diff --git a/frontend/app/lib/model/services/storage_service.dart b/frontend/app/lib/model/services/storage_service.dart new file mode 100644 index 0000000..dd3bc88 --- /dev/null +++ b/frontend/app/lib/model/services/storage_service.dart @@ -0,0 +1,84 @@ +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; + +class StorageItem { + StorageItem(this.key, this.value); + + final String key; + final String value; +} + +class StorageService { + final _secureStorage = const FlutterSecureStorage( + aOptions: AndroidOptions( + encryptedSharedPreferences: true, + ), + ); + + Future writeData(StorageItem item) async { + await _secureStorage.write( + key: item.key, + value: item.value, + ); + } + + Future readData(String key) async { + return await _secureStorage.read(key: key); + } + + Future> readAllSecureData() async { + var allData = await _secureStorage.readAll(); + List list = + allData.entries.map((e) => StorageItem(e.key, e.value)).toList(); + return list; + } + + Future containsData(String key) async { + return await _secureStorage.containsKey(key: key); + } + + Future deleteSecureData(StorageItem item) async { + await _secureStorage.delete( + key: item.key, + ); + } + + Future deleteAllSecureData() async { + await _secureStorage.deleteAll(); + } + + Future setNotificationSetting(bool enabled) async { + return await writeData(StorageItem('notifications', enabled ? '1' : '0')); + } + + Future get notificationSetting async { + final enabled = await readData('notifications') == '1' ? true : false; + return enabled; + } + + Future get accountLevel async { + int? level; + final l = await readData('account_level'); + if (l != null) { + level = int.tryParse(l); + } + return level ?? 0; + } + + Future setAccountLevel(int level) async { + return await writeData(StorageItem('account_level', '$level')); + } + + Future initAccountLevel() async { + return await writeData(StorageItem('account_level', '0')); + } + + Future addAccountLevel() async { + int? level; + final l = await readData('account_level'); + if (l != null) { + level = int.tryParse(l); + } + return await writeData( + StorageItem('account_level', '${level != null ? level + 1 : 1}')); + } +} diff --git a/frontend/app/lib/pages/notifications_page.dart b/frontend/app/lib/pages/notifications_page.dart index 91b2a4e..582b3ee 100644 --- a/frontend/app/lib/pages/notifications_page.dart +++ b/frontend/app/lib/pages/notifications_page.dart @@ -1,9 +1,21 @@ +import 'package:app/model/services/storage_service.dart'; import 'package:app/pages/registration_page.dart'; import 'package:app/util/colors.dart'; import 'package:flutter/material.dart'; class NotificationsPage extends StatelessWidget { - const NotificationsPage({super.key}); + NotificationsPage({super.key}); + + final StorageService _storageService = StorageService(); + + void _setNotificationSetting(bool enabled) { + _storageService.addAccountLevel(); + _storageService.setNotificationSetting(enabled).then( + (x) => _storageService.notificationSetting.then( + (value) => print('notifications: $value'), + ), + ); + } @override Widget build(BuildContext context) { @@ -60,6 +72,7 @@ class NotificationsPage extends StatelessWidget { backgroundColor: CustomColors.primary, ), onPressed: () { + _setNotificationSetting(true); Navigator.push( context, MaterialPageRoute( @@ -88,7 +101,9 @@ class NotificationsPage extends StatelessWidget { height: 10, ), TextButton( - onPressed: () {}, + onPressed: () { + _setNotificationSetting(false); + }, child: Text( 'Später', style: TextStyle(color: CustomColors.primary), diff --git a/frontend/app/lib/pages/password_page.dart b/frontend/app/lib/pages/password_page.dart new file mode 100644 index 0000000..39f7225 --- /dev/null +++ b/frontend/app/lib/pages/password_page.dart @@ -0,0 +1,219 @@ +import 'package:app/model/services/storage_service.dart'; +import 'package:app/model/view_model/base_vm.dart'; +import 'package:app/pages/verify_email_page.dart'; +import 'package:app/util/colors.dart'; +import 'package:flutter/material.dart'; +import 'package:app/util/validation.dart'; + +class PasswordPage extends StatefulWidget { + PasswordPage({super.key, required this.email, required this.register}); + + final String email; + final bool register; + + @override + State createState() => _PasswordPageState(); +} + +class _PasswordPageState extends State { + final BaseViewModel _vm = BaseViewModel(); + final StorageService _storageService = StorageService(); + final _formKey = GlobalKey(); + final _passwordController1 = TextEditingController(); + + final _passwordController2 = TextEditingController(); + + bool _validPassword = false; + + bool _passwordsFilled = false; + + bool _showPassword1 = false; + bool _showPassword2 = false; + + @override + void dispose() { + _passwordController1.dispose(); + _passwordController2.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + iconTheme: IconThemeData( + color: CustomColors.primary, + ), + ), + body: Padding( + padding: const EdgeInsets.all(20.0), + child: Form( + key: _formKey, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'Sichere dein Konto mit einem Passwort', + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'sans-serif', + fontWeight: FontWeight.bold, + letterSpacing: 2.0, + fontSize: 25, + ), + ), + const SizedBox( + height: 60, + ), + TextFormField( + controller: _passwordController1, + autocorrect: false, + autofocus: true, + keyboardType: TextInputType.visiblePassword, + obscureText: !_showPassword1, + autovalidateMode: AutovalidateMode.always, + decoration: InputDecoration( + suffixIcon: IconButton( + onPressed: () { + setState(() { + _showPassword1 = !_showPassword1; + }); + }, + icon: Icon(_showPassword1 + ? Icons.remove_red_eye + : Icons.remove_red_eye_outlined)), + label: const Text('Passwort'), + filled: true, + ), + validator: (value) { + if (value == null || !value.isValidPassword) { + _validPassword = false; + return 'Mindestens 12 Zeichen, Zahlen, Sonderzeichen (-_?!=.,*+), Groß- & Kleinbuchstaben'; + } else { + _validPassword = true; + return null; + } + }, + onChanged: (value) { + _formKey.currentState?.validate(); + if (!value.isValidPassword) { + setState(() { + _validPassword = false; + }); + } else { + setState(() { + _validPassword = true; + }); + } + }, + ), + const SizedBox( + height: 20, + ), + AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + child: !_validPassword + ? null + : TextFormField( + controller: _passwordController2, + keyboardType: TextInputType.visiblePassword, + obscureText: !_showPassword2, + decoration: InputDecoration( + suffixIcon: IconButton( + onPressed: () { + setState(() { + _showPassword2 = !_showPassword2; + }); + }, + icon: Icon(_showPassword2 + ? Icons.remove_red_eye + : Icons.remove_red_eye_outlined)), + label: const Text('Passwort bestätigen'), + filled: true, + ), + validator: (value) { + if (_passwordController1.text != + _passwordController2.text) { + setState(() { + _passwordsFilled = false; + }); + return 'Passwörter stimmen nicht überein'; + } else { + setState(() { + _passwordsFilled = true; + }); + return null; + } + }, + onTap: () => _formKey.currentState?.validate(), + onChanged: (value) { + _formKey.currentState?.validate(); + if (_passwordController1.text != + _passwordController2.text) { + setState(() { + _passwordsFilled = false; + }); + } else { + setState(() { + _passwordsFilled = true; + }); + } + }, + ), + ), + const SizedBox( + height: 20, + ), + AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + child: !_passwordsFilled || + _passwordController1.text != _passwordController2.text + ? null + : ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: CustomColors.primary, + ), + onPressed: _validPassword && _passwordsFilled + ? () async { + if (_formKey.currentState!.validate()) { + final navigator = Navigator.of(context); + final loggedin = await _vm.createAccount( + context, + email: widget.email, + password: _passwordController1.text, + ); + if (loggedin && mounted) { + _storageService.addAccountLevel(); + navigator.push( + MaterialPageRoute( + builder: (builder) => VerifyEmailPage(), + ), + ); + } + } + } + : null, + child: const SizedBox( + height: 50, + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Registrierung abschließen', + style: TextStyle( + fontSize: 20, + ), + ), + ], + ), + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/frontend/app/lib/pages/registration_page.dart b/frontend/app/lib/pages/registration_page.dart index feff349..1477d6a 100644 --- a/frontend/app/lib/pages/registration_page.dart +++ b/frontend/app/lib/pages/registration_page.dart @@ -1,10 +1,25 @@ -import 'package:app/pages_old/start_page.dart'; +import 'package:app/pages/password_page.dart'; import 'package:app/util/colors.dart'; +import 'package:app/util/validation.dart'; import 'package:flutter/material.dart'; -class RegistrationPage extends StatelessWidget { +class RegistrationPage extends StatefulWidget { const RegistrationPage({super.key}); + @override + State createState() => _RegistrationPageState(); +} + +class _RegistrationPageState extends State { + final formKey = GlobalKey(); + final mailController = TextEditingController(); + + @override + void dispose() { + mailController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return SafeArea( @@ -42,56 +57,99 @@ class RegistrationPage extends StatelessWidget { const SizedBox( height: 20, ), - const Text( - 'Du kannst die Mitteilungen jederzeit wieder deaktivieren.', - textAlign: TextAlign.center, - ), - const Spacer( - flex: 2, - ), - Hero( - tag: 'flow-button', - child: ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: CustomColors.primary, - ), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (builder) => StartPage(), - // builder: (builder) => SecurityPage(), + Form( + key: formKey, + child: Column( + children: [ + TextFormField( + autocorrect: false, + autofocus: true, + controller: mailController, + keyboardType: TextInputType.emailAddress, + decoration: const InputDecoration( + helperText: 'test', + label: Text('E-Mail Adresse'), + filled: true, ), - ); - }, - child: const SizedBox( - height: 60, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Mitteilungen erhalten', - style: TextStyle( - fontSize: 20, - ), - ), - ], + validator: (value) { + if (value == null || !value.isValidEmail) { + return 'Bitte eine valide E-Mail Adresse angeben'; + } else { + return null; + } + }, ), - ), + ], ), ), const SizedBox( - height: 10, + height: 20, ), - TextButton( - onPressed: () {}, - child: Text( - 'Später', - style: TextStyle(color: CustomColors.primary), - ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + onPressed: () { + if (formKey.currentState!.validate()) { + Navigator.push( + context, + MaterialPageRoute( + builder: (builder) => PasswordPage( + email: mailController.text, + register: false, + ), + ), + ); + } + }, + child: Text( + 'Stattdessen anmelden', + // textAlign: TextAlign.center, + style: TextStyle( + color: CustomColors.primary, + ), + ), + ), + Hero( + tag: 'flow-button', + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: CustomColors.primary, + ), + onPressed: () { + if (formKey.currentState!.validate()) { + Navigator.push( + context, + MaterialPageRoute( + builder: (builder) => PasswordPage( + email: mailController.text, + register: true, + ), + ), + ); + } + }, + child: const SizedBox( + height: 50, + width: 100, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Weiter', + style: TextStyle( + fontSize: 20, + ), + ), + ], + ), + ), + ), + ), + ], ), const Spacer( - flex: 1, + flex: 2, ), ], ), diff --git a/frontend/app/lib/pages/verify_email_page.dart b/frontend/app/lib/pages/verify_email_page.dart new file mode 100644 index 0000000..156cbf3 --- /dev/null +++ b/frontend/app/lib/pages/verify_email_page.dart @@ -0,0 +1,110 @@ +import 'package:app/util/colors.dart'; +import 'package:flutter/material.dart'; + +class VerifyEmailPage extends StatelessWidget { + VerifyEmailPage({super.key}); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Scaffold( + appBar: AppBar( + iconTheme: IconThemeData( + color: CustomColors.primary, + ), + ), + body: Padding( + padding: const EdgeInsets.fromLTRB(20, 20, 20, 16), + child: Column( + // mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox( + height: 80, + ), + const Text( + 'Verifizieren', + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'sans-serif', + fontWeight: FontWeight.bold, + letterSpacing: 2.0, + fontSize: 25, + ), + ), + const SizedBox( + height: 50, + ), + const Text( + 'Wir haben dir eine E-Mail geschickt.', + textAlign: TextAlign.center, + // textAlign: TextAlign.center, + ), + const SizedBox( + height: 20, + ), + const Text( + 'Bitte verifiziere deine E-Mail Adresse, dann geht es weiter.', + textAlign: TextAlign.center, + // textAlign: TextAlign.center, + ), + const SizedBox( + height: 80, + ), + Hero( + tag: 'flow-button', + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: CustomColors.primary, + ), + onPressed: () {}, + child: const SizedBox( + height: 50, + width: 100, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Weiter', + style: TextStyle( + fontSize: 20, + ), + ), + ], + ), + ), + ), + ), + const SizedBox( + height: 60, + ), + const Text( + 'Noch keine E-Mail erhalten?', + // textAlign: TextAlign.center, + ), + const Text( + 'Schon im Spam-Ordner nachgeschaut?', + // textAlign: TextAlign.center, + ), + const SizedBox( + height: 20, + ), + TextButton( + onPressed: () {}, + child: Text( + 'Erneut senden', + // textAlign: TextAlign.center, + style: TextStyle( + color: CustomColors.primary, + ), + ), + ), + const Spacer( + flex: 2, + ), + ], + ), + ), + ), + ); + } +} diff --git a/frontend/app/lib/util/colors.dart b/frontend/app/lib/util/colors.dart index 475a476..3000db3 100644 --- a/frontend/app/lib/util/colors.dart +++ b/frontend/app/lib/util/colors.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; class CustomColors { static Color get error { - return const Color.fromARGB(200, 255, 90, 90); + return const Color.fromARGB(255, 255, 82, 82); } static Color get success { diff --git a/frontend/app/lib/util/enums.dart b/frontend/app/lib/util/enums.dart new file mode 100644 index 0000000..e69de29 diff --git a/frontend/app/lib/util/validation.dart b/frontend/app/lib/util/validation.dart index bc20152..10f779c 100644 --- a/frontend/app/lib/util/validation.dart +++ b/frontend/app/lib/util/validation.dart @@ -2,7 +2,7 @@ final emailRegExp = RegExp(r"^[a-zA-Z0-9.]+@[a-zA-Z0-9]+\.[a-zA-Z]+"); final nameRegExp = RegExp(r"^\s*([A-Za-z]{1,}([\.,] |[-']| ))+[A-Za-z]+\.?\s*$"); final phoneRegExp = RegExp(r"^\+?0[0-9]{10}$"); -final passwordRegExp = RegExp(r'^.+$'); +final passwordRegExp = RegExp(r'^[0-9a-zA-Z\-\_\.\,\*\+\=?!]{12,64}$'); extension valString on String { bool get isValidEmail { diff --git a/frontend/app/linux/flutter/generated_plugin_registrant.cc b/frontend/app/linux/flutter/generated_plugin_registrant.cc index e71a16d..d0e7f79 100644 --- a/frontend/app/linux/flutter/generated_plugin_registrant.cc +++ b/frontend/app/linux/flutter/generated_plugin_registrant.cc @@ -6,6 +6,10 @@ #include "generated_plugin_registrant.h" +#include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); + flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); } diff --git a/frontend/app/linux/flutter/generated_plugins.cmake b/frontend/app/linux/flutter/generated_plugins.cmake index 2e1de87..b29e9ba 100644 --- a/frontend/app/linux/flutter/generated_plugins.cmake +++ b/frontend/app/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + flutter_secure_storage_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/frontend/app/pubspec.lock b/frontend/app/pubspec.lock index 9d8b480..e313442 100644 --- a/frontend/app/pubspec.lock +++ b/frontend/app/pubspec.lock @@ -89,6 +89,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + url: "https://pub.dev" + source: hosted + version: "2.1.0" fixnum: dependency: "direct main" description: @@ -123,11 +131,64 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.17" + flutter_secure_storage: + dependency: "direct main" + description: + name: flutter_secure_storage + sha256: ffdbb60130e4665d2af814a0267c481bcf522c41ae2e43caf69fa0146876d685 + url: "https://pub.dev" + source: hosted + version: "9.0.0" + flutter_secure_storage_linux: + dependency: transitive + description: + name: flutter_secure_storage_linux + sha256: "3d5032e314774ee0e1a7d0a9f5e2793486f0dff2dd9ef5a23f4e3fb2a0ae6a9e" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + flutter_secure_storage_macos: + dependency: transitive + description: + name: flutter_secure_storage_macos + sha256: bd33935b4b628abd0b86c8ca20655c5b36275c3a3f5194769a7b3f37c905369c + url: "https://pub.dev" + source: hosted + version: "3.0.1" + flutter_secure_storage_platform_interface: + dependency: transitive + description: + name: flutter_secure_storage_platform_interface + sha256: "0d4d3a5dd4db28c96ae414d7ba3b8422fd735a8255642774803b2532c9a61d7e" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + flutter_secure_storage_web: + dependency: transitive + description: + name: flutter_secure_storage_web + sha256: "30f84f102df9dcdaa2241866a958c2ec976902ebdaa8883fbfe525f1f2f3cf20" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + flutter_secure_storage_windows: + dependency: transitive + description: + name: flutter_secure_storage_windows + sha256: "5809c66f9dd3b4b93b0a6e2e8561539405322ee767ac2f64d084e2ab5429d108" + url: "https://pub.dev" + source: hosted + version: "3.0.0" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" googleapis_auth: dependency: transitive description: @@ -272,6 +333,62 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.3" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + url: "https://pub.dev" + source: hosted + version: "2.1.1" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + url: "https://pub.dev" + source: hosted + version: "2.3.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + url: "https://pub.dev" + source: hosted + version: "2.2.1" + platform: + dependency: transitive + description: + name: platform + sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59" + url: "https://pub.dev" + source: hosted + version: "3.1.3" plugin_platform_interface: dependency: transitive description: @@ -405,6 +522,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.1.4-beta" + win32: + dependency: transitive + description: + name: win32 + sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" + url: "https://pub.dev" + source: hosted + version: "5.0.9" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2" + url: "https://pub.dev" + source: hosted + version: "1.0.3" sdks: dart: ">=3.1.4 <4.0.0" flutter: ">=3.10.0" diff --git a/frontend/app/pubspec.yaml b/frontend/app/pubspec.yaml index 928928a..7b5cda3 100644 --- a/frontend/app/pubspec.yaml +++ b/frontend/app/pubspec.yaml @@ -47,6 +47,7 @@ dependencies: fixnum: ^1.1.0 provider: ^6.0.5 intl: ^0.18.1 + flutter_secure_storage: ^9.0.0 dev_dependencies: lints: ^2.0.0 diff --git a/frontend/app/windows/flutter/generated_plugin_registrant.cc b/frontend/app/windows/flutter/generated_plugin_registrant.cc index 7407ddd..011734d 100644 --- a/frontend/app/windows/flutter/generated_plugin_registrant.cc +++ b/frontend/app/windows/flutter/generated_plugin_registrant.cc @@ -6,9 +6,12 @@ #include "generated_plugin_registrant.h" +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { + FlutterSecureStorageWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); LocalAuthPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("LocalAuthPlugin")); } diff --git a/frontend/app/windows/flutter/generated_plugins.cmake b/frontend/app/windows/flutter/generated_plugins.cmake index ef187dc..11485fc 100644 --- a/frontend/app/windows/flutter/generated_plugins.cmake +++ b/frontend/app/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + flutter_secure_storage_windows local_auth_windows )