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._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<Account> loadAccounts() {
const storage = AppStorage('accounts');
const storage = AppStorage(StorageKeys.accounts);
if (storage.containsKey(_keyAccounts)) {
return storage
@ -294,7 +294,7 @@ List<Account> loadAccounts() {
/// Saves the given [accounts] to the storage.
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();
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({
final bool disabled = false,
}) {
const storage = SingleValueStorage('first-launch');
const storage = SingleValueStorage(StorageKeys.firstLaunch);
if (!disabled && !storage.hasValue()) {
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/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<PushNotification>();
@ -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 {

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));
@protected
late final AppStorage storage = AppStorage('app-$id');
late final AppStorage storage = AppStorage(StorageKeys.apps, id);
@mustBeOverridden
R get options;

53
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<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
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<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
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
@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));

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;
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: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<RSAKeypair> loadRSAKeypair(final AppStorage storage) async {
static Future<RSAKeypair> 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<String, dynamic>;

Loading…
Cancel
Save