added guardian login with views for their assigned childs
This commit is contained in:
@@ -3,7 +3,6 @@ import 'dart:io';
|
||||
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:nextcloud/notifications.dart' show generatePushTokenHash;
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
|
||||
import '../api/demo/demo_mode.dart';
|
||||
import '../api/marianumcloud/app_password/delete_app_password.dart';
|
||||
@@ -11,9 +10,12 @@ import '../api/marianumcloud/app_password/get_app_password.dart';
|
||||
import '../api/marianumconnect/marianumconnect_endpoint.dart';
|
||||
import '../api/marianumconnect/queries/push_device_register/push_device_register.dart';
|
||||
import '../api/marianumconnect/queries/push_device_unregister/push_device_unregister.dart';
|
||||
import '../model/account_data.dart';
|
||||
import '../model/endpoint_data.dart';
|
||||
import '../session/nextcloud_credentials.dart';
|
||||
import '../session/session_manager.dart';
|
||||
import 'direct_push_registration.dart';
|
||||
import 'nextcloud_push_api.dart';
|
||||
import 'push_device_info.dart';
|
||||
import 'push_keypair.dart';
|
||||
import 'push_registration_store.dart';
|
||||
import 'push_registration_type.dart';
|
||||
@@ -48,8 +50,6 @@ class PushRegistration {
|
||||
_store = store ?? const PushRegistrationStore(),
|
||||
_nextcloud = nextcloud ?? NextcloudPushApi();
|
||||
|
||||
String get _platform => Platform.isIOS ? 'ios' : 'android';
|
||||
|
||||
String get _talkUserAgent =>
|
||||
Platform.isIOS ? talkUserAgentIos : talkUserAgentAndroid;
|
||||
|
||||
@@ -63,20 +63,29 @@ class PushRegistration {
|
||||
/// slash) — persisted alongside the registration to detect endpoint changes.
|
||||
String get currentNcBaseUrl => 'https://${EndpointData().nextcloud().full()}';
|
||||
|
||||
NextcloudCredentials? get _nextcloudOrNull =>
|
||||
SessionManager().current?.nextcloud;
|
||||
|
||||
/// Channel for sessions without Nextcloud; see [DirectPushRegistration].
|
||||
static const _direct = DirectPushRegistration();
|
||||
|
||||
/// Ensures the Nextcloud app password exists (idempotent, best-effort). Push
|
||||
/// registration binds to it, so it must be obtained before registering.
|
||||
Future<void> ensureAppPassword() async {
|
||||
if (AccountData().hasAppPassword()) return;
|
||||
if (AccountData().usesLoginFlow) {
|
||||
final nextcloud = _nextcloudOrNull;
|
||||
if (nextcloud == null || nextcloud.hasAppPassword) return;
|
||||
if (nextcloud.usesLoginFlow) {
|
||||
// Flow-Konten (2FA): Basic Auth mit dem echten Passwort wird abgelehnt,
|
||||
// stilles Minting ist unmöglich. Reparatur nur interaktiv über
|
||||
// Einstellungen → „Nextcloud neu verbinden".
|
||||
log('Push: login-flow account without app password, cannot mint silently');
|
||||
log(
|
||||
'Push: login-flow account without app password, cannot mint silently',
|
||||
);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final appPassword = await GetAppPassword().run();
|
||||
await AccountData().setAppPassword(appPassword);
|
||||
await SessionManager().setAppPassword(appPassword);
|
||||
} on Object catch (e) {
|
||||
log('Push: could not obtain app password (non-blocking): $e');
|
||||
}
|
||||
@@ -85,15 +94,16 @@ class PushRegistration {
|
||||
/// Ensures the second app password backing the Talk registration exists
|
||||
/// (each `getapppassword` call with the real password mints a fresh one).
|
||||
Future<void> ensureTalkAppPassword() async {
|
||||
if (AccountData().hasAppPasswordTalk()) return;
|
||||
final nextcloud = _nextcloudOrNull;
|
||||
if (nextcloud == null || nextcloud.hasAppPasswordTalk) return;
|
||||
// Flow-Konten können still kein zweites App-Passwort münzen — das
|
||||
// Talk-Passwort kommt nur aus dem zweiten Login-Flow-Durchlauf; bis dahin
|
||||
// teilt sich die Talk-Registrierung das eine App-Passwort (siehe
|
||||
// AccountData.getTalkBasicAuthHeader).
|
||||
if (AccountData().usesLoginFlow) return;
|
||||
// NextcloudCredentials.talkBasicAuthHeader).
|
||||
if (nextcloud.usesLoginFlow) return;
|
||||
try {
|
||||
final appPassword = await GetAppPassword().run();
|
||||
await AccountData().setAppPasswordTalk(appPassword);
|
||||
await SessionManager().setAppPasswordTalk(appPassword);
|
||||
} on Object catch (e) {
|
||||
log('Push: could not obtain talk app password (non-blocking): $e');
|
||||
}
|
||||
@@ -107,6 +117,7 @@ class PushRegistration {
|
||||
/// fire-and-forget (and simply ignore the result).
|
||||
Future<bool> register() async {
|
||||
if (DemoMode.active) return false;
|
||||
if (_nextcloudOrNull == null) return _direct.register();
|
||||
final String? fcmToken;
|
||||
try {
|
||||
fcmToken = await FirebaseMessaging.instance.getToken();
|
||||
@@ -134,16 +145,13 @@ class PushRegistration {
|
||||
return false;
|
||||
}
|
||||
|
||||
String? appVersion;
|
||||
try {
|
||||
appVersion = (await PackageInfo.fromPlatform()).version;
|
||||
} on Object {
|
||||
appVersion = null;
|
||||
}
|
||||
final appVersion = await pushAppVersion();
|
||||
|
||||
// Re-read: the ensure* calls above may have swapped the credentials.
|
||||
final nextcloud = SessionManager().requireNextcloud();
|
||||
final types = registrationTypesFor(
|
||||
usesLoginFlow: AccountData().usesLoginFlow,
|
||||
hasTalkAppPassword: AccountData().hasAppPasswordTalk(),
|
||||
usesLoginFlow: nextcloud.usesLoginFlow,
|
||||
hasTalkAppPassword: nextcloud.hasAppPasswordTalk,
|
||||
);
|
||||
if (!types.contains(PushRegistrationType.general)) {
|
||||
await _recordAttempt(
|
||||
@@ -180,7 +188,7 @@ class PushRegistration {
|
||||
devicePublicKeyPem: pems.publicKeyPem,
|
||||
proxyServer: proxyServer,
|
||||
authorizationHeader: isTalk
|
||||
? AccountData().getTalkBasicAuthHeader()
|
||||
? SessionManager().requireNextcloud().talkBasicAuthHeader
|
||||
: null,
|
||||
userAgent: isTalk ? _talkUserAgent : null,
|
||||
);
|
||||
@@ -199,7 +207,7 @@ class PushRegistration {
|
||||
deviceIdentifierSignature: registration.signature,
|
||||
userPublicKey: registration.publicKey,
|
||||
pushToken: fcmToken,
|
||||
platform: _platform,
|
||||
platform: pushPlatform,
|
||||
registrationType: type.wireName,
|
||||
appVersion: appVersion,
|
||||
);
|
||||
@@ -248,7 +256,7 @@ class PushRegistration {
|
||||
try {
|
||||
final endpoint = EndpointData().nextcloud();
|
||||
await _store.saveNativeAuthContext(
|
||||
username: AccountData().getUsername(),
|
||||
username: SessionManager().requireNextcloud().username,
|
||||
baseUrl: 'https://${endpoint.full()}',
|
||||
);
|
||||
} on Object catch (e) {
|
||||
@@ -266,7 +274,7 @@ class PushRegistration {
|
||||
// session token — each registration with its own app password.
|
||||
await _nextcloud.unregister(
|
||||
authorizationHeader: type == PushRegistrationType.talk
|
||||
? AccountData().getTalkBasicAuthHeader()
|
||||
? SessionManager().requireNextcloud().talkBasicAuthHeader
|
||||
: null,
|
||||
);
|
||||
} on Object catch (e) {
|
||||
@@ -405,7 +413,9 @@ class PushRegistration {
|
||||
static Future<bool> syncSubscription({required bool capable}) async {
|
||||
if (!capable) return false;
|
||||
if (!await isOsPermissionGranted()) {
|
||||
log('Push: OS notification permission not granted, skipping registration');
|
||||
log(
|
||||
'Push: OS notification permission not granted, skipping registration',
|
||||
);
|
||||
return false;
|
||||
}
|
||||
final registration = PushRegistration();
|
||||
@@ -429,6 +439,7 @@ class PushRegistration {
|
||||
/// pushing before credentials are gone.
|
||||
Future<void> logoutCleanup() async {
|
||||
if (DemoMode.active) return;
|
||||
if (_nextcloudOrNull == null) return _direct.unregister();
|
||||
await unregister();
|
||||
try {
|
||||
await DeleteAppPassword().run();
|
||||
@@ -436,15 +447,16 @@ class PushRegistration {
|
||||
log('Push: delete app password failed: $e');
|
||||
}
|
||||
try {
|
||||
if (AccountData().hasAppPasswordTalk()) {
|
||||
final nextcloud = SessionManager().requireNextcloud();
|
||||
if (nextcloud.hasAppPasswordTalk) {
|
||||
await DeleteAppPassword().run(
|
||||
authorizationHeader: AccountData().getTalkBasicAuthHeader(),
|
||||
authorizationHeader: nextcloud.talkBasicAuthHeader,
|
||||
);
|
||||
}
|
||||
} on Object catch (e) {
|
||||
log('Push: delete talk app password failed: $e');
|
||||
}
|
||||
await AccountData().clearAppPassword();
|
||||
await AccountData().clearAppPasswordTalk();
|
||||
await SessionManager().clearAppPassword();
|
||||
await SessionManager().clearAppPasswordTalk();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user