trovesuite 1.0.17__py3-none-any.whl → 1.0.18__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.
@@ -98,8 +98,9 @@ class AuthService:
98
98
 
99
99
  # 1️⃣ Get all groups the user belongs to
100
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,),
101
+ f"""SELECT group_id FROM {db_settings.TENANT_USER_GROUPS_TABLE}
102
+ WHERE tenant_id = %s AND delete_status = 'NOT_DELETED' AND is_active = true AND user_id = %s""",
103
+ (tenant_id, user_id,),
103
104
  )
104
105
 
105
106
  # 2️⃣ Prepare list of group_ids
@@ -110,20 +111,20 @@ class AuthService:
110
111
  login_settings_details = DatabaseManager.execute_query(
111
112
  f"""SELECT user_id, group_id, is_suspended, can_always_login,
112
113
  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 )
114
+ login_on, logout_on FROM {db_settings.TENANT_LOGIN_SETTINGS_TABLE}
115
+ WHERE tenant_id = %s AND (delete_status = 'NOT_DELETED' AND is_active = true )
115
116
  AND (user_id = %s OR group_id = ANY(%s))
116
117
  ORDER BY user_id NULLS LAST
117
118
  LIMIT 1""",
118
- (user_id, group_ids),
119
+ (tenant_id, user_id, group_ids),
119
120
  )
120
121
  else:
121
122
  login_settings_details = DatabaseManager.execute_query(
122
123
  f"""SELECT user_id, group_id, is_suspended, can_always_login,
123
124
  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,),
125
+ login_on, logout_on FROM {db_settings.TENANT_LOGIN_SETTINGS_TABLE}
126
+ WHERE tenant_id = %s AND (delete_status = 'NOT_DELETED' AND is_active = true ) AND user_id = %s""",
127
+ (tenant_id, user_id,),
127
128
  )
128
129
 
129
130
  if not login_settings_details or len(login_settings_details) == 0:
@@ -202,13 +203,13 @@ class AuthService:
202
203
  f"""
203
204
  SELECT DISTINCT ON (group_id, user_id, role_id)
204
205
  group_id, user_id, role_id, resource_type
205
- FROM "{tenant_id}".{db_settings.TENANT_ASSIGN_ROLES_TABLE}
206
- WHERE delete_status = 'NOT_DELETED'
206
+ FROM {db_settings.TENANT_ASSIGN_ROLES_TABLE}
207
+ WHERE tenant_id = %s AND delete_status = 'NOT_DELETED'
207
208
  AND is_active = true
208
209
  AND (user_id = %s OR group_id = ANY(%s))
209
210
  ORDER BY group_id, user_id, role_id;
210
211
  """,
211
- (user_id, group_ids),
212
+ (tenant_id, user_id, group_ids),
212
213
  )
213
214
  else:
214
215
  # No groups, just check roles for user
@@ -216,13 +217,13 @@ class AuthService:
216
217
  f"""
217
218
  SELECT DISTINCT ON (user_id, role_id)
218
219
  user_id, role_id, resource_type
219
- FROM "{tenant_id}".{db_settings.TENANT_ASSIGN_ROLES_TABLE}
220
- WHERE delete_status = 'NOT_DELETED'
220
+ FROM {db_settings.TENANT_ASSIGN_ROLES_TABLE}
221
+ WHERE tenant_id = %s AND delete_status = 'NOT_DELETED'
221
222
  AND is_active = true
222
223
  AND user_id = %s
223
224
  ORDER BY user_id, role_id;
224
225
  """,
225
- (user_id,),
226
+ (tenant_id, user_id,),
226
227
  )
227
228
 
228
229
  # ✅ NEW: Get system-level roles from main.system_user_groups and main.system_assign_roles
@@ -301,7 +302,6 @@ class AuthService:
301
302
  error="Authorization check failed due to an internal error"
302
303
  )
303
304
 
304
-
305
305
  @staticmethod
306
306
  def check_permission(users_data: list, action=None, resource_type=None) -> bool:
