trovesuite 1.0.11__py3-none-any.whl → 1.0.13__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.
@@ -77,7 +77,7 @@ class AuthService:
77
77
  )
78
78
 
79
79
  if not is_tenant_verified or len(is_tenant_verified) == 0:
80
- logger.warning("Login failed - tenant not found: %s", tenant_id)
80
+ logger.warning("Authorization failed - tenant not found: %s", tenant_id)
81
81
  return Respons[AuthServiceReadDto](
82
82
  detail=f"Tenant '{tenant_id}' not found or has been deleted",
83
83
  data=[],
@@ -87,7 +87,7 @@ class AuthService:
87
87
  )
88
88
 
89
89
  if not is_tenant_verified[0]['is_verified']:
90
- logger.warning("Login failed - tenant not verified for user: %s, tenant: %s", user_id, tenant_id)
90
+ logger.warning("Authorization failed - tenant not verified for user: %s, tenant: %s", user_id, tenant_id)
91
91
  return Respons[AuthServiceReadDto](
92
92
  detail=f"Tenant '{tenant_id}' is not verified. Please contact your administrator.",
93
93
  data=[],
@@ -146,35 +146,54 @@ class AuthService:
146
146
  error="USER_SUSPENDED"
147
147
  )
148
148
 
149
+ # ✅ UPDATED: Mutually exclusive login restrictions logic
149
150
  if not login_settings_details[0]['can_always_login']:
150
- current_day = datetime.now().strftime("%A").upper()
151
+ # Get from database (should already be datetime objects)
152
+ login_on = login_settings_details[0]['login_on']
153
+ logout_on = login_settings_details[0]['logout_on']
154
+ working_days = login_settings_details[0]['working_days']
151
155
 
152
- if current_day not in login_settings_details[0]['working_days']:
153
- logger.warning("Authorization failed - outside working days for user: %s checking custom login period", user_id)
156
+ # Only ONE restriction type can be active at a time:
157
+ # 1. working_days restriction (if login_on/logout_on are NULL)
158
+ # 2. time period restriction (if login_on/logout_on are set)
154
159
 
155
- # Get current datetime (full date and time) with timezone
156
- current_datetime = datetime.now(timezone.utc).replace(microsecond=0, second=0)
157
-
158
- # Get from database (should already be datetime objects)
159
- login_on = login_settings_details[0]['login_on']
160
- logout_on = login_settings_details[0]['logout_on']
160
+ if login_on and logout_on:
161
+ # Time period restriction is active
162
+ logger.info(f"Checking time period restriction for user: {user_id}")
161
163
 
162
- # Set defaults if None (with timezone awareness)
163
- if not login_on:
164
- login_on = datetime.min.replace(tzinfo=timezone.utc)
165
- if not logout_on:
166
- logout_on = datetime.max.replace(tzinfo=timezone.utc)
164
+ # Get current datetime (full date and time) with timezone
165
+ current_datetime = datetime.now(timezone.utc).replace(
166
+ microsecond=0, second=0
167
+ )
167
168
 
168
169
  # Compare full datetime objects (both date and time)
169
170
  if not (login_on <= current_datetime <= logout_on):
170
- logger.warning("Authorization failed - outside allowed period for user: %s", user_id)
171
+ logger.warning(
172
+ f"Authorization failed - outside allowed period for user: {user_id}"
173
+ )
171
174
  return Respons[AuthServiceReadDto](
172
- detail="Login is not allowed at this time. Please check your access schedule.",
175
+ detail="Access is not allowed at this time. Please check your access schedule.",
173
176
  data=[],
174
177
  success=False,
175
178
  status_code=403,
176
179
  error="LOGIN_TIME_RESTRICTED"
177
180
  )
181
+ elif working_days:
182
+ # Working days restriction is active
183
+ logger.info(f"Checking working days restriction for user: {user_id}")
184
+ current_day = datetime.now().strftime("%A").upper()
185
+
186
+ if current_day not in working_days:
187
+ logger.warning(
188
+ f"Authorization failed - not a working day for user: {user_id}"
189
+ )
190
+ return Respons[AuthServiceReadDto](
191
+ detail="Access is not allowed on this day. Please contact your administrator.",
192
+ data=[],
193
+ success=False,
194
+ status_code=403,
195
+ error="LOGIN_DAY_RESTRICTED"
196
+ )
178
197
 
