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

101 lines
3.9 KiB
Swift
Raw Normal View History

2023-01-20 16:57:25 +01:00
//
// https://mczachurski.dev
// Copyright © 2022 Marcin Czachurski and the repository contributors.
2023-03-28 10:35:38 +02:00
// Licensed under the Apache License 2.0.
2023-01-20 16:57:25 +01:00
//
2023-01-10 08:04:25 +01:00
import Foundation
import OAuthSwift
2023-01-29 19:11:44 +01:00
import AuthenticationServices
2023-01-10 08:04:25 +01:00
2023-02-19 10:43:37 +01:00
public extension PixelfedClient {
2023-01-29 19:11:44 +01:00
/// Creates OAuth application in Pixelfed.
2023-01-10 08:04:25 +01:00
func createApp(named name: String,
2023-01-29 19:11:44 +01:00
redirectUri: String,
2023-01-10 08:04:25 +01:00
scopes: Scopes,
2023-01-22 13:49:19 +01:00
website: URL) async throws -> Application {
2023-01-10 08:04:25 +01:00
let request = try Self.request(
for: baseURL,
2023-02-19 10:43:37 +01:00
target: Pixelfed.Apps.register(
2023-01-10 08:04:25 +01:00
clientName: name,
redirectUris: redirectUri,
scopes: scopes.reduce("") { $0 == "" ? $1 : $0 + " " + $1},
website: website.absoluteString
)
)
2023-01-22 13:49:19 +01:00
return try await downloadJson(Application.self, request: request)
2023-01-10 08:04:25 +01:00
}
2023-01-29 19:11:44 +01:00
/// 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(
2023-02-06 14:50:28 +01:00
withRefreshToken: refreshToken,
2023-01-29 19:11:44 +01:00
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 {
2023-01-10 08:04:25 +01:00
oauthClient = OAuth2Swift(
consumerKey: app.clientId,
consumerSecret: app.clientSecret,
authorizeUrl: baseURL.appendingPathComponent("oauth/authorize"),
accessTokenUrl: baseURL.appendingPathComponent("oauth/token"),
responseType: "code"
)
2023-01-29 19:11:44 +01:00
oauthClient?.authorizeURLHandler = ASWebAuthenticationURLHandler(callbackUrlScheme: callbackUrlScheme,
2023-02-12 09:13:04 +01:00
presentationContextProvider: presentationContextProvider,
prefersEphemeralWebBrowserSession: true)
2023-01-29 19:11:44 +01:00
2023-01-10 08:04:25 +01:00
return try await withCheckedThrowingContinuation { [weak self] continuation in
self?.oAuthContinuation = continuation
oAuthHandle = oauthClient?.authorize(
withCallbackURL: app.redirectUri,
2023-01-29 19:11:44 +01:00
scope: scope.joined(separator: " "),
2023-02-19 10:43:37 +01:00
state: "PixELfed_AUTH",
2023-01-10 08:04:25 +01:00
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)
}
}