307
307
  """
@@ -58,25 +58,28 @@ class Settings:
58
58
  MAIN_SYSTEM_ASSIGN_ROLES_TABLE = os.getenv("MAIN_SYSTEM_ASSIGN_ROLES_TABLE", "main.system_assign_roles")
59
59
 
60
60
  # =============================================================================
61
- # TENANT-SPECIFIC TABLES (tenant schemas)
61
+ # TENANT-SPECIFIC TABLES (now in main schema with tenant_id)
62
62
  # =============================================================================
63
- TENANT_SUBSCRIPTIONS_TABLE = os.getenv("TENANT_SUBSCRIPTIONS_TABLE")
64
- TENANT_GROUPS_TABLE = os.getenv("TENANT_GROUPS_TABLE")
65
- TENANT_LOGIN_SETTINGS_TABLE = os.getenv("TENANT_LOGIN_SETTINGS_TABLE")
66
- TENANT_RESOURCES_TABLE = os.getenv("TENANT_RESOURCES_TABLE")
67
- TENANT_ASSIGN_ROLES_TABLE = os.getenv("TENANT_ASSIGN_ROLES_TABLE")
68
- TENANT_RESOURCE_ID_TABLE = os.getenv("TENANT_RESOURCE_ID_TABLE")
69
- TENANT_SUBSCRIPTION_HISTORY_TABLE = os.getenv("TENANT_SUBSCRIPTION_HISTORY_TABLE")
70
- TENANT_RESOURCE_DELETION_CHAT_HISTORY_TABLE = os.getenv("TENANT_RESOURCE_DELETION_CHAT_HISTORY_TABLE")
71
- TENANT_USER_GROUPS_TABLE = os.getenv("TENANT_USER_GROUPS_TABLE")
72
- TENANT_ACTIVITY_LOGS_TABLE = os.getenv("TENANT_ACTIVITY_LOGS_TABLE")
73
- TENANT_ORGANIZATIONS_TABLE = os.getenv("TENANT_ORGANIZATIONS_TABLE", "organizations")
74
- TENANT_BUSINESSES_TABLE = os.getenv("TENANT_BUSINESSES_TABLE", "businesses")
75
- TENANT_BUSINESS_APPS_TABLE = os.getenv("TENANT_BUSINESS_APPS_TABLE", "business_apps")
76
- TENANT_LOCATIONS_TABLE = os.getenv("TENANT_LOCATIONS_TABLE", "locations")
77
- TENANT_ASSIGN_LOCATIONS_TABLE = os.getenv("TENANT_ASSIGN_LOCATIONS_TABLE", "assign_locations")
78
- TENANT_UNIT_OF_MEASURE_TABLE = os.getenv("TENANT_UNIT_OF_MEASURE_TABLE")
79
- TENANT_CURRENCY=os.getenv("TENANT_CURRENCY")
63
+ # NOTE: These tables have been migrated from separate tenant schemas to main schema.
64
+ # All tables now include tenant_id column for multi-tenant isolation.
65
+ # =============================================================================
66
+ TENANT_SUBSCRIPTIONS_TABLE = os.getenv("TENANT_SUBSCRIPTIONS_TABLE", "main.tenant_subscriptions")
67
+ TENANT_GROUPS_TABLE = os.getenv("TENANT_GROUPS_TABLE", "main.tenant_groups")
68
+ TENANT_LOGIN_SETTINGS_TABLE = os.getenv("TENANT_LOGIN_SETTINGS_TABLE", "main.tenant_login_settings")
69
+ TENANT_RESOURCES_TABLE = os.getenv("TENANT_RESOURCES_TABLE", "main.tenant_resources")
70
+ TENANT_ASSIGN_ROLES_TABLE = os.getenv("TENANT_ASSIGN_ROLES_TABLE", "main.tenant_assign_roles")
71
+ TENANT_RESOURCE_ID_TABLE = os.getenv("TENANT_RESOURCE_ID_TABLE", "main.tenant_resource_ids")
72
+ TENANT_SUBSCRIPTION_HISTORY_TABLE = os.getenv("TENANT_SUBSCRIPTION_HISTORY_TABLE", "main.tenant_subscription_histories")
73
+ TENANT_RESOURCE_DELETION_CHAT_HISTORY_TABLE = os.getenv("TENANT_RESOURCE_DELETION_CHAT_HISTORY_TABLE", "main.tenant_resource_deletion_chat_histories")
74
+ TENANT_USER_GROUPS_TABLE = os.getenv("TENANT_USER_GROUPS_TABLE", "main.tenant_user_groups")
75
+ TENANT_ACTIVITY_LOGS_TABLE = os.getenv("TENANT_ACTIVITY_LOGS_TABLE", "main.tenant_activity_logs")
76
+ TENANT_ORGANIZATIONS_TABLE = os.getenv("TENANT_ORGANIZATIONS_TABLE", "main.tenant_organizations")
77
+ TENANT_BUSINESSES_TABLE = os.getenv("TENANT_BUSINESSES_TABLE", "main.tenant_businesses")
78
+ TENANT_BUSINESS_APPS_TABLE = os.getenv("TENANT_BUSINESS_APPS_TABLE", "main.tenant_business_apps")
79
+ TENANT_LOCATIONS_TABLE = os.getenv("TENANT_LOCATIONS_TABLE", "main.tenant_locations")
80
+ TENANT_ASSIGN_LOCATIONS_TABLE = os.getenv("TENANT_ASSIGN_LOCATIONS_TABLE", "main.tenant_assign_locations")
81
+ TENANT_UNIT_OF_MEASURE_TABLE = os.getenv("TENANT_UNIT_OF_MEASURE_TABLE", "main.tenant_unit_of_measure")
82
+ TENANT_CURRENCY = os.getenv("TENANT_CURRENCY", "main.tenant_currency")
80
83
 
81
84
  # Mail Configurations
82
85
  MAIL_SENDER_EMAIL=os.getenv("MAIL_SENDER_EMAIL")
@@ -96,14 +96,14 @@ class Helper:
96
96
 
97
97
  try:
98
98
  if tenant_id:
99
- # For tenant-specific resource IDs, check tenant schema
99
+ # For tenant-specific resource IDs, check shared schema with tenant_id filter
100
100
  # Note: TENANT_RESOURCE_ID_TABLE needs to be defined in settings
101
101
  tenant_resource_table = getattr(db_settings, 'TENANT_RESOURCE_ID_TABLE', None)
102
102
  if tenant_resource_table:
103
103
  resource_exists = DatabaseManager.execute_scalar(
104
- f"""SELECT COUNT(1) FROM "{tenant_id}".{tenant_resource_table}
105
- WHERE id = %s""",
106
- (candidate,),
104
+ f"""SELECT COUNT(1) FROM {tenant_resource_table}
105
+ WHERE tenant_id = %s AND id = %s""",
106
+ (tenant_id, candidate,),
107
107
  )
108
108
  else:
109
109
  # Fallback: assume no conflict if table not configured
@@ -289,10 +289,10 @@ class Helper:
289
289
  logger.debug(f"Activity log values - performed_by_email: {performed_by_email}, performed_by_contact: {performed_by_contact}, performed_by_fullname: {performed_by_fullname}")
290
290
 
291
291
  result = DatabaseManager.execute_update(
292
- f"""INSERT INTO "{tenant_id}".{tenant_activity_logs_table}
293
- (id, action, resource_type, old_data, new_data, description, performed_by_email, performed_by_contact, performed_by_fullname, cdate, ctime, cdatetime)
294
- VALUES (%s, %s, NULLIF(%s, '')::text, %s::jsonb, %s::jsonb, %s, %s, %s, %s, %s, %s, %s)""",
295
- (log_id, action, resource_type, old_json, new_json, description, performed_by_email, performed_by_contact, performed_by_fullname, cdate, ctime, cdatetime),
292
+ f"""INSERT INTO {tenant_activity_logs_table}
293
+ (id, tenant_id, action, resource_type, old_data, new_data, description, performed_by_email, performed_by_contact, performed_by_fullname, cdate, ctime, cdatetime)
294
+ VALUES (%s, %s, %s, NULLIF(%s, '')::text, %s::jsonb, %s::jsonb, %s, %s, %s, %s, %s, %s, %s)""",
295
+ (log_id, tenant_id, action, resource_type, old_json, new_json, description, performed_by_email, performed_by_contact, performed_by_fullname, cdate, ctime, cdatetime),
296
296
  )
297
297
 
298
298
  logger.info(f"Activity logged successfully. Rows affected: {result}")
@@ -301,9 +301,9 @@ class Helper:
301
301
  if result > 0:
302
302
  verify_data = DatabaseManager.execute_query(
303
303
  f"""SELECT performed_by_email, performed_by_contact, performed_by_fullname
