added guardian login with views for their assigned childs
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
import 'dart:convert';
|
||||
|
||||
/// Nextcloud identity of a session. Immutable; the session manager swaps in a
|
||||
/// new instance whenever an app password is minted or revoked.
|
||||
class NextcloudCredentials {
|
||||
final String username;
|
||||
|
||||
/// The real account password. Invalid against Nextcloud when
|
||||
/// [usesLoginFlow] is set (2FA accounts), where only [appPassword] works.
|
||||
final String password;
|
||||
final String? appPassword;
|
||||
|
||||
/// Backs the second (apptype=talk) push registration — Nextcloud binds each
|
||||
/// push subscription to its session token, so two registrations need two
|
||||
/// app passwords.
|
||||
final String? appPasswordTalk;
|
||||
|
||||
/// True when the credentials came from Login Flow v2 (browser login, e.g.
|
||||
/// because the account has two-factor authentication).
|
||||
final bool usesLoginFlow;
|
||||
|
||||
const NextcloudCredentials({
|
||||
required this.username,
|
||||
required this.password,
|
||||
this.appPassword,
|
||||
this.appPasswordTalk,
|
||||
this.usesLoginFlow = false,
|
||||
});
|
||||
|
||||
bool get hasAppPassword => appPassword != null && appPassword!.isNotEmpty;
|
||||
|
||||
bool get hasAppPasswordTalk =>
|
||||
appPasswordTalk != null && appPasswordTalk!.isNotEmpty;
|
||||
|
||||
/// The app password once available (minted or flow-issued), otherwise the
|
||||
/// real password. It survives real-password rotation and is what the push
|
||||
/// registration is bound to.
|
||||
String get secret => hasAppPassword ? appPassword! : password;
|
||||
|
||||
/// HTTP Basic header value. Prefer headers over credentials in URLs — error
|
||||
/// logs and crash reports often capture the URL but not headers.
|
||||
String get basicAuthHeader => _basicAuth(secret);
|
||||
|
||||
Map<String, String> get authHeaders => {'Authorization': basicAuthHeader};
|
||||
|
||||
/// Authenticates the apptype=talk push registration (and its unregister).
|
||||
/// Throws when the talk password has not been minted yet; callers treat that
|
||||
/// as a failed talk registration and retry on the next start.
|
||||
String get talkBasicAuthHeader {
|
||||
if (hasAppPasswordTalk) return _basicAuth(appPasswordTalk!);
|
||||
// Login-flow account whose second (talk) flow pass was skipped: no silent
|
||||
// minting possible, the talk registration shares the flow credential.
|
||||
if (usesLoginFlow && hasAppPassword) return _basicAuth(appPassword!);
|
||||
throw StateError('Talk app password not available yet');
|
||||
}
|
||||
|
||||
/// Always the real password. Needed to mint the app password via
|
||||
/// `core/getapppassword` — an app password cannot mint another.
|
||||
String get realPasswordBasicAuthHeader => _basicAuth(password);
|
||||
|
||||
NextcloudCredentials copyWith({
|
||||
String? Function()? appPassword,
|
||||
String? Function()? appPasswordTalk,
|
||||
bool? usesLoginFlow,
|
||||
}) => NextcloudCredentials(
|
||||
username: username,
|
||||
password: password,
|
||||
appPassword: appPassword != null ? appPassword() : this.appPassword,
|
||||
appPasswordTalk: appPasswordTalk != null
|
||||
? appPasswordTalk()
|
||||
: this.appPasswordTalk,
|
||||
usesLoginFlow: usesLoginFlow ?? this.usesLoginFlow,
|
||||
);
|
||||
|
||||
String _basicAuth(String secret) =>
|
||||
'Basic ${base64Encode(utf8.encode('$username:$secret'))}';
|
||||
}
|
||||
Reference in New Issue
Block a user