179
198
  # 4️⃣ Build query dynamically to include groups (if any) + user
180
199
  # ⚠️ CHANGED: Simplified to new schema - only select user_id, group_id, role_id, resource_type
@@ -206,18 +225,62 @@ class AuthService:
206
225
  (user_id,),
207
226
  )
208
227
 
228
+ # ✅ NEW: Get system-level roles from main.system_user_groups and main.system_assign_roles
229
+ logger.info(f"Fetching system-level roles for user: {user_id}")
230
+
231
+ system_roles = DatabaseManager.execute_query(
232
+ """
233
+ SELECT DISTINCT sug.group_id, sug.user_id, sar.role_id, sar.resource_type
234
+ FROM main.system_user_groups sug
235
+ INNER JOIN main.system_assign_roles sar ON sug.group_id = sar.group_id
236
+ WHERE sug.user_id = %s
237
+ AND sug.delete_status = 'NOT_DELETED'
238
+ AND sar.is_active = true
239
+ AND sar.delete_status = 'NOT_DELETED'
240
+ """,
241
+ (user_id,)
242
+ )
243
+
244
+ if system_roles:
245
+ logger.info(f"Found {len(system_roles)} system-level role(s) for user: {user_id}")
246
+ else:
247
+ logger.info(f"No system-level roles found for user: {user_id}")
248
+
249
+ # ✅ NEW: Also check for direct system role assignments (user_id in system_assign_roles)
250
+ direct_system_roles = DatabaseManager.execute_query(
251
+ """
252
+ SELECT DISTINCT NULL as group_id, sar.user_id, sar.role_id, sar.resource_type
253
+ FROM main.system_assign_roles sar
254
+ WHERE sar.user_id = %s
255
+ AND sar.is_active = true
256
+ AND sar.delete_status = 'NOT_DELETED'
257
+ """,
258
+ (user_id,)
259
+ )
260
+
261
+ if direct_system_roles:
262
+ logger.info(f"Found {len(direct_system_roles)} direct system-level role assignment(s) for user: {user_id}")
263
+ system_roles.extend(direct_system_roles)
264
+
265
+ # ✅ NEW: Merge tenant-level and system-level roles
266
+ all_roles = get_user_roles + system_roles
267
+ logger.info(f"Total roles (tenant + system) for user {user_id}: {len(all_roles)}")
268
+
209
269
  # GET permissions and Append to Role
210
270
  get_user_roles_with_tenant_and_permissions = []
211
- for role in get_user_roles:
271
+ for role in all_roles:
212
272
  permissions = DatabaseManager.execute_query(
213
273
  f"""SELECT permission_id FROM {db_settings.MAIN_ROLE_PERMISSIONS_TABLE} WHERE role_id = %s""",
214
- params=(role["role_id"],),)
274
+ params=(role["role_id"],),
275
+ )
215
276
 
216
277
  role_dict = {**role, "tenant_id": tenant_id, "permissions": [p['permission_id'] for p in permissions]}
217
278
  get_user_roles_with_tenant_and_permissions.append(role_dict)
218
279
 
219
280
  roles_dto = Helper.map_to_dto(get_user_roles_with_tenant_and_permissions, AuthServiceReadDto)
220
281
 
