-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathupdate_session.py
111 lines (102 loc) · 4.23 KB
/
update_session.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
"""
This module is the update_session API handler.
It updates the status of a session (token) stored in DynamoDB.
Session status is denoted by an integer. Sessions set to a status of 1 indicates completed, and -1 indicates abandoned.
Authorization is required to invoke this API.
"""
import redis
import json
import boto3
import os
from botocore.exceptions import ClientError
from botocore import config
from boto3.dynamodb.conditions import Attr
from counters import COMPLETED_SESSION_COUNTER, ABANDONED_SESSION_COUNTER
from vwr.common.sanitize import deep_clean
from vwr.common.validate import is_valid_rid
# connection info and other globals
REDIS_HOST = os.environ["REDIS_HOST"]
REDIS_PORT = os.environ["REDIS_PORT"]
EVENT_ID = os.environ["EVENT_ID"]
EVENT_BUS_NAME = os.environ["EVENT_BUS_NAME"]
DDB_TOKEN_TABLE_NAME = os.environ["TOKEN_TABLE"]
SOLUTION_ID = os.environ['SOLUTION_ID']
SECRET_NAME_PREFIX = os.environ["STACK_NAME"]
user_agent_extra = {"user_agent_extra": SOLUTION_ID}
user_config = config.Config(**user_agent_extra)
boto_session = boto3.session.Session()
region = boto_session.region_name
ddb_resource = boto3.resource('dynamodb', endpoint_url=f"https://dynamodb.{region}.amazonaws.com", config=user_config)
ddb_table = ddb_resource.Table(DDB_TOKEN_TABLE_NAME)
events_client = boto3.client('events', endpoint_url=f"https://events.{region}.amazonaws.com", config=user_config)
status_codes = {1: "completed", -1: "abandoned"}
secrets_client = boto3.client('secretsmanager', config=user_config, endpoint_url=f"https://secretsmanager.{region}.amazonaws.com")
response = secrets_client.get_secret_value(SecretId=f"{SECRET_NAME_PREFIX}/redis-auth")
redis_auth = response.get("SecretString")
rc = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, ssl=True, decode_responses=True, password=redis_auth)
def lambda_handler(event, _):
"""
This function is the entry handler for Lambda.
"""
print(event)
body = json.loads(event['body'])
request_id = deep_clean(body['request_id'])
client_event_id = deep_clean(body['event_id'])
status = int(body['status'])
headers = {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}
if client_event_id == EVENT_ID and is_valid_rid(request_id):
try:
result = ddb_table.update_item(
UpdateExpression='SET session_status = :status',
ConditionExpression=(Attr('request_id').eq(request_id) and Attr('session_status').eq(0)),
Key={'request_id': request_id},
ExpressionAttributeValues={':status': status}
)
response = {
"statusCode": 200,
"headers": headers,
"body": json.dumps(result)
}
# write to event bus
events_client.put_events(
Entries=[
{
'Source': 'custom.waitingroom',
'DetailType': 'session_updated',
'Detail': json.dumps({"event_id": EVENT_ID,
"request_id": request_id,
"status": status_codes[status]}),
'EventBusName': EVENT_BUS_NAME
}
]
)
# increment counter tracking sessions completed
if status == -1:
rc.incr(ABANDONED_SESSION_COUNTER, 1)
elif status == 1:
rc.incr(COMPLETED_SESSION_COUNTER, 1)
except ClientError as e:
if e.response['Error']['Code'] != 'ConditionalCheckFailedException':
raise e
print(e)
response = {
"statusCode": 404,
"headers": headers,
"body": json.dumps({"error": "Request ID doesn't exist or status already set."})
}
except Exception as e:
print(e)
raise e
else:
response = {
"statusCode": 400,
"headers": headers,
"body": json.dumps({"error": "Invalid event or request ID"})
}
print(response)
return response