allow basic auth with auth endpoint

Signed-off-by: Toni Förster <toni.foerster@gmail.com>
This commit is contained in:
Toni Förster 2024-08-28 17:40:16 +02:00
parent cea2684a29
commit 049a42f2e8
No known key found for this signature in database
GPG Key ID: 292F3E5086C83FC7

View File

@ -247,27 +247,27 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
} }
func feed(_ page: Int?) -> Resource? { func feed(_ page: Int?) -> Resource? {
resource(baseURL: account.url, path: "\(Self.basePath)/auth/feed") resourceWithAuthCheck(baseURL: account.url, path: "\(Self.basePath)/auth/feed")
.withParam("page", String(page ?? 1)) .withParam("page", String(page ?? 1))
} }
var feed: Resource? { var feed: Resource? {
resource(baseURL: account.url, path: basePathAppending("auth/feed")) resourceWithAuthCheck(baseURL: account.url, path: basePathAppending("auth/feed"))
} }
var subscriptions: Resource? { var subscriptions: Resource? {
resource(baseURL: account.url, path: basePathAppending("auth/subscriptions")) resourceWithAuthCheck(baseURL: account.url, path: basePathAppending("auth/subscriptions"))
} }
func subscribe(_ channelID: String, onCompletion: @escaping () -> Void = {}) { func subscribe(_ channelID: String, onCompletion: @escaping () -> Void = {}) {
resource(baseURL: account.url, path: basePathAppending("auth/subscriptions")) resourceWithAuthCheck(baseURL: account.url, path: basePathAppending("auth/subscriptions"))
.child(channelID) .child(channelID)
.request(.post) .request(.post)
.onCompletion { _ in onCompletion() } .onCompletion { _ in onCompletion() }
} }
func unsubscribe(_ channelID: String, onCompletion: @escaping () -> Void) { func unsubscribe(_ channelID: String, onCompletion: @escaping () -> Void) {
resource(baseURL: account.url, path: basePathAppending("auth/subscriptions")) resourceWithAuthCheck(baseURL: account.url, path: basePathAppending("auth/subscriptions"))
.child(channelID) .child(channelID)
.request(.delete) .request(.delete)
.onCompletion { _ in onCompletion() } .onCompletion { _ in onCompletion() }
@ -308,11 +308,11 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
return nil return nil
} }
return resource(baseURL: account.url, path: basePathAppending("auth/playlists")) return resourceWithAuthCheck(baseURL: account.url, path: basePathAppending("auth/playlists"))
} }
func playlist(_ id: String) -> Resource? { func playlist(_ id: String) -> Resource? {
resource(baseURL: account.url, path: basePathAppending("auth/playlists/\(id)")) resourceWithAuthCheck(baseURL: account.url, path: basePathAppending("auth/playlists/\(id)"))
} }
func playlistVideos(_ id: String) -> Resource? { func playlistVideos(_ id: String) -> Resource? {
@ -556,6 +556,30 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
) )
} }
// Determines if the request requires Basic Auth credentials to be removed
private func needsBasicAuthRemoval(for path: String) -> Bool {
return path.hasPrefix("\(Self.basePath)/auth/")
}
// Creates a resource URL with consideration for removing Basic Auth credentials
private func createResourceURL(baseURL: URL, path: String) -> URL {
var resourceURL = baseURL
// Remove Basic Auth credentials if required
if needsBasicAuthRemoval(for: path), var urlComponents = URLComponents(url: baseURL, resolvingAgainstBaseURL: false) {
urlComponents.user = nil
urlComponents.password = nil
resourceURL = urlComponents.url ?? baseURL
}
return resourceURL.appendingPathComponent(path)
}
func resourceWithAuthCheck(baseURL: URL, path: String) -> Resource {
let sanitizedURL = createResourceURL(baseURL: baseURL, path: path)
return super.resource(absoluteURL: sanitizedURL)
}
private func extractThumbnails(from details: JSON) -> [Thumbnail] { private func extractThumbnails(from details: JSON) -> [Thumbnail] {
details["videoThumbnails"].arrayValue.compactMap { json in details["videoThumbnails"].arrayValue.compactMap { json in
guard let url = json["url"].url, guard let url = json["url"].url,
@ -570,7 +594,7 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
// with an incorrect scheme or a missing port. // with an incorrect scheme or a missing port.
components.scheme = accountUrlComponents.scheme components.scheme = accountUrlComponents.scheme
components.port = accountUrlComponents.port components.port = accountUrlComponents.port
// If basic HTTP authentication is used, // If basic HTTP authentication is used,
// the username and password need to be prepended to the URL. // the username and password need to be prepended to the URL.
components.user = accountUrlComponents.user components.user = accountUrlComponents.user