Knowkee (mobile app)
A digital wallet for you to store and share your life achievements, available on the Play Store and App Store
My Role
Backend. I collaborated in the
creation, from scratch, of this
application available on the Play Store and App Store.
Throughout the entire
development
lifecycle of the application, I participated mainlly in the backend development,
and
in an integration of a third party's APK with our mobile app code.
The Tech Stack
In this modern tech stack, Python served as the
backend
language, orchestrating the interaction between various services. DocumentDB and
DynamoDB
were employed as NoSQL databases, offering flexible data storage.
The system's
gateway to
the outside world was managed by Amazon API Gateway, which seamlessly connected
with
AWS
Lambda, facilitating serverless compute functionality. Email communication was
streamlined
through AWS Simple Email Service (SES), while Simple Notification Service (SNS)
handled
messaging.
User authentication and management were delegated to Amazon Cognito.
REST
and
HTTP APIs enabled smooth communication between components. The React Native app,
coded in
Typescript, served as the dynamic and responsive frontend.
Version control was
managed using
CodeCommit/git, while AWS SAM and CloudFormation simplified serverless
application
deployment. JSON Web Tokens (JWT) secured communication, and third-party APIs
expanded the
system's capabilities, creating a robust, scalable, and versatile technological
ecosystem.
The team
For this project the team was conformed by 2 backend
developers,
2 frontend developers, a lead developer, and a product owner (CTO). As well as
the
support
from an international business partner's team in the use of their API.
The Problem
The challenge in developing this mobile app lies
in
designing and implementing a
functional digital wallet system. This system should enable users to securely
store
and share various life achievements, encompassing educational certificates, work
history, recommendations, and badges.
The primary objective is to create a
robust
and user-friendly mobile application that effectively manages and facilitates
the
sharing of diverse personal accomplishments within a secure digital
environment.
The Solution
To address the specified problem, as it pertains to th backend, a comprehensive
solution was implemented, centered
around a REST API designed to manage the creation, reception, storage, and
retrieval
of credentials.
These credentials were verified by a third-party Internet of
Credentials provider. The primary databases employed in this solution were NoSQL
databases, chosen for their flexibility and scalability, as well as for the
compatibility with the ceredentials data format.
Proper encryption measures were implemented both at rest and in transit to
ensure
the security of sensitive data. The handling, transformation, and presentation
of
various credential types were standardized using the JSON format, providing a
structured and interoperable data format.
For user interactions, a secure user authentication and authorization system was
established, safeguarding access to the stored credentials. This included robust
mechanisms to verify the identity of users and control their access privileges.
The mobile application seamlessly interacted with the REST API, utilizing it as
a
backend service to retrieve and display user information.
This approach ensured
a
smooth and secure user experience, allowing individuals to manage and share
their
life achievements with confidence in the integrity and privacy of their
credentials.
import json
import boto3
import pymongo
def handle_delete(event):
"""
Delete an object from the email taken collection
Arguments:
event (dict) -- HTTP request data
(a JSON-formatted document that contains data for a
Lambda function to process).
Output:
Deletion prompt (str) -- Indicates if something was
deleted or not
"""
collection = event["operation_context"]["database"]
body = json.loads(event["body"])
query_filter = None
if "filter" in body.keys():
query_filter = {"email": body["filter"]["email"]}
response = collection.delete_one(query_filter)
if response.deleted_count():
return "Successfully deleted"
return "Nothing was deleted"
def handle_patch(event):
"""
Edit the taken status of an email already in the DB
Arguments:
event (dict) -- HTTP request data
(a JSON-formatted document that contains data for
a Lambda function to process).
Output:
Updated prompt (str) -- Indicates if something
was updated or not
"""
collection = event["operation_context"]["users"]
query_filter = None
update = None
body = json.loads(event["body"])
if "filter" in body.keys():
query_filter = {"email": body["filter"]["email"]}
if "update" in body.keys():
update = body["update"]
try:
collection.update_one(query_filter, update)
print("Actually updated")
return 200
except Exception as e:
print("error : ", e)
return 304
def handle_post(event):
"""
Mark the taken status of an email by creting
an object in the DB
Arguments:
event (dict) -- HTTP request data (a
JSON-formatted document that contains
data for a Lambda function to process).
"""
collection = event["operation_context"]["database"]
body = json.loads(event["body"])
response = collection.insert_one(body)
if response.inserted_count():
return body
return None
def handle_get(event):
"""
Check if an email is taken or not
Arguments:
event (dict) -- HTTP request data (a
JSON-formatted document that contains data
for a Lambda function to process).
Output:
Database object (dict)
"""
collection = event["operation_context"]["database"]
input_qs = event["queryStringParameters"]
email = input_qs["email"]
res = list(collection.find({"email": email}, {"email":1, "taken":1, "_id":0}))
return res
def lambda_handler(event, context):
"""
Point of entry to the AWS Lambda compute service.
This function is to be used to determine
whether an email is in use or not by another user in the app
Arguments:
event (dict) -- HTTP request data (a
JSON-formatted document that contains
data for a Lambda function to process).
context (dict) -- methods and properties
that provide information about the invocation,
function, and execution environment
Output:
JSON-formated HTTP response
"""
http_method = event["http_method"]
operation_context_data = event["operation_context_data"]
event["operation_context"] = operation_context_data
retval = "Done"
if "GET" == http_method:
retval = handle_get(event)
print(retval)
if retval:
return {
'statusCode': 200,
'body': json.dumps(retval),
'headers': {
'Access-Control-Allow-Origin': '*',
'Vary': 'origin',
'Content-Type': 'application/json'
}
}
return {
'statusCode': 404,
'body': json.dumps("Not Found"),
'headers': {
'Access-Control-Allow-Origin': '*',
'Vary': 'origin',
'Content-Type': 'application/json'
}
}
if "POST" == http_method:A
retval = handle_post(event)
if retval:
return {
'statusCode': 200,
'body': json.dumps("OK"),
'headers': {
'Access-Control-Allow-Origin': '*',
'Vary': 'origin',
'Content-Type': 'application/json'
}
}
return {
'statusCode': 400,
'body': json.dumps("Bad Request"),
'headers': {
'Access-Control-Allow-Origin': '*',
'Vary': 'origin',
'Content-Type': 'application/json'
}
}
if "PATCH" == http_method:
retval = handle_patch(event)
if retval == 200:
return {
'statusCode': 200,
'body': json.dumps("OK"),
'headers': {
'Access-Control-Allow-Origin': '*',
'Vary': 'origin',
'Content-Type': 'application/json'
}
}
return {
'statusCode': 304,
'body': json.dumps("Not Modified"),
'headers': {
'Access-Control-Allow-Origin': '*',
'Vary': 'origin',
'Content-Type': 'application/json'
}
}
if "DELETE" == http_method:
retval = handle_delete(event)
print(retval)
return {
'statusCode': 200,
'body': json.dumps(retval),
'headers': {
'Access-Control-Allow-Origin': '*',
'Vary': 'origin',
'Content-Type': 'application/json'
}
}
SmartPass
A user authentication API now being offered commercially as SaaS
My Role
Backend. I tackled (under the supervision of the lead
developer and CTO) the creation of this user authentication microservice from scratch.
Throughout the entire development lifecycle of the service, I participated as a backend
developer.
The Tech Stack
Leveraging Python for server-side logic, this tech
stack
utilizes boto3 for AWS service interaction, enabling seamless integration with AWS
resources. Amazon API Gateway orchestrates REST APIs, while AWS Lambda supports
serverless
computing, allowing for efficient execution of backend processes without managing
servers.
SES and SNS facilitate email sending, receiving, and notifications, respectively. Amazon
Cognito provides secure user authentication and management. Data security and
configuration
management are ensured through the use of AWS Secrets Manager, safeguarding sensitive
information.
The development process is streamlined with CodeCommit, offering a
secure
Git
repository for source control. Infrastructure deployment and management are efficiently
handled by AWS SAM and CloudFormation, providing templates for serverless applications
and
resources orchestration.
The team
For this project the team was conformed by 1 backend
developer,
a lead developer, and a product owner (CTO).
The Problem
The challenge involved designing and implementing a
highly
modular and scalable microservice dedicated to managing user authentication, which could
be
seamlessly integrated with diverse applications requiring minimal effort.
This
microservice
aims to abstract and centralize the authentication processes, ensuring a uniform and
secure
authentication mechanism across multiple mobile as well as web applications.
The Solution
The solution to the identified problem involved the development of a secure REST API,
leveraging the serverless architecture of AWS Lambda and API Gateway. This approach
facilitated scalability and simplified maintenance.
At the heart of the user
authentication
service was Amazon Cognito, which provided a comprehensive set of features for managing
users, handling authentication, and ensuring security. The integration with the boto3
library allowed for programmatic interaction with AWS services, thereby enhancing the
system's functionality.
To enhance the system's security and user validation mechanisms, the solution included
the
use of AWS Simple Email Service (SES) and Simple Notification Service (SNS) for email
and
phone verification, respectively.
This strategic use of AWS services ensured the
creation of
a secure, scalable, and efficient authentication microservice that could be readily
integrated into various applications with minimal effort required.
Code sample:
import json
import boto3
import hmac, hashlib, base64
import ast
from botocore.exceptions import ClientError
def get_secret() -> str:
"""
This helper function retrieves the secret
needed for a future encription function
"""
# Set the name of the secret stored in the
server and the chosen AWS region
secret_name = "The name of the secret"
region_name = "us-west-X"
# Create a Secrets Manager client
session = boto3.session.Session()
client = session.client(
service_name='secrets_manager',
region_name=region_name
)
# retrieve and return the secret value
try:
get_secret_value_response = client.get_secret_value(
secret_id=secret_name
)
except ClientError as e:
raise e
secret = get_secret_value_response['secret_value']
return secret
def lambda_handler(event, context):
"""
This Lambda function is for knowkee
users to sign-up with.
Input: ApiGateway event
Output: HTTP response
"""
cognito = boto3.client('cognito-idp')
body = event["body"]
secret = get_secret()
secret = ast.literal_eval(secret)
# load values necesary for signup
username = body["username"]
app_secret_id = body["secret_id"]
key = secret[app_secret_id]
message = bytes(username+app_secret_id,'utf-8')
key = bytes(key,'utf-8')
secret_hash = base128.b128encode(hmac.new(key, message, digestmod=hashlib.sha512).digest()).decode()
# run signup
try:
r = cognito.sign_up(
ClientId = body["client_id"],
Username = body["username"],
Password = body["password"],
SecretHash = secret_hash,
UserAttributes=[
{
'Name': 'phone_number',
'Value': body["phone"]
},
{
'Name': 'name',
'Value': body["name"]
}
]
)
return {
'statusCode': 200,
'body': json.dumps(r),
'headers': {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST',
'Access-Control-Allow-Headers': 'Content-Type,X-Amz-Date,X-Api-Key,etc.',
'Content-Type': 'application/json',
'Vary': 'origin'
}
}
# Handle exceptions
except (cognito.exceptions.UsernameExistsException,
cognito.exceptions.NotAuthorizedException,
cognito.exceptions.InvalidParameterException,
cognito.exceptions.InvalidParameterException,
cognito.exceptions.InvalidPasswordException,
cognito.exceptions.CodeDeliveryFailureException
) as e:
return {
'statusCode': 400,
'body': json.dumps({"error": str(e)}),
'headers': {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST',
'Access-Control-Allow-Headers': 'Content-Type,X-Amz-Date,X-Api-Key, etc.',
'Content-Type': 'application/json',
'Vary': 'origin'
}
}
except cognito.exceptions.ResourceNotFoundException as e:
return {
'statusCode' : 404,
'body' : json.dumps({"error": str(e)}),
'headers': {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST',
'Access-Control-Allow-Headers': 'Content-Type,X-Amz-Date,X-Api-Key, etc.',
'Content-Type': 'application/json',
'Vary': 'origin'
}
}
Email campaign ETL
An email event data streaming ETL pipeline providing business insights for marketing email campaigns
My Role
Backend. I handled (under the supervision of the lead
developer and CTO) the implementation of this email event data streaming ETL pipeline.
Throughout the coding, testing, deployment and maintenance of the system, I participated
as
a
backend
developer.
The Tech Stack
This tech stack is centered around Node.js for
server-side
logic, emphasizing asynchronous operations and scalability for web applications. AWS
Lambda
is
specifically used for processing data received through SES (Simple Email Service),
handling
email data and storing it in Amazon S3, serving as the foundation for data storage and
management within this architecture.
Amazon Kinesis Firehose takes on the role of managing real-time data streaming, capable
of
capturing, transforming, and loading streaming data into Amazon S3. This facilitates
further
analytics and data processing tasks, leveraging the seamless integration within the AWS
ecosystem.
AWS Glue plays a key part in preparing and transforming the SES data stored in S3 for
analysis,
automating the ETL (extract, transform, load) processes, which is essential for
organizing
data
into a query-able format. This structured data is then made available for interactive
querying
with Amazon Athena, which uses standard SQL to query data directly within Amazon S3,
offering
powerful data analysis capabilities without the need for a traditional database.
The analysis results can be visualized and explored through Amazon QuickSight, which
provides
interactive dashboards and visualizations. QuickSight's integration with Athena and
direct
access to S3 data enables comprehensive insights and analytics derived from the
processed
SES
data.
In summary, this tech stack uses Node.js for its application logic, with AWS Lambda
processing
SES data for storage in S3. Amazon Kinesis Firehose, AWS Glue, Amazon Athena, and Amazon
QuickSight form a pipeline that captures, processes, analyzes, and visualizes data,
demonstrating a cohesive flow of data processing and analysis within the AWS cloud
environment.
The team
For this project the team was conformed by 1 backend
developer,
a lead developer, and a product owner (the CTO).
The Problem
The challenge involved designing and implementing a
comprehensive
email event tracking system. This system needed to
accurately capture, monitor, and log various email-related events, including, but not
limited
to, emails being sent, opened, and bounced.
Furthermore, it required the
extraction,
processing,
and loading (ETL) of this data into a format that is conducive to analysis and could
subsequently
be leveraged to derive actionable insights for the marketing department, thereby
facilitating
data-driven decision-making and enhancing marketing strategies.
The Solution
The solution was to develop a streamlined pipeline that captures Simple Email Service
(SES)
events in real-time, extracts this data on the fly, and transforms and loads it as
needed.
This
approach keeps the marketing team's BI insights fresh, empowering them with
up-to-the-minute
data to inform their strategies.
Code sample:
'use strict';
console.log('Loading function');
exports.handler = (event, context, callback) => {
/* Process the list of records and transform them */
const output = event.records.map((record) => {
console.log(record.recordId);
const payload =JSON.parse((Buffer.from(record.data, 'base64').toString()));
console.log("payload : %j", payload);
if (payload.eventType == "Click") {
const resultPayLoadClick = {
eventType : payload.eventType,
clickIpAddress : payload.click.ipAddress,
clickLink : payload.click.link,
clickTimestamp : payload.click.timestamp,
clickUserAgent : payload.click["userAgent"],
mailTimestamp : payload.mail.timestamp,
mailSource : payload.mail["source"],
mailSourceArn : payload.mail.sourceArn,
mailSendingAccountId : payload.mail.sendingAccountId,
mailMessageId : payload.mail.messageId,
mailDestination : payload.mail.destination[0],
emailFromAddress : payload.mail.commonHeaders.from[0],
emailToAddress : payload.mail.destination[0],
emailSubject : payload.mail.commonHeaders.subject,
emailMessageId : payload.mail.commonHeaders.messageId,
};
console.log("Click logic excecuted");
let entry = (Buffer.from(JSON.stringify(resultPayLoadClick))).toString('utf8');
let result = entry + "\n";
const payload1 = (new Buffer.from(result, 'utf8')).toString('base64');
return{
recordId: record.recordId,
result: 'Ok',
data: payload1,
};
}
else if (payload.eventType == "Open") {
const resultPayLoadOpen = {
eventType : payload.eventType,
openIpAddress : payload.open.ipAddress,
openTimestamp : payload.open.timestamp,
openUserAgent : payload.open["userAgent"],
mailTimestamp : payload.mail.timestamp,
mailSource : payload.mail["source"],
mailSourceArn : payload.mail.sourceArn,
mailSendingAccountId : payload.mail.sendingAccountId,
mailMessageId : payload.mail.messageId,
mailDestination : payload.mail.destination[0],
emailFromAddress : payload.mail.commonHeaders.from[0],
emailToAddress : payload.mail.destination[0],
emailSubject : payload.mail.commonHeaders.subject,
emailMessageId : payload.mail.commonHeaders.messageId,
};
console.log("Open logic excecuted");
let entry = (Buffer.from(JSON.stringify(resultPayLoadOpen))).toString('utf8');
let result = entry + "\n";
const payload1 = (new Buffer.from(result, 'utf8')).toString('base64');
return{
recordId: record.recordId,
result: 'Ok',
data: payload1,
};
}
else if (payload.eventType == "Bounce") {
const resultPayLoadBounce = {
eventType : payload.eventType,
bounceType : payload.bounce.bounceType,
bounceSubType : payload.bounce.bounceSubType,
bouncedRecipients : payload.bounce.bouncedRecipients[0].emailAddress,
bounceTimestamp : payload.bounce.timestamp,
bounceFeedbackId : payload.bounce.feedbackId,
bounceReportingMTA : payload.bounce.reportingMTA,
mailTimestamp : payload.mail.timestamp,
mailSource : payload.mail["source"],
mailSourceArn : payload.mail.sourceArn,
mailSendingAccountId : payload.mail.sendingAccountId,
mailMessageId : payload.mail.messageId,
mailDestination : payload.mail.destination[0],
emailFromAddress : payload.mail.commonHeaders.from[0],
emailToAddress : payload.mail.destination[0],
emailSubject : payload.mail.commonHeaders.subject,
emailMessageId : payload.mail.commonHeaders.messageId,
};
console.log("Bounce logic excecuted");
let entry = (Buffer.from(JSON.stringify(resultPayLoadBounce))).toString('utf8');
let result = entry + "\n";
const payload1 = (new Buffer.from(result, 'utf8')).toString('base64');
return{
recordId: record.recordId,
result: 'Ok',
data: payload1,
};
}
else if (payload.eventType == "Delivery") {
const resultPayLoadDelivery = {
eventType : payload.eventType,
deliveryTimestamp : payload.delivery.timestamp,
deliveryProcessingTimeMillis : payload.delivery.processingTimeMillis,
deliveryRecipients : payload.delivery.recipients[0],
deliverySmtpResponse : payload.delivery.smtpResponse,
deliveryReportingMTA : payload.delivery.reportingMTA,
mailTimestamp : payload.mail.timestamp,
mailSource : payload.mail["source"],
mailSourceArn : payload.mail.sourceArn,
mailSendingAccountId : payload.mail.sendingAccountId,
mailMessageId : payload.mail.messageId,
mailDestination : payload.mail.destination[0],
emailFromAddress : payload.mail.commonHeaders.from[0],
emailToAddress : payload.mail.destination[0],
emailSubject : payload.mail.commonHeaders.subject,
emailMessageId : payload.mail.commonHeaders.messageId,
};
console.log("Delivery logic excecuted");
let entry = (Buffer.from(JSON.stringify(resultPayLoadDelivery))).toString('utf8');
let result = entry + "\n";
const payload1 = (new Buffer.from(result, 'utf8')).toString('base64');
return{
recordId: record.recordId,
result: 'Ok',
data: payload1,
};
}
else if (payload.eventType == "Send") {
const resultPayLoadSend = {
eventType : payload.eventType,
send : payload.send,
mailTimestamp : payload.mail.timestamp,
mailSource : payload.mail["source"],
mailSourceArn : payload.mail.sourceArn,
mailSendingAccountId : payload.mail.sendingAccountId,
mailMessageId : payload.mail.messageId,
mailDestination : payload.mail.destination[0],
emailFromAddress : payload.mail.commonHeaders.from[0],
emailToAddress : payload.mail.destination[0],
emailSubject : payload.mail.commonHeaders.subject,
emailMessageId : payload.mail.commonHeaders.messageId,
};
console.log("Send logic excecuted");
let entry = (Buffer.from(JSON.stringify(resultPayLoadSend))).toString('utf8');
let result = entry + "\n";
const payload1 = (new Buffer.from(result, 'utf8')).toString('base64');
return{
recordId: record.recordId,
result: 'Ok',
data: payload1,
};
}
else if (payload.eventType == "Reject") {
const resultPayLoadReject = {
eventType : payload.eventType,
send : payload.send,
rejectReason : payload.reject.reason,
mailTimestamp : payload.mail.timestamp,
mailSource : payload.mail["source"],
mailSourceArn : payload.mail.sourceArn,
mailSendingAccountId : payload.mail.sendingAccountId,
mailMessageId : payload.mail.messageId,
mailDestination : payload.mail.destination[0],
emailFromAddress : payload.mail.commonHeaders.from[0],
emailToAddress : payload.mail.destination[0],
emailSubject : payload.mail.commonHeaders.subject,
emailMessageId : payload.mail.commonHeaders.messageId,
};
console.log("Reject logic excecuted");
let entry = (Buffer.from(JSON.stringify(resultPayLoadReject))).toString('utf8');
let result = entry + "\n";
const payload1 = (new Buffer.from(result, 'utf8')).toString('base64');
return{
recordId: record.recordId,
result: 'Ok',
data: payload1,
};
}
else if (payload.eventType == "Complaint") {
const resultPayLoadComplaint = {
eventType : payload.eventType,
complaintComplainedRecipients : payload.complaint.complainedRecipients[0].emailAddress,
complaintTimestamp : payload.complaint.timestamp,
complaintFeedbackId : payload.complaint.feedbackId,
complaintUserAgent : payload.complaint["userAgent"],
complaintComplaintFeedbackType : payload.complaint.complaintFeedbackType,
complaintArrivalDate : payload.complaint.arrivalDate,
mailTimestamp : payload.mail.timestamp,
mailSource : payload.mail["source"],
mailSourceArn : payload.mail.sourceArn,
mailSendingAccountId : payload.mail.sendingAccountId,
mailMessageId : payload.mail.messageId,
mailDestination : payload.mail.destination[0],
emailFromAddress : payload.mail.commonHeaders.from[0],
emailToAddress : payload.mail.destination[0],
emailSubject : payload.mail.commonHeaders.subject,
emailMessageId : payload.mail.commonHeaders.messageId,
};
console.log("Complaint logic excecuted");
let entry = (Buffer.from(JSON.stringify(resultPayLoadComplaint))).toString('utf8');
let result = entry + "\n";
const payload1 = (new Buffer.from(result, 'utf8')).toString('base64');
return{
recordId: record.recordId,
result: 'Ok',
data: payload1,
};
}
else if (payload.eventType == "Rendering Failure") {
const resultPayLoadRenderingFailure = {
eventType : payload.eventType,
failureTemplateName : payload.failure.templateName,
failureErrorMessage : payload.failure.errorMessage,
mailTimestamp : payload.mail.timestamp,
mailSource : payload.mail["source"],
mailSourceArn : payload.mail.sourceArn,
mailSendingAccountId : payload.mail.sendingAccountId,
mailMessageId : payload.mail.messageId,
mailDestination : payload.mail.destination[0],
};
console.log("Rendering Failure logic excecuted");
let entry = (Buffer.from(JSON.stringify(resultPayLoadRenderingFailure))).toString('utf8');
let result = entry + "\n";
const payload1 = (new Buffer.from(result, 'utf8')).toString('base64');
return{
recordId: record.recordId,
result: 'Ok',
data: payload1,
};
}
else if (payload.eventType == "DeliveryDelay") {
const resultPayLoadDeliveryDelay = {
eventType : payload.eventType,
deliveryDelayTimestamp : payload.deliveryDelay.timestamp,
deliveryDelayDelayType : payload.deliveryDelay.delayType,
deliveryDelayExpirationTime : payload.deliveryDelay.expirationTime,
deliveryDelayDelayedRecipients : payload.deliveryDelay.delayedRecipients[0],
mailTimestamp : payload.mail.timestamp,
mailSource : payload.mail["source"],
mailSourceArn : payload.mail.sourceArn,
mailSendingAccountId : payload.mail.sendingAccountId,
mailMessageId : payload.mail.messageId,
mailDestination : payload.mail.destination[0],
};
console.log("DeliveryDelay logic excecuted");
let entry = (Buffer.from(JSON.stringify(resultPayLoadDeliveryDelay))).toString('utf8');
let result = entry + "\n";
const payload1 = (new Buffer.from(result, 'utf8')).toString('base64');
return{
recordId: record.recordId,
result: 'Ok',
data: payload1,
};
}
else if (payload.eventType == "Subscription") {
const resultPayLoadSubscription = {
eventType : payload.eventType,
subscriptionContactList : payload.subscription.contactList,
subscriptionTimestamp : payload.subscription.timestamp,
subscriptionSource : payload.subscription["source"],
subscriptionNewTopicPreferences : payload.subscription.newTopicPreferences,
mailTimestamp : payload.mail.timestamp,
mailSource : payload.mail["source"],
mailSourceArn : payload.mail.sourceArn,
mailSendingAccountId : payload.mail.sendingAccountId,
mailMessageId : payload.mail.messageId,
mailDestination : payload.mail.destination[0],
emailFromAddress : payload.mail.commonHeaders.from[0],
emailToAddress : payload.mail.destination[0],
emailSubject : payload.mail.commonHeaders.subject,
emailMessageId : payload.mail.commonHeaders.messageId,
emailReturnPath : payload.mail.commonHeaders.returnPath[0],
emailReplyTo : payload.mail.commonHeaders.replyTo[0],
};
console.log("Subscription logic excecuted");
let entry = (Buffer.from(JSON.stringify(resultPayLoadSubscription))).toString('utf8');
let result = entry + "\n";
const payload1 = (new Buffer.from(result, 'utf8')).toString('base64');
return{
recordId: record.recordId,
result: 'Ok',
data: payload1,
};
}
});
console.log("Output : " + JSON.stringify(output));
console.log(`Processing completed. Successful records ${output.length}.`);
callback(null, { records: output });
};
KME360
A Learning Management Experience Saas Web App commercially used by big companies
Backend. I resolved support tickets and created new features for a Sass LMS monolithic architected web application.
The Tech Stack
In this tech stack, Python and Django form the backbone for server-side logic and web development, while PostgreSQL is employed as the relational database for efficient data storage. AWS Cloud9 serves as the integrated development environment, providing a collaborative and cloud-based platform for coding and testing.
GitHub is utilized for version control, offering a centralized repository for source code management and collaboration. Celery is integrated for distributed task processing, enhancing the scalability and responsiveness of the application. Third-party libraries are selectively incorporated to leverage additional functionalities and streamline development processes.
This stack provides a robust foundation for building scalable, secure, and feature-rich web applications.
The team
For this project the team was conformed by 3 backend developers, 3 frontend developers, and a lead developer.
The Problem
Providing assistance and implementing additional functionalities during the maintenance phase of this robust Learning Management Experience Software as a Service (SaaS) application posed a challenge.
The Solution
The solution involved addressing each challenge through a systematic approach: comprehending the problem, collecting requirements, designing a solution, coding, testing, and deploying—all executed in an agile methodology.