mirror of
https://github.com/yattee/yattee.git
synced 2026-10-23 13:12:53 +00:00
Delete declarations that Periphery reports unused on every platform that compiles them (iOS, macOS, tvOS), including nine views used only by their own previews. Platform-gated code still used on another platform, device- only MPV render paths, migration models, CloudKit record names, App Intents metadata and unused parameters are kept.
103 lines
4.8 KiB
Swift
103 lines
4.8 KiB
Swift
//
|
|
// AccountCredentialsManager.swift
|
|
// Yattee
|
|
//
|
|
// Account-keyed credential storage — the multi-login replacement for the
|
|
// instance-keyed InstanceCredentialsManager.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
/// Credential storage keyed by `Account`, not by `Instance`.
|
|
///
|
|
/// Adopted by `InvidiousCredentialsManager` and `PipedCredentialsManager`.
|
|
/// `BasicAuthCredentialsManager` deliberately does **not** adopt it and keeps
|
|
/// `InstanceCredentialsManager`: HTTP Basic auth is a property of the instance
|
|
/// (or the reverse proxy in front of it), not of a user account, and a single
|
|
/// proxy credential covers every account on that instance.
|
|
@MainActor
|
|
protocol AccountCredentialsManager: AnyObject, Observable {
|
|
/// Whether the identity scope has been resolved yet.
|
|
///
|
|
/// While `false`, every read below reports "no credential" because the app
|
|
/// cannot yet tell which scope to look in. Callers must render that as
|
|
/// *temporarily unavailable*, never as "signed out" — correcting state on
|
|
/// it would discard a perfectly good login.
|
|
var isScopeResolved: Bool { get }
|
|
|
|
func setCredential(_ credential: String, for account: Account)
|
|
func credential(for account: Account) -> String?
|
|
func deleteCredential(for account: Account)
|
|
|
|
/// Deletes the credential and stored login identifier for an account this
|
|
/// device may know nothing else about.
|
|
///
|
|
/// A deletion can reach this device before the account it deletes does —
|
|
/// the tombstone and the account are separate records, and iCloud Keychain
|
|
/// runs on its own timeline. The secret must go regardless, and the scoped
|
|
/// key needs only the account's ID.
|
|
func deleteCredential(forAccountID accountID: UUID)
|
|
|
|
/// The login identifier the user typed. Kept in the Keychain beside the
|
|
/// credential so it never enters synced metadata.
|
|
func setUsername(_ username: String, for account: Account)
|
|
func username(for account: Account) -> String?
|
|
|
|
func isLoggedIn(for account: Account) -> Bool
|
|
func refreshLoginStatus(for account: Account)
|
|
|
|
// MARK: - Identity migration
|
|
|
|
/// Moves an account's credential and username from `sourceScope` into the
|
|
/// current one, for a record being imported out of the `local` namespace
|
|
/// when an Apple account claims it.
|
|
///
|
|
/// - Returns: `true` only when `sourceScope` holds nothing for this account
|
|
/// any more — credential and username both. `false` means something is
|
|
/// still keyed to the source, so the record it belongs to must stay where
|
|
/// it is: that record is what brings the retry.
|
|
@discardableResult
|
|
func migrateCredential(forAccountID accountID: UUID, fromScope sourceScope: String) -> Bool
|
|
|
|
/// Deletes an account's credential and username under a named scope.
|
|
///
|
|
/// The scoped counterpart of `deleteCredential(forAccountID:)`: an import
|
|
/// refused because this identity already tombstoned the account has to take
|
|
/// the secret with it, and that secret is keyed by the scope being left
|
|
/// rather than the one in force.
|
|
///
|
|
/// - Returns: whether that scope is now free of the account, on the same
|
|
/// terms as `migrateCredential(forAccountID:fromScope:)`.
|
|
@discardableResult
|
|
func deleteCredential(forAccountID accountID: UUID, inScope scope: String) -> Bool
|
|
|
|
// MARK: - Legacy adoption
|
|
|
|
/// Whether a pre-revamp credential for this account's instance exists on
|
|
/// this device and has not been adopted by the current identity.
|
|
///
|
|
/// True only for the account the instance's legacy login was migrated into
|
|
/// — the old item is keyed by instance, and a second login the user added
|
|
/// themselves must never inherit it.
|
|
func hasAdoptableLegacyCredential(for account: Account) -> Bool
|
|
|
|
/// Copies the legacy item into this account's scoped key. Returns whether
|
|
/// the copy verified.
|
|
///
|
|
/// Runs by itself as part of recomputing account status: the upgrade is not
|
|
/// a decision to put to the user. A retained Keychain item carries no proof
|
|
/// of which Apple account it belonged to (measured — see
|
|
/// ``CredentialIdentityScope``), but the pre-revamp release read that item
|
|
/// with `kSecAttrSynchronizableAny` and no identity in its key, so it was
|
|
/// already being served to whoever held the device. The copy is written
|
|
/// device-local so this migration cannot put a secret of unproven
|
|
/// provenance into the current identity's iCloud Keychain.
|
|
@discardableResult
|
|
func adoptLegacyCredential(for account: Account) -> Bool
|
|
|
|
/// Deletes the unscoped legacy item **only** if this identity adopted it
|
|
/// and it still holds the adopted secret. Called when an account is really
|
|
/// deleted, never on mere absence.
|
|
func deleteLegacyCredentialIfOwned(for account: Account)
|
|
}
|