geek-cafe-saas-sdk 0.6.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 +9 -0
- geek_cafe_saas_sdk/core/__init__.py +11 -0
- geek_cafe_saas_sdk/core/audit_mixin.py +33 -0
- geek_cafe_saas_sdk/core/error_codes.py +132 -0
- geek_cafe_saas_sdk/core/service_errors.py +19 -0
- geek_cafe_saas_sdk/core/service_result.py +121 -0
- geek_cafe_saas_sdk/decorators/__init__.py +64 -0
- geek_cafe_saas_sdk/decorators/auth.py +373 -0
- geek_cafe_saas_sdk/decorators/core.py +358 -0
- geek_cafe_saas_sdk/domains/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/analytics/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/analytics/handlers/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/analytics/models/__init__.py +9 -0
- geek_cafe_saas_sdk/domains/analytics/models/website_analytics.py +219 -0
- geek_cafe_saas_sdk/domains/analytics/models/website_analytics_summary.py +220 -0
- geek_cafe_saas_sdk/domains/analytics/services/__init__.py +11 -0
- geek_cafe_saas_sdk/domains/analytics/services/website_analytics_service.py +232 -0
- geek_cafe_saas_sdk/domains/analytics/services/website_analytics_summary_service.py +212 -0
- geek_cafe_saas_sdk/domains/analytics/services/website_analytics_tally_service.py +610 -0
- geek_cafe_saas_sdk/domains/auth/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/auth/handlers/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/auth/handlers/users/create/app.py +41 -0
- geek_cafe_saas_sdk/domains/auth/handlers/users/delete/app.py +41 -0
- geek_cafe_saas_sdk/domains/auth/handlers/users/get/app.py +39 -0
- geek_cafe_saas_sdk/domains/auth/handlers/users/list/app.py +36 -0
- geek_cafe_saas_sdk/domains/auth/handlers/users/update/app.py +44 -0
- geek_cafe_saas_sdk/domains/auth/models/__init__.py +13 -0
- geek_cafe_saas_sdk/domains/auth/models/permission.py +134 -0
- geek_cafe_saas_sdk/domains/auth/models/resource_permission.py +245 -0
- geek_cafe_saas_sdk/domains/auth/models/role.py +213 -0
- geek_cafe_saas_sdk/domains/auth/models/user.py +285 -0
- geek_cafe_saas_sdk/domains/auth/services/__init__.py +16 -0
- geek_cafe_saas_sdk/domains/auth/services/authorization_service.py +376 -0
- geek_cafe_saas_sdk/domains/auth/services/permission_registry.py +464 -0
- geek_cafe_saas_sdk/domains/auth/services/resource_permission_service.py +408 -0
- geek_cafe_saas_sdk/domains/auth/services/user_service.py +274 -0
- geek_cafe_saas_sdk/domains/communities/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/communities/handlers/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/communities/handlers/communities/create/app.py +41 -0
- geek_cafe_saas_sdk/domains/communities/handlers/communities/delete/app.py +41 -0
- geek_cafe_saas_sdk/domains/communities/handlers/communities/get/app.py +39 -0
- geek_cafe_saas_sdk/domains/communities/handlers/communities/list/app.py +36 -0
- geek_cafe_saas_sdk/domains/communities/handlers/communities/update/app.py +44 -0
- geek_cafe_saas_sdk/domains/communities/models/__init__.py +6 -0
- geek_cafe_saas_sdk/domains/communities/models/community.py +326 -0
- geek_cafe_saas_sdk/domains/communities/models/community_member.py +227 -0
- geek_cafe_saas_sdk/domains/communities/services/__init__.py +6 -0
- geek_cafe_saas_sdk/domains/communities/services/community_member_service.py +412 -0
- geek_cafe_saas_sdk/domains/communities/services/community_service.py +479 -0
- geek_cafe_saas_sdk/domains/events/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/events/handlers/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/events/handlers/attendees/app.py +67 -0
- geek_cafe_saas_sdk/domains/events/handlers/cancel/app.py +66 -0
- geek_cafe_saas_sdk/domains/events/handlers/check_in/app.py +60 -0
- geek_cafe_saas_sdk/domains/events/handlers/create/app.py +93 -0
- geek_cafe_saas_sdk/domains/events/handlers/delete/app.py +42 -0
- geek_cafe_saas_sdk/domains/events/handlers/get/app.py +39 -0
- geek_cafe_saas_sdk/domains/events/handlers/invite/app.py +98 -0
- geek_cafe_saas_sdk/domains/events/handlers/list/app.py +125 -0
- geek_cafe_saas_sdk/domains/events/handlers/publish/app.py +49 -0
- geek_cafe_saas_sdk/domains/events/handlers/rsvp/app.py +83 -0
- geek_cafe_saas_sdk/domains/events/handlers/update/app.py +44 -0
- geek_cafe_saas_sdk/domains/events/models/__init__.py +3 -0
- geek_cafe_saas_sdk/domains/events/models/event.py +681 -0
- geek_cafe_saas_sdk/domains/events/models/event_attendee.py +324 -0
- geek_cafe_saas_sdk/domains/events/services/__init__.py +9 -0
- geek_cafe_saas_sdk/domains/events/services/event_attendee_service.py +571 -0
- geek_cafe_saas_sdk/domains/events/services/event_service.py +684 -0
- geek_cafe_saas_sdk/domains/files/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/files/models/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/files/models/directory.py +258 -0
- geek_cafe_saas_sdk/domains/files/models/file.py +312 -0
- geek_cafe_saas_sdk/domains/files/models/file_share.py +268 -0
- geek_cafe_saas_sdk/domains/files/models/file_version.py +216 -0
- geek_cafe_saas_sdk/domains/files/services/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/files/services/directory_service.py +701 -0
- geek_cafe_saas_sdk/domains/files/services/file_share_service.py +663 -0
- geek_cafe_saas_sdk/domains/files/services/file_system_service.py +575 -0
- geek_cafe_saas_sdk/domains/files/services/file_version_service.py +739 -0
- geek_cafe_saas_sdk/domains/files/services/s3_file_service.py +501 -0
- geek_cafe_saas_sdk/domains/messaging/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/create/app.py +86 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/delete/app.py +65 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/get/app.py +64 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/list/app.py +97 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/update/app.py +149 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/create/app.py +67 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/delete/app.py +65 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/get/app.py +64 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/list/app.py +102 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/update/app.py +127 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/create/app.py +94 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/delete/app.py +66 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/get/app.py +67 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/list/app.py +95 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/update/app.py +156 -0
- geek_cafe_saas_sdk/domains/messaging/models/__init__.py +13 -0
- geek_cafe_saas_sdk/domains/messaging/models/chat_channel.py +337 -0
- geek_cafe_saas_sdk/domains/messaging/models/chat_channel_member.py +180 -0
- geek_cafe_saas_sdk/domains/messaging/models/chat_message.py +426 -0
- geek_cafe_saas_sdk/domains/messaging/models/contact_thread.py +392 -0
- geek_cafe_saas_sdk/domains/messaging/services/__init__.py +11 -0
- geek_cafe_saas_sdk/domains/messaging/services/chat_channel_service.py +700 -0
- geek_cafe_saas_sdk/domains/messaging/services/chat_message_service.py +491 -0
- geek_cafe_saas_sdk/domains/messaging/services/contact_thread_service.py +497 -0
- geek_cafe_saas_sdk/domains/tenancy/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/activate/app.py +52 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/active/app.py +37 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/cancel/app.py +55 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/get/app.py +39 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/list/app.py +44 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/record_payment/app.py +56 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/get/app.py +39 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/me/app.py +37 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/signup/app.py +61 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/update/app.py +44 -0
- geek_cafe_saas_sdk/domains/tenancy/models/__init__.py +6 -0
- geek_cafe_saas_sdk/domains/tenancy/models/subscription.py +440 -0
- geek_cafe_saas_sdk/domains/tenancy/models/tenant.py +258 -0
- geek_cafe_saas_sdk/domains/tenancy/services/__init__.py +6 -0
- geek_cafe_saas_sdk/domains/tenancy/services/subscription_service.py +557 -0
- geek_cafe_saas_sdk/domains/tenancy/services/tenant_service.py +575 -0
- geek_cafe_saas_sdk/domains/voting/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/voting/handlers/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/voting/handlers/votes/create/app.py +128 -0
- geek_cafe_saas_sdk/domains/voting/handlers/votes/delete/app.py +41 -0
- geek_cafe_saas_sdk/domains/voting/handlers/votes/get/app.py +39 -0
- geek_cafe_saas_sdk/domains/voting/handlers/votes/list/app.py +38 -0
- geek_cafe_saas_sdk/domains/voting/handlers/votes/summerize/README.md +3 -0
- geek_cafe_saas_sdk/domains/voting/handlers/votes/update/app.py +44 -0
- geek_cafe_saas_sdk/domains/voting/models/__init__.py +9 -0
- geek_cafe_saas_sdk/domains/voting/models/vote.py +231 -0
- geek_cafe_saas_sdk/domains/voting/models/vote_summary.py +193 -0
- geek_cafe_saas_sdk/domains/voting/services/__init__.py +11 -0
- geek_cafe_saas_sdk/domains/voting/services/vote_service.py +264 -0
- geek_cafe_saas_sdk/domains/voting/services/vote_summary_service.py +198 -0
- geek_cafe_saas_sdk/domains/voting/services/vote_tally_service.py +533 -0
- geek_cafe_saas_sdk/lambda_handlers/README.md +404 -0
- geek_cafe_saas_sdk/lambda_handlers/__init__.py +67 -0
- geek_cafe_saas_sdk/lambda_handlers/_base/__init__.py +25 -0
- geek_cafe_saas_sdk/lambda_handlers/_base/api_key_handler.py +129 -0
- geek_cafe_saas_sdk/lambda_handlers/_base/authorized_secure_handler.py +218 -0
- geek_cafe_saas_sdk/lambda_handlers/_base/base_handler.py +185 -0
- geek_cafe_saas_sdk/lambda_handlers/_base/handler_factory.py +256 -0
- geek_cafe_saas_sdk/lambda_handlers/_base/public_handler.py +53 -0
- geek_cafe_saas_sdk/lambda_handlers/_base/secure_handler.py +89 -0
- geek_cafe_saas_sdk/lambda_handlers/_base/service_pool.py +94 -0
- geek_cafe_saas_sdk/lambda_handlers/directories/create/app.py +79 -0
- geek_cafe_saas_sdk/lambda_handlers/directories/delete/app.py +76 -0
- geek_cafe_saas_sdk/lambda_handlers/directories/get/app.py +74 -0
- geek_cafe_saas_sdk/lambda_handlers/directories/list/app.py +75 -0
- geek_cafe_saas_sdk/lambda_handlers/directories/move/app.py +79 -0
- geek_cafe_saas_sdk/lambda_handlers/files/delete/app.py +121 -0
- geek_cafe_saas_sdk/lambda_handlers/files/download/app.py +187 -0
- geek_cafe_saas_sdk/lambda_handlers/files/get/app.py +127 -0
- geek_cafe_saas_sdk/lambda_handlers/files/list/app.py +108 -0
- geek_cafe_saas_sdk/lambda_handlers/files/share/app.py +83 -0
- geek_cafe_saas_sdk/lambda_handlers/files/shares/list/app.py +84 -0
- geek_cafe_saas_sdk/lambda_handlers/files/shares/revoke/app.py +76 -0
- geek_cafe_saas_sdk/lambda_handlers/files/update/app.py +143 -0
- geek_cafe_saas_sdk/lambda_handlers/files/upload/app.py +151 -0
- geek_cafe_saas_sdk/middleware/__init__.py +36 -0
- geek_cafe_saas_sdk/middleware/auth.py +85 -0
- geek_cafe_saas_sdk/middleware/authorization.py +523 -0
- geek_cafe_saas_sdk/middleware/cors.py +63 -0
- geek_cafe_saas_sdk/middleware/error_handling.py +114 -0
- geek_cafe_saas_sdk/middleware/validation.py +80 -0
- geek_cafe_saas_sdk/models/__init__.py +20 -0
- geek_cafe_saas_sdk/models/base_model.py +233 -0
- geek_cafe_saas_sdk/services/__init__.py +18 -0
- geek_cafe_saas_sdk/services/database_service.py +441 -0
- geek_cafe_saas_sdk/utilities/__init__.py +88 -0
- geek_cafe_saas_sdk/utilities/cognito_utility.py +568 -0
- geek_cafe_saas_sdk/utilities/custom_exceptions.py +183 -0
- geek_cafe_saas_sdk/utilities/datetime_utility.py +410 -0
- geek_cafe_saas_sdk/utilities/dictionary_utility.py +78 -0
- geek_cafe_saas_sdk/utilities/dynamodb_utils.py +151 -0
- geek_cafe_saas_sdk/utilities/environment_loader.py +149 -0
- geek_cafe_saas_sdk/utilities/environment_variables.py +228 -0
- geek_cafe_saas_sdk/utilities/http_body_parameters.py +44 -0
- geek_cafe_saas_sdk/utilities/http_path_parameters.py +60 -0
- geek_cafe_saas_sdk/utilities/http_status_code.py +63 -0
- geek_cafe_saas_sdk/utilities/jwt_utility.py +234 -0
- geek_cafe_saas_sdk/utilities/lambda_event_utility.py +776 -0
- geek_cafe_saas_sdk/utilities/logging_utility.py +64 -0
- geek_cafe_saas_sdk/utilities/message_query_helper.py +340 -0
- geek_cafe_saas_sdk/utilities/response.py +209 -0
- geek_cafe_saas_sdk/utilities/string_functions.py +180 -0
- geek_cafe_saas_sdk-0.6.0.dist-info/METADATA +397 -0
- geek_cafe_saas_sdk-0.6.0.dist-info/RECORD +194 -0
- geek_cafe_saas_sdk-0.6.0.dist-info/WHEEL +4 -0
- geek_cafe_saas_sdk-0.6.0.dist-info/licenses/LICENSE +47 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# src/geek_cafe_saas_sdk/lambda_handlers/subscriptions/list/app.py
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Any
|
|
4
|
+
|
|
5
|
+
from geek_cafe_saas_sdk.services import SubscriptionService
|
|
6
|
+
from geek_cafe_saas_sdk.lambda_handlers import ServicePool
|
|
7
|
+
from geek_cafe_saas_sdk.utilities.response import service_result_to_response, error_response
|
|
8
|
+
from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
9
|
+
|
|
10
|
+
subscription_service_pool = ServicePool(SubscriptionService)
|
|
11
|
+
|
|
12
|
+
def handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
13
|
+
"""
|
|
14
|
+
Lambda handler for listing subscription history for a tenant.
|
|
15
|
+
|
|
16
|
+
Returns all subscriptions (current and past) sorted by date descending.
|
|
17
|
+
|
|
18
|
+
Query parameters:
|
|
19
|
+
- limit: Maximum number of results (default: 50)
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
event: API Gateway event
|
|
23
|
+
context: Lambda context
|
|
24
|
+
injected_service: Optional SubscriptionService for testing
|
|
25
|
+
"""
|
|
26
|
+
try:
|
|
27
|
+
subscription_service = injected_service if injected_service else subscription_service_pool.get()
|
|
28
|
+
user_id = LambdaEventUtility.get_authenticated_user_id(event)
|
|
29
|
+
tenant_id = LambdaEventUtility.get_authenticated_user_tenant_id(event)
|
|
30
|
+
query_params = event.get('queryStringParameters', {}) or {}
|
|
31
|
+
|
|
32
|
+
# Get limit from query params (default 50)
|
|
33
|
+
limit = int(query_params.get('limit', 50))
|
|
34
|
+
|
|
35
|
+
result = subscription_service.list_subscription_history(
|
|
36
|
+
tenant_id=tenant_id,
|
|
37
|
+
user_id=user_id,
|
|
38
|
+
limit=limit
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
return service_result_to_response(result)
|
|
42
|
+
|
|
43
|
+
except Exception as e:
|
|
44
|
+
return error_response(f"An unexpected error occurred: {str(e)}", "INTERNAL_ERROR", 500)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# src/geek_cafe_saas_sdk/lambda_handlers/subscriptions/record_payment/app.py
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from typing import Dict, Any
|
|
5
|
+
|
|
6
|
+
from geek_cafe_saas_sdk.services import SubscriptionService
|
|
7
|
+
from geek_cafe_saas_sdk.lambda_handlers import ServicePool
|
|
8
|
+
from geek_cafe_saas_sdk.utilities.response import service_result_to_response, error_response
|
|
9
|
+
from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
10
|
+
|
|
11
|
+
subscription_service_pool = ServicePool(SubscriptionService)
|
|
12
|
+
|
|
13
|
+
def handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
14
|
+
"""
|
|
15
|
+
Lambda handler for recording a payment on a subscription.
|
|
16
|
+
|
|
17
|
+
This updates the subscription with payment details and can change status from past_due to active.
|
|
18
|
+
|
|
19
|
+
Expected body:
|
|
20
|
+
{
|
|
21
|
+
"amount_cents": 2999
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
event: API Gateway event
|
|
26
|
+
context: Lambda context
|
|
27
|
+
injected_service: Optional SubscriptionService for testing
|
|
28
|
+
"""
|
|
29
|
+
try:
|
|
30
|
+
subscription_service = injected_service if injected_service else subscription_service_pool.get()
|
|
31
|
+
body = LambdaEventUtility.get_body_from_event(event)
|
|
32
|
+
user_id = LambdaEventUtility.get_authenticated_user_id(event)
|
|
33
|
+
tenant_id = LambdaEventUtility.get_authenticated_user_tenant_id(event)
|
|
34
|
+
resource_id = LambdaEventUtility.get_value_from_path_parameters(event, 'id')
|
|
35
|
+
|
|
36
|
+
if not resource_id:
|
|
37
|
+
return error_response("Subscription ID is required in the path.", "VALIDATION_ERROR", 400)
|
|
38
|
+
|
|
39
|
+
# Get payment amount
|
|
40
|
+
amount_cents = body.get('amount_cents')
|
|
41
|
+
if amount_cents is None:
|
|
42
|
+
return error_response("Payment amount_cents is required.", "VALIDATION_ERROR", 400)
|
|
43
|
+
|
|
44
|
+
result = subscription_service.record_payment(
|
|
45
|
+
subscription_id=resource_id,
|
|
46
|
+
tenant_id=tenant_id,
|
|
47
|
+
user_id=user_id,
|
|
48
|
+
amount_cents=amount_cents
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
return service_result_to_response(result)
|
|
52
|
+
|
|
53
|
+
except json.JSONDecodeError:
|
|
54
|
+
return error_response("Invalid JSON in request body.", "VALIDATION_ERROR", 400)
|
|
55
|
+
except Exception as e:
|
|
56
|
+
return error_response(f"An unexpected error occurred: {str(e)}", "INTERNAL_ERROR", 500)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# src/geek_cafe_saas_sdk/lambda_handlers/tenants/get/app.py
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Any
|
|
4
|
+
|
|
5
|
+
from geek_cafe_saas_sdk.services import TenantService
|
|
6
|
+
from geek_cafe_saas_sdk.lambda_handlers import ServicePool
|
|
7
|
+
from geek_cafe_saas_sdk.utilities.response import service_result_to_response, error_response
|
|
8
|
+
from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
9
|
+
|
|
10
|
+
tenant_service_pool = ServicePool(TenantService)
|
|
11
|
+
|
|
12
|
+
def handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
13
|
+
"""
|
|
14
|
+
Lambda handler for retrieving a tenant by ID.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
event: API Gateway event
|
|
18
|
+
context: Lambda context
|
|
19
|
+
injected_service: Optional TenantService for testing
|
|
20
|
+
"""
|
|
21
|
+
try:
|
|
22
|
+
tenant_service = injected_service if injected_service else tenant_service_pool.get()
|
|
23
|
+
user_id = LambdaEventUtility.get_authenticated_user_id(event)
|
|
24
|
+
tenant_id = LambdaEventUtility.get_authenticated_user_tenant_id(event)
|
|
25
|
+
resource_id = LambdaEventUtility.get_value_from_path_parameters(event, 'id')
|
|
26
|
+
|
|
27
|
+
if not resource_id:
|
|
28
|
+
return error_response("Tenant ID is required in the path.", "VALIDATION_ERROR", 400)
|
|
29
|
+
|
|
30
|
+
result = tenant_service.get_by_id(
|
|
31
|
+
resource_id=resource_id,
|
|
32
|
+
tenant_id=tenant_id,
|
|
33
|
+
user_id=user_id
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
return service_result_to_response(result)
|
|
37
|
+
|
|
38
|
+
except Exception as e:
|
|
39
|
+
return error_response(f"An unexpected error occurred: {str(e)}", "INTERNAL_ERROR", 500)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# src/geek_cafe_saas_sdk/lambda_handlers/tenants/me/app.py
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Any
|
|
4
|
+
|
|
5
|
+
from geek_cafe_saas_sdk.services import TenantService
|
|
6
|
+
from geek_cafe_saas_sdk.lambda_handlers import ServicePool
|
|
7
|
+
from geek_cafe_saas_sdk.utilities.response import service_result_to_response, error_response
|
|
8
|
+
from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
9
|
+
|
|
10
|
+
tenant_service_pool = ServicePool(TenantService)
|
|
11
|
+
|
|
12
|
+
def handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
13
|
+
"""
|
|
14
|
+
Lambda handler for retrieving the authenticated user's tenant.
|
|
15
|
+
|
|
16
|
+
This is a convenience endpoint for /tenants/me to get the current user's tenant.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
event: API Gateway event
|
|
20
|
+
context: Lambda context
|
|
21
|
+
injected_service: Optional TenantService for testing
|
|
22
|
+
"""
|
|
23
|
+
try:
|
|
24
|
+
tenant_service = injected_service if injected_service else tenant_service_pool.get()
|
|
25
|
+
user_id = LambdaEventUtility.get_authenticated_user_id(event)
|
|
26
|
+
tenant_id = LambdaEventUtility.get_authenticated_user_tenant_id(event)
|
|
27
|
+
|
|
28
|
+
result = tenant_service.get_by_id(
|
|
29
|
+
resource_id=tenant_id,
|
|
30
|
+
tenant_id=tenant_id,
|
|
31
|
+
user_id=user_id
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
return service_result_to_response(result)
|
|
35
|
+
|
|
36
|
+
except Exception as e:
|
|
37
|
+
return error_response(f"An unexpected error occurred: {str(e)}", "INTERNAL_ERROR", 500)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# src/geek_cafe_saas_sdk/lambda_handlers/tenants/signup/app.py
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from typing import Dict, Any
|
|
5
|
+
|
|
6
|
+
from geek_cafe_saas_sdk.services import TenantService
|
|
7
|
+
from geek_cafe_saas_sdk.lambda_handlers import ServicePool
|
|
8
|
+
from geek_cafe_saas_sdk.utilities.response import service_result_to_response, error_response
|
|
9
|
+
from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
10
|
+
|
|
11
|
+
tenant_service_pool = ServicePool(TenantService)
|
|
12
|
+
|
|
13
|
+
def handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
14
|
+
"""
|
|
15
|
+
Lambda handler for tenant signup (creates tenant + primary admin user).
|
|
16
|
+
|
|
17
|
+
This is the initial signup endpoint that creates both a tenant and its first admin user.
|
|
18
|
+
|
|
19
|
+
Expected body:
|
|
20
|
+
{
|
|
21
|
+
"user": {
|
|
22
|
+
"email": "admin@company.com",
|
|
23
|
+
"first_name": "John",
|
|
24
|
+
"last_name": "Doe"
|
|
25
|
+
},
|
|
26
|
+
"tenant": {
|
|
27
|
+
"name": "Company Name"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
event: API Gateway event
|
|
33
|
+
context: Lambda context
|
|
34
|
+
injected_service: Optional TenantService for testing
|
|
35
|
+
"""
|
|
36
|
+
try:
|
|
37
|
+
tenant_service = injected_service if injected_service else tenant_service_pool.get()
|
|
38
|
+
body = LambdaEventUtility.get_body_from_event(event)
|
|
39
|
+
|
|
40
|
+
# Extract user and tenant payloads
|
|
41
|
+
user_payload = body.get('user', {})
|
|
42
|
+
tenant_payload = body.get('tenant', {})
|
|
43
|
+
|
|
44
|
+
if not user_payload:
|
|
45
|
+
return error_response("User information is required.", "VALIDATION_ERROR", 400)
|
|
46
|
+
|
|
47
|
+
if not tenant_payload:
|
|
48
|
+
return error_response("Tenant information is required.", "VALIDATION_ERROR", 400)
|
|
49
|
+
|
|
50
|
+
# Create tenant with user (signup flow)
|
|
51
|
+
result = tenant_service.create_with_user(
|
|
52
|
+
user_payload=user_payload,
|
|
53
|
+
tenant_payload=tenant_payload
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
return service_result_to_response(result, success_status=201)
|
|
57
|
+
|
|
58
|
+
except json.JSONDecodeError:
|
|
59
|
+
return error_response("Invalid JSON in request body.", "VALIDATION_ERROR", 400)
|
|
60
|
+
except Exception as e:
|
|
61
|
+
return error_response(f"An unexpected error occurred: {str(e)}", "INTERNAL_ERROR", 500)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# src/geek_cafe_saas_sdk/lambda_handlers/tenants/update/app.py
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from typing import Dict, Any
|
|
5
|
+
|
|
6
|
+
from geek_cafe_saas_sdk.services import TenantService
|
|
7
|
+
from geek_cafe_saas_sdk.lambda_handlers import ServicePool
|
|
8
|
+
from geek_cafe_saas_sdk.utilities.response import service_result_to_response, error_response
|
|
9
|
+
from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
10
|
+
|
|
11
|
+
tenant_service_pool = ServicePool(TenantService)
|
|
12
|
+
|
|
13
|
+
def handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
|
|
14
|
+
"""
|
|
15
|
+
Lambda handler for updating a tenant.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
event: API Gateway event
|
|
19
|
+
context: Lambda context
|
|
20
|
+
injected_service: Optional TenantService for testing
|
|
21
|
+
"""
|
|
22
|
+
try:
|
|
23
|
+
tenant_service = injected_service if injected_service else tenant_service_pool.get()
|
|
24
|
+
body = LambdaEventUtility.get_body_from_event(event)
|
|
25
|
+
user_id = LambdaEventUtility.get_authenticated_user_id(event)
|
|
26
|
+
tenant_id = LambdaEventUtility.get_authenticated_user_tenant_id(event)
|
|
27
|
+
resource_id = LambdaEventUtility.get_value_from_path_parameters(event, 'id')
|
|
28
|
+
|
|
29
|
+
if not resource_id:
|
|
30
|
+
return error_response("Tenant ID is required in the path.", "VALIDATION_ERROR", 400)
|
|
31
|
+
|
|
32
|
+
result = tenant_service.update(
|
|
33
|
+
resource_id=resource_id,
|
|
34
|
+
tenant_id=tenant_id,
|
|
35
|
+
user_id=user_id,
|
|
36
|
+
updates=body
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
return service_result_to_response(result)
|
|
40
|
+
|
|
41
|
+
except json.JSONDecodeError:
|
|
42
|
+
return error_response("Invalid JSON in request body.", "VALIDATION_ERROR", 400)
|
|
43
|
+
except Exception as e:
|
|
44
|
+
return error_response(f"An unexpected error occurred: {str(e)}", "INTERNAL_ERROR", 500)
|