Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
df77ed1
refactor: update resources name with stack name
UmaxCode Jan 14, 2025
1302e5d
update workflow pipeline.yaml
UmaxCode Jan 14, 2025
940344b
update workflow pipeline.yaml
UmaxCode Jan 14, 2025
444ca8c
update workflow pipeline.yaml with hosted callback urls
UmaxCode Jan 14, 2025
c2af932
update workflow pipeline.yaml with hosted callback urls
UmaxCode Jan 14, 2025
e1aaa52
refactor: update cors allowed origins
UmaxCode Jan 14, 2025
0a00569
refactor: update resource name
UmaxCode Jan 14, 2025
80a6837
refactor: provide task table name for testing and production environment
UmaxCode Jan 14, 2025
2471e8b
feat: add sns service
UmaxCode Jan 15, 2025
1afd536
refactor: update lambda handler with sns service
UmaxCode Jan 15, 2025
86ed3cb
feat: add admin creation during stack creation
UmaxCode Jan 15, 2025
fb03353
refactor: update invite message template
UmaxCode Jan 15, 2025
f823cec
refactor: update condition expression parameter
UmaxCode Jan 16, 2025
60c9a13
refactor: update endpoint return type
UmaxCode Jan 16, 2025
e3fc75b
refactor: update response object
UmaxCode Jan 16, 2025
bf7e715
refactor: update user creation response type and user mapper function
UmaxCode Jan 16, 2025
c9d548c
refactor: return the right userId
UmaxCode Jan 16, 2025
b11d96a
refactor: update response message
UmaxCode Jan 16, 2025
f56d32d
refactor: update invite message
UmaxCode Jan 17, 2025
f440409
chore: update README.md
UmaxCode Jan 17, 2025
586f29a
fix: fix isNotifiedForApproachDeadline state when task is reassigned
UmaxCode Jan 17, 2025
8ba24e9
fix: fix isNotifiedForApproachDeadline state type mismatch error
UmaxCode Jan 17, 2025
398fa64
feat: add validation to request body and method renaming
UmaxCode Jan 17, 2025
1ffd303
feat: add validation to request body
UmaxCode Jan 17, 2025
f87291b
feat: update global exception handler
UmaxCode Jan 17, 2025
6b9828a
refactor: add response status to exception handler
UmaxCode Jan 17, 2025
e22d10b
fix: fix resource not found response status
UmaxCode Jan 17, 2025
556d126
chore: update README.md
UmaxCode Jan 17, 2025
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
7 changes: 4 additions & 3 deletions .github/workflows/pipeline.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- 'main'
- 'dev'