282
+ logger.info(f"Authorization successful for user: {user_id} with {len(roles_dto)} total role entries")
283
+
221
284
  return Respons[AuthServiceReadDto](
222
285
  detail="Authorized",
223
286
  data=roles_dto,
@@ -230,7 +293,7 @@ class AuthService:
230
293
  raise http_ex
231
294
 
232
295
  except Exception as e:
233
- logger.error("Authorization check failed for user: %s", str(e))
296
+ logger.error("Authorization check failed for user: %s - Error: %s", user_id, str(e), exc_info=True)
234
297
  return Respons[AuthServiceReadDto](
235
298
  detail=None,
236
299
  data=[],
@@ -239,6 +302,7 @@ class AuthService:
239
302
  error="Authorization check failed due to an internal error"
240
303
  )
241
304
 
305
+
242
306
  @staticmethod
243
307
  def check_permission(users_data: list, action=None, resource_type=None) -> bool:
244
308
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: trovesuite
3
- Version: 1.0.11
3
+ Version: 1.0.13
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
@@ -3,7 +3,7 @@ trovesuite/auth/__init__.py,sha256=OjZllVvjul1glDazJ-d5TrNjgHFigFlQQi1G99DYshk,2
3
3
  trovesuite/auth/auth_base.py,sha256=rZHQVLeJRBQ8GClgF5UwG-er4_HXVX5-nt8o6_Z29uY,75
4
4
  trovesuite/auth/auth_controller.py,sha256=PAgaVlf5TYEfkSfK4vGGsvO84i8zEmeVVXyUF2YBppI,420
5
5
  trovesuite/auth/auth_read_dto.py,sha256=e27JqKVPVUM83A_mYF452QCflsvGNo7aKje7q_urwFc,571
6
- trovesuite/auth/auth_service.py,sha256=CRGGXCdaAknznwq68ghmhtZ13NM73tu32OPJK8JJ2_Y,14488
6
+ trovesuite/auth/auth_service.py,sha256=N5ax0rdGlHcu7cpJyAFrrwdkwKN8gsoh-t6ngIvXBAk,17548
7
7
  trovesuite/auth/auth_write_dto.py,sha256=rdwI7w6-9QZGv1H0PAGrjkLBCzaMHjgPIXeLb9RmNec,234
8
8
  trovesuite/configs/__init__.py,sha256=h1mSZOaZ3kUy1ZMO_m9O9KklsxywM0RfMVZLh9h9WvQ,328
9
9
  trovesuite/configs/database.py,sha256=IPSu8fXjxyYeJ3bFknJG06Qm2L2ub6Ht19xhKv8g7nA,11731
@@ -26,8 +26,8 @@ trovesuite/storage/storage_service.py,sha256=V7LIePIV6b_iuhm-9x8r4zwpZHgeRPL1YIe
26
26
  trovesuite/storage/storage_write_dto.py,sha256=vl1iCZ93bpFmpvkCrn587QtMtOA_TPDseXSoTuj9RTQ,1355
27
27
  trovesuite/utils/__init__.py,sha256=3UPKTz9cluTgAM-ldNsJxsnoPTZiqacXlAmzUEHy6q8,143
28
28
  trovesuite/utils/helper.py,sha256=lvZ1mvaqY84dkIPB5Ov0uwYDOWBziAS8twobEJZh2Ik,1002
29
- trovesuite-1.0.11.dist-info/licenses/LICENSE,sha256=EJT35ct-Q794JYPdAQy3XNczQGKkU1HzToLeK1YVw2s,1070
30
- trovesuite-1.0.11.dist-info/METADATA,sha256=HTQhhc9Yps3NbrJz8JqfP493kSVIMux4ToJB2F31_-8,21737
31
- trovesuite-1.0.11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
32
- trovesuite-1.0.11.dist-info/top_level.txt,sha256=GzKhG_-MTaxeHrIgkGkBH_nof2vroGFBrjeHKWUIwNc,11
33
- trovesuite-1.0.11.dist-info/RECORD,,
29
+ trovesuite-1.0.13.dist-info/licenses/LICENSE,sha256=EJT35ct-Q794JYPdAQy3XNczQGKkU1HzToLeK1YVw2s,1070
30
+ trovesuite-1.0.13.dist-info/METADATA,sha256=V0DYYd8qAzusR_UKkg--F4scCYY0PhONHhjoa6fZ91k,21737
31
+ trovesuite-1.0.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
32
+ trovesuite-1.0.13.dist-info/top_level.txt,sha256=GzKhG_-MTaxeHrIgkGkBH_nof2vroGFBrjeHKWUIwNc,11
33
+ trovesuite-1.0.13.dist-info/RECORD,,