geek-cafe-saas-sdk 0.7.5__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 +1 -1
- 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.5.dist-info → geek_cafe_saas_sdk-0.8.0.dist-info}/METADATA +16 -16
- {geek_cafe_saas_sdk-0.7.5.dist-info → geek_cafe_saas_sdk-0.8.0.dist-info}/RECORD +131 -129
- {geek_cafe_saas_sdk-0.7.5.dist-info → geek_cafe_saas_sdk-0.8.0.dist-info}/WHEEL +0 -0
- {geek_cafe_saas_sdk-0.7.5.dist-info → geek_cafe_saas_sdk-0.8.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -9,6 +9,7 @@ from typing import Dict, Any, Optional, List
|
|
|
9
9
|
from boto3_assist.dynamodb.dynamodb import DynamoDB
|
|
10
10
|
from boto3_assist.dynamodb.dynamodb_index import DynamoDBKey
|
|
11
11
|
from geek_cafe_saas_sdk.services.database_service import DatabaseService
|
|
12
|
+
from geek_cafe_saas_sdk.core.request_context import RequestContext
|
|
12
13
|
from geek_cafe_saas_sdk.core.service_result import ServiceResult
|
|
13
14
|
from geek_cafe_saas_sdk.core.service_errors import ValidationError, NotFoundError, AccessDeniedError
|
|
14
15
|
from geek_cafe_saas_sdk.domains.messaging.models import ChatChannel, ChatChannelMember
|
|
@@ -18,8 +19,7 @@ import datetime as dt
|
|
|
18
19
|
class ChatChannelService(DatabaseService[ChatChannel]):
|
|
19
20
|
"""Service for ChatChannel database operations."""
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
super().__init__(dynamodb=dynamodb, table_name=table_name)
|
|
22
|
+
|
|
23
23
|
|
|
24
24
|
def create(self, tenant_id: str, user_id: str, payload: Dict[str, Any]) -> ServiceResult[ChatChannel]:
|
|
25
25
|
"""
|
|
@@ -36,6 +36,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
|
|
|
36
36
|
ServiceResult with ChatChannel
|
|
37
37
|
"""
|
|
38
38
|
try:
|
|
39
|
+
# Set targets for security validation
|
|
40
|
+
if self._request_context:
|
|
41
|
+
self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
|
|
39
42
|
# Validate required fields
|
|
40
43
|
required_fields = ['name']
|
|
41
44
|
self._validate_required_fields(payload, required_fields)
|
|
@@ -91,6 +94,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
|
|
|
91
94
|
ServiceResult with ChatChannel
|
|
92
95
|
"""
|
|
93
96
|
try:
|
|
97
|
+
# Set targets for security validation
|
|
98
|
+
if self._request_context:
|
|
99
|
+
self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
|
|
94
100
|
channel = self._get_model_by_id(resource_id, ChatChannel)
|
|
95
101
|
|
|
96
102
|
if not channel:
|
|
@@ -131,6 +137,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
|
|
|
131
137
|
ServiceResult with list of ChatChannels
|
|
132
138
|
"""
|
|
133
139
|
try:
|
|
140
|
+
# Set targets for security validation
|
|
141
|
+
if self._request_context:
|
|
142
|
+
self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
|
|
134
143
|
temp_channel = ChatChannel()
|
|
135
144
|
temp_channel.tenant_id = tenant_id
|
|
136
145
|
temp_channel.channel_type = channel_type
|
|
@@ -171,6 +180,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
|
|
|
171
180
|
ServiceResult with list of ChatChannels
|
|
172
181
|
"""
|
|
173
182
|
try:
|
|
183
|
+
# Set targets for security validation
|
|
184
|
+
if self._request_context:
|
|
185
|
+
self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
|
|
174
186
|
temp_channel = ChatChannel()
|
|
175
187
|
temp_channel.tenant_id = tenant_id
|
|
176
188
|
|
|
@@ -246,6 +258,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
|
|
|
246
258
|
ServiceResult with list of ChatChannels
|
|
247
259
|
"""
|
|
248
260
|
try:
|
|
261
|
+
# Set targets for security validation
|
|
262
|
+
if self._request_context:
|
|
263
|
+
self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
|
|
249
264
|
# Get user's channel memberships (fast via GSI1)
|
|
250
265
|
memberships_result = self.list_user_channels_fast(user_id, limit)
|
|
251
266
|
if not memberships_result.success:
|
|
@@ -285,6 +300,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
|
|
|
285
300
|
ServiceResult with updated ChatChannel
|
|
286
301
|
"""
|
|
287
302
|
try:
|
|
303
|
+
# Set targets for security validation
|
|
304
|
+
if self._request_context:
|
|
305
|
+
self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
|
|
288
306
|
channel_result = self.get_by_id(channel_id, tenant_id, user_id)
|
|
289
307
|
if not channel_result.success:
|
|
290
308
|
return channel_result
|
|
@@ -331,6 +349,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
|
|
|
331
349
|
ServiceResult with updated ChatChannel
|
|
332
350
|
"""
|
|
333
351
|
try:
|
|
352
|
+
# Set targets for security validation
|
|
353
|
+
if self._request_context:
|
|
354
|
+
self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
|
|
334
355
|
channel_result = self.get_by_id(channel_id, tenant_id, user_id)
|
|
335
356
|
if not channel_result.success:
|
|
336
357
|
return channel_result
|
|
@@ -409,6 +430,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
|
|
|
409
430
|
ServiceResult with updated ChatChannel
|
|
410
431
|
"""
|
|
411
432
|
try:
|
|
433
|
+
# Set targets for security validation
|
|
434
|
+
if self._request_context:
|
|
435
|
+
self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
|
|
412
436
|
channel_result = self.get_by_id(channel_id, tenant_id, user_id)
|
|
413
437
|
if not channel_result.success:
|
|
414
438
|
return channel_result
|
|
@@ -441,6 +465,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
|
|
|
441
465
|
ServiceResult with updated ChatChannel
|
|
442
466
|
"""
|
|
443
467
|
try:
|
|
468
|
+
# Set targets for security validation
|
|
469
|
+
if self._request_context:
|
|
470
|
+
self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
|
|
444
471
|
# For unarchive, we need to get the channel even if archived
|
|
445
472
|
channel = self._get_model_by_id(channel_id, ChatChannel)
|
|
446
473
|
if not channel:
|
|
@@ -476,6 +503,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
|
|
|
476
503
|
ServiceResult with updated ChatChannel
|
|
477
504
|
"""
|
|
478
505
|
try:
|
|
506
|
+
# Set targets for security validation
|
|
507
|
+
if self._request_context:
|
|
508
|
+
self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
|
|
479
509
|
channel = self._get_model_by_id(resource_id, ChatChannel)
|
|
480
510
|
|
|
481
511
|
if not channel:
|
|
@@ -521,6 +551,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
|
|
|
521
551
|
ServiceResult with boolean success
|
|
522
552
|
"""
|
|
523
553
|
try:
|
|
554
|
+
# Set targets for security validation
|
|
555
|
+
if self._request_context:
|
|
556
|
+
self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
|
|
524
557
|
channel = self._get_model_by_id(resource_id, ChatChannel)
|
|
525
558
|
|
|
526
559
|
if not channel:
|
|
@@ -8,6 +8,7 @@ ChatMessageService for managing individual chat messages.
|
|
|
8
8
|
from typing import Dict, Any, Optional, List
|
|
9
9
|
from boto3_assist.dynamodb.dynamodb import DynamoDB
|
|
10
10
|
from geek_cafe_saas_sdk.services.database_service import DatabaseService
|
|
11
|
+
from geek_cafe_saas_sdk.core.request_context import RequestContext
|
|
11
12
|
from .chat_channel_service import ChatChannelService
|
|
12
13
|
from geek_cafe_saas_sdk.core.service_result import ServiceResult
|
|
13
14
|
from geek_cafe_saas_sdk.core.service_errors import ValidationError, NotFoundError, AccessDeniedError
|
|
@@ -20,11 +21,12 @@ class ChatMessageService(DatabaseService[ChatMessage]):
|
|
|
20
21
|
"""Service for ChatMessage database operations."""
|
|
21
22
|
|
|
22
23
|
def __init__(self, *, dynamodb: DynamoDB = None, table_name: str = None,
|
|
24
|
+
request_context: Optional[RequestContext] = None,
|
|
23
25
|
channel_service: ChatChannelService = None):
|
|
24
|
-
super().__init__(dynamodb=dynamodb, table_name=table_name)
|
|
25
|
-
# Channel service for updating channel metadata
|
|
26
|
+
super().__init__(dynamodb=dynamodb, table_name=table_name, request_context=request_context)
|
|
27
|
+
# Channel service for updating channel metadata (share request_context)
|
|
26
28
|
self.channel_service = channel_service or ChatChannelService(
|
|
27
|
-
dynamodb=dynamodb, table_name=table_name
|
|
29
|
+
dynamodb=dynamodb, table_name=table_name, request_context=request_context
|
|
28
30
|
)
|
|
29
31
|
# Query helper for sharded message reads
|
|
30
32
|
self.query_helper = MessageQueryHelper(dynamodb, table_name)
|
|
@@ -42,6 +44,9 @@ class ChatMessageService(DatabaseService[ChatMessage]):
|
|
|
42
44
|
ServiceResult with ChatMessage
|
|
43
45
|
"""
|
|
44
46
|
try:
|
|
47
|
+
# Set targets for security validation
|
|
48
|
+
if self._request_context:
|
|
49
|
+
self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
|
|
45
50
|
# Validate required fields
|
|
46
51
|
required_fields = ['channel_id', 'content']
|
|
47
52
|
self._validate_required_fields(payload, required_fields)
|
|
@@ -129,6 +134,9 @@ class ChatMessageService(DatabaseService[ChatMessage]):
|
|
|
129
134
|
ServiceResult with ChatMessage
|
|
130
135
|
"""
|
|
131
136
|
try:
|
|
137
|
+
# Set targets for security validation
|
|
138
|
+
if self._request_context:
|
|
139
|
+
self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
|
|
132
140
|
message = self._get_model_by_id(resource_id, ChatMessage)
|
|
133
141
|
|
|
134
142
|
if not message:
|
|
@@ -174,6 +182,9 @@ class ChatMessageService(DatabaseService[ChatMessage]):
|
|
|
174
182
|
ServiceResult with list of ChatMessages and pagination metadata
|
|
175
183
|
"""
|
|
176
184
|
try:
|
|
185
|
+
# Set targets for security validation
|
|
186
|
+
if self._request_context:
|
|
187
|
+
self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
|
|
177
188
|
# Verify user has access to the channel
|
|
178
189
|
channel_result = self.channel_service.get_by_id(channel_id, tenant_id, user_id)
|
|
179
190
|
if not channel_result.success:
|
|
@@ -382,6 +393,9 @@ class ChatMessageService(DatabaseService[ChatMessage]):
|
|
|
382
393
|
ServiceResult with updated ChatMessage
|
|
383
394
|
"""
|
|
384
395
|
try:
|
|
396
|
+
# Set targets for security validation
|
|
397
|
+
if self._request_context:
|
|
398
|
+
self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
|
|
385
399
|
message = self._get_model_by_id(resource_id, ChatMessage)
|
|
386
400
|
|
|
387
401
|
if not message:
|
|
@@ -423,6 +437,9 @@ class ChatMessageService(DatabaseService[ChatMessage]):
|
|
|
423
437
|
ServiceResult with boolean success
|
|
424
438
|
"""
|
|
425
439
|
try:
|
|
440
|
+
# Set targets for security validation
|
|
441
|
+
if self._request_context:
|
|
442
|
+
self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
|
|
426
443
|
message = self._get_model_by_id(resource_id, ChatMessage)
|
|
427
444
|
|
|
428
445
|
if not message:
|
|
@@ -16,9 +16,7 @@ import datetime as dt
|
|
|
16
16
|
|
|
17
17
|
class ContactThreadService(DatabaseService[ContactThread]):
|
|
18
18
|
"""Service for ContactThread database operations."""
|
|
19
|
-
|
|
20
|
-
def __init__(self, *, dynamodb: DynamoDB = None, table_name: str = None):
|
|
21
|
-
super().__init__(dynamodb=dynamodb, table_name=table_name)
|
|
19
|
+
|
|
22
20
|
|
|
23
21
|
def _user_has_cross_tenant_access(self, user_context: Optional[Dict[str, str]]) -> bool:
|
|
24
22
|
"""
|
|
@@ -12,7 +12,7 @@ handler_wrapper = create_handler(
|
|
|
12
12
|
)
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def
|
|
15
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
16
16
|
"""
|
|
17
17
|
Create webhook subscription.
|
|
18
18
|
|
|
@@ -12,7 +12,7 @@ handler_wrapper = create_handler(
|
|
|
12
12
|
)
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def
|
|
15
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
16
16
|
"""
|
|
17
17
|
Get a notification by ID.
|
|
18
18
|
|
|
@@ -12,7 +12,7 @@ handler_wrapper = create_handler(
|
|
|
12
12
|
)
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def
|
|
15
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
16
16
|
"""
|
|
17
17
|
Get user notification preferences.
|
|
18
18
|
|
|
@@ -12,7 +12,7 @@ handler_wrapper = create_handler(
|
|
|
12
12
|
)
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def
|
|
15
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
16
16
|
"""
|
|
17
17
|
List notifications for current user.
|
|
18
18
|
|
|
@@ -12,7 +12,7 @@ handler_wrapper = create_handler(
|
|
|
12
12
|
)
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def
|
|
15
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
16
16
|
"""
|
|
17
17
|
List webhook subscriptions.
|
|
18
18
|
|
|
@@ -12,7 +12,7 @@ handler_wrapper = create_handler(
|
|
|
12
12
|
)
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def
|
|
15
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
16
16
|
"""
|
|
17
17
|
Mark notification as read.
|
|
18
18
|
|
|
@@ -12,7 +12,7 @@ handler_wrapper = create_handler(
|
|
|
12
12
|
)
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def
|
|
15
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
16
16
|
"""
|
|
17
17
|
Send a notification.
|
|
18
18
|
|
|
@@ -12,7 +12,7 @@ handler_wrapper = create_handler(
|
|
|
12
12
|
)
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def
|
|
15
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
16
16
|
"""
|
|
17
17
|
Update user notification preferences.
|
|
18
18
|
|
|
@@ -35,8 +35,7 @@ class NotificationService(DatabaseService[Notification]):
|
|
|
35
35
|
- Webhook subscriptions
|
|
36
36
|
"""
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
super().__init__(dynamodb=dynamodb, table_name=table_name)
|
|
38
|
+
|
|
40
39
|
|
|
41
40
|
# ========================================================================
|
|
42
41
|
# Abstract Method Implementations (Required by DatabaseService)
|
|
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def
|
|
20
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
21
21
|
"""
|
|
22
22
|
Create a new billing account.
|
|
23
23
|
|
|
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def
|
|
20
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
21
21
|
"""
|
|
22
22
|
Get billing account by ID.
|
|
23
23
|
|
|
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def
|
|
20
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
21
21
|
"""
|
|
22
22
|
Update a billing account.
|
|
23
23
|
|
|
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def
|
|
20
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
21
21
|
"""
|
|
22
22
|
Create a payment intent.
|
|
23
23
|
|
|
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def
|
|
20
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
21
21
|
"""
|
|
22
22
|
Get payment intent by ID.
|
|
23
23
|
|
|
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def
|
|
20
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
21
21
|
"""
|
|
22
22
|
Get payment by ID.
|
|
23
23
|
|
|
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def
|
|
20
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
21
21
|
"""
|
|
22
22
|
List payments for a tenant or billing account.
|
|
23
23
|
|
|
@@ -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
|
Record a settled payment.
|
|
24
24
|
|
|
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def
|
|
20
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
21
21
|
"""
|
|
22
22
|
Create a refund for a payment.
|
|
23
23
|
|
|
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def
|
|
20
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
21
21
|
"""
|
|
22
22
|
Get refund by ID.
|
|
23
23
|
|
|
@@ -21,8 +21,7 @@ from geek_cafe_saas_sdk.domains.payments.models.refund import Refund
|
|
|
21
21
|
class PaymentService(DatabaseService[Payment]):
|
|
22
22
|
"""Service for managing payments, billing accounts, and refunds."""
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
super().__init__(dynamodb=dynamodb, table_name=table_name)
|
|
24
|
+
|
|
26
25
|
|
|
27
26
|
# Abstract method implementations (delegating to specific methods)
|
|
28
27
|
def create(self, **kwargs) -> ServiceResult[Payment]:
|
|
@@ -341,7 +341,7 @@ PlanListFunction:
|
|
|
341
341
|
Handlers support dependency injection for testing:
|
|
342
342
|
|
|
343
343
|
```python
|
|
344
|
-
from handlers.plans.list.app import
|
|
344
|
+
from handlers.plans.list.app import lambda_handler
|
|
345
345
|
|
|
346
346
|
# Mock service
|
|
347
347
|
class MockService:
|
|
@@ -350,7 +350,7 @@ class MockService:
|
|
|
350
350
|
|
|
351
351
|
# Test
|
|
352
352
|
event = {"queryStringParameters": {"status": "active"}}
|
|
353
|
-
response =
|
|
353
|
+
response = lambda_handler(event, None, injected_service=MockService())
|
|
354
354
|
```
|
|
355
355
|
|
|
356
356
|
---
|
|
@@ -16,7 +16,7 @@ handler_wrapper = create_handler(
|
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def
|
|
19
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
20
20
|
"""
|
|
21
21
|
Create a new addon.
|
|
22
22
|
|
|
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def
|
|
20
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
21
21
|
"""
|
|
22
22
|
Get an addon by ID.
|
|
23
23
|
|
|
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def
|
|
20
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
21
21
|
"""
|
|
22
22
|
List public addons.
|
|
23
23
|
|
|
@@ -16,7 +16,7 @@ handler_wrapper = create_handler(
|
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def
|
|
19
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
20
20
|
"""
|
|
21
21
|
Update an addon.
|
|
22
22
|
|
|
@@ -16,7 +16,7 @@ handler_wrapper = create_handler(
|
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def
|
|
19
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
20
20
|
"""
|
|
21
21
|
Create a new discount/promo code.
|
|
22
22
|
|
|
@@ -16,7 +16,7 @@ handler_wrapper = create_handler(
|
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def
|
|
19
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
20
20
|
"""
|
|
21
21
|
Get a discount by ID.
|
|
22
22
|
|
|
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def
|
|
20
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
21
21
|
"""
|
|
22
22
|
Validate a discount code.
|
|
23
23
|
|
|
@@ -16,7 +16,7 @@ handler_wrapper = create_handler(
|
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def
|
|
19
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
20
20
|
"""
|
|
21
21
|
Create a new subscription plan.
|
|
22
22
|
|
|
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def
|
|
20
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
21
21
|
"""
|
|
22
22
|
Get a subscription plan by ID.
|
|
23
23
|
|
|
@@ -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
|
List public subscription plans.
|
|
24
24
|
|
|
@@ -16,7 +16,7 @@ handler_wrapper = create_handler(
|
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def
|
|
19
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
20
20
|
"""
|
|
21
21
|
Update a subscription plan.
|
|
22
22
|
|
|
@@ -16,7 +16,7 @@ handler_wrapper = create_handler(
|
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def
|
|
19
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
20
20
|
"""
|
|
21
21
|
Get aggregated usage for a billing period.
|
|
22
22
|
|
|
@@ -16,7 +16,7 @@ handler_wrapper = create_handler(
|
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def
|
|
19
|
+
def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
|
|
20
20
|
"""
|
|
21
21
|
Record a usage event for metered billing.
|
|
22
22
|
|
|
@@ -30,8 +30,6 @@ class SubscriptionManagerService(DatabaseService[Plan]):
|
|
|
30
30
|
per-tenant subscription instances.
|
|
31
31
|
"""
|
|
32
32
|
|
|
33
|
-
def __init__(self, *, dynamodb: Optional[DynamoDB] = None, table_name: Optional[str] = None):
|
|
34
|
-
super().__init__(dynamodb=dynamodb, table_name=table_name)
|
|
35
33
|
|
|
36
34
|
# ========================================================================
|
|
37
35
|
# Abstract Method Implementations (DatabaseService)
|
|
@@ -10,7 +10,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
10
10
|
|
|
11
11
|
subscription_service_pool = ServicePool(SubscriptionService)
|
|
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 activating a subscription (upgrade/downgrade).
|
|
16
16
|
|
|
@@ -9,7 +9,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
9
9
|
|
|
10
10
|
subscription_service_pool = ServicePool(SubscriptionService)
|
|
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 the tenant's active subscription.
|
|
15
15
|
|
|
@@ -10,7 +10,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
10
10
|
|
|
11
11
|
subscription_service_pool = ServicePool(SubscriptionService)
|
|
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 canceling a subscription.
|
|
16
16
|
|
|
@@ -9,7 +9,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
9
9
|
|
|
10
10
|
subscription_service_pool = ServicePool(SubscriptionService)
|
|
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 subscription by ID.
|
|
15
15
|
|
|
@@ -9,7 +9,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
9
9
|
|
|
10
10
|
subscription_service_pool = ServicePool(SubscriptionService)
|
|
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 subscription history for a tenant.
|
|
15
15
|
|
|
@@ -10,7 +10,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
|
10
10
|
|
|
11
11
|
subscription_service_pool = ServicePool(SubscriptionService)
|
|
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 recording a payment on a subscription.
|
|
16
16
|
|