fix(linux): crash on no secret service (#608)

This commit is contained in:
Kingkor Roy Tirtho 2023-08-02 15:12:55 +06:00 committed by GitHub
parent f3e7f0d405
commit 888a4b1162
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 96 additions and 19 deletions

View File

@ -1,11 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:spotube/extensions/context.dart';
Future<bool> showPromptDialog({ Future<bool> showPromptDialog({
required BuildContext context, required BuildContext context,
required String title, required String title,
required String message, required String message,
String okText = "Ok", String okText = "Ok",
String cancelText = "Cancel", String? cancelText = "Cancel",
}) async { }) async {
return showDialog<bool>( return showDialog<bool>(
context: context, context: context,
@ -14,12 +15,15 @@ Future<bool> showPromptDialog({
title: Text(title), title: Text(title),
content: Text(message), content: Text(message),
actions: [ actions: [
if (cancelText != null)
OutlinedButton( OutlinedButton(
onPressed: () => Navigator.of(context).pop(false), onPressed: () => Navigator.of(context).pop(false),
child: Text(cancelText), child: Text(
cancelText == "Cancel" ? context.l10n.cancel : cancelText,
),
), ),
FilledButton( FilledButton(
child: Text(okText), child: Text(okText == "Ok" ? context.l10n.ok : okText),
onPressed: () => Navigator.of(context).pop(true), onPressed: () => Navigator.of(context).pop(true),
), ),
], ],

View File

@ -249,5 +249,8 @@
"developers": "ডেভেলপার", "developers": "ডেভেলপার",
"not_logged_in": "আপনি লগইন করা নেই", "not_logged_in": "আপনি লগইন করা নেই",
"search_mode": "অনুসন্ধান মোড", "search_mode": "অনুসন্ধান মোড",
"youtube_api_type": "API প্রকার" "youtube_api_type": "API প্রকার",
"ok": "ঠিক আছে",
"failed_to_encrypt": "এনক্রিপ্ট করা ব্যর্থ হয়েছে",
"encryption_failed_warning": "Spotube আপনার তথ্যগুলি নিরাপদভাবে স্টোর করতে এনক্রিপশন ব্যবহার করে। কিন্তু এটি ব্যর্থ হয়েছে। তাই এটি অনিরাপদ স্টোরে ফলফল হবে\nযদি আপনি Linux ব্যবহার করেন, তবে দয়া করে নিশ্চিত হউন যে আপনার কোনও সিক্রেট-সার্ভিস gnome-keyring, kde-wallet, keepassxc ইত্যাদি ইনস্টল করা আছে"
} }

View File

@ -249,5 +249,8 @@
"developers": "Entwickler", "developers": "Entwickler",
"not_logged_in": "Sie sind nicht angemeldet", "not_logged_in": "Sie sind nicht angemeldet",
"search_mode": "Suchmodus", "search_mode": "Suchmodus",
"youtube_api_type": "API-Typ" "youtube_api_type": "API-Typ",
"ok": "OK",
"failed_to_encrypt": "Verschlüsselung fehlgeschlagen",
"encryption_failed_warning": "Spotube verwendet Verschlüsselung, um Ihre Daten sicher zu speichern. Dies ist jedoch fehlgeschlagen. Daher wird es auf unsichere Speicherung zurückgreifen\nWenn Sie Linux verwenden, stellen Sie bitte sicher, dass Sie Secret-Services wie gnome-keyring, kde-wallet und keepassxc installiert haben"
} }

View File

@ -249,5 +249,8 @@
"developers": "Developers", "developers": "Developers",
"not_logged_in": "You're not logged in", "not_logged_in": "You're not logged in",
"search_mode": "Search Mode", "search_mode": "Search Mode",
"youtube_api_type": "API Type" "youtube_api_type": "API Type",
"ok": "Ok",
"failed_to_encrypt": "Failed to encrypt",
"encryption_failed_warning": "Spotube uses encryption to securely store your data. But failed to do so. So it'll fallback to insecure storage\nIf you're using linux, please make sure you've any secret-service (gnome-keyring, kde-wallet, keepassxc etc) installed"
} }

View File

@ -249,5 +249,8 @@
"developers": "Desarrolladores", "developers": "Desarrolladores",
"not_logged_in": "No has iniciado sesión", "not_logged_in": "No has iniciado sesión",
"search_mode": "Modo de búsqueda", "search_mode": "Modo de búsqueda",
"youtube_api_type": "Tipo de API de YouTube" "youtube_api_type": "Tipo de API de YouTube",
"ok": "OK",
"failed_to_encrypt": "Error al cifrar",
"encryption_failed_warning": "Spotube utiliza el cifrado para almacenar sus datos de forma segura. Pero ha fallado. Por lo tanto, volverá a un almacenamiento no seguro\nSi está utilizando Linux, asegúrese de tener instalados servicios secretos como gnome-keyring, kde-wallet y keepassxc"
} }

