71 lines
2.7 KiB
Dart
71 lines
2.7 KiB
Dart
import 'session.dart';
|
|
|
|
/// Keychain keys of the session. Names are frozen: installed versions and the
|
|
/// iOS AppDelegate/NSE read them, so renaming would log every user out.
|
|
abstract final class SessionKeys {
|
|
static const username = 'username';
|
|
static const password = 'password';
|
|
static const appPassword = 'nextcloud_app_password';
|
|
static const appPasswordTalk = 'nextcloud_app_password_talk';
|
|
static const loginFlow = 'nextcloud_login_flow';
|
|
static const demo = 'is_demo';
|
|
|
|
// Added with guardian accounts. Absent on installs from before — see
|
|
// [decodeSession].
|
|
static const kind = 'session_kind';
|
|
static const guardianEmail = 'guardian_email';
|
|
|
|
static const kindCredential = 'credential';
|
|
static const kindGuardian = 'guardian';
|
|
}
|
|
|
|
/// Rebuilds the session from raw keychain values. Installs from before
|
|
/// guardian accounts carry no [SessionKeys.kind]; a stored username and
|
|
/// password then mean a credential session, so existing users stay signed in.
|
|
Session? decodeSession(Map<String, String?> raw) {
|
|
final isDemo = raw[SessionKeys.demo] == 'true';
|
|
switch (raw[SessionKeys.kind]) {
|
|
case SessionKeys.kindGuardian:
|
|
final email = raw[SessionKeys.guardianEmail];
|
|
if (email == null || email.isEmpty) return null;
|
|
return GuardianSession(email: email, isDemo: isDemo);
|
|
case null:
|
|
case SessionKeys.kindCredential:
|
|
final username = raw[SessionKeys.username];
|
|
final password = raw[SessionKeys.password];
|
|
if (username == null || password == null) return null;
|
|
return CredentialSession(
|
|
username: username,
|
|
password: password,
|
|
appPassword: raw[SessionKeys.appPassword],
|
|
appPasswordTalk: raw[SessionKeys.appPasswordTalk],
|
|
usesLoginFlow: raw[SessionKeys.loginFlow] == 'true',
|
|
isDemo: isDemo,
|
|
);
|
|
default:
|
|
// Written by a newer app version; unknown here, treat as signed out.
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// Keychain values for [session], excluding the group-scoped app passwords
|
|
/// (written separately so the iOS NSE can read them). `null` = delete.
|
|
Map<String, String?> encodeSessionFields(Session session) => switch (session) {
|
|
CredentialSession() => {
|
|
SessionKeys.kind: SessionKeys.kindCredential,
|
|
SessionKeys.username: session.username,
|
|
SessionKeys.password: session.password,
|
|
SessionKeys.demo: session.isDemo ? 'true' : null,
|
|
SessionKeys.loginFlow: session.nextcloud.usesLoginFlow ? 'true' : null,
|
|
SessionKeys.guardianEmail: null,
|
|
},
|
|
GuardianSession() => {
|
|
SessionKeys.kind: SessionKeys.kindGuardian,
|
|
SessionKeys.guardianEmail: session.email,
|
|
SessionKeys.demo: session.isDemo ? 'true' : null,
|
|
SessionKeys.username: null,
|
|
SessionKeys.password: null,
|
|
SessionKeys.loginFlow: null,
|
|
},
|
|
};
|