Vernissage/PixelfedKit/Sources/PixelfedKit/PixelfedClient+Convenience....

101 lines
3.9 KiB
Swift

//
// https://mczachurski.dev
// Copyright © 2022 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import OAuthSwift
import AuthenticationServices
public extension PixelfedClient {
/// Creates OAuth application in Pixelfed.
func createApp(named name: String,
redirectUri: String,
scopes: Scopes,
website: URL) async throws -> Application {
let request = try Self.request(
for: baseURL,
target: Pixelfed.Apps.register(
clientName: name,
redirectUris: redirectUri,
scopes: scopes.reduce("") { $0 == "" ? $1 : $0 + " " + $1},
website: website.absoluteString
)
)
return try await downloadJson(Application.self, request: request)
}
/// Refresh access token..
func refreshToken(clientId: String, clientSecret: String, refreshToken: String) async throws -> OAuthSwiftCredential {
oauthClient = OAuth2Swift(
consumerKey: clientId,
consumerSecret: clientSecret,
authorizeUrl: baseURL.appendingPathComponent("oauth/authorize"),
accessTokenUrl: baseURL.appendingPathComponent("oauth/token"),
responseType: "code"
)
return try await withCheckedThrowingContinuation { [weak self] continuation in
self?.oAuthContinuation = continuation
oauthClient?.renewAccessToken(
withRefreshToken: refreshToken,
completionHandler: { result in
switch result {
case let .success((credentials, _, _)):
continuation.resume(with: .success(credentials))
case let .failure(error):
continuation.resume(throwing: error)
}
self?.oAuthContinuation = nil
})
}
}
/// User authentication.
func authenticate(app: Application,
scope: Scopes,
callbackUrlScheme: String,
presentationContextProvider: ASWebAuthenticationPresentationContextProviding
) async throws -> OAuthSwiftCredential {
oauthClient = OAuth2Swift(
consumerKey: app.clientId,
consumerSecret: app.clientSecret,
authorizeUrl: baseURL.appendingPathComponent("oauth/authorize"),
accessTokenUrl: baseURL.appendingPathComponent("oauth/token"),
responseType: "code"
)
oauthClient?.authorizeURLHandler = ASWebAuthenticationURLHandler(callbackUrlScheme: callbackUrlScheme,
presentationContextProvider: presentationContextProvider,
prefersEphemeralWebBrowserSession: true)
return try await withCheckedThrowingContinuation { [weak self] continuation in
self?.oAuthContinuation = continuation
oAuthHandle = oauthClient?.authorize(
withCallbackURL: app.redirectUri,
scope: scope.joined(separator: " "),
state: "PixELfed_AUTH",
completionHandler: { result in
switch result {
case let .success((credentials, _, _)):
continuation.resume(with: .success(credentials))
case let .failure(error):
continuation.resume(throwing: error)
}
self?.oAuthContinuation = nil
}
)
}
}
static func handleOAuthResponse(url: URL) {
OAuthSwift.handle(url: url)
}
}