mirror of
https://github.com/yattee/yattee.git
synced 2026-04-09 17:16:57 +00:00
Fix HTTP basic auth credentials being stripped from instance URLs
Preserve user:pass credentials in instance URLs so Invidious instances behind nginx reverse proxies with HTTP basic auth work correctly (#926). Add displayURL property to mask credentials in the UI.
This commit is contained in:
@@ -119,6 +119,17 @@ struct Instance: Identifiable, Codable, Hashable, Sendable {
|
|||||||
name ?? url.host ?? url.absoluteString
|
name ?? url.host ?? url.absoluteString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the URL string with embedded credentials stripped for safe display in the UI.
|
||||||
|
var displayURL: String {
|
||||||
|
guard var components = URLComponents(url: url, resolvingAgainstBaseURL: false),
|
||||||
|
components.user != nil else {
|
||||||
|
return url.absoluteString
|
||||||
|
}
|
||||||
|
components.user = nil
|
||||||
|
components.password = nil
|
||||||
|
return components.url?.absoluteString ?? url.absoluteString
|
||||||
|
}
|
||||||
|
|
||||||
var contentSource: ContentSource {
|
var contentSource: ContentSource {
|
||||||
type.contentSource(for: url)
|
type.contentSource(for: url)
|
||||||
}
|
}
|
||||||
@@ -268,10 +279,6 @@ extension Instance {
|
|||||||
components.path = String(components.path.dropLast())
|
components.path = String(components.path.dropLast())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strip embedded credentials (security best practice)
|
|
||||||
components.user = nil
|
|
||||||
components.password = nil
|
|
||||||
|
|
||||||
return components.url
|
return components.url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ private struct EditRemoteServerContent: View {
|
|||||||
Form {
|
Form {
|
||||||
Section {
|
Section {
|
||||||
LabeledContent(String(localized: "sources.field.type"), value: instance.type.displayName)
|
LabeledContent(String(localized: "sources.field.type"), value: instance.type.displayName)
|
||||||
LabeledContent(String(localized: "sources.field.url"), value: instance.url.absoluteString)
|
LabeledContent(String(localized: "sources.field.url"), value: instance.displayURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
|
|||||||
@@ -248,6 +248,32 @@ struct InstanceTests {
|
|||||||
#expect(simpleHost?.scheme == "https")
|
#expect(simpleHost?.scheme == "https")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test("Instance URL normalization preserves embedded credentials")
|
||||||
|
func normalizeSourceURLPreservesCredentials() {
|
||||||
|
let url = Instance.normalizeSourceURL("https://user:pass@server.com")
|
||||||
|
#expect(url?.user == "user")
|
||||||
|
#expect(url?.password == "pass")
|
||||||
|
#expect(url?.host == "server.com")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test("Instance displayURL strips credentials")
|
||||||
|
func displayURLStripsCredentials() {
|
||||||
|
let instance = Instance(
|
||||||
|
type: .invidious,
|
||||||
|
url: URL(string: "https://user:pass@server.com")!
|
||||||
|
)
|
||||||
|
#expect(instance.displayURL == "https://server.com")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test("Instance displayURL returns absoluteString when no credentials")
|
||||||
|
func displayURLWithoutCredentials() {
|
||||||
|
let instance = Instance(
|
||||||
|
type: .invidious,
|
||||||
|
url: URL(string: "https://server.com")!
|
||||||
|
)
|
||||||
|
#expect(instance.displayURL == "https://server.com")
|
||||||
|
}
|
||||||
|
|
||||||
@Test("Instance display name uses custom name if set")
|
@Test("Instance display name uses custom name if set")
|
||||||
func displayNameCustom() {
|
func displayNameCustom() {
|
||||||
let instance = Instance(
|
let instance = Instance(
|
||||||
|
|||||||
Reference in New Issue
Block a user