diff --git a/assets/translations/en.json b/assets/translations/en.json index 42178a89..8cb0235a 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -39,6 +39,16 @@ "generate_key": "Generate key", "generate_key_text": "You can generate ssh key", "console": "Console", + "remove": "Remove", + "enable": "Enable", + "ok": "ok", + "continue": "Continue", + "ssh_key_exist_text": "You have generated ssh key", + "yes_delete": "Yes, delete my SSH key", + "share": "Share", + "copy_buffer": "Copy to buffer", + "copied_ssh": "SSH copied to clipboard", + "delete_ssh_text": "Delete SSH key?", "about_app_page": { "text": "Application version v.{}" }, diff --git a/assets/translations/ru.json b/assets/translations/ru.json index ac731421..855adf60 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -39,6 +39,16 @@ "create_ssh_key": "Создать ssh ключ", "generate_key": "Сгенерировать ключ", "generate_key_text": "Вы сможете сгенерировать ключ", + "remove": "Отключить", + "enable": "Включить", + "ok": "ok", + "continue": "Продолжить", + "ssh_key_exist_text": "У вас уже есть сгенерированный ssk ключ", + "yes_delete": "Да, удалить", + "share": "Поделиться", + "copy_buffer": "Копировать в буфер", + "copied_ssh": "SSH копировано в буфер", + "delete_ssh_text": "Удалить SSH ключ?", "about_app_page": { "text": "Версия приложения: v.{}" }, diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 373cec68..7eefa660 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -2,6 +2,8 @@ PODS: - Flutter (1.0.0) - flutter_secure_storage (3.3.1): - Flutter + - local_auth (0.0.1): + - Flutter - package_info (0.0.1): - Flutter - path_provider (0.0.1): @@ -18,6 +20,7 @@ PODS: DEPENDENCIES: - Flutter (from `Flutter`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) + - local_auth (from `.symlinks/plugins/local_auth/ios`) - package_info (from `.symlinks/plugins/package_info/ios`) - path_provider (from `.symlinks/plugins/path_provider/ios`) - share_plus (from `.symlinks/plugins/share_plus/ios`) @@ -30,6 +33,8 @@ EXTERNAL SOURCES: :path: Flutter flutter_secure_storage: :path: ".symlinks/plugins/flutter_secure_storage/ios" + local_auth: + :path: ".symlinks/plugins/local_auth/ios" package_info: :path: ".symlinks/plugins/package_info/ios" path_provider: @@ -46,6 +51,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec + local_auth: 25938960984c3a7f6e3253e3f8d962fdd16852bd package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62 path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 9140ef0c..106017ec 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -361,6 +361,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = UVNTKR53DD; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -499,6 +500,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = UVNTKR53DD; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -529,6 +531,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = UVNTKR53DD; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png index 1e296c4f..fb07346c 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png index dff68e1d..c9e0c452 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png index af5f0604..93c986fb 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png index 7da4d77f..6cffb871 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png index 856c5156..9e785db5 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png index ce53aa9f..17a096ee 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png index 0495ef99..622fae1d 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png index af5f0604..93c986fb 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png index bb04514b..e5c3c043 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png index abf56f6c..5f7802aa 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png index c95dfa17..4382a3b6 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png index 8b55ab5b..bae4d5c1 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png index 23e713a5..cfb62108 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png index caf8cb40..565fd300 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/ios/build/Pods.build/Release-iphonesimulator/local_auth.build/dgph b/ios/build/Pods.build/Release-iphonesimulator/local_auth.build/dgph new file mode 100644 index 00000000..0c4ca337 Binary files /dev/null and b/ios/build/Pods.build/Release-iphonesimulator/local_auth.build/dgph differ diff --git a/lib/config/hive_config.dart b/lib/config/hive_config.dart index be47b879..a9659869 100644 --- a/lib/config/hive_config.dart +++ b/lib/config/hive_config.dart @@ -24,6 +24,7 @@ class HiveConfig { var cipher = HiveAesCipher(await getEncriptedKey(BNames.key)); await Hive.openBox(BNames.appConfig, encryptionCipher: cipher); + var sshCipher = HiveAesCipher(await getEncriptedKey(BNames.sshEnckey)); await Hive.openBox(BNames.sshConfig, encryptionCipher: sshCipher); } diff --git a/lib/logic/api_maps/server.dart b/lib/logic/api_maps/server.dart index 6e5686f6..18807b90 100644 --- a/lib/logic/api_maps/server.dart +++ b/lib/logic/api_maps/server.dart @@ -33,7 +33,7 @@ class ServerApi extends ApiMap { var client = await getClient(); try { - response = await client.get('/serviceStatus'); + response = await client.get('/services/status'); res = response.statusCode == HttpStatus.ok; } catch (e) { res = false; @@ -49,7 +49,7 @@ class ServerApi extends ApiMap { var client = await getClient(); try { response = await client.post( - '/createUser', + '/users/create', options: Options( headers: { "X-User": user.login, @@ -78,7 +78,7 @@ class ServerApi extends ApiMap { var client = await getClient(); try { response = await client.get( - '/apply', + '/system/configuration/apply', ); res = response.statusCode == HttpStatus.ok; diff --git a/lib/logic/get_it/ssh_helper.dart b/lib/logic/get_it/ssh_helper.dart index 46ded1a6..1d9ce416 100644 --- a/lib/logic/get_it/ssh_helper.dart +++ b/lib/logic/get_it/ssh_helper.dart @@ -1,5 +1,3 @@ -import 'dart:developer'; - import 'package:hive/hive.dart'; import 'package:pointycastle/pointycastle.dart'; import 'package:rsa_encrypt/rsa_encrypt.dart'; @@ -30,4 +28,12 @@ class SSHModel { savedPrivateKey = _box.get(BNames.sshPrivateKey); savedPubKey = _box.get(BNames.sshPublicKey); } + + bool get isSSHKeyGenerated => savedPrivateKey != null && savedPubKey != null; + + clear() async { + savedPrivateKey = null; + savedPubKey = null; + await _box.clear(); + } } diff --git a/lib/ui/pages/more/app_settings/app_setting.dart b/lib/ui/pages/more/app_settings/app_setting.dart index a9a15c99..a5c50108 100644 --- a/lib/ui/pages/more/app_settings/app_setting.dart +++ b/lib/ui/pages/more/app_settings/app_setting.dart @@ -119,7 +119,7 @@ class _AppSettingsPageState extends State { ], ), ), - // deleteServer(context) + deleteServer(context) ], ), ); diff --git a/lib/ui/pages/more/more.dart b/lib/ui/pages/more/more.dart index da9b116a..93473b7c 100644 --- a/lib/ui/pages/more/more.dart +++ b/lib/ui/pages/more/more.dart @@ -1,11 +1,16 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:ionicons/ionicons.dart'; import 'package:selfprivacy/config/brand_colors.dart'; import 'package:selfprivacy/config/brand_theme.dart'; +import 'package:selfprivacy/config/get_it_config.dart'; import 'package:selfprivacy/config/text_themes.dart'; import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart'; +import 'package:selfprivacy/logic/get_it/ssh_helper.dart'; import 'package:selfprivacy/logic/models/job.dart'; import 'package:selfprivacy/logic/models/state_types.dart'; +import 'package:selfprivacy/ui/components/action_button/action_button.dart'; +import 'package:selfprivacy/ui/components/brand_alert/brand_alert.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; @@ -17,6 +22,7 @@ import 'package:selfprivacy/ui/pages/onboarding/onboarding.dart'; import 'package:selfprivacy/ui/pages/rootRoute.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart'; import 'package:easy_localization/easy_localization.dart'; +import 'package:share_plus/share_plus.dart'; import 'about/about.dart'; import 'app_settings/app_setting.dart'; @@ -79,19 +85,66 @@ class MorePage extends StatelessWidget { title: 'more.create_ssh_key'.tr(), iconData: Ionicons.key_outline, onTap: () { - showDialog( - context: context, - builder: (BuildContext context) { - return _MoreDetails( - title: 'more.create_ssh_key'.tr(), - icon: Ionicons.key_outline, - onTap: () { - jobsCubit.createShhJobIfNotExist(CreateSSHKeyJob()); - }, - text: 'more.generate_key_text'.tr(), - ); - }, - ); + if (getIt().isSSHKeyGenerated) { + showDialog( + context: context, + builder: (BuildContext context) { + return _SSHExitsDetails( + onShareTap: () { + Share.share(getIt().savedPrivateKey!); + }, + onDeleteTap: () { + showDialog( + context: context, + builder: (_) { + return BrandAlert( + title: 'modals.3'.tr(), + contentText: 'more.delete_ssh_text'.tr(), + acitons: [ + ActionButton( + text: 'more.yes_delete'.tr(), + isRed: true, + onPressed: () { + getIt().clear(); + Navigator.of(context).pop(); + }), + ActionButton( + text: 'basis.cancel'.tr(), + ), + ], + ); + }, + ); + }, + onCopyTap: () { + Clipboard.setData(ClipboardData( + text: getIt().savedPrivateKey!)); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('more.copied_ssh'.tr()), + duration: const Duration(seconds: 2), + ), + ); + }, + ); + }, + ); + } else { + showDialog( + context: context, + builder: (BuildContext context) { + return _MoreDetails( + title: 'more.create_ssh_key'.tr(), + icon: Ionicons.key_outline, + onTap: () { + jobsCubit + .createShhJobIfNotExist(CreateSSHKeyJob()); + }, + text: 'more.generate_key_text'.tr(), + ); + }, + ); + } }, ), ], @@ -103,6 +156,83 @@ class MorePage extends StatelessWidget { } } +class _SSHExitsDetails extends StatelessWidget { + const _SSHExitsDetails({ + Key? key, + required this.onDeleteTap, + required this.onShareTap, + required this.onCopyTap, + }) : super(key: key); + final Function onDeleteTap; + final Function onShareTap; + final Function onCopyTap; + + @override + Widget build(BuildContext context) { + var textStyle = body1Style.copyWith( + color: Theme.of(context).brightness == Brightness.dark + ? Colors.white + : BrandColors.black); + return Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + child: SingleChildScrollView( + child: Container( + width: 350, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Padding( + padding: paddingH15V30, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + SizedBox(height: 10), + Text( + 'more.ssh_key_exist_text'.tr(), + style: textStyle, + ), + SizedBox(height: 10), + Container( + child: BrandButton.text( + onPressed: () { + Navigator.of(context).pop(); + onShareTap(); + }, + title: 'more.share'.tr(), + ), + ), + Container( + alignment: Alignment.centerLeft, + child: BrandButton.text( + onPressed: () { + Navigator.of(context).pop(); + onDeleteTap(); + }, + title: 'basis.delete'.tr(), + ), + ), + Container( + child: BrandButton.text( + onPressed: () { + Navigator.of(context).pop(); + onCopyTap(); + }, + title: 'more.copy_buffer'.tr(), + ), + ), + ], + ), + ) + ], + ), + ), + ), + ); + } +} + class _MoreDetails extends StatelessWidget { const _MoreDetails({ Key? key, diff --git a/pubspec.lock b/pubspec.lock index 944a7ea6..903ec020 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -333,6 +333,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.6.5" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" flutter_secure_storage: dependency: "direct main" description: @@ -469,6 +476,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.1.4" + local_auth: + dependency: "direct main" + description: + name: local_auth + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.7" logging: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index e3ed9839..504d4387 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -38,6 +38,7 @@ dependencies: pointycastle: ^3.3.2 rsa_encrypt: ^2.0.0 ssh_key: ^0.7.0 + local_auth: ^1.1.7 dev_dependencies: flutter_test: