Browse Source

refactor(neon): reequire unique keys for the storage

Signed-off-by: Nikolas Rimikis <rimikis.nikolas@gmail.com>
pull/674/head
Nikolas Rimikis 1 year ago
parent
commit
198df01bcc
No known key found for this signature in database
GPG Key ID: 85ED1DE9786A4FF2
  1. 8
      packages/neon/neon/lib/src/blocs/accounts.dart
  2. 2
      packages/neon/neon/lib/src/blocs/first_launch.dart
  3. 5
      packages/neon/neon/lib/src/blocs/push_notifications.dart
  4. 2
      packages/neon/neon/lib/src/models/app_implementation.dart
  5. 53
      packages/neon/neon/lib/src/settings/models/storage.dart
  6. 2
      packages/neon/neon/lib/src/utils/global_options.dart
  7. 6
      packages/neon/neon/lib/src/utils/push_utils.dart

8
packages/neon/neon/lib/src/blocs/accounts.dart

@ -58,7 +58,7 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState
this._globalOptions, this._globalOptions,
this._allAppImplementations, this._allAppImplementations,
) { ) {
const lastUsedStorage = SingleValueStorage('last-used-account'); const lastUsedStorage = SingleValueStorage(StorageKeys.lastUsedAccount);
accounts accounts
..add(loadAccounts()) ..add(loadAccounts())
@ -210,7 +210,7 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState
/// Use [activeOptions] to get them for the [activeAccount]. /// Use [activeOptions] to get them for the [activeAccount].
AccountSpecificOptions getOptionsFor(final Account account) => AccountSpecificOptions getOptionsFor(final Account account) =>
_accountsOptions[account.id] ??= AccountSpecificOptions( _accountsOptions[account.id] ??= AccountSpecificOptions(
AppStorage('accounts-${account.id}'), AppStorage(StorageKeys.accounts, account.id),
getAppsBlocFor(account), getAppsBlocFor(account),
); );
@ -281,7 +281,7 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState
/// ///
/// It is not checked whether the stored information is still valid. /// It is not checked whether the stored information is still valid.
List<Account> loadAccounts() { List<Account> loadAccounts() {
const storage = AppStorage('accounts'); const storage = AppStorage(StorageKeys.accounts);
if (storage.containsKey(_keyAccounts)) { if (storage.containsKey(_keyAccounts)) {
return storage return storage
@ -294,7 +294,7 @@ List<Account> loadAccounts() {
/// Saves the given [accounts] to the storage. /// Saves the given [accounts] to the storage.
Future<void> saveAccounts(final List<Account> accounts) async { Future<void> saveAccounts(final List<Account> accounts) async {
const storage = AppStorage('accounts'); const storage = AppStorage(StorageKeys.accounts);
final values = accounts.map((final a) => json.encode(a.toJson())).toList(); final values = accounts.map((final a) => json.encode(a.toJson())).toList();
await storage.setStringList(_keyAccounts, values); await storage.setStringList(_keyAccounts, values);

2
packages/neon/neon/lib/src/blocs/first_launch.dart

@ -17,7 +17,7 @@ class FirstLaunchBloc extends Bloc implements FirstLaunchBlocEvents, FirstLaunch
FirstLaunchBloc({ FirstLaunchBloc({
final bool disabled = false, final bool disabled = false,
}) { }) {
const storage = SingleValueStorage('first-launch'); const storage = SingleValueStorage(StorageKeys.firstLaunch);
if (!disabled && !storage.hasValue()) { if (!disabled && !storage.hasValue()) {
onFirstLaunch.add(null); onFirstLaunch.add(null);

5
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/bloc/bloc.dart';
import 'package:neon/src/blocs/accounts.dart'; import 'package:neon/src/blocs/accounts.dart';
import 'package:neon/src/models/account.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/models/push_notification.dart';
import 'package:neon/src/platform/platform.dart'; import 'package:neon/src/platform/platform.dart';
import 'package:neon/src/settings/models/storage.dart'; import 'package:neon/src/settings/models/storage.dart';
@ -37,7 +36,7 @@ class PushNotificationsBloc extends Bloc implements PushNotificationsBlocEvents,
} }
final AccountsBloc _accountsBloc; final AccountsBloc _accountsBloc;
late final _storage = const AppStorage(AppIDs.notifications); late final _storage = const AppStorage(StorageKeys.notifications);
final GlobalOptions _globalOptions; final GlobalOptions _globalOptions;
final _notificationsController = StreamController<PushNotification>(); final _notificationsController = StreamController<PushNotification>();
@ -69,7 +68,7 @@ class PushNotificationsBloc extends Bloc implements PushNotificationsBlocEvents,
Future _setupUnifiedPush() async { Future _setupUnifiedPush() async {
// We just use a single RSA keypair for all accounts // We just use a single RSA keypair for all accounts
final keypair = await PushUtils.loadRSAKeypair(_storage); final keypair = await PushUtils.loadRSAKeypair();
await UnifiedPush.initialize( await UnifiedPush.initialize(
onNewEndpoint: (final endpoint, final instance) async { onNewEndpoint: (final endpoint, final instance) async {

2
packages/neon/neon/lib/src/models/app_implementation.dart

@ -25,7 +25,7 @@ abstract class AppImplementation<T extends Bloc, R extends NextcloudAppOptions>
String name(final BuildContext context) => nameFromLocalization(AppLocalizations.of(context)); String name(final BuildContext context) => nameFromLocalization(AppLocalizations.of(context));
@protected @protected
late final AppStorage storage = AppStorage('app-$id'); late final AppStorage storage = AppStorage(StorageKeys.apps, id);
@mustBeOverridden @mustBeOverridden
R get options; R get options;

53
packages/neon/neon/lib/src/settings/models/storage.dart

@ -1,4 +1,5 @@
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:neon/src/models/app_ids.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@internal @internal
@ -15,6 +16,21 @@ abstract interface class SettingsStorage {
Future<bool> remove(final String key); Future<bool> 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 @internal
final class NeonStorage { final class NeonStorage {
/// Shared preferences instance. /// Shared preferences instance.
@ -49,36 +65,47 @@ final class NeonStorage {
@immutable @immutable
@internal @internal
final class SingleValueStorage { 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<bool> remove() => NeonStorage.database.remove(_id); Future<bool> 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 // 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<String>? getStringList() => NeonStorage.database.getStringList(_id); List<String>? getStringList() => NeonStorage.database.getStringList(key.value);
Future setStringList(final List<String> value) => NeonStorage.database.setStringList(_id, value); Future setStringList(final List<String> value) => NeonStorage.database.setStringList(key.value, value);
} }
@immutable @immutable
@internal @internal
final class AppStorage implements SettingsStorage { 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)); bool containsKey(final String key) => NeonStorage.database.containsKey(_formatKey(key));

2
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; final PackageInfo _packageInfo;
late final _distributorsMap = <String, String Function(BuildContext)>{ late final _distributorsMap = <String, String Function(BuildContext)>{

6
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:meta/meta.dart';
import 'package:neon/src/blocs/accounts.dart'; import 'package:neon/src/blocs/accounts.dart';
import 'package:neon/src/models/account.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/models/push_notification.dart';
import 'package:neon/src/settings/models/storage.dart'; import 'package:neon/src/settings/models/storage.dart';
import 'package:neon/src/theme/colors.dart'; import 'package:neon/src/theme/colors.dart';
@ -22,7 +21,8 @@ import 'package:nextcloud/nextcloud.dart';
@internal @internal
@immutable @immutable
class PushUtils { class PushUtils {
static Future<RSAKeypair> loadRSAKeypair(final AppStorage storage) async { static Future<RSAKeypair> loadRSAKeypair() async {
const storage = AppStorage(StorageKeys.notifications);
const keyDevicePrivateKey = 'device-private-key'; const keyDevicePrivateKey = 'device-private-key';
late RSAKeypair keypair; late RSAKeypair keypair;
@ -72,7 +72,7 @@ class PushUtils {
); );
await NeonStorage.init(); 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) { for (final message in Uri(query: utf8.decode(messages)).queryParameters.values) {
final data = json.decode(message) as Map<String, dynamic>; final data = json.decode(message) as Map<String, dynamic>;

Loading…
Cancel
Save