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,464 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright 2024-2025 Geek Cafe, LLC
|
|
3
|
+
MIT License. See Project Root for the license information.
|
|
4
|
+
|
|
5
|
+
Permission Registry for extensible permission definitions.
|
|
6
|
+
Allows applications to register custom permissions and roles.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Dict, List, Optional, Set
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
import threading
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class PermissionDefinition:
|
|
16
|
+
"""Definition of a permission."""
|
|
17
|
+
code: str # "events:read"
|
|
18
|
+
name: str # "Read Events"
|
|
19
|
+
description: str
|
|
20
|
+
category: str # "events"
|
|
21
|
+
is_system: bool = True
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class RoleDefinition:
|
|
26
|
+
"""Definition of a role."""
|
|
27
|
+
code: str # "tenant_admin"
|
|
28
|
+
name: str # "Tenant Administrator"
|
|
29
|
+
description: str
|
|
30
|
+
permissions: List[str] # Permission codes
|
|
31
|
+
scope: str = "tenant" # "global" or "tenant"
|
|
32
|
+
inherits_from: List[str] = None # Role codes
|
|
33
|
+
level: int = 0
|
|
34
|
+
is_system: bool = True
|
|
35
|
+
is_assignable: bool = True
|
|
36
|
+
|
|
37
|
+
def __post_init__(self):
|
|
38
|
+
if self.inherits_from is None:
|
|
39
|
+
self.inherits_from = []
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class PermissionRegistry:
|
|
43
|
+
"""
|
|
44
|
+
Singleton registry for permissions and roles.
|
|
45
|
+
|
|
46
|
+
Allows applications to register custom permissions and roles
|
|
47
|
+
that extend the base system. Provides in-memory lookup for
|
|
48
|
+
fast permission resolution.
|
|
49
|
+
|
|
50
|
+
Thread-safe for concurrent access.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
_instance = None
|
|
54
|
+
_lock = threading.Lock()
|
|
55
|
+
|
|
56
|
+
def __new__(cls):
|
|
57
|
+
if cls._instance is None:
|
|
58
|
+
with cls._lock:
|
|
59
|
+
if cls._instance is None:
|
|
60
|
+
cls._instance = super().__new__(cls)
|
|
61
|
+
cls._instance._initialized = False
|
|
62
|
+
return cls._instance
|
|
63
|
+
|
|
64
|
+
def __init__(self):
|
|
65
|
+
if self._initialized:
|
|
66
|
+
return
|
|
67
|
+
|
|
68
|
+
self._permissions: Dict[str, PermissionDefinition] = {}
|
|
69
|
+
self._roles: Dict[str, RoleDefinition] = {}
|
|
70
|
+
self._categories: Set[str] = set()
|
|
71
|
+
self._lock = threading.Lock()
|
|
72
|
+
|
|
73
|
+
# Register default permissions and roles
|
|
74
|
+
self._register_defaults()
|
|
75
|
+
self._initialized = True
|
|
76
|
+
|
|
77
|
+
def _register_defaults(self):
|
|
78
|
+
"""Register default system permissions and roles."""
|
|
79
|
+
|
|
80
|
+
# Platform Permissions
|
|
81
|
+
self.register_permission(PermissionDefinition(
|
|
82
|
+
code="platform:admin",
|
|
83
|
+
name="Platform Admin",
|
|
84
|
+
description="Full system access across all tenants",
|
|
85
|
+
category="platform",
|
|
86
|
+
is_system=True
|
|
87
|
+
))
|
|
88
|
+
|
|
89
|
+
self.register_permission(PermissionDefinition(
|
|
90
|
+
code="platform:support",
|
|
91
|
+
name="Platform Support",
|
|
92
|
+
description="Read-only access across tenants for support",
|
|
93
|
+
category="platform",
|
|
94
|
+
is_system=True
|
|
95
|
+
))
|
|
96
|
+
|
|
97
|
+
# Tenant Permissions
|
|
98
|
+
self.register_permission(PermissionDefinition(
|
|
99
|
+
code="tenant:admin",
|
|
100
|
+
name="Tenant Admin",
|
|
101
|
+
description="Full administrative access within tenant",
|
|
102
|
+
category="tenant",
|
|
103
|
+
is_system=True
|
|
104
|
+
))
|
|
105
|
+
|
|
106
|
+
self.register_permission(PermissionDefinition(
|
|
107
|
+
code="tenant:read",
|
|
108
|
+
name="Read Tenant",
|
|
109
|
+
description="View tenant information",
|
|
110
|
+
category="tenant",
|
|
111
|
+
is_system=True
|
|
112
|
+
))
|
|
113
|
+
|
|
114
|
+
self.register_permission(PermissionDefinition(
|
|
115
|
+
code="tenant:write",
|
|
116
|
+
name="Write Tenant",
|
|
117
|
+
description="Modify tenant settings",
|
|
118
|
+
category="tenant",
|
|
119
|
+
is_system=True
|
|
120
|
+
))
|
|
121
|
+
|
|
122
|
+
# User Permissions
|
|
123
|
+
self.register_permission(PermissionDefinition(
|
|
124
|
+
code="users:read",
|
|
125
|
+
name="Read Users",
|
|
126
|
+
description="View users in tenant",
|
|
127
|
+
category="users",
|
|
128
|
+
is_system=True
|
|
129
|
+
))
|
|
130
|
+
|
|
131
|
+
self.register_permission(PermissionDefinition(
|
|
132
|
+
code="users:write",
|
|
133
|
+
name="Manage Users",
|
|
134
|
+
description="Create, update, delete users",
|
|
135
|
+
category="users",
|
|
136
|
+
is_system=True
|
|
137
|
+
))
|
|
138
|
+
|
|
139
|
+
# Profile Permissions
|
|
140
|
+
self.register_permission(PermissionDefinition(
|
|
141
|
+
code="profile:read_own",
|
|
142
|
+
name="Read Own Profile",
|
|
143
|
+
description="View own profile",
|
|
144
|
+
category="profile",
|
|
145
|
+
is_system=True
|
|
146
|
+
))
|
|
147
|
+
|
|
148
|
+
self.register_permission(PermissionDefinition(
|
|
149
|
+
code="profile:write_own",
|
|
150
|
+
name="Write Own Profile",
|
|
151
|
+
description="Update own profile",
|
|
152
|
+
category="profile",
|
|
153
|
+
is_system=True
|
|
154
|
+
))
|
|
155
|
+
|
|
156
|
+
# Event Permissions
|
|
157
|
+
self.register_permission(PermissionDefinition(
|
|
158
|
+
code="events:read",
|
|
159
|
+
name="Read Events",
|
|
160
|
+
description="View events",
|
|
161
|
+
category="events",
|
|
162
|
+
is_system=True
|
|
163
|
+
))
|
|
164
|
+
|
|
165
|
+
self.register_permission(PermissionDefinition(
|
|
166
|
+
code="events:write",
|
|
167
|
+
name="Write Events",
|
|
168
|
+
description="Create and update events",
|
|
169
|
+
category="events",
|
|
170
|
+
is_system=True
|
|
171
|
+
))
|
|
172
|
+
|
|
173
|
+
self.register_permission(PermissionDefinition(
|
|
174
|
+
code="events:write_own",
|
|
175
|
+
name="Write Own Events",
|
|
176
|
+
description="Create and update own events only",
|
|
177
|
+
category="events",
|
|
178
|
+
is_system=True
|
|
179
|
+
))
|
|
180
|
+
|
|
181
|
+
self.register_permission(PermissionDefinition(
|
|
182
|
+
code="events:delete",
|
|
183
|
+
name="Delete Events",
|
|
184
|
+
description="Delete events",
|
|
185
|
+
category="events",
|
|
186
|
+
is_system=True
|
|
187
|
+
))
|
|
188
|
+
|
|
189
|
+
self.register_permission(PermissionDefinition(
|
|
190
|
+
code="events:admin",
|
|
191
|
+
name="Event Admin",
|
|
192
|
+
description="Full event management",
|
|
193
|
+
category="events",
|
|
194
|
+
is_system=True
|
|
195
|
+
))
|
|
196
|
+
|
|
197
|
+
# Chat Permissions
|
|
198
|
+
self.register_permission(PermissionDefinition(
|
|
199
|
+
code="chat:read",
|
|
200
|
+
name="Read Chat",
|
|
201
|
+
description="View chat messages",
|
|
202
|
+
category="chat",
|
|
203
|
+
is_system=True
|
|
204
|
+
))
|
|
205
|
+
|
|
206
|
+
self.register_permission(PermissionDefinition(
|
|
207
|
+
code="chat:write",
|
|
208
|
+
name="Send Messages",
|
|
209
|
+
description="Send chat messages",
|
|
210
|
+
category="chat",
|
|
211
|
+
is_system=True
|
|
212
|
+
))
|
|
213
|
+
|
|
214
|
+
self.register_permission(PermissionDefinition(
|
|
215
|
+
code="chat:admin",
|
|
216
|
+
name="Chat Admin",
|
|
217
|
+
description="Manage channels and messages",
|
|
218
|
+
category="chat",
|
|
219
|
+
is_system=True
|
|
220
|
+
))
|
|
221
|
+
|
|
222
|
+
# Community Permissions
|
|
223
|
+
self.register_permission(PermissionDefinition(
|
|
224
|
+
code="communities:read",
|
|
225
|
+
name="Read Communities",
|
|
226
|
+
description="View communities",
|
|
227
|
+
category="communities",
|
|
228
|
+
is_system=True
|
|
229
|
+
))
|
|
230
|
+
|
|
231
|
+
self.register_permission(PermissionDefinition(
|
|
232
|
+
code="communities:write",
|
|
233
|
+
name="Write Communities",
|
|
234
|
+
description="Create and update communities",
|
|
235
|
+
category="communities",
|
|
236
|
+
is_system=True
|
|
237
|
+
))
|
|
238
|
+
|
|
239
|
+
self.register_permission(PermissionDefinition(
|
|
240
|
+
code="communities:write_own",
|
|
241
|
+
name="Write Own Communities",
|
|
242
|
+
description="Create and update own communities only",
|
|
243
|
+
category="communities",
|
|
244
|
+
is_system=True
|
|
245
|
+
))
|
|
246
|
+
|
|
247
|
+
self.register_permission(PermissionDefinition(
|
|
248
|
+
code="communities:admin",
|
|
249
|
+
name="Community Admin",
|
|
250
|
+
description="Full community management",
|
|
251
|
+
category="communities",
|
|
252
|
+
is_system=True
|
|
253
|
+
))
|
|
254
|
+
|
|
255
|
+
# Analytics Permissions
|
|
256
|
+
self.register_permission(PermissionDefinition(
|
|
257
|
+
code="analytics:read",
|
|
258
|
+
name="View Analytics",
|
|
259
|
+
description="View analytics and reports",
|
|
260
|
+
category="analytics",
|
|
261
|
+
is_system=True
|
|
262
|
+
))
|
|
263
|
+
|
|
264
|
+
# Subscription Permissions
|
|
265
|
+
self.register_permission(PermissionDefinition(
|
|
266
|
+
code="subscriptions:read",
|
|
267
|
+
name="Read Subscriptions",
|
|
268
|
+
description="View subscription information",
|
|
269
|
+
category="subscriptions",
|
|
270
|
+
is_system=True
|
|
271
|
+
))
|
|
272
|
+
|
|
273
|
+
self.register_permission(PermissionDefinition(
|
|
274
|
+
code="subscriptions:write",
|
|
275
|
+
name="Manage Subscriptions",
|
|
276
|
+
description="Update subscription and billing",
|
|
277
|
+
category="subscriptions",
|
|
278
|
+
is_system=True
|
|
279
|
+
))
|
|
280
|
+
|
|
281
|
+
# Register default roles
|
|
282
|
+
self._register_default_roles()
|
|
283
|
+
|
|
284
|
+
def _register_default_roles(self):
|
|
285
|
+
"""Register default system roles."""
|
|
286
|
+
|
|
287
|
+
# Platform Admin
|
|
288
|
+
self.register_role(RoleDefinition(
|
|
289
|
+
code="platform_admin",
|
|
290
|
+
name="Platform Administrator",
|
|
291
|
+
description="Full system access across all tenants",
|
|
292
|
+
permissions=["platform:admin"],
|
|
293
|
+
scope="platform",
|
|
294
|
+
level=1000,
|
|
295
|
+
is_system=True,
|
|
296
|
+
is_assignable=True
|
|
297
|
+
))
|
|
298
|
+
|
|
299
|
+
# Platform Support
|
|
300
|
+
self.register_role(RoleDefinition(
|
|
301
|
+
code="platform_support",
|
|
302
|
+
name="Platform Support",
|
|
303
|
+
description="Read-only access for customer support",
|
|
304
|
+
permissions=["platform:support", "tenant:read", "users:read"],
|
|
305
|
+
scope="platform",
|
|
306
|
+
level=500,
|
|
307
|
+
is_system=True,
|
|
308
|
+
is_assignable=True
|
|
309
|
+
))
|
|
310
|
+
|
|
311
|
+
# Tenant Admin
|
|
312
|
+
self.register_role(RoleDefinition(
|
|
313
|
+
code="tenant_admin",
|
|
314
|
+
name="Tenant Administrator",
|
|
315
|
+
description="Full administrative access within tenant",
|
|
316
|
+
permissions=[
|
|
317
|
+
"tenant:admin", "tenant:read", "tenant:write",
|
|
318
|
+
"users:read", "users:write",
|
|
319
|
+
"events:admin", "chat:admin", "communities:admin",
|
|
320
|
+
"analytics:read", "subscriptions:read", "subscriptions:write"
|
|
321
|
+
],
|
|
322
|
+
scope="tenant",
|
|
323
|
+
level=100,
|
|
324
|
+
is_system=True,
|
|
325
|
+
is_assignable=True
|
|
326
|
+
))
|
|
327
|
+
|
|
328
|
+
# Event Organizer
|
|
329
|
+
self.register_role(RoleDefinition(
|
|
330
|
+
code="tenant_organizer",
|
|
331
|
+
name="Event Organizer",
|
|
332
|
+
description="Enhanced event and group management",
|
|
333
|
+
permissions=[
|
|
334
|
+
"events:admin", "communities:admin", "chat:write",
|
|
335
|
+
"profile:read_own", "profile:write_own"
|
|
336
|
+
],
|
|
337
|
+
scope="tenant",
|
|
338
|
+
level=50,
|
|
339
|
+
is_system=True,
|
|
340
|
+
is_assignable=True
|
|
341
|
+
))
|
|
342
|
+
|
|
343
|
+
# Tenant User
|
|
344
|
+
self.register_role(RoleDefinition(
|
|
345
|
+
code="tenant_user",
|
|
346
|
+
name="Tenant User",
|
|
347
|
+
description="Standard user with basic permissions",
|
|
348
|
+
permissions=[
|
|
349
|
+
"events:read", "events:write_own",
|
|
350
|
+
"communities:read", "communities:write_own",
|
|
351
|
+
"chat:read", "chat:write",
|
|
352
|
+
"profile:read_own", "profile:write_own"
|
|
353
|
+
],
|
|
354
|
+
scope="tenant",
|
|
355
|
+
level=10,
|
|
356
|
+
is_system=True,
|
|
357
|
+
is_assignable=True
|
|
358
|
+
))
|
|
359
|
+
|
|
360
|
+
# Viewer
|
|
361
|
+
self.register_role(RoleDefinition(
|
|
362
|
+
code="tenant_viewer",
|
|
363
|
+
name="Viewer",
|
|
364
|
+
description="Read-only access to tenant resources",
|
|
365
|
+
permissions=[
|
|
366
|
+
"events:read", "communities:read", "chat:read",
|
|
367
|
+
"profile:read_own"
|
|
368
|
+
],
|
|
369
|
+
scope="tenant",
|
|
370
|
+
level=1,
|
|
371
|
+
is_system=True,
|
|
372
|
+
is_assignable=True
|
|
373
|
+
))
|
|
374
|
+
|
|
375
|
+
def register_permission(self, permission: PermissionDefinition):
|
|
376
|
+
"""
|
|
377
|
+
Register a new permission.
|
|
378
|
+
|
|
379
|
+
Args:
|
|
380
|
+
permission: Permission definition to register
|
|
381
|
+
"""
|
|
382
|
+
with self._lock:
|
|
383
|
+
self._permissions[permission.code] = permission
|
|
384
|
+
self._categories.add(permission.category)
|
|
385
|
+
|
|
386
|
+
def register_role(self, role: RoleDefinition):
|
|
387
|
+
"""
|
|
388
|
+
Register a new role.
|
|
389
|
+
|
|
390
|
+
Args:
|
|
391
|
+
role: Role definition to register
|
|
392
|
+
"""
|
|
393
|
+
with self._lock:
|
|
394
|
+
self._roles[role.code] = role
|
|
395
|
+
|
|
396
|
+
def get_permission(self, code: str) -> Optional[PermissionDefinition]:
|
|
397
|
+
"""Get permission by code."""
|
|
398
|
+
return self._permissions.get(code)
|
|
399
|
+
|
|
400
|
+
def get_role(self, code: str) -> Optional[RoleDefinition]:
|
|
401
|
+
"""Get role by code."""
|
|
402
|
+
return self._roles.get(code)
|
|
403
|
+
|
|
404
|
+
def get_all_permissions(self) -> List[PermissionDefinition]:
|
|
405
|
+
"""Get all registered permissions."""
|
|
406
|
+
return list(self._permissions.values())
|
|
407
|
+
|
|
408
|
+
def get_all_roles(self) -> List[RoleDefinition]:
|
|
409
|
+
"""Get all registered roles."""
|
|
410
|
+
return list(self._roles.values())
|
|
411
|
+
|
|
412
|
+
def get_permissions_by_category(self, category: str) -> List[PermissionDefinition]:
|
|
413
|
+
"""Get all permissions in a category."""
|
|
414
|
+
return [p for p in self._permissions.values() if p.category == category]
|
|
415
|
+
|
|
416
|
+
def get_roles_by_scope(self, scope: str) -> List[RoleDefinition]:
|
|
417
|
+
"""Get all roles by scope (global or tenant)."""
|
|
418
|
+
return [r for r in self._roles.values() if r.scope == scope]
|
|
419
|
+
|
|
420
|
+
def resolve_role_permissions(self, role_code: str, resolved: Set[str] = None) -> Set[str]:
|
|
421
|
+
"""
|
|
422
|
+
Resolve all permissions for a role, including inherited.
|
|
423
|
+
|
|
424
|
+
Args:
|
|
425
|
+
role_code: Role code to resolve
|
|
426
|
+
resolved: Set of already resolved permissions (for recursion)
|
|
427
|
+
|
|
428
|
+
Returns:
|
|
429
|
+
Set of permission codes
|
|
430
|
+
"""
|
|
431
|
+
if resolved is None:
|
|
432
|
+
resolved = set()
|
|
433
|
+
|
|
434
|
+
role = self.get_role(role_code)
|
|
435
|
+
if not role:
|
|
436
|
+
return resolved
|
|
437
|
+
|
|
438
|
+
# Add direct permissions
|
|
439
|
+
resolved.update(role.permissions)
|
|
440
|
+
|
|
441
|
+
# Recursively add inherited permissions
|
|
442
|
+
for inherited_role in role.inherits_from:
|
|
443
|
+
self.resolve_role_permissions(inherited_role, resolved)
|
|
444
|
+
|
|
445
|
+
return resolved
|
|
446
|
+
|
|
447
|
+
def get_permissions_for_roles(self, role_codes: List[str]) -> List[str]:
|
|
448
|
+
"""
|
|
449
|
+
Get all unique permissions for a list of roles.
|
|
450
|
+
|
|
451
|
+
Args:
|
|
452
|
+
role_codes: List of role codes
|
|
453
|
+
|
|
454
|
+
Returns:
|
|
455
|
+
List of unique permission codes
|
|
456
|
+
"""
|
|
457
|
+
all_perms = set()
|
|
458
|
+
for role_code in role_codes:
|
|
459
|
+
all_perms.update(self.resolve_role_permissions(role_code))
|
|
460
|
+
return list(all_perms)
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
# Global singleton instance
|
|
464
|
+
permission_registry = PermissionRegistry()
|