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

chore: kickoff release #3411

Merged
merged 2 commits into from
Dec 8, 2023
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
13 changes: 11 additions & 2 deletions Amplify/Categories/Auth/AuthCategory+UserBehavior.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,19 @@ extension AuthCategory: AuthCategoryUserBehavior {
try await plugin.update(userAttributes: userAttributes, options: options)
}

public func resendConfirmationCode(forUserAttributeKey userAttributeKey: AuthUserAttributeKey,
options: AuthAttributeResendConfirmationCodeRequest.Options? = nil) async throws -> AuthCodeDeliveryDetails {
@available(*, deprecated, renamed: "sendVerificationCode(forUserAttributeKey:options:)")
public func resendConfirmationCode(
forUserAttributeKey userAttributeKey: AuthUserAttributeKey,
options: AuthAttributeResendConfirmationCodeRequest.Options? = nil
) async throws -> AuthCodeDeliveryDetails {
try await plugin.resendConfirmationCode(forUserAttributeKey: userAttributeKey, options: options)
}

public func sendVerificationCode(
forUserAttributeKey userAttributeKey: AuthUserAttributeKey,
options: AuthSendUserAttributeVerificationCodeRequest.Options? = nil
) async throws -> AuthCodeDeliveryDetails {
try await plugin.sendVerificationCode(forUserAttributeKey: userAttributeKey, options: options)
}

public func confirm(userAttribute: AuthUserAttributeKey,
Expand Down
17 changes: 15 additions & 2 deletions Amplify/Categories/Auth/AuthCategoryUserBehavior.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,21 @@ public protocol AuthCategoryUserBehavior: AnyObject {
/// - Parameters:
/// - userAttributeKey: Attribute to be verified
/// - options: Parameters specific to plugin behavior
func resendConfirmationCode(forUserAttributeKey userAttributeKey: AuthUserAttributeKey,
options: AuthAttributeResendConfirmationCodeRequest.Options?) async throws -> AuthCodeDeliveryDetails
@available(*, deprecated, renamed: "sendVerificationCode(forUserAttributeKey:options:)")
func resendConfirmationCode(
forUserAttributeKey userAttributeKey: AuthUserAttributeKey,
options: AuthAttributeResendConfirmationCodeRequest.Options?
) async throws -> AuthCodeDeliveryDetails

/// Sends the verification code required to verify an attribute
///
/// - Parameters:
/// - userAttributeKey: Attribute to be verified
/// - options: Parameters specific to plugin behavior
func sendVerificationCode(
forUserAttributeKey userAttributeKey: AuthUserAttributeKey,
options: AuthSendUserAttributeVerificationCodeRequest.Options?
) async throws -> AuthCodeDeliveryDetails

/// Confirm an attribute using confirmation code
///
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Foundation

// swiftlint:disable type_name

/// Request for sending verification code that was generated for update attribute
public struct AuthSendUserAttributeVerificationCodeRequest: AmplifyOperationRequest {

/// Attribute key for which the confirmation code was sent
public let attributeKey: AuthUserAttributeKey

/// Extra request options defined in `AuthSendUserAttributeVerificationCodeRequest.Options`
public var options: Options

public init(attributeKey: AuthUserAttributeKey,
options: Options) {
self.attributeKey = attributeKey
self.options = options
}
}

public extension AuthSendUserAttributeVerificationCodeRequest {

struct Options {

/// Extra plugin specific options, only used in special circumstances when the existing options do not provide
/// a way to utilize the underlying auth plugin functionality. See plugin documentation for expected
/// key/values
public let pluginOptions: Any?

public init(pluginOptions: Any? = nil) {
self.pluginOptions = pluginOptions
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,11 @@ public extension AWSCognitoAuthPlugin {
} as! [AuthUserAttributeKey: AuthUpdateAttributeResult]
}

func resendConfirmationCode(forUserAttributeKey userAttributeKey: AuthUserAttributeKey,
options: AuthAttributeResendConfirmationCodeRequest.Options? = nil) async throws -> AuthCodeDeliveryDetails {
@available(*, deprecated, renamed: "sendVerificationCode(forUserAttributeKey:options:)")
func resendConfirmationCode(
forUserAttributeKey userAttributeKey: AuthUserAttributeKey,
options: AuthAttributeResendConfirmationCodeRequest.Options? = nil
) async throws -> AuthCodeDeliveryDetails {

let options = options ?? AuthAttributeResendConfirmationCodeRequest.Options()
let request = AuthAttributeResendConfirmationCodeRequest(
Expand All @@ -53,6 +56,22 @@ public extension AWSCognitoAuthPlugin {
} as! AuthCodeDeliveryDetails
}

func sendVerificationCode(
forUserAttributeKey userAttributeKey:
AuthUserAttributeKey,
options: AuthSendUserAttributeVerificationCodeRequest.Options? = nil
) async throws -> AuthCodeDeliveryDetails {
let options = options ?? AuthSendUserAttributeVerificationCodeRequest.Options()
let request = AuthSendUserAttributeVerificationCodeRequest(
attributeKey: userAttributeKey, options: options)
let task = AWSAuthSendUserAttributeVerificationCodeTask(
request, authStateMachine: authStateMachine,
userPoolFactory: authEnvironment.cognitoUserPoolFactory)
return try await taskQueue.sync {
return try await task.value
} as! AuthCodeDeliveryDetails
}

func confirm(userAttribute: AuthUserAttributeKey, confirmationCode: String, options: AuthConfirmUserAttributeRequest.Options? = nil) async throws {
let options = options ?? AuthConfirmUserAttributeRequest.Options()
let request = AuthConfirmUserAttributeRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import Foundation

@available(*, deprecated, renamed: "AWSSendUserAttributeVerificationCodeOptions")
public struct AWSAttributeResendConfirmationCodeOptions {

/// A map of custom key-value pairs that you can provide as input for any custom workflows that this action triggers.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Foundation

public struct AWSSendUserAttributeVerificationCodeOptions {

/// A map of custom key-value pairs that you can provide as input for any custom workflows that this action triggers.
///
/// When you use the ResendConfirmationCode API action, Amazon Cognito invokes the function that is assigned to the custom message trigger.
/// When Amazon Cognito invokes this function, it passes a JSON payload, which the function receives as input.
/// This payload contains a clientMetadata attribute, which provides the data that you assigned to the ClientMetadata parameter in your GetUserAttributeVerificationCode request.
/// In your function code in AWS Lambda, you can process the clientMetadata value to enhance your workflow for your specific needs.
///
/// For more information, see Customizing user pool Workflows with Lambda Triggers in the Amazon Cognito Developer Guide.
public let metadata: [String: String]?

public init(metadata: [String: String]? = nil) {
self.metadata = metadata
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Amplify

protocol AuthSendUserAttributeVerificationCodeTask: AmplifyAuthTask where Request == AuthSendUserAttributeVerificationCodeRequest, Success == AuthCodeDeliveryDetails, Failure == AuthError {}

public extension HubPayload.EventName.Auth {

/// eventName for HubPayloads emitted by this operation
static let sendUserAttributeVerificationCodeAPI = "Auth.sendUserAttributeVerificationCodeAPI"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Foundation
import Amplify
import AWSPluginsCore
import AWSCognitoIdentityProvider

class AWSAuthSendUserAttributeVerificationCodeTask: AuthSendUserAttributeVerificationCodeTask {
typealias CognitoUserPoolFactory = () throws -> CognitoUserPoolBehavior

private let request: AuthSendUserAttributeVerificationCodeRequest
private let authStateMachine: AuthStateMachine
private let userPoolFactory: CognitoUserPoolFactory
private let taskHelper: AWSAuthTaskHelper

var eventName: HubPayloadEventName {
HubPayload.EventName.Auth.sendUserAttributeVerificationCodeAPI
}

init(_ request: AuthSendUserAttributeVerificationCodeRequest,
authStateMachine: AuthStateMachine,
userPoolFactory: @escaping CognitoUserPoolFactory) {
self.request = request
self.authStateMachine = authStateMachine
self.userPoolFactory = userPoolFactory
self.taskHelper = AWSAuthTaskHelper(authStateMachine: authStateMachine)
}

func execute() async throws -> AuthCodeDeliveryDetails {
do {
await taskHelper.didStateMachineConfigured()
let accessToken = try await taskHelper.getAccessToken()
let devices = try await initiateGettingVerificationCode(with: accessToken)
return devices
} catch let error as AuthErrorConvertible {
throw error.authError
} catch {
throw AuthError.configuration(
"Unable to execute auth task",
AuthPluginErrorConstants.configurationError,
error
)
}
}

func initiateGettingVerificationCode(with accessToken: String) async throws -> AuthCodeDeliveryDetails {
let userPoolService = try userPoolFactory()
let clientMetaData = (request.options.pluginOptions as? AWSSendUserAttributeVerificationCodeOptions)?.metadata ?? [:]

let input = GetUserAttributeVerificationCodeInput(
accessToken: accessToken,
attributeName: request.attributeKey.rawValue,
clientMetadata: clientMetaData)

let result = try await userPoolService.getUserAttributeVerificationCode(input: input)
guard let deliveryDetails = result.codeDeliveryDetails?.toAuthCodeDeliveryDetails() else {
let authError = AuthError.unknown("Unable to get Auth code delivery details", nil)
throw authError
}
return deliveryDetails
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,36 +136,36 @@ class AWSCognitoAuthUserBehaviorTests: BasePluginTest {
_ = try await plugin.update(userAttributes: [emailAttribute, phoneAttribute])
}

/// Test resendConfirmationCode(for:) operation can be invoked
/// Test sendVerificationCode(for:) operation can be invoked
///
/// - Given: Given a configured auth plugin
/// - When:
/// - I call resendConfirmationCode(for:) operation
/// - I call sendVerificationCode(for:) operation
/// - Then:
/// - I should get a valid task completion
///
func testResendConfirmationCodeAttributeRequest() async throws {
func testSendVerificationCodeAttributeRequest() async throws {
mockIdentityProvider = MockIdentityProvider(mockGetUserAttributeVerificationCodeOutput: { _ in
GetUserAttributeVerificationCodeOutput(
codeDeliveryDetails: .init(
attributeName: "attributeName",
deliveryMedium: .email,
destination: "destination"))
})
let pluginOptions = AWSAttributeResendConfirmationCodeOptions(metadata: ["key": "value"])
let options = AuthAttributeResendConfirmationCodeRequest.Options(pluginOptions: pluginOptions)
_ = try await plugin.resendConfirmationCode(forUserAttributeKey: .email, options: options)
let pluginOptions = AWSSendUserAttributeVerificationCodeOptions(metadata: ["key": "value"])
let options = AuthSendUserAttributeVerificationCodeRequest.Options(pluginOptions: pluginOptions)
_ = try await plugin.sendVerificationCode(forUserAttributeKey: .email, options: options)
}

/// Test resendConfirmationCode(for:) operation can be invoked with plugin options
/// Test sendVerificationCode(for:) operation can be invoked with plugin options
///
/// - Given: Given a configured auth plugin
/// - When:
/// - I call resendConfirmationCode(for:) operation
/// - I call sendVerificationCode(for:) operation
/// - Then:
/// - I should get a valid task completion
///
func testResendConfirmationCodeWithPluginOptions() async throws {
func testSendVerificationCodeWithPluginOptions() async throws {
mockIdentityProvider = MockIdentityProvider(mockGetUserAttributeVerificationCodeOutput: { request in

XCTAssertNotNil(request.clientMetadata)
Expand All @@ -176,28 +176,28 @@ class AWSCognitoAuthUserBehaviorTests: BasePluginTest {
deliveryMedium: .email,
destination: "destination"))
})
let pluginOptions = AWSAttributeResendConfirmationCodeOptions(metadata: ["key": "value"])
let options = AuthAttributeResendConfirmationCodeRequest.Options(pluginOptions: pluginOptions)
_ = try await plugin.resendConfirmationCode(forUserAttributeKey: .email, options: options)
let pluginOptions = AWSSendUserAttributeVerificationCodeOptions(metadata: ["key": "value"])
let options = AuthSendUserAttributeVerificationCodeRequest.Options(pluginOptions: pluginOptions)
_ = try await plugin.sendVerificationCode(forUserAttributeKey: .email, options: options)
}

/// Test resendConfirmationCode(for:) operation can be invoked without options
/// Test sendVerificationCode(for:) operation can be invoked without options
///
/// - Given: Given a configured auth plugin
/// - When:
/// - I call resendConfirmationCode(for:) operation
/// - I call sendVerificationCode(for:) operation
/// - Then:
/// - I should get a valid task completion
///
func testResendConfirmationCodeAttributeRequestWithoutOptions() async throws {
func testSendVerificationCodeAttributeRequestWithoutOptions() async throws {
mockIdentityProvider = MockIdentityProvider(mockGetUserAttributeVerificationCodeOutput: { _ in
GetUserAttributeVerificationCodeOutput(
codeDeliveryDetails: .init(
attributeName: "attributeName",
deliveryMedium: .email,
destination: "destination"))
})
_ = try await plugin.resendConfirmationCode(forUserAttributeKey: .email)
_ = try await plugin.sendVerificationCode(forUserAttributeKey: .email)
}

/// Test confirm(userAttribute: ) operation can be invoked
Expand Down
Loading
Loading