304
- FROM "{tenant_id}".{tenant_activity_logs_table}
305
- WHERE id = %s""",
306
- (log_id,)
304
+ FROM {tenant_activity_logs_table}
305
+ WHERE tenant_id = %s AND id = %s""",
306
+ (tenant_id, log_id,)
307
307
  )
308
308
  if verify_data:
309
309
  logger.debug(f"Verification - Inserted activity log data: {verify_data[0]}")
@@ -416,8 +416,8 @@ class Helper:
416
416
  # Get table names from settings with fallbacks
417
417
  main_users_table = getattr(db_settings, 'MAIN_USERS_TABLE', 'main.users')
418
418
  main_roles_table = getattr(db_settings, 'MAIN_ROLES_TABLE', 'main.roles')
419
- tenant_assign_roles_table = getattr(db_settings, 'TENANT_ASSIGN_ROLES_TABLE', 'assign_roles')
420
- tenant_user_groups_table = getattr(db_settings, 'TENANT_USER_GROUPS_TABLE', 'user_groups')
419
+ tenant_assign_roles_table = getattr(db_settings, 'TENANT_ASSIGN_ROLES_TABLE', 'main.tenant_assign_roles')
420
+ tenant_user_groups_table = getattr(db_settings, 'TENANT_USER_GROUPS_TABLE', 'main.tenant_user_groups')
421
421
 
