Simple Leave Management System with AWS Serverless
Tags: showdev, aws, serverless, cdk
Published: 2022-05-09 22:03:24

In this project, I will discuss how you can build a simple leave apply/approval system using AWS Serverless services.

These are the main functionalities of this implementation.

1. Apply for a leave
2. Confirmation for leave application.
3. Send notification to the approver regarding new leave request.
4. Send reminder notification to the approver.
5. Send notification upon approval/rejection.

And below services/functionalities are in use in this project:

1. Step functions [SDK integrations](https://docs.aws.amazon.com/step-functions/latest/dg/supported-services-awssdk.html) for SES, DynamoDB
2. Step functions [Parallel processing](https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-parallel-state.html)
3. Step functions [wait for callback pattern](https://docs.aws.amazon.com/step-functions/latest/dg/connect-to-resource.html#connect-wait-token)
4. Lambda [function URLs](https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html)
5. DynamoDB [streams](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.html) with [filtering](https://aws.amazon.com/blogs/compute/filtering-event-sources-for-aws-lambda-functions/)
6. AWS [CDK](https://docs.aws.amazon.com/cdk/v2/guide/home.html) with TypeScript as IAC


## Architecture

![Architecture - Simple Leave System](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h67eelktclui15z9pm44.png)

#### State Machine

![State machine](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8nrtg0xhg96b8hm7xcz8.png)

## How it works
### Create a leave request
1. CreateLeave Lambda function accepts leave requester's email, leave approver's email, leave dates and reason and is responsible to validate and save it to the DyanmoDB table.
2. Lambda function url is enabled for CreateLeave Lambda function.
3. Simple web form is created to simulate creation of leave request which is hosted using Amplify Web Hosting.

### Leave request processing
1. When a leave request is saved into the DynamoDB table, using DynamoDB steams, Init Lambda function is triggered.
2. Here, event source mapping is enabled with filtering, so that only the event type INSERT, record type 'leaveRequest' and record status 'pending' will trigger the lambda function.
3. This Init Lambda function's only responsibility is to format the input and start new Step Function execution.
4. Within step function first step is to send a email notification to the leave applicant to inform the receipt of the request. For this, Step function SDK integration for SES v2 is used.
5. Next, there are 2 branches runs parallel. One for leave reject/approval flow, and the other is to remind the approver about leave request until being processed.

**Leave reject/approval flow**
6. In the leave reject/approval flow, first an email will be send to the approver with the leave information and link to mark the leave as approved or rejected. This step has wait for the task token option enabled.
7. This link is generated as the function url of the LeaveApproveOrReject Lambda function.
8. Also, this link consist of the task token generated in the step, so in the LeaveApproveOrReject Lambda function, based on the reject/approval selection, it can call sendTaskSuccess or sendTaskFailure APIs.
9. If the leave is approved with sendTaskSuccess, then the record in the DynamoDB table will be updated using the Step function SDK integration for DynamoDB.
10. If the leave is rejected with sendTaskFailure, then there is an additional step to transform the error object before update the record in the DynamoDB table.
11. As the final step of that branch, an email will be sent to the applicant with the outcome of the processed leave request.

**Reminder flow**
1. In the other branch, it starts with a wait status which has a pre-configured wait time before sending the reminder.
2. After the wait time, it checks the status of the leave request using Step function SDK integration for DynamoDB.
3. Then it checks if the leave request status is pending.
4. If the status is pending, it sends an email to the approver reminding the leave request using Step function SDK integration for SES v2.
5. And the flow goes back to the wait step in order to retry later.
6. If the leave request is not in pending status, it goes into a Pass step to conclude the flow there.
7. With this, until the leave request is being processed, a reminder will be sent to the approver in regular interval defined by the wait time.

**Email Notifications**

_Leave Request Confirmation:_
![Leave request confirmation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jc5d1j28fy6tpao4eayv.png)

_Leave approver notification:_
![Leave approver notification](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bj5zwgxa6gszvywcdvpd.png)

_Leave approver reminder:_
![Leave approver reminder](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fj1gbt1oomfov9e6c7ik.png)


## How to set up
This project is implemented using AWS CDK v2.
Source code of this application is available at [https://github.com/pubudusj/simple-leave-management](https://github.com/pubudusj/simple-leave-management)

**Prerequisites:**
1. AWS CDK CLI (2.22.0+)
2. Verified from-email address in SES

**Installation:**
1. Clone the repository.
2. Update the `Makefile` with the sending email for SES and AWS CLI profile (if required).
3. Run `make build` to install required dependancies.
4. Run `make deploy` to deploy the stacks.
5. Once deployed, using the `HostingUrl` output value of CreateLeaveFrontendStack, you can access the frontend application to create a leave request.

**Remove the stack:**
1. Run `make destroy` to remove all the resources of the project.

## Key points/Lessons learned
1. SES by default in sandbox mode and only verified email addresses can receive emails. You need to raise a support ticket from your account to take it out of the sandbox mode so you can send emails to any address.
2. This is the first time I used CDK in a project and I am so much impressed how easy it is to deploy Serverless resources with it. This deserves a separate blog post :)
3. I have used few CDK modules which are still in alpha version (ex: aws-amplify-alpha). Those functionalities might be changed without prior notice.
4. Here, for demo purposes, Lambda function urls are not protected and can be triggered as public url. For a production system, those needs to be protected with `AWS_IAM` auth type.
5. To deploy the frontend in Amplify Web Hosting, locally built artifacts are used here. However, it is better to build this as part of a CI/CD pipeline where source code is fetched from Github.
6. For demo purposes, retry interval is set to 2 minutes. So, every 2 minutes the approver will get an email until leave request is processed.
7. Init Lambda function is only one from many other alternatives to trigger the step function (ex: event bridge rule).

## Feedbacks are welcome
Please feel free to deploy this to your own AWS environment and share your experience with me. And you can connect with me in LinkedIn: https://www.linkedin.com/in/pubudusj and Twitter https://twitter.com/pubudusj

Keep building! Keep sharing!