View File

@ -249,5 +249,8 @@
"developers": "Développeurs", "developers": "Développeurs",
"not_logged_in": "Vous n'êtes pas connecté(e)", "not_logged_in": "Vous n'êtes pas connecté(e)",
"search_mode": "Mode de recherche", "search_mode": "Mode de recherche",
"youtube_api_type": "Type d'API" "youtube_api_type": "Type d'API",
"ok": "OK",
"failed_to_encrypt": "Échec de la cryptage",
"encryption_failed_warning": "Spotube utilise le cryptage pour stocker vos données en toute sécurité. Mais cela a échoué. Il basculera donc vers un stockage non sécurisé\nSi vous utilisez Linux, assurez-vous d'avoir installé des services secrets tels que gnome-keyring, kde-wallet et keepassxc"
} }

View File

@ -249,5 +249,8 @@
"developers": "डेवलपर्स", "developers": "डेवलपर्स",
"not_logged_in": "आप लॉग इन नहीं हैं", "not_logged_in": "आप लॉग इन नहीं हैं",
"search_mode": "खोज मोड", "search_mode": "खोज मोड",
"youtube_api_type": "API प्रकार" "youtube_api_type": "API प्रकार",
"ok": "ठीक है",
"failed_to_encrypt": "एन्क्रिप्ट करने में विफल रहा",
"encryption_failed_warning": "Spotube आपके डेटा को सुरक्षित रूप से स्टोर करने के लिए एन्क्रिप्शन का उपयोग करता है। लेकिन इसमें विफल रहा। इसलिए, यह असुरक्षित स्टोरेज पर फॉलबैक करेगा\nयदि आप Linux का उपयोग कर रहे हैं, तो कृपया सुनिश्चित करें कि आपके पास gnome-keyring, kde-wallet, keepassxc आदि जैसी कोई सीक्रेट-सर्विस इंस्टॉल की गई है"
} }

View File

@ -249,5 +249,8 @@
"developers": "開発", "developers": "開発",
"not_logged_in": "ログインしていません", "not_logged_in": "ログインしていません",
"search_mode": "検索モード", "search_mode": "検索モード",
"youtube_api_type": "APIの種類" "youtube_api_type": "APIの種類",
"ok": "分かりました",
"failed_to_encrypt": "暗号化に失敗しました",
"encryption_failed_warning": "Spotubeはデータを安全に保存するために暗号化を使用しています。しかし、失敗しました。したがって、安全でないストレージにフォールバックします\nLinuxを使用している場合は、gnome-keyring、kde-wallet、keepassxcなどのシークレットサービスがインストールされていることを確認してください"
} }

View File

@ -249,5 +249,8 @@
"developers": "开发者", "developers": "开发者",
"not_logged_in": "你尚未登录", "not_logged_in": "你尚未登录",
"search_mode": "搜索模式", "search_mode": "搜索模式",
"youtube_api_type": "API 类型" "youtube_api_type": "API 类型",
"ok": "确定",
"failed_to_encrypt": "加密失败",
"encryption_failed_warning": "Spotube使用加密来安全地存储您的数据。但是失败了。因此它将回退到不安全的存储\n如果您使用Linux请确保已安装gnome-keyring、kde-wallet和keepassxc等秘密服务"
} }

View File

