Skip to content

Commit a374581

Browse files
Initial cognito trigger support (#27)
* Initial cognito trigger support * Fix up formatting
1 parent 40a2be9 commit a374581

File tree

4 files changed

+281
-0
lines changed

4 files changed

+281
-0
lines changed

Sources/AWSLambdaEvents/Cognito.swift

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftAWSLambdaRuntime open source project
4+
//
5+
// Copyright (c) 2017-2022 Apple Inc. and the SwiftAWSLambdaRuntime project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
enum CognitoEventError: Error {
16+
case unimplementedEvent(String)
17+
}
18+
19+
/// https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html
20+
public enum CognitoEvent: Equatable {
21+
public struct CallerContext: Codable, Hashable {
22+
let awsSdkVersion: String
23+
let clientId: String
24+
}
25+
26+
public struct Parameters: Codable, Equatable {
27+
let version: String
28+
let triggerSource: String
29+
let region: AWSRegion
30+
let userPoolId: String
31+
let userName: String
32+
let callerContext: CallerContext
33+
}
34+
35+
case preSignUpSignUp(Parameters, PreSignUp)
36+
37+
public struct PreSignUp: Codable, Hashable {
38+
/// One or more name-value pairs representing user attributes. The attribute names are the keys.
39+
public let userAttributes: [String: String]
40+
/// One or more name-value pairs containing the validation data in the request to register a user.
41+
///
42+
/// The validation data is set and then passed from the client in the request to register a user. You can pass this data to your Lambda function by using the ClientMetadata parameter in the InitiateAuth and AdminInitiateAuth API actions.
43+
public let validationData: [String: String]?
44+
/// One or more key-value pairs that you can provide as custom input to the Lambda function that you specify for the pre sign-up trigger.
45+
///
46+
/// You can pass this data to your Lambda function by using the ClientMetadata parameter in the following API actions: AdminCreateUser, AdminRespondToAuthChallenge, ForgotPassword, and SignUp.
47+
public let clientMetadata: [String: String]?
48+
}
49+
50+
public var commonParameters: Parameters {
51+
switch self {
52+
case .preSignUpSignUp(let params, _):
53+
return params
54+
}
55+
}
56+
}
57+
58+
extension CognitoEvent: Codable {
59+
public enum CodingKeys: String, CodingKey {
60+
case version
61+
case triggerSource
62+
case region
63+
case userPoolId
64+
case userName
65+
case callerContext
66+
case request
67+
case response
68+
}
69+
70+
public init(from decoder: Decoder) throws {
71+
let container = try decoder.container(keyedBy: CodingKeys.self)
72+
73+
let version = try container.decode(String.self, forKey: .version)
74+
let triggerSource = try container.decode(String.self, forKey: .triggerSource)
75+
let region = try container.decode(AWSRegion.self, forKey: .region)
76+
let userPoolId = try container.decode(String.self, forKey: .userPoolId)
77+
let userName = try container.decode(String.self, forKey: .userName)
78+
let callerContext = try container.decode(CallerContext.self, forKey: .callerContext)
79+
80+
let params = CognitoEvent.Parameters(version: version, triggerSource: triggerSource, region: region, userPoolId: userPoolId, userName: userName, callerContext: callerContext)
81+
82+
switch triggerSource {
83+
case "PreSignUp_SignUp":
84+
let value = try container.decode(CognitoEvent.PreSignUp.self, forKey: .request)
85+
86+
self = .preSignUpSignUp(params, value)
87+
default:
88+
throw CognitoEventError.unimplementedEvent(triggerSource)
89+
}
90+
}
91+
92+
public func encode(to encoder: Encoder) throws {
93+
var container = encoder.container(keyedBy: CodingKeys.self)
94+
95+
let params = self.commonParameters
96+
97+
try container.encode(params.version, forKey: .version)
98+
try container.encode(params.triggerSource, forKey: .triggerSource)
99+
try container.encode(params.region, forKey: .region)
100+
try container.encode(params.userPoolId, forKey: .userPoolId)
101+
try container.encode(params.userName, forKey: .userName)
102+
try container.encode(params.callerContext, forKey: .callerContext)
103+
104+
switch self {
105+
case .preSignUpSignUp(_, let value):
106+
try container.encode(value, forKey: .response)
107+
}
108+
}
109+
}
110+
111+
public enum CognitoEventResponse {
112+
case preSignUpSignUp(CognitoEvent.Parameters, CognitoEvent.PreSignUp, PreSignUp)
113+
114+
public struct PreSignUp: Codable, Hashable {
115+
public let autoConfirmUser: Bool
116+
public let autoVerifyPhone: Bool
117+
public let autoVerifyEmail: Bool
118+
119+
public init(autoConfirmUser: Bool, autoVerifyPhone: Bool, autoVerifyEmail: Bool) {
120+
self.autoConfirmUser = autoConfirmUser
121+
self.autoVerifyPhone = autoVerifyPhone
122+
self.autoVerifyEmail = autoVerifyEmail
123+
}
124+
}
125+
126+
public var commonParameters: CognitoEvent.Parameters {
127+
switch self {
128+
case .preSignUpSignUp(let params, _, _):
129+
return params
130+
}
131+
}
132+
}
133+
134+
extension CognitoEventResponse: Codable {
135+
public enum CodingKeys: String, CodingKey {
136+
case version
137+
case triggerSource
138+
case region
139+
case userPoolId
140+
case userName
141+
case callerContext
142+
case request
143+
case response
144+
}
145+
146+
public init(from decoder: Decoder) throws {
147+
let container = try decoder.container(keyedBy: CodingKeys.self)
148+
149+
let version = try container.decode(String.self, forKey: .version)
150+
let triggerSource = try container.decode(String.self, forKey: .triggerSource)
151+
let region = try container.decode(AWSRegion.self, forKey: .region)
152+
let userPoolId = try container.decode(String.self, forKey: .userPoolId)
153+
let userName = try container.decode(String.self, forKey: .userName)
154+
let callerContext = try container.decode(CognitoEvent.CallerContext.self, forKey: .callerContext)
155+
156+
let params = CognitoEvent.Parameters(version: version, triggerSource: triggerSource, region: region, userPoolId: userPoolId, userName: userName, callerContext: callerContext)
157+
158+
switch triggerSource {
159+
case "PreSignUp_SignUp":
160+
let request = try container.decode(CognitoEvent.PreSignUp.self, forKey: .request)
161+
let response = try container.decode(CognitoEventResponse.PreSignUp.self, forKey: .response)
162+
163+
self = .preSignUpSignUp(params, request, response)
164+
default:
165+
throw CognitoEventError.unimplementedEvent(triggerSource)
166+
}
167+
}
168+
169+
public func encode(to encoder: Encoder) throws {
170+
var container = encoder.container(keyedBy: CodingKeys.self)
171+
172+
let params = self.commonParameters
173+
174+
try container.encode(params.version, forKey: .version)
175+
try container.encode(params.triggerSource, forKey: .triggerSource)
176+
try container.encode(params.region, forKey: .region)
177+
try container.encode(params.userPoolId, forKey: .userPoolId)
178+
try container.encode(params.userName, forKey: .userName)
179+
try container.encode(params.callerContext, forKey: .callerContext)
180+
181+
switch self {
182+
case .preSignUpSignUp(_, let request, let response):
183+
try container.encode(request, forKey: .request)
184+
try container.encode(response, forKey: .response)
185+
}
186+
}
187+
}

Sources/AWSLambdaEvents/Docs.docc/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ AWS Lambda functions can be invoked directly from the AWS Lambda console UI, AWS
1818
* [SNS Events](https://docs.aws.amazon.com/lambda/latest/dg/with-sns.html)
1919
* [SQS Events](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html)
2020
* [CloudWatch Events](https://docs.aws.amazon.com/lambda/latest/dg/services-cloudwatchevents.html)
21+
* [Cognito Lambda Triggers](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html)
2122

2223
**Note**: Each one of the integration points mentioned above includes a set of `Codable` structs that mirror AWS' data model for these APIs.
2324

@@ -38,3 +39,4 @@ Swift AWS Lambda Events is a supporting library for the [Swift AWS Lambda Runtim
3839
- ``SESEvent``
3940
- ``SNSEvent``
4041
- ``SQSEvent``
42+
- ``CognitoEvent``
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftAWSLambdaRuntime open source project
4+
//
5+
// Copyright (c) 2017-2020 Apple Inc. and the SwiftAWSLambdaRuntime project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
@testable import AWSLambdaEvents
16+
import XCTest
17+
18+
final class CognitoTests: XCTestCase {
19+
func testPreSignUpRequest() throws {
20+
let json = """
21+
{
22+
"version": "1",
23+
"triggerSource": "PreSignUp_SignUp",
24+
"region": "us-east-1",
25+
"userPoolId": "abc",
26+
"userName": "blob",
27+
"callerContext": {
28+
"awsSdkVersion": "1",
29+
"clientId": "abc",
30+
},
31+
"request": {
32+
"userAttributes": {
33+
"string": "string"
34+
},
35+
"validationData": {
36+
"string": "string"
37+
},
38+
"clientMetadata": {
39+
"string": "string"
40+
}
41+
},
42+
43+
"response": {}
44+
}
45+
"""
46+
let event = try JSONDecoder().decode(CognitoEvent.self, from: json.data(using: .utf8)!)
47+
48+
guard case .preSignUpSignUp(let params, let request) = event else {
49+
XCTFail()
50+
return
51+
}
52+
53+
XCTAssertEqual(params.triggerSource, "PreSignUp_SignUp")
54+
55+
let signUp = CognitoEvent.PreSignUp(userAttributes: ["string": "string"],
56+
validationData: ["string": "string"],
57+
clientMetadata: ["string": "string"])
58+
XCTAssertEqual(request, signUp)
59+
}
60+
61+
func testPreSignUpResponse() throws {
62+
let params = CognitoEvent.Parameters(version: "1",
63+
triggerSource: "PreSignUp_SignUp",
64+
region: .us_east_1,
65+
userPoolId: "abc",
66+
userName: "blob",
67+
callerContext: .init(awsSdkVersion: "1", clientId: "abc"))
68+
let request = CognitoEvent.PreSignUp(userAttributes: ["string": "string"],
69+
validationData: ["string": "string"],
70+
clientMetadata: ["string": "string"])
71+
72+
let signUpResponse = CognitoEventResponse.PreSignUp(autoConfirmUser: true,
73+
autoVerifyPhone: true,
74+
autoVerifyEmail: true)
75+
76+
let response = CognitoEventResponse.preSignUpSignUp(params, request, signUpResponse)
77+
78+
let data = try JSONEncoder().encode(response)
79+
80+
let decodedResponse = try JSONDecoder().decode(CognitoEventResponse.self, from: data)
81+
82+
guard case .preSignUpSignUp(let decodedParams, let decodedRequest, let decodedResponse) = decodedResponse else {
83+
XCTFail()
84+
return
85+
}
86+
87+
XCTAssertEqual(decodedParams, params)
88+
XCTAssertEqual(decodedRequest, request)
89+
XCTAssertEqual(decodedResponse, signUpResponse)
90+
}
91+
}

readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ AWS Lambda functions can be invoked directly from the AWS Lambda console UI, AWS
1616
* [SNS Events](https://docs.aws.amazon.com/lambda/latest/dg/with-sns.html)
1717
* [SQS Events](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html)
1818
* [CloudWatch Events](https://docs.aws.amazon.com/lambda/latest/dg/services-cloudwatchevents.html)
19+
* [Cognito Lambda Triggers](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html)
1920

2021
**Note**: Each one of the integration points mentioned above includes a set of `Codable` structs that mirror AWS' data model for these APIs.
2122

0 commit comments

Comments
 (0)