trovesuite 1.0.10__tar.gz → 1.0.11__tar.gz
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.
- {trovesuite-1.0.10/src/trovesuite.egg-info → trovesuite-1.0.11}/PKG-INFO +1 -1
- {trovesuite-1.0.10 → trovesuite-1.0.11}/pyproject.toml +2 -2
- {trovesuite-1.0.10 → trovesuite-1.0.11}/setup.py +1 -1
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/auth/auth_read_dto.py +3 -2
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/auth/auth_service.py +59 -49
- {trovesuite-1.0.10 → trovesuite-1.0.11/src/trovesuite.egg-info}/PKG-INFO +1 -1
- {trovesuite-1.0.10 → trovesuite-1.0.11}/LICENSE +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/MANIFEST.in +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/README.md +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/requirements.txt +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/setup.cfg +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/__init__.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/auth/__init__.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/auth/auth_base.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/auth/auth_controller.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/auth/auth_write_dto.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/configs/__init__.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/configs/database.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/configs/logging.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/configs/settings.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/entities/__init__.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/entities/health.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/entities/sh_response.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/notification/__init__.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/notification/notification_base.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/notification/notification_controller.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/notification/notification_read_dto.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/notification/notification_service.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/notification/notification_write_dto.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/storage/__init__.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/storage/storage_base.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/storage/storage_controller.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/storage/storage_read_dto.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/storage/storage_service.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/storage/storage_write_dto.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/utils/__init__.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/utils/helper.py +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite.egg-info/SOURCES.txt +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite.egg-info/dependency_links.txt +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite.egg-info/not-zip-safe +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite.egg-info/requires.txt +0 -0
- {trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: trovesuite
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.11
|
|
4
4
|
Summary: TroveSuite services package providing authentication, authorization, notifications, Azure Storage, and other enterprise services for TroveSuite applications
|
|
5
5
|
Home-page: https://dev.azure.com/brightgclt/trovesuite/_git/packages
|
|
6
6
|
Author: Bright Debrah Owusu
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
6
|
name = "trovesuite"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.11"
|
|
8
8
|
description = "TroveSuite services package providing authentication, authorization, notifications, Azure Storage, and other enterprise services for TroveSuite applications"
|
|
9
9
|
authors = ["brightgclt <brightgclt@gmail.com>"]
|
|
10
10
|
license = "MIT"
|
|
@@ -58,7 +58,7 @@ Documentation = "https://dev.azure.com/brightgclt/trovesuite/_git/packages"
|
|
|
58
58
|
|
|
59
59
|
[project]
|
|
60
60
|
name = "trovesuite"
|
|
61
|
-
version = "1.0.
|
|
61
|
+
version = "1.0.11"
|
|
62
62
|
description = "TroveSuite services package providing authentication, authorization, notifications, Azure Storage, and other enterprise services for TroveSuite applications"
|
|
63
63
|
readme = "README.md"
|
|
64
64
|
license = {text = "MIT"}
|
|
@@ -15,7 +15,7 @@ with open("pyproject.toml", "r", encoding="utf-8") as fh:
|
|
|
15
15
|
|
|
16
16
|
setup(
|
|
17
17
|
name="trovesuite",
|
|
18
|
-
version="1.0.
|
|
18
|
+
version="1.0.11",
|
|
19
19
|
author="Bright Debrah Owusu",
|
|
20
20
|
author_email="owusu.debrah@deladetech.com",
|
|
21
21
|
description="TroveSuite services package providing authentication, authorization, notifications, and other enterprise services for TroveSuite applications",
|
|
@@ -3,8 +3,8 @@ from pydantic import BaseModel
|
|
|
3
3
|
|
|
4
4
|
class AuthControllerReadDto(BaseModel):
|
|
5
5
|
org_id: Optional[str] = None
|
|
6
|
-
bus_id: Optional[str] = None
|
|
7
|
-
app_id: Optional[str] = None
|
|
6
|
+
bus_id: Optional[str] = None
|
|
7
|
+
app_id: Optional[str] = None
|
|
8
8
|
shared_resource_id: Optional[str] = None
|
|
9
9
|
user_id: Optional[str] = None
|
|
10
10
|
group_id: Optional[str] = None
|
|
@@ -12,6 +12,7 @@ class AuthControllerReadDto(BaseModel):
|
|
|
12
12
|
tenant_id: Optional[str] = None
|
|
13
13
|
permissions: Optional[List[str]] = None
|
|
14
14
|
resource_id: Optional[str] = None
|
|
15
|
+
resource_type: Optional[str] = None
|
|
15
16
|
|
|
16
17
|
class AuthServiceReadDto(AuthControllerReadDto):
|
|
17
18
|
pass
|
|
@@ -45,10 +45,10 @@ class AuthService:
|
|
|
45
45
|
|
|
46
46
|
@staticmethod
|
|
47
47
|
def authorize(data: AuthServiceWriteDto) -> Respons[AuthServiceReadDto]:
|
|
48
|
-
|
|
48
|
+
|
|
49
49
|
user_id: str = data.user_id
|
|
50
50
|
tenant_id: str = data.tenant_id
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
"""Check if a user is authorized based on login settings and roles"""
|
|
53
53
|
# Input validation
|
|
54
54
|
if not user_id or not isinstance(user_id, str):
|
|
@@ -59,7 +59,7 @@ class AuthService:
|
|
|
59
59
|
status_code=400,
|
|
60
60
|
error="INVALID_USER_ID"
|
|
61
61
|
)
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
if not tenant_id or not isinstance(tenant_id, str):
|
|
64
64
|
return Respons[AuthServiceReadDto](
|
|
65
65
|
detail="Invalid tenant_id: must be a non-empty string",
|
|
@@ -75,7 +75,7 @@ class AuthService:
|
|
|
75
75
|
f"SELECT is_verified FROM {db_settings.MAIN_TENANTS_TABLE} WHERE delete_status = 'NOT_DELETED' AND id = %s",
|
|
76
76
|
(tenant_id,),
|
|
77
77
|
)
|
|
78
|
-
|
|
78
|
+
|
|
79
79
|
if not is_tenant_verified or len(is_tenant_verified) == 0:
|
|
80
80
|
logger.warning("Login failed - tenant not found: %s", tenant_id)
|
|
81
81
|
return Respons[AuthServiceReadDto](
|
|
@@ -85,7 +85,7 @@ class AuthService:
|
|
|
85
85
|
status_code=404,
|
|
86
86
|
error="TENANT_NOT_FOUND"
|
|
87
87
|
)
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
if not is_tenant_verified[0]['is_verified']:
|
|
90
90
|
logger.warning("Login failed - tenant not verified for user: %s, tenant: %s", user_id, tenant_id)
|
|
91
91
|
return Respons[AuthServiceReadDto](
|
|
@@ -96,14 +96,36 @@ class AuthService:
|
|
|
96
96
|
error="TENANT_NOT_VERIFIED"
|
|
97
97
|
)
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
WHERE (delete_status = 'NOT_DELETED' AND is_active = true ) AND user_id = %s""",
|
|
104
|
-
(user_id,),
|
|
99
|
+
# 1️⃣ Get all groups the user belongs to
|
|
100
|
+
user_groups = DatabaseManager.execute_query(
|
|
101
|
+
f"""SELECT group_id FROM "{tenant_id}".{db_settings.TENANT_USER_GROUPS_TABLE}
|
|
102
|
+
WHERE delete_status = 'NOT_DELETED' AND is_active = true AND user_id = %s""",(user_id,),
|
|
105
103
|
)
|
|
106
104
|
|
|
105
|
+
# 2️⃣ Prepare list of group_ids
|
|
106
|
+
group_ids = [g["group_id"] for g in user_groups] if user_groups else []
|
|
107
|
+
|
|
108
|
+
# 3️⃣ Get login settings - check user-level first, then group-level
|
|
109
|
+
if group_ids:
|
|
110
|
+
login_settings_details = DatabaseManager.execute_query(
|
|
111
|
+
f"""SELECT user_id, group_id, is_suspended, can_always_login,
|
|
112
|
+
is_multi_factor_enabled, is_login_before, working_days,
|
|
113
|
+
login_on, logout_on FROM "{tenant_id}".{db_settings.TENANT_LOGIN_SETTINGS_TABLE}
|
|
114
|
+
WHERE (delete_status = 'NOT_DELETED' AND is_active = true )
|
|
115
|
+
AND (user_id = %s OR group_id = ANY(%s))
|
|
116
|
+
ORDER BY user_id NULLS LAST
|
|
117
|
+
LIMIT 1""",
|
|
118
|
+
(user_id, group_ids),
|
|
119
|
+
)
|
|
120
|
+
else:
|
|
121
|
+
login_settings_details = DatabaseManager.execute_query(
|
|
122
|
+
f"""SELECT user_id, group_id, is_suspended, can_always_login,
|
|
123
|
+
is_multi_factor_enabled, is_login_before, working_days,
|
|
124
|
+
login_on, logout_on FROM "{tenant_id}".{db_settings.TENANT_LOGIN_SETTINGS_TABLE}
|
|
125
|
+
WHERE (delete_status = 'NOT_DELETED' AND is_active = true ) AND user_id = %s""",
|
|
126
|
+
(user_id,),
|
|
127
|
+
)
|
|
128
|
+
|
|
107
129
|
if not login_settings_details or len(login_settings_details) == 0:
|
|
108
130
|
logger.warning("Authorization failed - user not found: %s in tenant: %s", user_id, tenant_id)
|
|
109
131
|
return Respons[AuthServiceReadDto](
|
|
@@ -126,17 +148,17 @@ class AuthService:
|
|
|
126
148
|
|
|
127
149
|
if not login_settings_details[0]['can_always_login']:
|
|
128
150
|
current_day = datetime.now().strftime("%A").upper()
|
|
129
|
-
|
|
151
|
+
|
|
130
152
|
if current_day not in login_settings_details[0]['working_days']:
|
|
131
153
|
logger.warning("Authorization failed - outside working days for user: %s checking custom login period", user_id)
|
|
132
|
-
|
|
154
|
+
|
|
133
155
|
# Get current datetime (full date and time) with timezone
|
|
134
156
|
current_datetime = datetime.now(timezone.utc).replace(microsecond=0, second=0)
|
|
135
|
-
|
|
157
|
+
|
|
136
158
|
# Get from database (should already be datetime objects)
|
|
137
159
|
login_on = login_settings_details[0]['login_on']
|
|
138
160
|
logout_on = login_settings_details[0]['logout_on']
|
|
139
|
-
|
|
161
|
+
|
|
140
162
|
# Set defaults if None (with timezone awareness)
|
|
141
163
|
if not login_on:
|
|
142
164
|
login_on = datetime.min.replace(tzinfo=timezone.utc)
|
|
@@ -153,27 +175,19 @@ class AuthService:
|
|
|
153
175
|
status_code=403,
|
|
154
176
|
error="LOGIN_TIME_RESTRICTED"
|
|
155
177
|
)
|
|
156
|
-
|
|
157
|
-
# 1️⃣ Get all groups the user belongs to
|
|
158
|
-
user_groups = DatabaseManager.execute_query(
|
|
159
|
-
f"""SELECT group_id FROM "{tenant_id}".{db_settings.TENANT_USER_GROUPS_TABLE}
|
|
160
|
-
WHERE delete_status = 'NOT_DELETED' AND is_active = true AND user_id = %s""",(user_id,),
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
# 2️⃣ Prepare list of group_ids
|
|
164
|
-
group_ids = [g["group_id"] for g in user_groups] if user_groups else []
|
|
165
178
|
|
|
166
|
-
#
|
|
179
|
+
# 4️⃣ Build query dynamically to include groups (if any) + user
|
|
180
|
+
# ⚠️ CHANGED: Simplified to new schema - only select user_id, group_id, role_id, resource_type
|
|
167
181
|
if group_ids:
|
|
168
182
|
get_user_roles = DatabaseManager.execute_query(
|
|
169
183
|
f"""
|
|
170
|
-
SELECT DISTINCT ON (
|
|
171
|
-
|
|
184
|
+
SELECT DISTINCT ON (group_id, user_id, role_id)
|
|
185
|
+
group_id, user_id, role_id, resource_type
|
|
172
186
|
FROM "{tenant_id}".{db_settings.TENANT_ASSIGN_ROLES_TABLE}
|
|
173
187
|
WHERE delete_status = 'NOT_DELETED'
|
|
174
188
|
AND is_active = true
|
|
175
189
|
AND (user_id = %s OR group_id = ANY(%s))
|
|
176
|
-
ORDER BY
|
|
190
|
+
ORDER BY group_id, user_id, role_id;
|
|
177
191
|
""",
|
|
178
192
|
(user_id, group_ids),
|
|
179
193
|
)
|
|
@@ -181,13 +195,13 @@ class AuthService:
|
|
|
181
195
|
# No groups, just check roles for user
|
|
182
196
|
get_user_roles = DatabaseManager.execute_query(
|
|
183
197
|
f"""
|
|
184
|
-
SELECT DISTINCT ON (
|
|
185
|
-
|
|
198
|
+
SELECT DISTINCT ON (user_id, role_id)
|
|
199
|
+
user_id, role_id, resource_type
|
|
186
200
|
FROM "{tenant_id}".{db_settings.TENANT_ASSIGN_ROLES_TABLE}
|
|
187
201
|
WHERE delete_status = 'NOT_DELETED'
|
|
188
202
|
AND is_active = true
|
|
189
203
|
AND user_id = %s
|
|
190
|
-
ORDER BY
|
|
204
|
+
ORDER BY user_id, role_id;
|
|
191
205
|
""",
|
|
192
206
|
(user_id,),
|
|
193
207
|
)
|
|
@@ -224,31 +238,27 @@ class AuthService:
|
|
|
224
238
|
status_code=500,
|
|
225
239
|
error="Authorization check failed due to an internal error"
|
|
226
240
|
)
|
|
227
|
-
|
|
241
|
+
|
|
228
242
|
@staticmethod
|
|
229
|
-
def check_permission(users_data: list, action=None,
|
|
230
|
-
resource_id=None, shared_resource_id=None) -> bool:
|
|
243
|
+
def check_permission(users_data: list, action=None, resource_type=None) -> bool:
|
|
231
244
|
"""
|
|
232
|
-
Check if user has a given permission (action)
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
245
|
+
Check if user has a given permission (action).
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
users_data: List of user authorization data containing roles and permissions
|
|
249
|
+
action: The permission/action to check for
|
|
250
|
+
resource_type: Optional resource type filter (e.g., 'rt-user', 'rt-group')
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
bool: True if user has the permission, False otherwise
|
|
236
254
|
"""
|
|
237
255
|
for user_data in users_data:
|
|
238
|
-
# Check
|
|
239
|
-
if user_data.
|
|
240
|
-
continue
|
|
241
|
-
if user_data.bus_id not in (None, bus_id):
|
|
242
|
-
continue
|
|
243
|
-
if user_data.app_id not in (None, app_id):
|
|
244
|
-
continue
|
|
245
|
-
if user_data.resource_id not in (None, resource_id):
|
|
246
|
-
continue
|
|
247
|
-
if user_data.shared_resource_id not in (None, shared_resource_id):
|
|
256
|
+
# Check resource_type if specified
|
|
257
|
+
if resource_type and user_data.resource_type and user_data.resource_type != resource_type:
|
|
248
258
|
continue
|
|
249
259
|
|
|
250
260
|
# Check if the permission exists
|
|
251
|
-
if action in user_data.permissions:
|
|
261
|
+
if action and action in user_data.permissions:
|
|
252
262
|
return True
|
|
253
263
|
|
|
254
264
|
return False
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: trovesuite
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.11
|
|
4
4
|
Summary: TroveSuite services package providing authentication, authorization, notifications, Azure Storage, and other enterprise services for TroveSuite applications
|
|
5
5
|
Home-page: https://dev.azure.com/brightgclt/trovesuite/_git/packages
|
|
6
6
|
Author: Bright Debrah Owusu
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/notification/notification_controller.py
RENAMED
|
File without changes
|
{trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/notification/notification_read_dto.py
RENAMED
|
File without changes
|
|
File without changes
|
{trovesuite-1.0.10 → trovesuite-1.0.11}/src/trovesuite/notification/notification_write_dto.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|