trovesuite 1.0.10__py3-none-any.whl → 1.0.11__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.
@@ -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
- login_settings_details = DatabaseManager.execute_query(
100
- f"""SELECT user_id, group_id, is_suspended, can_always_login,
101
- is_multi_factor_enabled, is_login_before, working_days,
102
- login_on, logout_on FROM "{tenant_id}".{db_settings.TENANT_LOGIN_SETTINGS_TABLE}
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
- # 3️⃣ Build query dynamically to include groups (if any) + user
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 (org_id, group_id, bus_id, app_id, shared_resource_id, resource_id, user_id, role_id)
171
- org_id, group_id, bus_id, app_id, shared_resource_id, resource_id, user_id, role_id
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 org_id, group_id, bus_id, app_id, shared_resource_id, resource_id, user_id, role_id;
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 (org_id, bus_id, app_id, shared_resource_id, resource_id, user_id, role_id)
185
- org_id, bus_id, app_id, shared_resource_id, resource_id, user_id, role_id
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 org_id, bus_id, app_id, shared_resource_id, resource_id, user_id, role_id;
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, org_id=None, bus_id=None, app_id=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) for a specific target.
233
-
234
- Hierarchy: organization > business > app > location > resource/shared_resource
235
- If a field in role is None, it applies to all under that level.
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 hierarchy: None means "all"
239
- if user_data.org_id not in (None, org_id):
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.10
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
@@ -2,8 +2,8 @@ trovesuite/__init__.py,sha256=QIY7iN7TVyJKjCoB6CBA4pSqm_mL41frcFgFS4maO8k,555
2
2
  trovesuite/auth/__init__.py,sha256=OjZllVvjul1glDazJ-d5TrNjgHFigFlQQi1G99DYshk,239
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
- trovesuite/auth/auth_read_dto.py,sha256=pQT1ouRVZMAiJn4wAG7NQOKQKTquTMWUe-dYcpLTmEo,533
6
- trovesuite/auth/auth_service.py,sha256=if2RFI6F1DpbNEuCTSpPbhHVBdYQEg4hVkoxTCnvC4k,14298
5
+ trovesuite/auth/auth_read_dto.py,sha256=e27JqKVPVUM83A_mYF452QCflsvGNo7aKje7q_urwFc,571
6
+ trovesuite/auth/auth_service.py,sha256=CRGGXCdaAknznwq68ghmhtZ13NM73tu32OPJK8JJ2_Y,14488
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.10.dist-info/licenses/LICENSE,sha256=EJT35ct-Q794JYPdAQy3XNczQGKkU1HzToLeK1YVw2s,1070
30
- trovesuite-1.0.10.dist-info/METADATA,sha256=LMpOSCZRz-a7s54MlVZLsRBmsb7jL1y9x5EjegdYYK4,21737
31
- trovesuite-1.0.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
32
- trovesuite-1.0.10.dist-info/top_level.txt,sha256=GzKhG_-MTaxeHrIgkGkBH_nof2vroGFBrjeHKWUIwNc,11
33
- trovesuite-1.0.10.dist-info/RECORD,,
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,,