Skip to content
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
1 change: 1 addition & 0 deletions examples/basic-cognito-post-confirmation/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
24 changes: 24 additions & 0 deletions examples/basic-cognito-post-confirmation/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "basic-cognito-post-confirmation"
version = "0.1.0"
edition = "2021"

# Starting in Rust 1.62 you can use `cargo add` to add dependencies
# to your project.
#
# If you're using an older Rust version,
# download cargo-edit(https://github.com/killercup/cargo-edit#installation)
# to install the `add` subcommand.
#
# Running `cargo add DEPENDENCY_NAME` will
# add the latest version of a dependency to the list,
# and it will keep the alphabetic ordering for you.

[dependencies]
aws-config = "1.5.0"
aws-sdk-ses = "1.28.0"
aws_lambda_events = { path = "../../lambda-events", default-features = false, features = ["cognito"] }

lambda_runtime = { path = "../../lambda-runtime" }
tokio = { version = "1", features = ["macros"] }

15 changes: 15 additions & 0 deletions examples/basic-cognito-post-confirmation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Cognito Post Confirmation Request example

This example shows how to write a Lambda function in Rust to process Cognito's Post Confirmation requests.

This is a translation of the example in the AWS Docs to Rust: https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-post-confirmation.html#aws-lambda-triggers-post-confirmation-example

## Build & Deploy

1. Install [cargo-lambda](https://github.com/cargo-lambda/cargo-lambda#installation)
2. Build the function with `cargo lambda build --release`
3. Deploy the function to AWS Lambda with `cargo lambda deploy`

## Build for ARM 64

Build the function with `cargo lambda build --release --arm64`
60 changes: 60 additions & 0 deletions examples/basic-cognito-post-confirmation/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use aws_config::BehaviorVersion;
use aws_lambda_events::event::cognito::CognitoEventUserPoolsPostConfirmation;
use aws_sdk_ses::{
types::{Body, Content, Destination, Message},
Client,
};
use lambda_runtime::{run, service_fn, tracing, Error, LambdaEvent};

const SOURCE_EMAIL: &str = "<source_email>";

async fn function_handler(
client: &aws_sdk_ses::Client,
event: LambdaEvent<CognitoEventUserPoolsPostConfirmation>,
) -> Result<CognitoEventUserPoolsPostConfirmation, Error> {
let payload = event.payload;

if let Some(email) = payload.request.user_attributes.get("email") {
let body = if let Some(name) = payload.request.user_attributes.get("name") {
format!("Welcome {name}, you have been confirmed.")
} else {
"Welcome, you have been confirmed.".to_string()
};
send_post_confirmation_email(client, email, "Cognito Identity Provider registration completed", &body).await?;
}

// Cognito always expect a response with the same shape as
// the event when it handles Post Confirmation triggers.
Ok(payload)
}

async fn send_post_confirmation_email(client: &Client, email: &str, subject: &str, body: &str) -> Result<(), Error> {
let destination = Destination::builder().to_addresses(email).build();
let subject = Content::builder().data(subject).build()?;
let body = Content::builder().data(body).build()?;

let message = Message::builder()
.body(Body::builder().text(body).build())
.subject(subject)
.build();

client
.send_email()
.source(SOURCE_EMAIL)
.destination(destination)
.message(message)
.send()
.await?;

Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Error> {
tracing::init_default_subscriber();

let config = aws_config::load_defaults(BehaviorVersion::latest()).await;
let client = Client::new(&config);

run(service_fn(|event| function_handler(&client, event))).await
}
10 changes: 8 additions & 2 deletions lambda-events/src/event/cognito/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,18 @@ pub enum CognitoEventUserPoolsPreAuthenticationTriggerSource {
/// allowing the Lambda to send custom messages or add custom logic.
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CognitoEventUserPoolsPostConfirmation {
pub struct CognitoEventUserPoolsPostConfirmation<T = CognitoEventUserPoolsPostConfirmationResponse>
where
T: DeserializeOwned,
T: Serialize,
{
#[serde(rename = "CognitoEventUserPoolsHeader")]
#[serde(flatten)]
pub cognito_event_user_pools_header:
CognitoEventUserPoolsHeader<CognitoEventUserPoolsPostConfirmationTriggerSource>,
pub request: CognitoEventUserPoolsPostConfirmationRequest,
pub response: CognitoEventUserPoolsPostConfirmationResponse,
#[serde(bound = "")]
pub response: T,
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, Default)]
Expand Down Expand Up @@ -254,6 +259,7 @@ pub struct CognitoEventUserPoolsPostConfirmationRequest {
/// `CognitoEventUserPoolsPostConfirmationResponse` contains the response portion of a PostConfirmation event
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
pub struct CognitoEventUserPoolsPostConfirmationResponse {}

/// `CognitoEventUserPoolsPreTokenGenRequest` contains request portion of PreTokenGen event
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
Expand Down