env:
PIPELINE_USER_ACCESS_KEY_ID: ${{ secrets.PIPELINE_USER_ACCESS_KEY_ID}}
Expand All @@ -13,7 +14,7 @@ env:
TESTING_PIPELINE_EXECUTION_ROLE: ${{ secrets.TESTING_PIPELINE_EXECUTION_ROLE }}
TESTING_CLOUDFORMATION_EXECUTION_ROLE: ${{ secrets.TESTING_CLOUDFORMATION_EXECUTION_ROLE }}
TESTING_ARTIFACTS_BUCKET: ${{ secrets.TESTING_ARTIFACTS_BUCKET }}
TESTING_PARAMETER_OVERRIDES: TasksTableName=tasks,CognitoCallbackURL=https://start.spring.io/,UserPoolAdminGroupName=apiAdmins
TESTING_PARAMETER_OVERRIDES: TasksTableName=test-tasks CognitoCallbackURL=https://dev.d2x151q2vf1tfl.amplifyapp.com/auth/callback UserPoolAdminGroupName=apiAdmins FrontendLoginUrl=https://dev.d2x151q2vf1tfl.amplifyapp.com/ AdminEmail=${{ secrets.ADMIN_EMAIL_TEST }} AdminUsername=${{ secrets.ADMIN_USERNAME_TEST }}
# If there are functions with "Image" PackageType in your template,
# uncomment the line below and add "--image-repository ${TESTING_IMAGE_REPOSITORY}" to
# testing "sam package" and "sam deploy" commands.
Expand All @@ -23,7 +24,7 @@ env:
PROD_PIPELINE_EXECUTION_ROLE: ${{ secrets.PROD_PIPELINE_EXECUTION_ROLE }}
PROD_CLOUDFORMATION_EXECUTION_ROLE: ${{ secrets.PROD_CLOUDFORMATION_EXECUTION_ROLE }}
PROD_ARTIFACTS_BUCKET: ${{ secrets.PROD_ARTIFACTS_BUCKET }}
PRODUCTION_PARAMETER_OVERRIDES: TasksTableName=tasks,CognitoCallbackURL=https://django-rest-framework.org/tutorial/,UserPoolAdminGroupName=apiAdmins
PRODUCTION_PARAMETER_OVERRIDES: TasksTableName=prod-tasks CognitoCallbackURL=https://main.d1m5j798vicdd1.amplifyapp.com/auth/callback UserPoolAdminGroupName=apiAdmins FrontendLoginUrl=https://main.d1m5j798vicdd1.amplifyapp.com/ AdminEmail=${{ secrets.ADMIN_EMAIL_PROD }} AdminUsername=${{ secrets.ADMIN_USERNAME_PROD }}
# If there are functions with "Image" PackageType in your template,
# uncomment the line below and add "--image-repository ${PROD_IMAGE_REPOSITORY}" to
# prod "sam package" and "sam deploy" commands.
Expand Down Expand Up @@ -191,4 +192,4 @@ jobs:
--s3-bucket ${PROD_ARTIFACTS_BUCKET} \
--no-fail-on-empty-changeset \
--role-arn ${PROD_CLOUDFORMATION_EXECUTION_ROLE} \
--parameter-overrides TasksTableName=tasks CognitoCallbackURL=https://django-rest-framework.org/tutorial/ UserPoolAdminGroupName=apiAdmins
--parameter-overrides ${PRODUCTION_PARAMETER_OVERRIDES}
166 changes: 84 additions & 82 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,82 +1,84 @@
# task-management-system serverless API
The task-management-system project, created with [`aws-serverless-java-container`](https://github.com/aws/serverless-java-container).

The starter project defines a simple `/ping` resource that can accept `GET` requests with its tests.

The project folder also includes a `template.yml` file. You can use this [SAM](https://github.com/awslabs/serverless-application-model) file to deploy the project to AWS Lambda and Amazon API Gateway or test in local with the [SAM CLI](https://github.com/awslabs/aws-sam-cli).

## Pre-requisites
* [AWS CLI](https://aws.amazon.com/cli/)
* [SAM CLI](https://github.com/awslabs/aws-sam-cli)
* [Gradle](https://gradle.org/) or [Maven](https://maven.apache.org/)

## Building the project
You can use the SAM CLI to quickly build the project
```bash
$ mvn archetype:generate -DartifactId=task-management-system -DarchetypeGroupId=com.amazonaws.serverless.archetypes -DarchetypeArtifactId=aws-serverless-jersey-archetype -DarchetypeVersion=2.1.0 -DgroupId=org.umaxcode -Dversion=1.0-SNAPSHOT -Dinteractive=false
$ cd task-management-system
$ sam build
Building resource 'TaskManagementSystemFunction'
Running JavaGradleWorkflow:GradleBuild
Running JavaGradleWorkflow:CopyArtifacts

Build Succeeded

Built Artifacts : .aws-sam/build
Built Template : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided
```

## Testing locally with the SAM CLI

From the project root folder - where the `template.yml` file is located - start the API with the SAM CLI.

```bash
$ sam local start-api

...
Mounting com.amazonaws.serverless.archetypes.StreamLambdaHandler::handleRequest (java11) at http://127.0.0.1:3000/{proxy+} [OPTIONS GET HEAD POST PUT DELETE PATCH]
...
```

Using a new shell, you can send a test ping request to your API:

```bash
$ curl -s http://127.0.0.1:3000/ping | python -m json.tool

{
"pong": "Hello, World!"
}
```

## Deploying to AWS
To deploy the application in your AWS account, you can use the SAM CLI's guided deployment process and follow the instructions on the screen

```
$ sam deploy --guided
```

Once the deployment is completed, the SAM CLI will print out the stack's outputs, including the new application URL. You can use `curl` or a web browser to make a call to the URL

```
...
-------------------------------------------------------------------------------------------------------------
OutputKey-Description OutputValue
-------------------------------------------------------------------------------------------------------------
TaskManagementSystemApi - URL for application https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/Prod/pets
-------------------------------------------------------------------------------------------------------------
```

Copy the `OutputValue` into a browser or use curl to test your first request:

```bash
$ curl -s https://xxxxxxx.execute-api.us-west-2.amazonaws.com/Prod/ping | python -m json.tool

{
"pong": "Hello, World!"
}
```
# Task Management System

## Project Overview

The **Task Management System** is designed to streamline task allocation, monitoring, and updates for a field team. The system enables an administrator to create and assign tasks, track their progress, and ensure timely completion. Team members can log in to view, update, and complete their tasks, while notifications and deadline tracking ensure efficient workflows.

## Features

- **Role-based Access**: Administrators manage all tasks, assignments, and deadlines. Team members only see their assigned tasks.
- **Notifications**:
- Assigned users receive email notifications for task details and deadlines.
- Administrators are notified of task completions or deadline breaches.
- **Task Management**:
- Tasks can be created, updated, and reopened.
- Tasks include attributes such as name, description, status, responsibility, deadlines, and user comments.
- **Scalable and Secure Architecture**: Built using AWS serverless services to ensure high availability and scalability.

---

## Technical Requirements

### Backend

- **Deployment**:
- AWS SAM for backend resources.
- Support for test and production environments.
- **Services Used**:
- **Amazon Cognito**: User onboarding and authentication.
- **Amazon DynamoDB**: Data storage for tasks and user information. Also utilized DynamoDB Stream
- **AWS Lambda**: Business logic implementation.
- **Amazon SNS**: Notifications via email for various task-related events.
- **Amazon SQS**: Queueing for notifications and processing tasks.
- **AWS Step Functions**: Orchestrating workflows for task notifications and updates.
- **Amazon Amplify**: Serving the frontend securely and efficiently.

### Frontend

- **Deployment**:
- Hosted on **AWS Amplify** with testing and production environment
- **Continuous Integration/Deployment**:
- GitHub integration for automated deployments to Amplify.
- **Code**:
- [Frontend GitHub Repository](https://github.com/UmaxCode/tasks-management-app.git)

---

## Functional Requirements

1. **Task Creation**:
- Admin creates tasks with attributes: name, description, status (default: open), responsibility, deadline, and comments.
2. **Task Assignment**:
- Admin assigns tasks to users.
- Notifications are sent to assigned users via email using SNS Topic filtering.
3. **Task Status Updates**:
- Team members can update task status (e.g., mark as completed).
- Admin is notified of status changes.
- Team members can add comment
4. **Task Deadline Notifications**:
- 1 hour before a deadline, users are notified via SNS Topic filtering.
5. **Task Reopening**:
- Only admins can reopen closed tasks, triggering notifications to the assigned user.
6. **Task Deadline Breaches**:
- When a task deadline is missed:
- Task status is updated to "expired."
- Notifications are sent to the user and admin.
7. **Reassignment**:
- If a task's assigned user is changed:
- The task is removed from the old user's list.
- The new user is notified.

---

## Architectural Diagram
[Link to architectural diagram](https://drive.google.com/file/d/1hnCXGY69D11RBGM_5vxP1taGss-_BIyE/view?usp=sharing)

---

## Deployment Guidelines

### Manual Deployment
Follow these steps to deploy the project manually.

### Automated Deployment - GITHUB ACTIONS
Follow these steps to deploy the project manually.
9 changes: 9 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,20 @@
<artifactId>sqs</artifactId>
<version>2.20.31</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.4.1</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>

<dependencyManagement>
Expand Down
43 changes: 5 additions & 38 deletions src/main/java/org/umaxcode/SNSTopicSubscriptionHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import org.umaxcode.service.impl.SNSServiceImpl;
import software.amazon.awssdk.services.sns.SnsClient;
import software.amazon.awssdk.services.sns.model.SetSubscriptionAttributesRequest;
import software.amazon.awssdk.services.sns.model.SubscribeRequest;
import software.amazon.awssdk.services.sns.model.SubscribeResponse;

import java.util.Map;

public class SNSTopicSubscriptionHandler implements RequestHandler<Map<String, String>, String> {
public class SNSTopicSubscriptionHandler implements RequestHandler<Map<String, String>, Void> {

private final SnsClient snsClient;

Expand All @@ -18,7 +16,7 @@ public SNSTopicSubscriptionHandler() {
}

@Override
public String handleRequest(Map<String, String> event, Context context) {
public Void handleRequest(Map<String, String> event, Context context) {

System.out.println("Event" + event);
// Extract the user's email from the event
Expand All @@ -27,39 +25,8 @@ public String handleRequest(Map<String, String> event, Context context) {
// SNS Topic ARN (can be passed in environment variables or hardcoded)
String snsTopicArn = event.get("topicArn");

// Create SNS subscription request
SubscribeRequest subscribeRequest = SubscribeRequest.builder()
.protocol("email") // Protocol is email to receive notifications
.endpoint(userEmail) // User's email address to subscribe
.returnSubscriptionArn(true)
.topicArn(snsTopicArn) // SNS Topic ARN
.build();
SNSServiceImpl.subscribeToTopic(snsClient, context, snsTopicArn, userEmail);

try {
SubscribeResponse response = snsClient.subscribe(subscribeRequest);
context.getLogger().log("Subscription result: " + response);

// Define a filter policy
String filterPolicy = String.format("{ \"endpointEmail\": [\"%s\"] }", userEmail);

// Set the filter policy for the subscription
String subscriptionArn = response.subscriptionArn();

System.out.println("SubscriptionArn" + subscriptionArn);
SetSubscriptionAttributesRequest filterPolicyRequest = SetSubscriptionAttributesRequest.builder()
.subscriptionArn(subscriptionArn)
.attributeName("FilterPolicy")
.attributeValue(filterPolicy)
.build();

snsClient.setSubscriptionAttributes(filterPolicyRequest);

context.getLogger().log("Filter policy set for subscription: " + subscriptionArn);

return "Successfully subscribed " + userEmail + " to the SNS topic with filter policy: " + snsTopicArn;
} catch (Exception e) {
context.getLogger().log("Error subscribing user: " + e.getMessage());
return "Failed to subscribe user to SNS topic.";
}
return null;
}
}
Loading
Loading