From 198df01bcc261afafc898d4c4fa0e8e5d434413d Mon Sep 17 00:00:00 2001 From: Nikolas Rimikis Date: Tue, 29 Aug 2023 17:13:34 +0200 Subject: [PATCH] refactor(neon): reequire unique keys for the storage Signed-off-by: Nikolas Rimikis --- .../neon/neon/lib/src/blocs/accounts.dart | 8 +-- .../neon/neon/lib/src/blocs/first_launch.dart | 2 +- .../lib/src/blocs/push_notifications.dart | 5 +- .../lib/src/models/app_implementation.dart | 2 +- .../neon/lib/src/settings/models/storage.dart | 53 ++++++++++++++----- .../neon/lib/src/utils/global_options.dart | 2 +- .../neon/neon/lib/src/utils/push_utils.dart | 6 +-- 7 files changed, 52 insertions(+), 26 deletions(-) diff --git a/packages/neon/neon/lib/src/blocs/accounts.dart b/packages/neon/neon/lib/src/blocs/accounts.dart index 02b4a6d3..a8ad92b1 100644 --- a/packages/neon/neon/lib/src/blocs/accounts.dart +++ b/packages/neon/neon/lib/src/blocs/accounts.dart @@ -58,7 +58,7 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState this._globalOptions, this._allAppImplementations, ) { - const lastUsedStorage = SingleValueStorage('last-used-account'); + const lastUsedStorage = SingleValueStorage(StorageKeys.lastUsedAccount); accounts ..add(loadAccounts()) @@ -210,7 +210,7 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState /// Use [activeOptions] to get them for the [activeAccount]. AccountSpecificOptions getOptionsFor(final Account account) => _accountsOptions[account.id] ??= AccountSpecificOptions( - AppStorage('accounts-${account.id}'), + AppStorage(StorageKeys.accounts, account.id), getAppsBlocFor(account), ); @@ -281,7 +281,7 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState /// /// It is not checked whether the stored information is still valid. List loadAccounts() { - const storage = AppStorage('accounts'); + const storage = AppStorage(StorageKeys.accounts); if (storage.containsKey(_keyAccounts)) { return storage @@ -294,7 +294,7 @@ List loadAccounts() { /// Saves the given [accounts] to the storage. Future saveAccounts(final List accounts) async { - const storage = AppStorage('accounts'); + const storage = AppStorage(StorageKeys.accounts); final values = accounts.map((final a) => json.encode(a.toJson())).toList(); await storage.setStringList(_keyAccounts, values); diff --git a/packages/neon/neon/lib/src/blocs/first_launch.dart b/packages/neon/neon/lib/src/blocs/first_launch.dart index bcf83f8b..056e9378 100644 --- a/packages/neon/neon/lib/src/blocs/first_launch.dart +++ b/packages/neon/neon/lib/src/blocs/first_launch.dart @@ -17,7 +17,7 @@ class FirstLaunchBloc extends Bloc implements FirstLaunchBlocEvents, FirstLaunch FirstLaunchBloc({ final bool disabled = false, }) { - const storage = SingleValueStorage('first-launch'); + const storage = SingleValueStorage(StorageKeys.firstLaunch); if (!disabled && !storage.hasValue()) { onFirstLaunch.add(null); diff --git a/packages/neon/neon/lib/src/blocs/push_notifications.dart b/packages/neon/neon/lib/src/blocs/push_notifications.dart index 7e3c6698..a1fde3fd 100644 --- a/packages/neon/neon/lib/src/blocs/push_notifications.dart +++ b/packages/neon/neon/lib/src/blocs/push_notifications.dart @@ -6,7 +6,6 @@ import 'package:meta/meta.dart'; import 'package:neon/src/bloc/bloc.dart'; import 'package:neon/src/blocs/accounts.dart'; import 'package:neon/src/models/account.dart'; -import 'package:neon/src/models/app_ids.dart'; import 'package:neon/src/models/push_notification.dart'; import 'package:neon/src/platform/platform.dart'; import 'package:neon/src/settings/models/storage.dart'; @@ -37,7 +36,7 @@ class PushNotificationsBloc extends Bloc implements PushNotificationsBlocEvents, } final AccountsBloc _accountsBloc; - late final _storage = const AppStorage(AppIDs.notifications); + late final _storage = const AppStorage(StorageKeys.notifications); final GlobalOptions _globalOptions; final _notificationsController = StreamController(); @@ -69,7 +68,7 @@ class PushNotificationsBloc extends Bloc implements PushNotificationsBlocEvents, Future _setupUnifiedPush() async { // We just use a single RSA keypair for all accounts - final keypair = await PushUtils.loadRSAKeypair(_storage); + final keypair = await PushUtils.loadRSAKeypair(); await UnifiedPush.initialize( onNewEndpoint: (final endpoint, final instance) async { diff --git a/packages/neon/neon/lib/src/models/app_implementation.dart b/packages/neon/neon/lib/src/models/app_implementation.dart index 4628d10d..1051a571 100644 --- a/packages/neon/neon/lib/src/models/app_implementation.dart +++ b/packages/neon/neon/lib/src/models/app_implementation.dart @@ -25,7 +25,7 @@ abstract class AppImplementation String name(final BuildContext context) => nameFromLocalization(AppLocalizations.of(context)); @protected - late final AppStorage storage = AppStorage('app-$id'); + late final AppStorage storage = AppStorage(StorageKeys.apps, id); @mustBeOverridden R get options; diff --git a/packages/neon/neon/lib/src/settings/models/storage.dart b/packages/neon/neon/lib/src/settings/models/storage.dart index ab4fc105..76575fc8 100644 --- a/packages/neon/neon/lib/src/settings/models/storage.dart +++ b/packages/neon/neon/lib/src/settings/models/storage.dart @@ -1,4 +1,5 @@ import 'package:meta/meta.dart'; +import 'package:neon/src/models/app_ids.dart'; import 'package:shared_preferences/shared_preferences.dart'; @internal @@ -15,6 +16,21 @@ abstract interface class SettingsStorage { Future remove(final String key); } +@internal +enum StorageKeys { + apps._('app'), + accounts._('accounts'), + global._('global'), + lastUsedAccount._('last-used-account'), + lastEndpoint._('last-endpoint'), + firstLaunch._('first-launch'), + notifications._(AppIDs.notifications); + + const StorageKeys._(this.value); + + final String value; +} + @internal final class NeonStorage { /// Shared preferences instance. @@ -49,36 +65,47 @@ final class NeonStorage { @immutable @internal final class SingleValueStorage { - const SingleValueStorage(this._id); + const SingleValueStorage(this.key); - final String _id; + final StorageKeys key; - bool hasValue() => NeonStorage.database.containsKey(_id); + bool hasValue() => NeonStorage.database.containsKey(key.value); - Future remove() => NeonStorage.database.remove(_id); + Future remove() => NeonStorage.database.remove(key.value); - String? getString() => NeonStorage.database.getString(_id); + String? getString() => NeonStorage.database.getString(key.value); - Future setString(final String value) => NeonStorage.database.setString(_id, value); + Future setString(final String value) => NeonStorage.database.setString(key.value, value); - bool? getBool() => NeonStorage.database.getBool(_id); + bool? getBool() => NeonStorage.database.getBool(key.value); // ignore: avoid_positional_boolean_parameters - Future setBool(final bool value) => NeonStorage.database.setBool(_id, value); + Future setBool(final bool value) => NeonStorage.database.setBool(key.value, value); - List? getStringList() => NeonStorage.database.getStringList(_id); + List? getStringList() => NeonStorage.database.getStringList(key.value); - Future setStringList(final List value) => NeonStorage.database.setStringList(_id, value); + Future setStringList(final List value) => NeonStorage.database.setStringList(key.value, value); } @immutable @internal final class AppStorage implements SettingsStorage { - const AppStorage(this._id); + const AppStorage( + this.key, [ + this.suffix, + ]); + + final StorageKeys key; - final String _id; + final String? suffix; - String _formatKey(final String key) => '$_id-$key'; + String _formatKey(final String key) { + if (suffix != null) { + return '${this.key.value}-$suffix-$key'; + } + + return '${this.key.value}-$key'; + } bool containsKey(final String key) => NeonStorage.database.containsKey(_formatKey(key)); diff --git a/packages/neon/neon/lib/src/utils/global_options.dart b/packages/neon/neon/lib/src/utils/global_options.dart index 9319b927..ca31d8c5 100644 --- a/packages/neon/neon/lib/src/utils/global_options.dart +++ b/packages/neon/neon/lib/src/utils/global_options.dart @@ -49,7 +49,7 @@ class GlobalOptions { } } - late final AppStorage _storage = const AppStorage('global'); + late final AppStorage _storage = const AppStorage(StorageKeys.global); final PackageInfo _packageInfo; late final _distributorsMap = { diff --git a/packages/neon/neon/lib/src/utils/push_utils.dart b/packages/neon/neon/lib/src/utils/push_utils.dart index 1ee1121e..35b7cd1a 100644 --- a/packages/neon/neon/lib/src/utils/push_utils.dart +++ b/packages/neon/neon/lib/src/utils/push_utils.dart @@ -11,7 +11,6 @@ import 'package:image/image.dart' as img; import 'package:meta/meta.dart'; import 'package:neon/src/blocs/accounts.dart'; import 'package:neon/src/models/account.dart'; -import 'package:neon/src/models/app_ids.dart'; import 'package:neon/src/models/push_notification.dart'; import 'package:neon/src/settings/models/storage.dart'; import 'package:neon/src/theme/colors.dart'; @@ -22,7 +21,8 @@ import 'package:nextcloud/nextcloud.dart'; @internal @immutable class PushUtils { - static Future loadRSAKeypair(final AppStorage storage) async { + static Future loadRSAKeypair() async { + const storage = AppStorage(StorageKeys.notifications); const keyDevicePrivateKey = 'device-private-key'; late RSAKeypair keypair; @@ -72,7 +72,7 @@ class PushUtils { ); await NeonStorage.init(); - final keypair = await loadRSAKeypair(const AppStorage(AppIDs.notifications)); + final keypair = await loadRSAKeypair(); for (final message in Uri(query: utf8.decode(messages)).queryParameters.values) { final data = json.decode(message) as Map;