|
4 | 4 | import logging
|
5 | 5 | import cognitojwt
|
6 | 6 |
|
7 |
| - |
8 |
| -# Set up logging |
| 7 | +# Enhanced logging configuration |
9 | 8 | logger = logging.getLogger(__name__)
|
10 | 9 | logger.setLevel(logging.INFO)
|
| 10 | +formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') |
| 11 | +handler = logging.StreamHandler() |
| 12 | +handler.setFormatter(formatter) |
| 13 | +logger.addHandler(handler) |
11 | 14 |
|
12 | 15 | verified_permissions_client = boto3.client("verifiedpermissions")
|
13 | 16 |
|
14 |
| - |
15 | 17 | def get_named_parameter(event, name):
|
16 |
| - return next(item for item in event['parameters'] if item['name'] == name)['value'] |
17 |
| - |
18 |
| - |
19 |
| -def list_claims(event): |
20 |
| - # TODO: Implement logic to retrieve and return a list of claims |
| 18 | + logger.info(f"Retrieving parameter: {name} from event") |
| 19 | + value = next(item for item in event['parameters'] if item['name'] == name)['value'] |
| 20 | + logger.info(f"Retrieved parameter value: {value}") |
| 21 | + return value |
| 22 | + |
| 23 | +def list_claims(event, user_info): |
| 24 | + # This function retrieves claims based on user role, filtering for adjusters by region. |
| 25 | + # TODO: Implement logic to retrieve and return a list of claims from DynamoDB. |
| 26 | + # For now, we'll use dummy claims for demonstration purposes. |
| 27 | + logger.info(f"Entering list_claims function with user_info: {user_info}") |
21 | 28 | dummy_claims = [
|
22 | 29 | {
|
23 | 30 | "id": 1,
|
24 | 31 | "claimAmount": 1000.0,
|
25 | 32 | "claimDescription": "Dummy claim 1",
|
26 |
| - "claimStatus": "approved" |
| 33 | + "claimStatus": "approved", |
| 34 | + "region": "northeast" |
27 | 35 | },
|
28 | 36 | {
|
29 | 37 | "id": 2,
|
30 | 38 | "claimAmount": 2500.75,
|
31 | 39 | "claimDescription": "Dummy claim 2",
|
32 |
| - "claimStatus": "pending" |
| 40 | + "claimStatus": "pending", |
| 41 | + "region": "northwest" |
33 | 42 | }
|
34 | 43 | ]
|
35 |
| - return dummy_claims |
36 |
| - |
| 44 | + logger.info(f"Retrieved dummy claims: {dummy_claims}") |
| 45 | + |
| 46 | + user_role = user_info.get('role') |
| 47 | + user_region = user_info.get('region') |
| 48 | + logger.info(f"Processing claims for user_role: {user_role}, region: {user_region}") |
| 49 | + |
| 50 | + # Adjusters can only access claims in their assigned region |
| 51 | + if user_role == 'ClaimsAdjuster': |
| 52 | + logger.info("Filtering claims for adjuster role") |
| 53 | + filtered_claims = [claim for claim in dummy_claims if claim['region'] == user_region] |
| 54 | + logger.info(f"Filtered claims count: {len(filtered_claims)}") |
| 55 | + return filtered_claims |
| 56 | + else: |
| 57 | + # Non-adjusters (assumed to be admins) can access all claims |
| 58 | + logger.info("Returning all claims for admin role") |
| 59 | + return dummy_claims |
37 | 60 |
|
38 |
| -def get_claim(event): |
| 61 | +def get_claim(event, user_info): |
| 62 | + # This function retrieves a claim by ID and applies role-based access control. |
| 63 | + logger.info(f"Entering get_claim function with user_info: {user_info}") |
39 | 64 | claim_id = int(get_named_parameter(event, 'claimId'))
|
40 |
| - # TODO: Implement logic to retrieve and return a claim by ID |
| 65 | + logger.info(f"Retrieving claim with ID: {claim_id}") |
| 66 | + |
| 67 | + # TODO: Implement logic to retrieve a claim by ID from DynamoDB. |
| 68 | + # For now, we'll use a dummy claim for demonstration purposes. |
41 | 69 | dummy_claim = {
|
42 | 70 | "id": claim_id,
|
43 | 71 | "claimAmount": 1000.0,
|
44 | 72 | "claimDescription": "Dummy claim 1",
|
45 |
| - "claimStatus": "approved" |
| 73 | + "claimStatus": "approved", |
| 74 | + "region": "northeast" |
46 | 75 | }
|
47 |
| - return dummy_claim |
| 76 | + logger.info(f"Retrieved dummy claim: {dummy_claim}") |
| 77 | + |
| 78 | + user_role = user_info.get('role') |
| 79 | + user_region = user_info.get('region') |
| 80 | + logger.info(f"Checking access for user_role: {user_role}, region: {user_region}") |
| 81 | + |
| 82 | + if user_role == 'ClaimsAdjuster': |
| 83 | + # Adjusters can only access claims in their assigned region |
| 84 | + if dummy_claim['region'] == user_region: |
| 85 | + logger.info("Access granted: Claim region matches adjuster region") |
| 86 | + return dummy_claim |
| 87 | + else: |
| 88 | + logger.warning("Access denied: Claim region does not match adjuster region") |
| 89 | + return None |
| 90 | + else: |
| 91 | + # Non-adjusters (assumed to be admins) can access all claims |
| 92 | + logger.info("Access granted: Admin role") |
| 93 | + return dummy_claim |
| 94 | + |
| 95 | + |
| 96 | + # TODO: Implement error handling for cases where the claim doesn't exist |
48 | 97 |
|
49 | 98 |
|
50 |
| -def update_claim(event): |
| 99 | +def update_claim(event, user_info): |
| 100 | + # This method allows adjusters to update claims they are managing. |
| 101 | + # It assumes any calling method has already validated the adjuster's region. |
| 102 | + logger.info(f"Entering update_claim function with user_info: {user_info}") |
| 103 | + |
51 | 104 | claim_id = int(get_named_parameter(event, 'claimId'))
|
52 |
| - # TODO: Implement logic to update and return a claim by ID |
| 105 | + logger.info(f"Updating claim with ID: {claim_id}") |
| 106 | + |
| 107 | + # Using dummy claim data for demonstration purpose (to be replaced by database retrieval). |
53 | 108 | dummy_claim = {
|
54 | 109 | "id": claim_id,
|
55 | 110 | "claimAmount": 3000.0,
|
56 | 111 | "claimDescription": "Updated dummy claim",
|
57 |
| - "claimStatus": "approved" |
| 112 | + "claimStatus": "approved", |
| 113 | + "region": "northeast" |
58 | 114 | }
|
59 |
| - return dummy_claim |
60 | 115 |
|
| 116 | + # Here we would normally retrieve the existing claim from the database but for now, we use the dummy claim. |
| 117 | + existing_claim = dummy_claim # Placeholder: Replace this with actual database retrieval logic. |
| 118 | + logger.info(f"Retrieved existing claim: {existing_claim}") |
| 119 | + |
| 120 | + # Since the adjuster's region is already validated in the calling method, |
| 121 | + # we can proceed to update the claim data. Assuming we're updating to some new values: |
| 122 | + updated_claim = { |
| 123 | + "id": existing_claim['id'], |
| 124 | + "claimAmount": existing_claim['claimAmount'] + 500.0, # Example update |
| 125 | + "claimDescription": "Further updated dummy claim", |
| 126 | + "claimStatus": "approved", |
| 127 | + "region": existing_claim['region'] |
| 128 | + } |
61 | 129 |
|
62 |
| -def lambda_handler(event, context): |
63 |
| - logger.info(f'event: {event}') |
64 |
| - logger.info(f'context: {context}') |
| 130 | + # TODO: Implement logic to save the updated claim to the database. |
| 131 | + logger.info(f"Updated claim: {updated_claim}") |
| 132 | + return updated_claim # Return the updated claim to confirm the changes. |
65 | 133 |
|
66 |
| - # sessionAttributes contain the authorization_header which is later retrieved to validate the request. This is the JWT token. |
67 |
| - sessionAttributes = event.get("sessionAttributes") |
68 |
| - |
69 |
| - # print("sessionAttributes:", sessionAttributes) |
70 |
| - response_code = 200 |
71 |
| - action_group = event['actionGroup'] |
72 |
| - api_path = event['apiPath'] |
73 |
| - http_method = event['httpMethod'].upper() |
74 |
| - action_id = getActionID(api_path, http_method) |
75 |
| - |
76 |
| - auth, reason = verifyAccess(sessionAttributes, action_id) |
77 |
| - print("auth",auth) |
78 |
| - print("reason",reason) |
79 |
| - |
80 |
| - |
81 |
| - if auth == "ALLOW": |
82 |
| - if api_path == '/listClaims' and http_method == 'GET': |
83 |
| - result = list_claims(event) |
84 |
| - elif api_path == '/getClaim/{claimId}' and http_method == 'GET': |
85 |
| - result = get_claim(event) |
86 |
| - elif api_path == '/updateClaim/{claimId}' and http_method == 'PUT': |
87 |
| - result = update_claim(event) |
| 134 | +def lambda_handler(event, context): |
| 135 | + logger.info(f"Lambda handler invoked with event: {event}") |
| 136 | + try: |
| 137 | + # sessionAttributes contain the authorization_header which is later retrieved to validate the request. |
| 138 | + # This is the JWT token. |
| 139 | + sessionAttributes = event.get("sessionAttributes") |
| 140 | + logger.info(f"Session attributes retrieved: {sessionAttributes}") |
| 141 | + |
| 142 | + action_group = event['actionGroup'] |
| 143 | + api_path = event['apiPath'] |
| 144 | + http_method = event['httpMethod'].upper() |
| 145 | + action_id = getActionID(api_path, http_method) |
| 146 | + logger.info(f"Processing request - Path: {api_path}, Method: {http_method}, Action ID: {action_id}") |
| 147 | + |
| 148 | + user_info, auth, reason = verifyAccess(sessionAttributes, action_id) |
| 149 | + logger.info(f"Access verification result - Auth: {auth}, Reason: {reason}") |
| 150 | + |
| 151 | + if auth == "ALLOW": |
| 152 | + response_code = 200 |
| 153 | + if api_path == '/listClaims' and http_method == 'GET': |
| 154 | + claims = list_claims(event, user_info) |
| 155 | + # Return the raw claims data without any text formatting |
| 156 | + result = claims |
| 157 | + elif api_path == '/getClaim/{claimId}' and http_method == 'GET': |
| 158 | + result = get_claim(event, user_info) |
| 159 | + elif api_path == '/updateClaim/{claimId}' and http_method == 'PUT': |
| 160 | + result = update_claim(event, user_info) |
| 161 | + else: |
| 162 | + response_code = 404 |
| 163 | + result = {"error": f"Unrecognized api path: {action_group}::{api_path}"} |
| 164 | + logger.error(f"Unrecognized API path: {api_path}") |
88 | 165 | else:
|
89 |
| - response_code = 404 |
90 |
| - result = f"Unrecognized api path: {action_group}::{api_path}" |
| 166 | + response_code = 401 |
| 167 | + result = {"error": reason} |
| 168 | + logger.warning(f"Access denied: {reason}") |
91 | 169 |
|
92 | 170 | response_body = {
|
93 | 171 | 'application/json': {
|
94 |
| - 'body': result |
| 172 | + 'body': result # Don't use json.dumps here as it's not needed |
95 | 173 | }
|
96 | 174 | }
|
97 |
| - else: # auth == "DENY" |
98 |
| - response_code = 401 |
99 |
| - response_body = { |
100 |
| - 'application/json': { |
101 |
| - 'body': reason |
| 175 | + |
| 176 | + api_response = { |
| 177 | + 'messageVersion': '1.0', |
| 178 | + 'response': { |
| 179 | + 'actionGroup': action_group, |
| 180 | + 'apiPath': api_path, |
| 181 | + 'httpMethod': http_method, |
| 182 | + 'httpStatusCode': response_code, |
| 183 | + 'responseBody': response_body |
102 | 184 | }
|
103 | 185 | }
|
104 |
| - |
105 |
| - action_response = { |
106 |
| - 'actionGroup': event['actionGroup'], |
107 |
| - 'apiPath': event['apiPath'], |
108 |
| - 'httpMethod': event['httpMethod'], |
109 |
| - 'httpStatusCode': response_code, |
110 |
| - 'responseBody': response_body |
111 |
| - } |
112 |
| - |
113 |
| - api_response = {'messageVersion': '1.0', 'response': action_response} |
114 |
| - return api_response |
| 186 | + logger.info(f"Returning response with status code: {response_code}") |
| 187 | + return api_response |
| 188 | + except Exception as e: |
| 189 | + logger.error(f"Error in lambda_handler: {str(e)}", exc_info=True) |
| 190 | + raise |
115 | 191 |
|
116 | 192 |
|
117 | 193 | def verifyAccess(sessionAttributes, action_id):
|
@@ -142,7 +218,7 @@ def verifyAccess(sessionAttributes, action_id):
|
142 | 218 | else:
|
143 | 219 | reason = "Unauthorized request"
|
144 | 220 |
|
145 |
| - return auth, reason |
| 221 | + return user_info, auth, reason |
146 | 222 |
|
147 | 223 |
|
148 | 224 | def verifyJWT_getUserInfo(token):
|
|
0 commit comments