422
422
  # Query to get users with admin roles - both direct and through groups
423
423
  query = f"""
@@ -430,9 +430,10 @@ class Helper:
430
430
  -- Direct role assignment
431
431
  u.id IN (
432
432
  SELECT ar.user_id
433
- FROM "{tenant_id}".{tenant_assign_roles_table} ar
433
+ FROM {tenant_assign_roles_table} ar
434
434
  INNER JOIN {main_roles_table} r ON ar.role_id = r.id
435
- WHERE ar.delete_status = 'NOT_DELETED'
435
+ WHERE ar.tenant_id = %s
436
+ AND ar.delete_status = 'NOT_DELETED'
436
437
  AND ar.is_active = true
437
438
  AND r.delete_status = 'NOT_DELETED'
438
439
  AND r.is_active = true
@@ -443,10 +444,12 @@ class Helper:
443
444
  -- Group-based role assignment
444
445
  u.id IN (
445
446
  SELECT ug.user_id
446
- FROM "{tenant_id}".{tenant_user_groups_table} ug
447
- INNER JOIN "{tenant_id}".{tenant_assign_roles_table} ar ON ug.group_id = ar.group_id
447
+ FROM {tenant_user_groups_table} ug
448
+ INNER JOIN {tenant_assign_roles_table} ar ON ug.group_id = ar.group_id
448
449
  INNER JOIN {main_roles_table} r ON ar.role_id = r.id
449
- WHERE ug.delete_status = 'NOT_DELETED'
450
+ WHERE ug.tenant_id = %s
451
+ AND ar.tenant_id = %s
452
+ AND ug.delete_status = 'NOT_DELETED'
450
453
  AND ug.is_active = true
451
454
  AND ar.delete_status = 'NOT_DELETED'
452
455
  AND ar.is_active = true
@@ -458,7 +461,7 @@ class Helper:
458
461
  )
459
462
  """
460
463
 
461
- results = DatabaseManager.execute_query(query)
464
+ results = DatabaseManager.execute_query(query, (tenant_id, tenant_id, tenant_id,))
462
465
 
