Skip to content

Commit

Permalink
feat(auth): add resend method (#190)
Browse files Browse the repository at this point in the history
  • Loading branch information
grdsdev authored Dec 14, 2023
1 parent 7ec9d60 commit ec07c95
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 0 deletions.
64 changes: 64 additions & 0 deletions Sources/Auth/AuthClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,70 @@ public actor AuthClient {
return response
}

/// Resends an existing signup confirmation email or email change email.
///
/// To obfuscate whether such the email already exists in the system this method succeeds in both
/// cases.
public func resend(
email: String,
type: ResendEmailType,
emailRedirectTo: URL? = nil,
captchaToken: String? = nil
) async throws {
if type != .emailChange {
await sessionManager.remove()
}

_ = try await api.execute(
Request(
path: "/resend",
method: .post,
query: [
emailRedirectTo.map { URLQueryItem(name: "redirect_to", value: $0.absoluteString) },
].compactMap { $0 },
body: configuration.encoder.encode(
ResendEmailParams(
type: type,
email: email,
gotrueMetaSecurity: captchaToken.map(AuthMetaSecurity.init(captchaToken:))
)
)
)
)
}

/// Resends an existing SMS OTP or phone change OTP.
/// - Returns: An object containing the unique ID of the message as reported by the SMS sending
/// provider. Useful for tracking deliverability problems.
///
/// To obfuscate whether such the phone number already exists in the system this method succeeds
/// in both cases.
@discardableResult
public func resend(
phone: String,
type: ResendMobileType,
captchaToken: String? = nil
) async throws -> ResendMobileResponse {
if type != .phoneChange {
await sessionManager.remove()
}

return try await api.execute(
Request(
path: "/resend",
method: .post,
body: configuration.encoder.encode(
ResendMobileParams(
type: type,
phone: phone,
gotrueMetaSecurity: captchaToken.map(AuthMetaSecurity.init(captchaToken:))
)
)
)
)
.decoded(decoder: configuration.decoder)
}

/// Gets the current user details if there is an existing session.
/// - Parameter jwt: Takes in an optional access token jwt. If no jwt is provided, user() will
/// attempt to get the jwt from the current session.
Expand Down
32 changes: 32 additions & 0 deletions Sources/Auth/Types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -586,3 +586,35 @@ public enum SignOutScope: String, Sendable {
/// session.
case others
}

public enum ResendEmailType: String, Hashable, Sendable, Encodable {
case signup
case emailChange = "email_change"
}

struct ResendEmailParams: Encodable {
let type: ResendEmailType
let email: String
let gotrueMetaSecurity: AuthMetaSecurity?
}

public enum ResendMobileType: String, Hashable, Sendable, Encodable {
case sms
case phoneChange = "phone_change"
}

struct ResendMobileParams: Encodable {
let type: ResendMobileType
let phone: String
let gotrueMetaSecurity: AuthMetaSecurity?
}

public struct ResendMobileResponse: Decodable, Hashable, Sendable {
/// Unique ID of the message as reported by the SMS sending provider. Useful for tracking
/// deliverability problems.
public let messageId: String?

public init(messageId: String?) {
self.messageId = messageId
}
}
25 changes: 25 additions & 0 deletions Tests/AuthTests/RequestsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,31 @@ final class RequestsTests: XCTestCase {
}
}

func testResendEmail() async {
let sut = makeSUT()

await assert {
try await sut.resend(
email: "[email protected]",
type: .emailChange,
emailRedirectTo: URL(string: "https://supabase.com"),
captchaToken: "captcha-token"
)
}
}

func testResendPhone() async {
let sut = makeSUT()

await assert {
try await sut.resend(
phone: "+1 202-918-2132",
type: .phoneChange,
captchaToken: "captcha-token"
)
}
}

private func assert(_ block: () async throws -> Void) async {
do {
try await block()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
curl \
--request POST \
--header "Content-Type: application/json" \
--header "X-Client-Info: gotrue-swift/x.y.z" \
--header "apikey: dummy.api.key" \
--data "{\"email\":\"[email protected]\",\"gotrue_meta_security\":{\"captcha_token\":\"captcha-token\"},\"type\":\"email_change\"}" \
"http://localhost:54321/auth/v1/resend?redirect_to=https://supabase.com"
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
curl \
--request POST \
--header "Content-Type: application/json" \
--header "X-Client-Info: gotrue-swift/x.y.z" \
--header "apikey: dummy.api.key" \
--data "{\"gotrue_meta_security\":{\"captcha_token\":\"captcha-token\"},\"phone\":\"+1 202-918-2132\",\"type\":\"phone_change\"}" \
"http://localhost:54321/auth/v1/resend"

0 comments on commit ec07c95

Please sign in to comment.