@ -5,12 +5,14 @@ import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:spotube/components/shared/dialogs/replace_downloaded_dialog.dart'; import 'package:spotube/components/shared/dialogs/replace_downloaded_dialog.dart';
import 'package:spotube/components/root/bottom_player.dart'; import 'package:spotube/components/root/bottom_player.dart';
import 'package:spotube/components/root/sidebar.dart'; import 'package:spotube/components/root/sidebar.dart';
import 'package:spotube/components/root/spotube_navigation_bar.dart'; import 'package:spotube/components/root/spotube_navigation_bar.dart';
import 'package:spotube/hooks/use_update_checker.dart'; import 'package:spotube/hooks/use_update_checker.dart';
import 'package:spotube/provider/download_manager_provider.dart'; import 'package:spotube/provider/download_manager_provider.dart';
import 'package:spotube/utils/persisted_state_notifier.dart';
const rootPaths = { const rootPaths = {
0: "/", 0: "/",
@ -33,6 +35,17 @@ class RootApp extends HookConsumerWidget {
final showingDialogCompleter = useRef(Completer()..complete()); final showingDialogCompleter = useRef(Completer()..complete());
final downloader = ref.watch(downloadManagerProvider.notifier); final downloader = ref.watch(downloadManagerProvider.notifier);
useEffect(() {
WidgetsBinding.instance.addPostFrameCallback((_) async {
final sharedPreferences = await SharedPreferences.getInstance();
if (sharedPreferences.getBool(kIsUsingEncryption) == false &&
context.mounted) {
await PersistedStateNotifier.showNoEncryptionDialog(context);
}
});
}, []);
useEffect(() { useEffect(() {
downloader.onFileExists = (track) async { downloader.onFileExists = (track) async {
if (!isMounted()) return false; if (!isMounted()) return false;

View File

@ -1,10 +1,14 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/widgets.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:spotube/collections/routes.dart';
import 'package:spotube/components/shared/dialogs/prompt_dialog.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/utils/platform.dart'; import 'package:spotube/utils/platform.dart';
import 'package:spotube/utils/primitive_utils.dart'; import 'package:spotube/utils/primitive_utils.dart';
@ -15,6 +19,8 @@ const secureStorage = FlutterSecureStorage(
); );
const kKeyBoxName = "spotube_box_name"; const kKeyBoxName = "spotube_box_name";
const kNoEncryptionWarningShownKey = "showedNoEncryptionWarning";
const kIsUsingEncryption = "isUsingEncryption";
String getBoxKey(String boxName) => "spotube_box_$boxName"; String getBoxKey(String boxName) => "spotube_box_$boxName";
abstract class PersistedStateNotifier<T> extends StateNotifier<T> { abstract class PersistedStateNotifier<T> extends StateNotifier<T> {
@ -34,12 +40,36 @@ abstract class PersistedStateNotifier<T> extends StateNotifier<T> {
static late LazyBox _box; static late LazyBox _box;
static late LazyBox _encryptedBox; static late LazyBox _encryptedBox;
static Future<void> showNoEncryptionDialog(BuildContext context) async {
final localStorage = await SharedPreferences.getInstance();
final wasShownAlready =
localStorage.getBool(kNoEncryptionWarningShownKey) == true;
if (wasShownAlready || !context.mounted) {
return;
}
await showPromptDialog(
context: context,
title: context.l10n.failed_to_encrypt,
message: context.l10n.encryption_failed_warning,
cancelText: null,
);
await localStorage.setBool(kNoEncryptionWarningShownKey, true);
}
static Future<String?> read(String key) async { static Future<String?> read(String key) async {
final localStorage = await SharedPreferences.getInstance(); final localStorage = await SharedPreferences.getInstance();
if (kIsMacOS || kIsIOS) { if (kIsMacOS || kIsIOS) {
return localStorage.getString(key); return localStorage.getString(key);
} else { } else {
return secureStorage.read(key: key); try {
await localStorage.setBool(kIsUsingEncryption, true);
return await secureStorage.read(key: key);
} catch (e) {
await localStorage.setBool(kIsUsingEncryption, false);
return localStorage.getString(key);
}
} }
} }
@ -49,7 +79,13 @@ abstract class PersistedStateNotifier<T> extends StateNotifier<T> {
await localStorage.setString(key, value); await localStorage.setString(key, value);
return; return;
} else { } else {
return secureStorage.write(key: key, value: value); try {
await localStorage.setBool(kIsUsingEncryption, true);
await secureStorage.write(key: key, value: value);
} catch (e) {
await localStorage.setBool(kIsUsingEncryption, false);
await localStorage.setString(key, value);
}
} }
} }