Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: new HTTPClient type #361

Merged
merged 11 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ let package = Package(
name: "FunctionsTests",
dependencies: [
"Functions",
"TestHelpers",
.product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"),
.product(name: "SnapshotTesting", package: "swift-snapshot-testing"),
.product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay"),
]
),
.testTarget(
Expand Down
5 changes: 3 additions & 2 deletions Sources/Auth/AuthAdmin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import _Helpers
import Foundation

public struct AuthAdmin: Sendable {
var configuration: AuthClient.Configuration { Current.configuration }
var api: APIClient { Current.api }
var encoder: JSONEncoder { Current.encoder }

Expand All @@ -21,8 +22,8 @@ public struct AuthAdmin: Sendable {
/// - Warning: Never expose your `service_role` key on the client.
public func deleteUser(id: String, shouldSoftDelete: Bool = false) async throws {
_ = try await api.execute(
Request(
path: "/admin/users/\(id)",
HTTPRequest(
url: configuration.url.appendingPathComponent("admin/users/\(id)"),
method: .delete,
body: encoder.encode(
DeleteUserRequest(shouldSoftDelete: shouldSoftDelete)
Expand Down
76 changes: 42 additions & 34 deletions Sources/Auth/AuthClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ public final class AuthClient: Sendable {
configuration: configuration,
sessionRefresher: SessionRefresher { [weak self] in
try await self?.refreshSession(refreshToken: $0) ?? .empty
}
},
http: HTTPClient(configuration: configuration)
)
}

Expand Down Expand Up @@ -105,7 +106,7 @@ public final class AuthClient: Sendable {

return try await _signUp(
request: .init(
path: "/signup",
url: configuration.url.appendingPathComponent("signup"),
method: .post,
query: [
(redirectTo ?? configuration.redirectToURL).map { URLQueryItem(
Expand Down Expand Up @@ -141,7 +142,7 @@ public final class AuthClient: Sendable {
) async throws -> AuthResponse {
try await _signUp(
request: .init(
path: "/signup",
url: configuration.url.appendingPathComponent("signup"),
method: .post,
body: configuration.encoder.encode(
SignUpRequest(
Expand All @@ -155,7 +156,7 @@ public final class AuthClient: Sendable {
)
}

private func _signUp(request: Request) async throws -> AuthResponse {
private func _signUp(request: HTTPRequest) async throws -> AuthResponse {
await sessionManager.remove()
let response = try await api.execute(request).decoded(
as: AuthResponse.self,
Expand All @@ -179,7 +180,7 @@ public final class AuthClient: Sendable {
) async throws -> Session {
try await _signIn(
request: .init(
path: "/token",
url: configuration.url.appendingPathComponent("token"),
method: .post,
query: [URLQueryItem(name: "grant_type", value: "password")],
body: configuration.encoder.encode(
Expand All @@ -202,7 +203,7 @@ public final class AuthClient: Sendable {
) async throws -> Session {
try await _signIn(
request: .init(
path: "/token",
url: configuration.url.appendingPathComponent("token"),
method: .post,
query: [URLQueryItem(name: "grant_type", value: "password")],
body: configuration.encoder.encode(
Expand All @@ -222,7 +223,7 @@ public final class AuthClient: Sendable {
public func signInWithIdToken(credentials: OpenIDConnectCredentials) async throws -> Session {
try await _signIn(
request: .init(
path: "/token",
url: configuration.url.appendingPathComponent("token"),
method: .post,
query: [URLQueryItem(name: "grant_type", value: "id_token")],
body: configuration.encoder.encode(credentials)
Expand All @@ -242,8 +243,8 @@ public final class AuthClient: Sendable {
captchaToken: String? = nil
) async throws -> Session {
try await _signIn(
request: Request(
path: "/signup",
request: HTTPRequest(
url: configuration.url.appendingPathComponent("signup"),
method: .post,
body: configuration.encoder.encode(
SignUpRequest(
Expand All @@ -255,7 +256,7 @@ public final class AuthClient: Sendable {
)
}

private func _signIn(request: Request) async throws -> Session {
private func _signIn(request: HTTPRequest) async throws -> Session {
await sessionManager.remove()

let session = try await api.execute(request).decoded(
Expand Down Expand Up @@ -293,7 +294,7 @@ public final class AuthClient: Sendable {

_ = try await api.execute(
.init(
path: "/otp",
url: configuration.url.appendingPathComponent("otp"),
method: .post,
query: [
(redirectTo ?? configuration.redirectToURL).map { URLQueryItem(
Expand Down Expand Up @@ -336,7 +337,7 @@ public final class AuthClient: Sendable {
await sessionManager.remove()
_ = try await api.execute(
.init(
path: "/otp",
url: configuration.url.appendingPathComponent("otp"),
method: .post,
body: configuration.encoder.encode(
OTPParams(
Expand Down Expand Up @@ -368,8 +369,8 @@ public final class AuthClient: Sendable {
let (codeChallenge, codeChallengeMethod) = prepareForPKCE()

return try await api.execute(
Request(
path: "/sso",
HTTPRequest(
url: configuration.url.appendingPathComponent("sso"),
method: .post,
body: configuration.encoder.encode(
SignInWithSSORequest(
Expand Down Expand Up @@ -403,8 +404,8 @@ public final class AuthClient: Sendable {
let (codeChallenge, codeChallengeMethod) = prepareForPKCE()

return try await api.execute(
Request(
path: "/sso",
HTTPRequest(
url: configuration.url.appendingPathComponent("sso"),
method: .post,
body: configuration.encoder.encode(
SignInWithSSORequest(
Expand All @@ -429,7 +430,7 @@ public final class AuthClient: Sendable {

let session: Session = try await api.execute(
.init(
path: "/token",
url: configuration.url.appendingPathComponent("token"),
method: .post,
query: [URLQueryItem(name: "grant_type", value: "pkce")],
body: configuration.encoder.encode(
Expand Down Expand Up @@ -622,7 +623,7 @@ public final class AuthClient: Sendable {

let user = try await api.execute(
.init(
path: "/user",
url: configuration.url.appendingPathComponent("user"),
method: .get,
headers: ["Authorization": "\(tokenType) \(accessToken)"]
)
Expand Down Expand Up @@ -703,7 +704,7 @@ public final class AuthClient: Sendable {

try await api.authorizedExecute(
.init(
path: "/logout",
url: configuration.url.appendingPathComponent("logout"),
method: .post,
query: [URLQueryItem(name: "scope", value: scope.rawValue)]
)
Expand Down Expand Up @@ -737,7 +738,7 @@ public final class AuthClient: Sendable {
) async throws -> AuthResponse {
try await _verifyOTP(
request: .init(
path: "/verify",
url: configuration.url.appendingPathComponent("verify"),
method: .post,
query: [
(redirectTo ?? configuration.redirectToURL).map { URLQueryItem(
Expand Down Expand Up @@ -770,7 +771,7 @@ public final class AuthClient: Sendable {
) async throws -> AuthResponse {
try await _verifyOTP(
request: .init(
path: "/verify",
url: configuration.url.appendingPathComponent("verify"),
method: .post,
body: configuration.encoder.encode(
VerifyOTPParams.mobile(
Expand All @@ -788,7 +789,7 @@ public final class AuthClient: Sendable {
}

private func _verifyOTP(
request: Request,
request: HTTPRequest,
shouldRemoveSession: Bool
) async throws -> AuthResponse {
if shouldRemoveSession {
Expand Down Expand Up @@ -823,8 +824,8 @@ public final class AuthClient: Sendable {
}

_ = try await api.execute(
Request(
path: "/resend",
HTTPRequest(
url: configuration.url.appendingPathComponent("resend"),
method: .post,
query: [
(emailRedirectTo ?? configuration.redirectToURL).map { URLQueryItem(
Expand Down Expand Up @@ -860,8 +861,8 @@ public final class AuthClient: Sendable {
}

return try await api.execute(
Request(
path: "/resend",
HTTPRequest(
url: configuration.url.appendingPathComponent("resend"),
method: .post,
body: configuration.encoder.encode(
ResendMobileParams(
Expand All @@ -878,7 +879,10 @@ public final class AuthClient: Sendable {
/// Sends a re-authentication OTP to the user's email or phone number.
public func reauthenticate() async throws {
try await api.authorizedExecute(
Request(path: "/reauthenticate", method: .get)
HTTPRequest(
url: configuration.url.appendingPathComponent("reauthenticate"),
method: .get
)
)
}

Expand All @@ -889,7 +893,7 @@ public final class AuthClient: Sendable {
/// Should be used only when you require the most current user data. For faster results,
/// session.user is recommended.
public func user(jwt: String? = nil) async throws -> User {
var request = Request(path: "/user", method: .get)
var request = HTTPRequest(url: configuration.url.appendingPathComponent("user"), method: .get)

if let jwt {
request.headers["Authorization"] = "Bearer \(jwt)"
Expand All @@ -912,7 +916,11 @@ public final class AuthClient: Sendable {

var session = try await sessionManager.session()
let updatedUser = try await api.authorizedExecute(
.init(path: "/user", method: .put, body: configuration.encoder.encode(user))
.init(
url: configuration.url.appendingPathComponent("user"),
method: .put,
body: configuration.encoder.encode(user)
)
).decoded(as: User.self, decoder: configuration.decoder)
session.user = updatedUser
try await sessionManager.update(session)
Expand Down Expand Up @@ -954,7 +962,7 @@ public final class AuthClient: Sendable {
}

let response = try await api.authorizedExecute(
Request(
HTTPRequest(
url: url,
method: .get
)
Expand All @@ -968,8 +976,8 @@ public final class AuthClient: Sendable {
/// with that identity once it's unlinked.
public func unlinkIdentity(_ identity: UserIdentity) async throws {
try await api.authorizedExecute(
Request(
path: "/user/identities/\(identity.identityId)",
HTTPRequest(
url: configuration.url.appendingPathComponent("user/identities/\(identity.identityId)"),
method: .delete
)
)
Expand All @@ -985,7 +993,7 @@ public final class AuthClient: Sendable {

_ = try await api.execute(
.init(
path: "/recover",
url: configuration.url.appendingPathComponent("recover"),
method: .post,
query: [
(redirectTo ?? configuration.redirectToURL).map { URLQueryItem(
Expand Down Expand Up @@ -1019,7 +1027,7 @@ public final class AuthClient: Sendable {

let session = try await api.execute(
.init(
path: "/token",
url: configuration.url.appendingPathComponent("token"),
method: .post,
query: [URLQueryItem(name: "grant_type", value: "refresh_token")],
body: configuration.encoder.encode(credentials)
Expand Down
21 changes: 15 additions & 6 deletions Sources/Auth/AuthMFA.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Foundation

/// Contains the full multi-factor authentication API.
public struct AuthMFA: Sendable {
var configuration: AuthClient.Configuration { Current.configuration }
var api: APIClient { Current.api }
var encoder: JSONEncoder { Current.encoder }
var decoder: JSONDecoder { Current.decoder }
Expand All @@ -22,8 +23,9 @@ public struct AuthMFA: Sendable {
/// - Returns: An authentication response after enrolling the factor.
public func enroll(params: MFAEnrollParams) async throws -> AuthMFAEnrollResponse {
try await api.authorizedExecute(
Request(
path: "/factors", method: .post,
HTTPRequest(
url: configuration.url.appendingPathComponent("factors"),
method: .post,
body: encoder.encode(params)
)
)
Expand All @@ -36,7 +38,10 @@ public struct AuthMFA: Sendable {
/// - Returns: An authentication response with the challenge information.
public func challenge(params: MFAChallengeParams) async throws -> AuthMFAChallengeResponse {
try await api.authorizedExecute(
Request(path: "/factors/\(params.factorId)/challenge", method: .post)
HTTPRequest(
url: configuration.url.appendingPathComponent("factors/\(params.factorId)/challenge"),
method: .post
)
)
.decoded(decoder: decoder)
}
Expand All @@ -48,8 +53,9 @@ public struct AuthMFA: Sendable {
/// - Returns: An authentication response after verifying the factor.
public func verify(params: MFAVerifyParams) async throws -> AuthMFAVerifyResponse {
let response: AuthMFAVerifyResponse = try await api.authorizedExecute(
Request(
path: "/factors/\(params.factorId)/verify", method: .post,
HTTPRequest(
url: configuration.url.appendingPathComponent("factors/\(params.factorId)/verify"),
method: .post,
body: encoder.encode(params)
)
).decoded(decoder: decoder)
Expand All @@ -69,7 +75,10 @@ public struct AuthMFA: Sendable {
@discardableResult
public func unenroll(params: MFAUnenrollParams) async throws -> AuthMFAUnenrollResponse {
try await api.authorizedExecute(
Request(path: "/factors/\(params.factorId)", method: .delete)
HTTPRequest(
url: configuration.url.appendingPathComponent("factors/\(params.factorId)"),
method: .delete
)
)
.decoded(decoder: decoder)
}
Expand Down
Loading
Loading