geek-cafe-saas-sdk 0.7.4__py3-none-any.whl → 0.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of geek-cafe-saas-sdk might be problematic. Click here for more details.
- geek_cafe_saas_sdk/__init__.py +1 -1
- geek_cafe_saas_sdk/core/anonymous_context.py +321 -0
- geek_cafe_saas_sdk/core/request_context.py +184 -0
- geek_cafe_saas_sdk/decorators/__init__.py +1 -1
- geek_cafe_saas_sdk/decorators/auth.py +6 -6
- geek_cafe_saas_sdk/decorators/core.py +44 -44
- geek_cafe_saas_sdk/domains/analytics/services/website_analytics_service.py +1 -3
- geek_cafe_saas_sdk/domains/analytics/services/website_analytics_summary_service.py +1 -3
- geek_cafe_saas_sdk/domains/analytics/services/website_analytics_tally_service.py +15 -3
- geek_cafe_saas_sdk/domains/auth/handlers/users/create/app.py +1 -1
- geek_cafe_saas_sdk/domains/auth/handlers/users/delete/app.py +1 -1
- geek_cafe_saas_sdk/domains/auth/handlers/users/get/app.py +1 -1
- geek_cafe_saas_sdk/domains/auth/handlers/users/list/app.py +1 -1
- geek_cafe_saas_sdk/domains/auth/handlers/users/update/app.py +1 -1
- geek_cafe_saas_sdk/domains/auth/services/resource_permission_service.py +1 -4
- geek_cafe_saas_sdk/domains/auth/services/user_service.py +0 -2
- geek_cafe_saas_sdk/domains/communities/handlers/communities/create/app.py +1 -1
- geek_cafe_saas_sdk/domains/communities/handlers/communities/delete/app.py +1 -1
- geek_cafe_saas_sdk/domains/communities/handlers/communities/get/app.py +1 -1
- geek_cafe_saas_sdk/domains/communities/handlers/communities/list/app.py +1 -1
- geek_cafe_saas_sdk/domains/communities/handlers/communities/update/app.py +1 -1
- geek_cafe_saas_sdk/domains/communities/services/community_member_service.py +1 -3
- geek_cafe_saas_sdk/domains/communities/services/community_service.py +3 -3
- geek_cafe_saas_sdk/domains/events/handlers/attendees/app.py +1 -1
- geek_cafe_saas_sdk/domains/events/handlers/cancel/app.py +1 -1
- geek_cafe_saas_sdk/domains/events/handlers/check_in/app.py +1 -1
- geek_cafe_saas_sdk/domains/events/handlers/create/app.py +1 -1
- geek_cafe_saas_sdk/domains/events/handlers/delete/app.py +1 -1
- geek_cafe_saas_sdk/domains/events/handlers/get/app.py +1 -1
- geek_cafe_saas_sdk/domains/events/handlers/invite/app.py +1 -1
- geek_cafe_saas_sdk/domains/events/handlers/list/app.py +1 -1
- geek_cafe_saas_sdk/domains/events/handlers/publish/app.py +1 -1
- geek_cafe_saas_sdk/domains/events/handlers/rsvp/app.py +1 -1
- geek_cafe_saas_sdk/domains/events/handlers/update/app.py +1 -1
- geek_cafe_saas_sdk/domains/events/services/event_attendee_service.py +1 -2
- geek_cafe_saas_sdk/domains/events/services/event_service.py +6 -4
- geek_cafe_saas_sdk/domains/files/handlers/README.md +1 -1
- geek_cafe_saas_sdk/domains/files/handlers/files/create/app.py +1 -1
- geek_cafe_saas_sdk/domains/files/handlers/files/download/app.py +1 -1
- geek_cafe_saas_sdk/domains/files/handlers/files/get/app.py +1 -1
- geek_cafe_saas_sdk/domains/files/handlers/files/list/app.py +1 -1
- geek_cafe_saas_sdk/domains/files/handlers/lineage/create_derived/app.py +1 -1
- geek_cafe_saas_sdk/domains/files/handlers/lineage/create_main/app.py +1 -1
- geek_cafe_saas_sdk/domains/files/handlers/lineage/download_bundle/app.py +1 -1
- geek_cafe_saas_sdk/domains/files/handlers/lineage/get_lineage/app.py +1 -1
- geek_cafe_saas_sdk/domains/files/handlers/lineage/prepare_bundle/app.py +1 -1
- geek_cafe_saas_sdk/domains/files/models/file.py +16 -6
- geek_cafe_saas_sdk/domains/files/services/directory_service.py +34 -9
- geek_cafe_saas_sdk/domains/files/services/file_system_service.py +38 -3
- geek_cafe_saas_sdk/domains/files/services/file_version_service.py +33 -36
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/create/app.py +1 -1
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/delete/app.py +1 -1
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/get/app.py +1 -1
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/list/app.py +1 -1
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/update/app.py +1 -1
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/create/app.py +1 -1
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/delete/app.py +1 -1
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/get/app.py +1 -1
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/list/app.py +1 -1
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/update/app.py +1 -1
- geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/create/app.py +1 -1
- geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/delete/app.py +1 -1
- geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/get/app.py +1 -1
- geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/list/app.py +3 -2
- geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/update/app.py +1 -1
- geek_cafe_saas_sdk/domains/messaging/services/chat_channel_service.py +35 -2
- geek_cafe_saas_sdk/domains/messaging/services/chat_message_service.py +20 -3
- geek_cafe_saas_sdk/domains/messaging/services/contact_thread_service.py +1 -3
- geek_cafe_saas_sdk/domains/notifications/handlers/create_webhook/app.py +1 -1
- geek_cafe_saas_sdk/domains/notifications/handlers/get/app.py +1 -1
- geek_cafe_saas_sdk/domains/notifications/handlers/get_preferences/app.py +1 -1
- geek_cafe_saas_sdk/domains/notifications/handlers/list/app.py +1 -1
- geek_cafe_saas_sdk/domains/notifications/handlers/list_webhooks/app.py +1 -1
- geek_cafe_saas_sdk/domains/notifications/handlers/mark_read/app.py +1 -1
- geek_cafe_saas_sdk/domains/notifications/handlers/send/app.py +1 -1
- geek_cafe_saas_sdk/domains/notifications/handlers/update_preferences/app.py +1 -1
- geek_cafe_saas_sdk/domains/notifications/services/notification_service.py +1 -2
- geek_cafe_saas_sdk/domains/payments/handlers/billing_accounts/create/app.py +1 -1
- geek_cafe_saas_sdk/domains/payments/handlers/billing_accounts/get/app.py +1 -1
- geek_cafe_saas_sdk/domains/payments/handlers/billing_accounts/update/app.py +1 -1
- geek_cafe_saas_sdk/domains/payments/handlers/payment_intents/create/app.py +1 -1
- geek_cafe_saas_sdk/domains/payments/handlers/payment_intents/get/app.py +1 -1
- geek_cafe_saas_sdk/domains/payments/handlers/payments/get/app.py +1 -1
- geek_cafe_saas_sdk/domains/payments/handlers/payments/list/app.py +1 -1
- geek_cafe_saas_sdk/domains/payments/handlers/payments/record/app.py +1 -1
- geek_cafe_saas_sdk/domains/payments/handlers/refunds/create/app.py +1 -1
- geek_cafe_saas_sdk/domains/payments/handlers/refunds/get/app.py +1 -1
- geek_cafe_saas_sdk/domains/payments/services/payment_service.py +1 -2
- geek_cafe_saas_sdk/domains/subscriptions/handlers/README.md +2 -2
- geek_cafe_saas_sdk/domains/subscriptions/handlers/addons/create/app.py +1 -1
- geek_cafe_saas_sdk/domains/subscriptions/handlers/addons/get/app.py +1 -1
- geek_cafe_saas_sdk/domains/subscriptions/handlers/addons/list/app.py +1 -1
- geek_cafe_saas_sdk/domains/subscriptions/handlers/addons/update/app.py +1 -1
- geek_cafe_saas_sdk/domains/subscriptions/handlers/discounts/create/app.py +1 -1
- geek_cafe_saas_sdk/domains/subscriptions/handlers/discounts/get/app.py +1 -1
- geek_cafe_saas_sdk/domains/subscriptions/handlers/discounts/validate/app.py +1 -1
- geek_cafe_saas_sdk/domains/subscriptions/handlers/plans/create/app.py +1 -1
- geek_cafe_saas_sdk/domains/subscriptions/handlers/plans/get/app.py +1 -1
- geek_cafe_saas_sdk/domains/subscriptions/handlers/plans/list/app.py +1 -1
- geek_cafe_saas_sdk/domains/subscriptions/handlers/plans/update/app.py +1 -1
- geek_cafe_saas_sdk/domains/subscriptions/handlers/usage/aggregate/app.py +1 -1
- geek_cafe_saas_sdk/domains/subscriptions/handlers/usage/record/app.py +1 -1
- geek_cafe_saas_sdk/domains/subscriptions/services/subscription_manager_service.py +0 -2
- geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/activate/app.py +1 -1
- geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/active/app.py +1 -1
- geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/cancel/app.py +1 -1
- geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/get/app.py +1 -1
- geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/list/app.py +1 -1
- geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/record_payment/app.py +1 -1
- geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/get/app.py +1 -1
- geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/me/app.py +1 -1
- geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/signup/app.py +1 -1
- geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/update/app.py +1 -1
- geek_cafe_saas_sdk/domains/tenancy/services/subscription_service.py +3 -3
- geek_cafe_saas_sdk/domains/tenancy/services/tenant_service.py +3 -3
- geek_cafe_saas_sdk/domains/voting/handlers/votes/delete/app.py +1 -1
- geek_cafe_saas_sdk/domains/voting/handlers/votes/get/app.py +1 -1
- geek_cafe_saas_sdk/domains/voting/handlers/votes/list/app.py +1 -1
- geek_cafe_saas_sdk/domains/voting/handlers/votes/update/app.py +1 -1
- geek_cafe_saas_sdk/domains/voting/services/vote_service.py +1 -5
- geek_cafe_saas_sdk/domains/voting/services/vote_summary_service.py +1 -5
- geek_cafe_saas_sdk/domains/voting/services/vote_tally_service.py +10 -3
- geek_cafe_saas_sdk/lambda_handlers/_base/base_handler.py +40 -6
- geek_cafe_saas_sdk/lambda_handlers/_base/service_pool.py +157 -12
- geek_cafe_saas_sdk/middleware/authorization.py +1 -1
- geek_cafe_saas_sdk/middleware/cors.py +8 -8
- geek_cafe_saas_sdk/services/database_service.py +76 -5
- {geek_cafe_saas_sdk-0.7.4.dist-info → geek_cafe_saas_sdk-0.8.0.dist-info}/METADATA +16 -16
- {geek_cafe_saas_sdk-0.7.4.dist-info → geek_cafe_saas_sdk-0.8.0.dist-info}/RECORD +131 -129
- {geek_cafe_saas_sdk-0.7.4.dist-info → geek_cafe_saas_sdk-0.8.0.dist-info}/WHEEL +0 -0
- {geek_cafe_saas_sdk-0.7.4.dist-info → geek_cafe_saas_sdk-0.8.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Core Lambda
|
|
2
|
+
Core Lambda lambda_handler decorators for common cross-cutting concerns.
|
|
3
3
|
|
|
4
4
|
These decorators handle:
|
|
5
5
|
- Error handling and standardized error responses
|
|
@@ -25,7 +25,7 @@ from geek_cafe_saas_sdk.lambda_handlers._base.service_pool import ServicePool
|
|
|
25
25
|
logger = Logger()
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
def handle_errors(
|
|
28
|
+
def handle_errors(lambda_handler: Callable) -> Callable:
|
|
29
29
|
"""
|
|
30
30
|
Catch exceptions and return standardized error responses.
|
|
31
31
|
|
|
@@ -34,17 +34,17 @@ def handle_errors(handler: Callable) -> Callable:
|
|
|
34
34
|
|
|
35
35
|
Usage:
|
|
36
36
|
@handle_errors
|
|
37
|
-
def
|
|
37
|
+
def lambda_handler(event, context):
|
|
38
38
|
# Any exception becomes a 500 response
|
|
39
39
|
raise ValueError("Something went wrong")
|
|
40
40
|
|
|
41
41
|
Returns:
|
|
42
|
-
Decorated
|
|
42
|
+
Decorated lambda_handler that catches exceptions
|
|
43
43
|
"""
|
|
44
|
-
@functools.wraps(
|
|
44
|
+
@functools.wraps(lambda_handler)
|
|
45
45
|
def wrapper(event: Dict[str, Any], context: Any, *args, **kwargs) -> Dict[str, Any]:
|
|
46
46
|
try:
|
|
47
|
-
return
|
|
47
|
+
return lambda_handler(event, context, *args, **kwargs)
|
|
48
48
|
except ValueError as e:
|
|
49
49
|
# Validation errors -> 400
|
|
50
50
|
logger.warning(f"Validation error: {e}")
|
|
@@ -59,7 +59,7 @@ def handle_errors(handler: Callable) -> Callable:
|
|
|
59
59
|
return error_response(f"Missing required field: {str(e)}", "MISSING_FIELD", 400)
|
|
60
60
|
except Exception as e:
|
|
61
61
|
# Unexpected errors -> 500
|
|
62
|
-
logger.exception(f"Unexpected error in
|
|
62
|
+
logger.exception(f"Unexpected error in lambda_handler: {e}")
|
|
63
63
|
return error_response(
|
|
64
64
|
"An unexpected error occurred",
|
|
65
65
|
"INTERNAL_ERROR",
|
|
@@ -83,21 +83,21 @@ def add_cors(
|
|
|
83
83
|
|
|
84
84
|
Usage:
|
|
85
85
|
@add_cors()
|
|
86
|
-
def
|
|
86
|
+
def lambda_handler(event, context):
|
|
87
87
|
return {'statusCode': 200, 'body': '{}'}
|
|
88
88
|
|
|
89
89
|
# Custom CORS
|
|
90
90
|
@add_cors(allow_origin="https://example.com")
|
|
91
|
-
def
|
|
91
|
+
def lambda_handler(event, context):
|
|
92
92
|
return {'statusCode': 200, 'body': '{}'}
|
|
93
93
|
|
|
94
94
|
Returns:
|
|
95
|
-
Decorated
|
|
95
|
+
Decorated lambda_handler with CORS headers
|
|
96
96
|
"""
|
|
97
|
-
def decorator(
|
|
98
|
-
@functools.wraps(
|
|
97
|
+
def decorator(lambda_handler: Callable) -> Callable:
|
|
98
|
+
@functools.wraps(lambda_handler)
|
|
99
99
|
def wrapper(event: Dict[str, Any], context: Any, *args, **kwargs) -> Dict[str, Any]:
|
|
100
|
-
response =
|
|
100
|
+
response = lambda_handler(event, context, *args, **kwargs)
|
|
101
101
|
|
|
102
102
|
# Ensure headers dict exists
|
|
103
103
|
if 'headers' not in response:
|
|
@@ -129,15 +129,15 @@ def parse_request_body(
|
|
|
129
129
|
|
|
130
130
|
Usage:
|
|
131
131
|
@parse_request_body(required=True)
|
|
132
|
-
def
|
|
132
|
+
def lambda_handler(event, context):
|
|
133
133
|
payload = event['parsed_body']
|
|
134
134
|
return {'statusCode': 200, 'body': json.dumps(payload)}
|
|
135
135
|
|
|
136
136
|
Returns:
|
|
137
|
-
Decorated
|
|
137
|
+
Decorated lambda_handler with parsed body in event['parsed_body']
|
|
138
138
|
"""
|
|
139
|
-
def decorator(
|
|
140
|
-
@functools.wraps(
|
|
139
|
+
def decorator(lambda_handler: Callable) -> Callable:
|
|
140
|
+
@functools.wraps(lambda_handler)
|
|
141
141
|
def wrapper(event: Dict[str, Any], context: Any, *args, **kwargs) -> Dict[str, Any]:
|
|
142
142
|
# Check if body is required
|
|
143
143
|
if required and not event.get('body'):
|
|
@@ -166,7 +166,7 @@ def parse_request_body(
|
|
|
166
166
|
400
|
|
167
167
|
)
|
|
168
168
|
|
|
169
|
-
return
|
|
169
|
+
return lambda_handler(event, context, *args, **kwargs)
|
|
170
170
|
return wrapper
|
|
171
171
|
return decorator
|
|
172
172
|
|
|
@@ -178,10 +178,10 @@ def inject_service(
|
|
|
178
178
|
**service_kwargs
|
|
179
179
|
) -> Callable:
|
|
180
180
|
"""
|
|
181
|
-
Inject service instance into
|
|
181
|
+
Inject service instance into lambda_handler.
|
|
182
182
|
|
|
183
183
|
Creates and injects a service instance, optionally using connection pooling.
|
|
184
|
-
The service is passed as a keyword argument to the
|
|
184
|
+
The service is passed as a keyword argument to the lambda_handler.
|
|
185
185
|
|
|
186
186
|
Args:
|
|
187
187
|
service_class: Service class to instantiate
|
|
@@ -191,23 +191,23 @@ def inject_service(
|
|
|
191
191
|
|
|
192
192
|
Usage:
|
|
193
193
|
@inject_service(MessageService)
|
|
194
|
-
def
|
|
194
|
+
def lambda_handler(event, context, service):
|
|
195
195
|
return service.get_by_id(message_id)
|
|
196
196
|
|
|
197
197
|
# Custom parameter name
|
|
198
198
|
@inject_service(MessageService, param_name="msg_service")
|
|
199
|
-
def
|
|
199
|
+
def lambda_handler(event, context, msg_service):
|
|
200
200
|
return msg_service.get_by_id(message_id)
|
|
201
201
|
|
|
202
202
|
Returns:
|
|
203
|
-
Decorated
|
|
203
|
+
Decorated lambda_handler with service injected
|
|
204
204
|
"""
|
|
205
205
|
# Initialize service pool if using pooling
|
|
206
206
|
if use_pooling:
|
|
207
207
|
service_pool = ServicePool(service_class, **service_kwargs)
|
|
208
208
|
|
|
209
|
-
def decorator(
|
|
210
|
-
@functools.wraps(
|
|
209
|
+
def decorator(lambda_handler: Callable) -> Callable:
|
|
210
|
+
@functools.wraps(lambda_handler)
|
|
211
211
|
def wrapper(event: Dict[str, Any], context: Any, *args, **kwargs) -> Dict[str, Any]:
|
|
212
212
|
# Get service from pool or create new instance
|
|
213
213
|
if use_pooling:
|
|
@@ -218,7 +218,7 @@ def inject_service(
|
|
|
218
218
|
# Inject service as keyword argument
|
|
219
219
|
kwargs[param_name] = service
|
|
220
220
|
|
|
221
|
-
return
|
|
221
|
+
return lambda_handler(event, context, *args, **kwargs)
|
|
222
222
|
return wrapper
|
|
223
223
|
return decorator
|
|
224
224
|
|
|
@@ -229,7 +229,7 @@ def log_execution(
|
|
|
229
229
|
log_duration: bool = True
|
|
230
230
|
) -> Callable:
|
|
231
231
|
"""
|
|
232
|
-
Log
|
|
232
|
+
Log lambda_handler execution details.
|
|
233
233
|
|
|
234
234
|
Logs request/response details and execution duration for monitoring
|
|
235
235
|
and debugging purposes.
|
|
@@ -241,14 +241,14 @@ def log_execution(
|
|
|
241
241
|
|
|
242
242
|
Usage:
|
|
243
243
|
@log_execution(log_response=True)
|
|
244
|
-
def
|
|
244
|
+
def lambda_handler(event, context):
|
|
245
245
|
return {'statusCode': 200, 'body': '{}'}
|
|
246
246
|
|
|
247
247
|
Returns:
|
|
248
|
-
Decorated
|
|
248
|
+
Decorated lambda_handler with execution logging
|
|
249
249
|
"""
|
|
250
|
-
def decorator(
|
|
251
|
-
@functools.wraps(
|
|
250
|
+
def decorator(lambda_handler: Callable) -> Callable:
|
|
251
|
+
@functools.wraps(lambda_handler)
|
|
252
252
|
def wrapper(event: Dict[str, Any], context: Any, *args, **kwargs) -> Dict[str, Any]:
|
|
253
253
|
start_time = time.time()
|
|
254
254
|
|
|
@@ -263,8 +263,8 @@ def log_execution(
|
|
|
263
263
|
}
|
|
264
264
|
)
|
|
265
265
|
|
|
266
|
-
# Execute
|
|
267
|
-
response =
|
|
266
|
+
# Execute lambda_handler
|
|
267
|
+
response = lambda_handler(event, context, *args, **kwargs)
|
|
268
268
|
|
|
269
269
|
duration = time.time() - start_time
|
|
270
270
|
|
|
@@ -300,16 +300,16 @@ def validate_path_params(required_params: List[str]) -> Callable:
|
|
|
300
300
|
|
|
301
301
|
Usage:
|
|
302
302
|
@validate_path_params(['tenant_id', 'user_id', 'message_id'])
|
|
303
|
-
def
|
|
303
|
+
def lambda_handler(event, context):
|
|
304
304
|
# All required params guaranteed to exist
|
|
305
305
|
message_id = event['pathParameters']['message_id']
|
|
306
306
|
return {'statusCode': 200}
|
|
307
307
|
|
|
308
308
|
Returns:
|
|
309
|
-
Decorated
|
|
309
|
+
Decorated lambda_handler with validated path parameters
|
|
310
310
|
"""
|
|
311
|
-
def decorator(
|
|
312
|
-
@functools.wraps(
|
|
311
|
+
def decorator(lambda_handler: Callable) -> Callable:
|
|
312
|
+
@functools.wraps(lambda_handler)
|
|
313
313
|
def wrapper(event: Dict[str, Any], context: Any, *args, **kwargs) -> Dict[str, Any]:
|
|
314
314
|
path_params = event.get('pathParameters', {})
|
|
315
315
|
|
|
@@ -326,33 +326,33 @@ def validate_path_params(required_params: List[str]) -> Callable:
|
|
|
326
326
|
400
|
|
327
327
|
)
|
|
328
328
|
|
|
329
|
-
return
|
|
329
|
+
return lambda_handler(event, context, *args, **kwargs)
|
|
330
330
|
return wrapper
|
|
331
331
|
return decorator
|
|
332
332
|
|
|
333
333
|
|
|
334
|
-
def extract_user_context_decorator(
|
|
334
|
+
def extract_user_context_decorator(lambda_handler: Callable) -> Callable:
|
|
335
335
|
"""
|
|
336
336
|
Extract user context from JWT and add to event.
|
|
337
337
|
|
|
338
338
|
Extracts user context from API Gateway authorizer and adds it to
|
|
339
|
-
event['user_context'] for easy access in
|
|
339
|
+
event['user_context'] for easy access in lambda_handler.
|
|
340
340
|
|
|
341
341
|
Usage:
|
|
342
342
|
@extract_user_context_decorator
|
|
343
|
-
def
|
|
343
|
+
def lambda_handler(event, context):
|
|
344
344
|
user_id = event['user_context']['user_id']
|
|
345
345
|
tenant_id = event['user_context']['tenant_id']
|
|
346
346
|
return {'statusCode': 200}
|
|
347
347
|
|
|
348
348
|
Returns:
|
|
349
|
-
Decorated
|
|
349
|
+
Decorated lambda_handler with user_context in event
|
|
350
350
|
"""
|
|
351
|
-
@functools.wraps(
|
|
351
|
+
@functools.wraps(lambda_handler)
|
|
352
352
|
def wrapper(event: Dict[str, Any], context: Any, *args, **kwargs) -> Dict[str, Any]:
|
|
353
353
|
# Extract user context from authorizer
|
|
354
354
|
user_context = extract_user_context(event)
|
|
355
355
|
event['user_context'] = user_context
|
|
356
356
|
|
|
357
|
-
return
|
|
357
|
+
return lambda_handler(event, context, *args, **kwargs)
|
|
358
358
|
return wrapper
|
|
@@ -11,9 +11,7 @@ from geek_cafe_saas_sdk.domains.analytics.models import WebsiteAnalytics
|
|
|
11
11
|
class WebsiteAnalyticsService(DatabaseService[WebsiteAnalytics]):
|
|
12
12
|
"""Service for WebsiteAnalytics database operations."""
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
super().__init__(dynamodb=dynamodb, table_name=table_name)
|
|
16
|
-
|
|
14
|
+
|
|
17
15
|
def create(self, tenant_id: str, user_id: str, **kwargs) -> ServiceResult[WebsiteAnalytics]:
|
|
18
16
|
"""Create a new analytics record."""
|
|
19
17
|
try:
|
|
@@ -10,9 +10,7 @@ from geek_cafe_saas_sdk.domains.analytics.models import WebsiteAnalyticsSummary
|
|
|
10
10
|
|
|
11
11
|
class WebsiteAnalyticsSummaryService(DatabaseService[WebsiteAnalyticsSummary]):
|
|
12
12
|
"""Service for WebsiteAnalyticsSummary database operations."""
|
|
13
|
-
|
|
14
|
-
def __init__(self, *, dynamodb: DynamoDB = None, table_name: str = None):
|
|
15
|
-
super().__init__(dynamodb=dynamodb, table_name=table_name)
|
|
13
|
+
|
|
16
14
|
|
|
17
15
|
def create(self, tenant_id: str, user_id: str, **kwargs) -> ServiceResult[WebsiteAnalyticsSummary]:
|
|
18
16
|
"""Create or update (upsert) an analytics summary."""
|
|
@@ -4,6 +4,7 @@ from typing import Dict, Any, Optional, List
|
|
|
4
4
|
from boto3_assist.dynamodb.dynamodb import DynamoDB
|
|
5
5
|
from geek_cafe_saas_sdk.core.service_result import ServiceResult
|
|
6
6
|
from geek_cafe_saas_sdk.core.error_codes import ErrorCode
|
|
7
|
+
from geek_cafe_saas_sdk.core.request_context import RequestContext
|
|
7
8
|
from .website_analytics_service import WebsiteAnalyticsService
|
|
8
9
|
from .website_analytics_summary_service import WebsiteAnalyticsSummaryService
|
|
9
10
|
from geek_cafe_saas_sdk.domains.analytics.models import WebsiteAnalytics, WebsiteAnalyticsSummary
|
|
@@ -23,9 +24,20 @@ class WebsiteAnalyticsTallyService:
|
|
|
23
24
|
Aggregates raw analytics events into summary records for efficient querying.
|
|
24
25
|
"""
|
|
25
26
|
|
|
26
|
-
def __init__(self, *, dynamodb: DynamoDB = None, table_name: str = None
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
def __init__(self, *, dynamodb: DynamoDB = None, table_name: str = None,
|
|
28
|
+
request_context: RequestContext):
|
|
29
|
+
"""
|
|
30
|
+
Initialize tally service with child services.
|
|
31
|
+
|
|
32
|
+
NOTE: This service keeps custom __init__ because it creates child services.
|
|
33
|
+
Simple services inherit DatabaseService.__init__ directly.
|
|
34
|
+
"""
|
|
35
|
+
self.analytics_service = WebsiteAnalyticsService(
|
|
36
|
+
dynamodb=dynamodb, table_name=table_name, request_context=request_context
|
|
37
|
+
)
|
|
38
|
+
self.summary_service = WebsiteAnalyticsSummaryService(
|
|
39
|
+
dynamodb=dynamodb, table_name=table_name, request_context=request_context
|
|
40
|
+
)
|
|
29
41
|
self.page_size = 100 # Configurable page size for pagination
|
|
30
42
|
|
|
31
43
|
# Pagination monitoring configuration from environment variables
|
|
@@ -10,7 +10,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
10
10
|
|
|
11
11
|
user_service_pool = ServicePool(UserService)
|
|
12
12
|
|
|
13
|
-
def
|
|
13
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
14
14
|
"""
|
|
15
15
|
Lambda handler for creating a new user.
|
|
16
16
|
|
|
@@ -9,7 +9,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
9
9
|
|
|
10
10
|
user_service_pool = ServicePool(UserService)
|
|
11
11
|
|
|
12
|
-
def
|
|
12
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
13
13
|
"""
|
|
14
14
|
Lambda handler for deleting a user by its ID.
|
|
15
15
|
|
|
@@ -9,7 +9,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
9
9
|
|
|
10
10
|
user_service_pool = ServicePool(UserService)
|
|
11
11
|
|
|
12
|
-
def
|
|
12
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
13
13
|
"""
|
|
14
14
|
Lambda handler for retrieving a single user by its ID.
|
|
15
15
|
|
|
@@ -9,7 +9,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
9
9
|
|
|
10
10
|
user_service_pool = ServicePool(UserService)
|
|
11
11
|
|
|
12
|
-
def
|
|
12
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
13
13
|
"""
|
|
14
14
|
Lambda handler for listing users with optional filters.
|
|
15
15
|
|
|
@@ -10,7 +10,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
10
10
|
|
|
11
11
|
user_service_pool = ServicePool(UserService)
|
|
12
12
|
|
|
13
|
-
def
|
|
13
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
14
14
|
"""
|
|
15
15
|
Lambda handler for updating an existing user.
|
|
16
16
|
|
|
@@ -15,10 +15,7 @@ class ResourcePermissionService(DatabaseService[ResourcePermission]):
|
|
|
15
15
|
Service for ResourcePermission operations (ABAC).
|
|
16
16
|
|
|
17
17
|
Manages resource-level permission grants for fine-grained sharing.
|
|
18
|
-
"""
|
|
19
|
-
|
|
20
|
-
def __init__(self, *, dynamodb: DynamoDB = None, table_name: str = None):
|
|
21
|
-
super().__init__(dynamodb=dynamodb, table_name=table_name)
|
|
18
|
+
"""
|
|
22
19
|
|
|
23
20
|
# Required abstract methods from DatabaseService
|
|
24
21
|
def create(self, tenant_id: str, user_id: str, **kwargs) -> ServiceResult[ResourcePermission]:
|
|
@@ -12,8 +12,6 @@ import datetime as dt
|
|
|
12
12
|
|
|
13
13
|
class UserService(DatabaseService[User]):
|
|
14
14
|
|
|
15
|
-
def __init__(self, *, dynamodb: DynamoDB = None, table_name: str = None):
|
|
16
|
-
super().__init__(dynamodb=dynamodb, table_name=table_name)
|
|
17
15
|
|
|
18
16
|
def create(self, tenant_id: str, user_id: str, **kwargs) -> ServiceResult[User]:
|
|
19
17
|
"""Create a new user."""
|
|
@@ -10,7 +10,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
10
10
|
|
|
11
11
|
community_service_pool = ServicePool(CommunityService)
|
|
12
12
|
|
|
13
|
-
def
|
|
13
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
14
14
|
"""
|
|
15
15
|
Lambda handler for creating a new community.
|
|
16
16
|
|
|
@@ -9,7 +9,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
9
9
|
|
|
10
10
|
community_service_pool = ServicePool(CommunityService)
|
|
11
11
|
|
|
12
|
-
def
|
|
12
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
13
13
|
"""
|
|
14
14
|
Lambda handler for deleting a community.
|
|
15
15
|
|
|
@@ -9,7 +9,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
9
9
|
|
|
10
10
|
community_service_pool = ServicePool(CommunityService)
|
|
11
11
|
|
|
12
|
-
def
|
|
12
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
13
13
|
"""
|
|
14
14
|
Lambda handler for getting a community by ID.
|
|
15
15
|
|
|
@@ -9,7 +9,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
9
9
|
|
|
10
10
|
community_service_pool = ServicePool(CommunityService)
|
|
11
11
|
|
|
12
|
-
def
|
|
12
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
13
13
|
"""
|
|
14
14
|
Lambda handler for listing communities.
|
|
15
15
|
|
|
@@ -10,7 +10,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
10
10
|
|
|
11
11
|
community_service_pool = ServicePool(CommunityService)
|
|
12
12
|
|
|
13
|
-
def
|
|
13
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
14
14
|
"""
|
|
15
15
|
Lambda handler for updating a community.
|
|
16
16
|
|
|
@@ -15,9 +15,7 @@ class CommunityMemberService(DatabaseService[CommunityMember]):
|
|
|
15
15
|
|
|
16
16
|
Manages scalable membership using adjacent record pattern.
|
|
17
17
|
"""
|
|
18
|
-
|
|
19
|
-
def __init__(self, *, dynamodb: DynamoDB = None, table_name: str = None):
|
|
20
|
-
super().__init__(dynamodb=dynamodb, table_name=table_name)
|
|
18
|
+
|
|
21
19
|
|
|
22
20
|
# Required abstract methods from DatabaseService
|
|
23
21
|
def create(self, tenant_id: str, user_id: str, **kwargs) -> ServiceResult[CommunityMember]:
|
|
@@ -13,10 +13,10 @@ import datetime as dt
|
|
|
13
13
|
class CommunityService(DatabaseService[Community]):
|
|
14
14
|
"""Service for Community database operations."""
|
|
15
15
|
|
|
16
|
-
def __init__(self, *, dynamodb: DynamoDB = None, table_name: str = None):
|
|
17
|
-
super().__init__(dynamodb=dynamodb, table_name=table_name)
|
|
16
|
+
def __init__(self, *, dynamodb: DynamoDB = None, table_name: str = None, request_context: Optional[Dict[str, str]] = None):
|
|
17
|
+
super().__init__(dynamodb=dynamodb, table_name=table_name, request_context=request_context)
|
|
18
18
|
# Initialize member service with same DB connection
|
|
19
|
-
self.member_service = CommunityMemberService(dynamodb=dynamodb, table_name=table_name)
|
|
19
|
+
self.member_service = CommunityMemberService(dynamodb=dynamodb, table_name=table_name, request_context=request_context)
|
|
20
20
|
|
|
21
21
|
def create(self, tenant_id: str, user_id: str, **kwargs) -> ServiceResult[Community]:
|
|
22
22
|
"""Create a new community."""
|
|
@@ -9,7 +9,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
9
9
|
|
|
10
10
|
attendee_service_pool = ServicePool(EventAttendeeService)
|
|
11
11
|
|
|
12
|
-
def
|
|
12
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
13
13
|
"""
|
|
14
14
|
Lambda handler for listing event attendees.
|
|
15
15
|
|
|
@@ -10,7 +10,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
10
10
|
|
|
11
11
|
event_service_pool = ServicePool(EventService)
|
|
12
12
|
|
|
13
|
-
def
|
|
13
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
14
14
|
"""
|
|
15
15
|
Lambda handler for cancelling an event.
|
|
16
16
|
|
|
@@ -10,7 +10,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
10
10
|
|
|
11
11
|
attendee_service_pool = ServicePool(EventAttendeeService)
|
|
12
12
|
|
|
13
|
-
def
|
|
13
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
14
14
|
"""
|
|
15
15
|
Lambda handler for checking in attendees.
|
|
16
16
|
|
|
@@ -11,7 +11,7 @@ from geek_cafe_saas_sdk.domains.events.models.event import Event
|
|
|
11
11
|
|
|
12
12
|
event_service_pool = ServicePool(EventService)
|
|
13
13
|
|
|
14
|
-
def
|
|
14
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
15
15
|
"""
|
|
16
16
|
Lambda handler for creating a new event.
|
|
17
17
|
|
|
@@ -9,7 +9,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
9
9
|
|
|
10
10
|
event_service_pool = ServicePool(EventService)
|
|
11
11
|
|
|
12
|
-
def
|
|
12
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
13
13
|
"""
|
|
14
14
|
Lambda handler for deleting an event by its ID.
|
|
15
15
|
|
|
@@ -9,7 +9,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
9
9
|
|
|
10
10
|
event_service_pool = ServicePool(EventService)
|
|
11
11
|
|
|
12
|
-
def
|
|
12
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
13
13
|
"""
|
|
14
14
|
Lambda handler for retrieving a single event by its ID.
|
|
15
15
|
|
|
@@ -10,7 +10,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
10
10
|
|
|
11
11
|
attendee_service_pool = ServicePool(EventAttendeeService)
|
|
12
12
|
|
|
13
|
-
def
|
|
13
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
14
14
|
"""
|
|
15
15
|
Lambda handler for inviting user(s) to an event.
|
|
16
16
|
|
|
@@ -9,7 +9,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
9
9
|
|
|
10
10
|
event_service_pool = ServicePool(EventService)
|
|
11
11
|
|
|
12
|
-
def
|
|
12
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
13
13
|
"""
|
|
14
14
|
Lambda handler for listing events with location-based and other filters.
|
|
15
15
|
|
|
@@ -9,7 +9,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
9
9
|
|
|
10
10
|
event_service_pool = ServicePool(EventService)
|
|
11
11
|
|
|
12
|
-
def
|
|
12
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
13
13
|
"""
|
|
14
14
|
Lambda handler for publishing a draft event.
|
|
15
15
|
|
|
@@ -10,7 +10,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
10
10
|
|
|
11
11
|
attendee_service_pool = ServicePool(EventAttendeeService)
|
|
12
12
|
|
|
13
|
-
def
|
|
13
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
14
14
|
"""
|
|
15
15
|
Lambda handler for updating RSVP status.
|
|
16
16
|
|
|
@@ -10,7 +10,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
10
10
|
|
|
11
11
|
event_service_pool = ServicePool(EventService)
|
|
12
12
|
|
|
13
|
-
def
|
|
13
|
+
def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
14
14
|
"""
|
|
15
15
|
Lambda handler for updating an existing event.
|
|
16
16
|
|
|
@@ -13,8 +13,7 @@ import datetime as dt
|
|
|
13
13
|
class EventAttendeeService(DatabaseService[EventAttendee]):
|
|
14
14
|
"""Service for EventAttendee database operations (RSVP tracking, invitations, check-in)."""
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
super().__init__(dynamodb=dynamodb, table_name=table_name)
|
|
16
|
+
|
|
18
17
|
|
|
19
18
|
# Required abstract methods from DatabaseService
|
|
20
19
|
def create(self, tenant_id: str, user_id: str, **kwargs) -> ServiceResult[EventAttendee]:
|
|
@@ -22,9 +22,7 @@ class EventService(DatabaseService[Event]):
|
|
|
22
22
|
- Capacity management
|
|
23
23
|
- Multi-host support via EventAttendee
|
|
24
24
|
"""
|
|
25
|
-
|
|
26
|
-
def __init__(self, *, dynamodb: DynamoDB = None, table_name: str = None):
|
|
27
|
-
super().__init__(dynamodb=dynamodb, table_name=table_name)
|
|
25
|
+
|
|
28
26
|
|
|
29
27
|
def create(self, tenant_id: str, user_id: str, create_organizer_attendee: bool = True,
|
|
30
28
|
**kwargs) -> ServiceResult[Event]:
|
|
@@ -85,7 +83,11 @@ class EventService(DatabaseService[Event]):
|
|
|
85
83
|
if save_result.success and create_organizer_attendee:
|
|
86
84
|
# Create EventAttendee record for organizer
|
|
87
85
|
from .event_attendee_service import EventAttendeeService
|
|
88
|
-
attendee_service = EventAttendeeService(
|
|
86
|
+
attendee_service = EventAttendeeService(
|
|
87
|
+
dynamodb=self.dynamodb,
|
|
88
|
+
table_name=self.table_name,
|
|
89
|
+
request_context=self._request_context
|
|
90
|
+
)
|
|
89
91
|
|
|
90
92
|
attendee_result = attendee_service.invite(
|
|
91
93
|
event_id=event.id,
|
|
@@ -18,7 +18,7 @@ handler_wrapper = create_handler(
|
|
|
18
18
|
)
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
def
|
|
21
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
22
22
|
"""
|
|
23
23
|
Upload a new file.
|
|
24
24
|
|
|
@@ -18,7 +18,7 @@ handler_wrapper = create_handler(
|
|
|
18
18
|
)
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
def
|
|
21
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
22
22
|
"""
|
|
23
23
|
Download file content.
|
|
24
24
|
|