463
466
  admin_users = []
464
467
  if results:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: trovesuite
3
- Version: 1.0.17
3
+ Version: 1.0.18
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,12 +3,12 @@ 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=G2_lkXdMnuqpBjKFYGlRUrUvVyq8keukXaSyboiWiUM,18106
6
+ trovesuite/auth/auth_service.py,sha256=YtPtYvzOAiYnsvRutYcYFsyOuJxc41MAmIGY4qiPsM4,18202
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
10
10
  trovesuite/configs/logging.py,sha256=mGjR2d4urVNry9l5_aXycMMtcY2RAFIpEL35hw33KZg,9308
11
- trovesuite/configs/settings.py,sha256=9kl4f7AOtulUnmoWcrLVa8LKjGirZkPYSWtACoTqr5U,5652
11
+ trovesuite/configs/settings.py,sha256=baXR6OQefNm0vkyTWNCbL8jGdgD-k9RwDid5cyZSme0,6339
12
12
  trovesuite/entities/__init__.py,sha256=Dbl_03Bueyh2vOP2hykd40MmNMrl5nNHSRGP-kqwwNo,160
13
13
  trovesuite/entities/health.py,sha256=KaW7yxTQdymIPlnkJJkDqEebBXkD0a7A66i5GgNZLoE,2700
14
14
  trovesuite/entities/sh_response.py,sha256=1_sw3PpVaDxWsNiBU0W9YLHZgTFxEj4JJBLBfSY63Ho,1579
@@ -25,10 +25,10 @@ trovesuite/storage/storage_read_dto.py,sha256=o7EVJdwrwVZAaeyGU9O01WMECGVaytkvLR
25
25
  trovesuite/storage/storage_service.py,sha256=V7LIePIV6b_iuhm-9x8r4zwpZHgeRPL1YIe5IBnxhco,19768
26
26
  trovesuite/storage/storage_write_dto.py,sha256=vl1iCZ93bpFmpvkCrn587QtMtOA_TPDseXSoTuj9RTQ,1355
27
27
  trovesuite/utils/__init__.py,sha256=mDZuY77BphvQFYLmcWxjP5Tcq9ZZ3WXJWBKB1v6wzHU,185
28
- trovesuite/utils/helper.py,sha256=k7Meg8sN4aPBdqcjaF1tQcZ32KvuA-IqjpWniQP_Mpk,26438
28
+ trovesuite/utils/helper.py,sha256=GY9PUUgAQsOYrsNrzNHdyfPlAyZvQy-49m-XxpQokz0,26660
29
29
  trovesuite/utils/templates.py,sha256=_92k4-EkqWs-h0LNJxPgorbspmp24kDngS7O3qWIFyQ,20388
30
- trovesuite-1.0.17.dist-info/licenses/LICENSE,sha256=EJT35ct-Q794JYPdAQy3XNczQGKkU1HzToLeK1YVw2s,1070
31
- trovesuite-1.0.17.dist-info/METADATA,sha256=UB2VoJbb7XXl1GUPVjq8BL_zXB_DMQMzSmuYabHBuAo,21737
32
- trovesuite-1.0.17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
33
- trovesuite-1.0.17.dist-info/top_level.txt,sha256=GzKhG_-MTaxeHrIgkGkBH_nof2vroGFBrjeHKWUIwNc,11
34
- trovesuite-1.0.17.dist-info/RECORD,,
30
+ trovesuite-1.0.18.dist-info/licenses/LICENSE,sha256=EJT35ct-Q794JYPdAQy3XNczQGKkU1HzToLeK1YVw2s,1070
31
+ trovesuite-1.0.18.dist-info/METADATA,sha256=rNEcWB2xkxHziv7voEoirrUhJlsF4qZFOMeLtGD5SMg,21737
32
+ trovesuite-1.0.18.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
33
+ trovesuite-1.0.18.dist-info/top_level.txt,sha256=GzKhG_-MTaxeHrIgkGkBH_nof2vroGFBrjeHKWUIwNc,11
34
+ trovesuite-1.0.18.dist-info/RECORD,,