57 lines
2.4 KiB
Dart
57 lines
2.4 KiB
Dart
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
|
|
/// Keychain access group shared between the Runner and the (Phase 3) iOS
|
|
/// Notification Service Extension so the NSE can read the RSA private key,
|
|
/// the server public key and the Nextcloud app password to decrypt pushes
|
|
/// while the app is not running.
|
|
///
|
|
/// A team-prefixed keychain access group (`$(AppIdentifierPrefix)eu.mhsl…push`)
|
|
/// listed under `keychain-access-groups` in both the Runner and the NSE
|
|
/// entitlements. The literal `MY55VF3KPG.` prefix is the team's stable
|
|
/// AppIdentifierPrefix; Runner and NSE share the group because they sign with
|
|
/// the same team. (App-group ids like `group.*` can't be used here because the
|
|
/// Xcode-managed profiles only grant `<TeamID>.*` keychain groups.)
|
|
/// On Android `groupId` is ignored, so this is a no-op there.
|
|
const String kPushKeychainGroup =
|
|
'MY55VF3KPG.eu.mhsl.marianum.mobile.client.push';
|
|
|
|
/// [IOSOptions] used for every push-related secure-storage entry. Uses
|
|
/// `first_unlock` accessibility so the NSE can read the key material after the
|
|
/// first device unlock following a reboot (the NSE may run while locked).
|
|
const IOSOptions kPushIosOptions = IOSOptions(
|
|
groupId: kPushKeychainGroup,
|
|
accessibility: KeychainAccessibility.first_unlock,
|
|
);
|
|
|
|
/// Shared secure storage instance for all push key material and registration
|
|
/// bookkeeping. Kept separate from [AccountData]'s default storage because the
|
|
/// entries here are group-scoped for NSE access.
|
|
const FlutterSecureStorage pushSecureStorage = FlutterSecureStorage(
|
|
iOptions: kPushIosOptions,
|
|
);
|
|
|
|
/// Minimal storage contract so tests can inject an in-memory fake instead of
|
|
/// touching the platform keystore.
|
|
abstract class FlutterSecureStorageLike {
|
|
Future<String?> read({required String key});
|
|
Future<void> write({required String key, required String? value});
|
|
Future<void> delete({required String key});
|
|
}
|
|
|
|
/// Default [FlutterSecureStorageLike] backed by [pushSecureStorage].
|
|
class PushSecureStorage implements FlutterSecureStorageLike {
|
|
const PushSecureStorage();
|
|
|
|
@override
|
|
Future<String?> read({required String key}) =>
|
|
pushSecureStorage.read(key: key);
|
|
|
|
@override
|
|
Future<void> write({required String key, required String? value}) =>
|
|
pushSecureStorage.write(key: key, value: value);
|
|
|
|
@override
|
|
Future<void> delete({required String key}) =>
|
|
pushSecureStorage.delete(key: key);
|
|
}
|