mirror of
https://github.com/yattee/yattee.git
synced 2026-06-06 23:04:19 +00:00
Allow HTTP Basic Auth credentials for any remote-server instance type
EditSourceView now exposes the basic-auth username/password fields for every instance type (Invidious, Piped, PeerTube, Yattee Server), keeping the existing required-credentials UI for Yattee Server and adding an optional section for the others. Credentials are loaded and persisted via BasicAuthCredentialsManager regardless of type, and clearing both fields deletes stored credentials for non-Yattee types. AddRemoteServerView gains a new basicAuthRequired UI state: when instance detection hits a 401 (the entire instance is behind a reverse proxy), the view reveals username/password fields and a Retry Detection button. The retry calls the detector with the credentials injected as an Authorization header; on success the form transitions into the normal detected state with the credentials pre-populated. A repeat 401 shows an inline "invalid credentials" message instead of restarting the flow. For non-Yattee types, any credentials entered during the flow are persisted alongside the new instance.
This commit is contained in:
@@ -36,9 +36,13 @@ private struct EditRemoteServerContent: View {
|
||||
@State private var allowInvalidCertificates: Bool
|
||||
@State private var proxiesVideos: Bool
|
||||
|
||||
// Yattee Server credentials
|
||||
@State private var yatteeServerUsername: String = ""
|
||||
@State private var yatteeServerPassword: String = ""
|
||||
// HTTP Basic Auth credentials (for any instance type behind a reverse proxy;
|
||||
// required for Yattee Server, optional for Invidious/Piped/PeerTube).
|
||||
@State private var basicAuthUsername: String = ""
|
||||
@State private var basicAuthPassword: String = ""
|
||||
/// Tracks whether credentials existed when the view loaded, so we can detect
|
||||
/// "user cleared the fields" and delete the stored credentials on save.
|
||||
@State private var hadStoredBasicAuth: Bool = false
|
||||
|
||||
// Invidious login state
|
||||
@State private var showLoginSheet = false
|
||||
@@ -137,28 +141,28 @@ private struct EditRemoteServerContent: View {
|
||||
#endif
|
||||
}
|
||||
|
||||
if instance.type == .yatteeServer {
|
||||
Section {
|
||||
#if os(tvOS)
|
||||
TVSettingsTextField(title: String(localized: "sources.field.username"), text: $yatteeServerUsername)
|
||||
TVSettingsTextField(title: String(localized: "sources.field.password"), text: $yatteeServerPassword, isSecure: true)
|
||||
#else
|
||||
TextField(String(localized: "sources.field.username"), text: $yatteeServerUsername)
|
||||
.textContentType(.username)
|
||||
#if os(iOS)
|
||||
.textInputAutocapitalization(.never)
|
||||
#endif
|
||||
.autocorrectionDisabled()
|
||||
|
||||
SecureField(String(localized: "sources.field.password"), text: $yatteeServerPassword)
|
||||
.textContentType(.password)
|
||||
Section {
|
||||
#if os(tvOS)
|
||||
TVSettingsTextField(title: String(localized: "sources.field.username"), text: $basicAuthUsername)
|
||||
TVSettingsTextField(title: String(localized: "sources.field.password"), text: $basicAuthPassword, isSecure: true)
|
||||
#else
|
||||
TextField(String(localized: "sources.field.username"), text: $basicAuthUsername)
|
||||
.textContentType(.username)
|
||||
#if os(iOS)
|
||||
.textInputAutocapitalization(.never)
|
||||
#endif
|
||||
} header: {
|
||||
Text(String(localized: "sources.header.auth"))
|
||||
} footer: {
|
||||
Text(String(localized: "sources.footer.yatteeServerAuth"))
|
||||
}
|
||||
.autocorrectionDisabled()
|
||||
|
||||
SecureField(String(localized: "sources.field.password"), text: $basicAuthPassword)
|
||||
.textContentType(.password)
|
||||
#endif
|
||||
} header: {
|
||||
Text(String(localized: instance.type == .yatteeServer ? "sources.header.auth" : "sources.header.basicAuth"))
|
||||
} footer: {
|
||||
Text(String(localized: instance.type == .yatteeServer ? "sources.footer.yatteeServerAuth" : "sources.footer.basicAuth"))
|
||||
}
|
||||
|
||||
if instance.type == .yatteeServer {
|
||||
// Server Info Section
|
||||
Section {
|
||||
if isLoadingServerInfo {
|
||||
@@ -344,11 +348,11 @@ private struct EditRemoteServerContent: View {
|
||||
.onAppear {
|
||||
isLoggedIn = appEnvironment?.credentialsManager(for: instance)?.isLoggedIn(for: instance) ?? false
|
||||
|
||||
// Load existing Yattee Server credentials
|
||||
if instance.type == .yatteeServer,
|
||||
let credentials = appEnvironment?.basicAuthCredentialsManager.credentials(for: instance) {
|
||||
yatteeServerUsername = credentials.username
|
||||
yatteeServerPassword = credentials.password
|
||||
// Load existing HTTP Basic Auth credentials (works for any instance type)
|
||||
if let credentials = appEnvironment?.basicAuthCredentialsManager.credentials(for: instance) {
|
||||
basicAuthUsername = credentials.username
|
||||
basicAuthPassword = credentials.password
|
||||
hadStoredBasicAuth = true
|
||||
}
|
||||
}
|
||||
.task {
|
||||
@@ -436,13 +440,17 @@ private struct EditRemoteServerContent: View {
|
||||
updated.allowInvalidCertificates = allowInvalidCertificates
|
||||
updated.proxiesVideos = proxiesVideos
|
||||
|
||||
// Save Yattee Server credentials if provided
|
||||
if instance.type == .yatteeServer && !yatteeServerUsername.isEmpty && !yatteeServerPassword.isEmpty {
|
||||
// Save / clear HTTP Basic Auth credentials.
|
||||
// Works for any instance type, but for Yattee Server we never auto-clear
|
||||
// (credentials are required there; the user can re-enter to overwrite).
|
||||
if !basicAuthUsername.isEmpty && !basicAuthPassword.isEmpty {
|
||||
appEnvironment?.basicAuthCredentialsManager.setCredentials(
|
||||
username: yatteeServerUsername,
|
||||
password: yatteeServerPassword,
|
||||
username: basicAuthUsername,
|
||||
password: basicAuthPassword,
|
||||
for: instance
|
||||
)
|
||||
} else if hadStoredBasicAuth && instance.type != .yatteeServer {
|
||||
appEnvironment?.basicAuthCredentialsManager.deleteCredentials(for: instance)
|
||||
}
|
||||
|
||||
appEnvironment?.instancesManager.update(updated)
|
||||
|
||||
Reference in New Issue
Block a user