ipulse-shared-core-ftredge 18.0.1__py3-none-any.whl → 20.0.1__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 ipulse-shared-core-ftredge might be problematic. Click here for more details.

Files changed (35) hide show
  1. ipulse_shared_core_ftredge/__init__.py +1 -12
  2. ipulse_shared_core_ftredge/exceptions/__init__.py +47 -0
  3. ipulse_shared_core_ftredge/exceptions/user_exceptions.py +219 -0
  4. ipulse_shared_core_ftredge/models/__init__.py +0 -2
  5. ipulse_shared_core_ftredge/models/base_data_model.py +6 -6
  6. ipulse_shared_core_ftredge/models/user_auth.py +59 -4
  7. ipulse_shared_core_ftredge/models/user_profile.py +41 -7
  8. ipulse_shared_core_ftredge/models/user_status.py +44 -138
  9. ipulse_shared_core_ftredge/monitoring/__init__.py +7 -0
  10. ipulse_shared_core_ftredge/monitoring/microservmon.py +526 -0
  11. ipulse_shared_core_ftredge/monitoring/tracemon.py +320 -0
  12. ipulse_shared_core_ftredge/services/__init__.py +21 -14
  13. ipulse_shared_core_ftredge/services/base/__init__.py +12 -0
  14. ipulse_shared_core_ftredge/services/base/base_firestore_service.py +520 -0
  15. ipulse_shared_core_ftredge/services/cache_aware_firestore_service.py +44 -8
  16. ipulse_shared_core_ftredge/services/charging_service.py +1 -1
  17. ipulse_shared_core_ftredge/services/user/__init__.py +37 -0
  18. ipulse_shared_core_ftredge/services/user/iam_management_operations.py +326 -0
  19. ipulse_shared_core_ftredge/services/user/subscription_management_operations.py +384 -0
  20. ipulse_shared_core_ftredge/services/user/user_account_operations.py +479 -0
  21. ipulse_shared_core_ftredge/services/user/user_auth_operations.py +305 -0
  22. ipulse_shared_core_ftredge/services/user/user_core_service.py +651 -0
  23. ipulse_shared_core_ftredge/services/user/user_holistic_operations.py +436 -0
  24. {ipulse_shared_core_ftredge-18.0.1.dist-info → ipulse_shared_core_ftredge-20.0.1.dist-info}/METADATA +1 -1
  25. ipulse_shared_core_ftredge-20.0.1.dist-info/RECORD +42 -0
  26. ipulse_shared_core_ftredge/models/organization_profile.py +0 -96
  27. ipulse_shared_core_ftredge/models/user_profile_update.py +0 -39
  28. ipulse_shared_core_ftredge/services/base_firestore_service.py +0 -249
  29. ipulse_shared_core_ftredge/services/fastapiservicemon.py +0 -140
  30. ipulse_shared_core_ftredge/services/servicemon.py +0 -240
  31. ipulse_shared_core_ftredge-18.0.1.dist-info/RECORD +0 -33
  32. ipulse_shared_core_ftredge/{services/base_service_exceptions.py → exceptions/base_exceptions.py} +1 -1
  33. {ipulse_shared_core_ftredge-18.0.1.dist-info → ipulse_shared_core_ftredge-20.0.1.dist-info}/WHEEL +0 -0
  34. {ipulse_shared_core_ftredge-18.0.1.dist-info → ipulse_shared_core_ftredge-20.0.1.dist-info}/licenses/LICENCE +0 -0
  35. {ipulse_shared_core_ftredge-18.0.1.dist-info → ipulse_shared_core_ftredge-20.0.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,305 @@
1
+ """
2
+ User Auth Operations - Handle Firebase Auth user creation, management, and deletion
3
+ """
4
+ import os
5
+ import asyncio
6
+ import logging
7
+ from typing import Dict, Any, Optional, List
8
+ from firebase_admin import auth
9
+ from ...models.user_auth import UserAuth
10
+ from ...exceptions import UserAuthError
11
+
12
+
13
+ class UserAuthOperations:
14
+ """
15
+ Handles Firebase Auth operations for user creation, management, and deletion
16
+ """
17
+
18
+ def __init__(self, logger: Optional[logging.Logger] = None):
19
+ self.logger = logger or logging.getLogger(__name__)
20
+
21
+ # User Auth Operations
22
+
23
+ async def create_userauth(
24
+ self,
25
+ user_auth: UserAuth
26
+ ) -> str:
27
+ """Create a new Firebase Auth user from UserAuth model and return the UID"""
28
+ try:
29
+ # Create user synchronously
30
+ loop = asyncio.get_event_loop()
31
+ user_record = await loop.run_in_executor(
32
+ None,
33
+ lambda: auth.create_user(
34
+ email=user_auth.email,
35
+ email_verified=user_auth.email_verified,
36
+ password=user_auth.password,
37
+ phone_number=user_auth.phone_number,
38
+ disabled=user_auth.disabled
39
+ )
40
+ )
41
+
42
+ user_uid = user_record.uid
43
+ self.logger.info(f"Successfully created Firebase Auth user with UID: {user_uid}")
44
+
45
+ # Set custom claims if provided
46
+ if user_auth.custom_claims:
47
+ await self.set_userauth_custom_claims(user_uid, user_auth.custom_claims)
48
+
49
+ return user_uid
50
+
51
+ except auth.EmailAlreadyExistsError:
52
+ raise UserAuthError(
53
+ detail=f"User with email {user_auth.email} already exists",
54
+ operation="create_userauth",
55
+ additional_info={"email": str(user_auth.email)}
56
+ )
57
+ except Exception as e:
58
+ self.logger.error(f"Failed to create Firebase Auth user: {e}", exc_info=True)
59
+ raise UserAuthError(
60
+ detail=f"Failed to create Firebase Auth user: {str(e)}",
61
+ operation="create_userauth",
62
+ additional_info={"email": str(user_auth.email)},
63
+ original_error=e
64
+ )
65
+
66
+ # Firebase Auth User Management
67
+
68
+ async def get_userauth(self, user_uid: str) -> Optional[auth.UserRecord]:
69
+ """Get Firebase Auth user by UID"""
70
+ try:
71
+ loop = asyncio.get_event_loop()
72
+ user_record = await loop.run_in_executor(
73
+ None,
74
+ auth.get_user,
75
+ user_uid
76
+ )
77
+ return user_record
78
+ except auth.UserNotFoundError:
79
+ return None
80
+ except Exception as e:
81
+ self.logger.error(f"Failed to get Firebase Auth user {user_uid}: {e}", exc_info=True)
82
+ raise UserAuthError(
83
+ detail=f"Failed to get Firebase Auth user: {str(e)}",
84
+ user_uid=user_uid,
85
+ operation="get_userauth",
86
+ original_error=e
87
+ )
88
+
89
+ async def get_userauth_by_email(self, email: str) -> Optional[auth.UserRecord]:
90
+ """Get Firebase Auth user by email"""
91
+ try:
92
+ loop = asyncio.get_event_loop()
93
+ user_record = await loop.run_in_executor(
94
+ None,
95
+ auth.get_user_by_email,
96
+ email
97
+ )
98
+ return user_record
99
+ except auth.UserNotFoundError:
100
+ return None
101
+ except Exception as e:
102
+ self.logger.error(f"Failed to get Firebase Auth user by email {email}: {e}", exc_info=True)
103
+ raise UserAuthError(
104
+ detail=f"Failed to get Firebase Auth user by email: {str(e)}",
105
+ operation="get_userauth_by_email",
106
+ additional_info={"email": email},
107
+ original_error=e
108
+ )
109
+
110
+ async def update_userauth(
111
+ self,
112
+ user_uid: str,
113
+ email: Optional[str] = None,
114
+ password: Optional[str] = None,
115
+ display_name: Optional[str] = None,
116
+ phone_number: Optional[str] = None,
117
+ email_verified: Optional[bool] = None,
118
+ disabled: Optional[bool] = None
119
+ ) -> auth.UserRecord:
120
+ """Update Firebase Auth user"""
121
+ try:
122
+ loop = asyncio.get_event_loop()
123
+ user_record = await loop.run_in_executor(
124
+ None,
125
+ lambda: auth.update_user(
126
+ uid=user_uid,
127
+ email=email,
128
+ password=password,
129
+ display_name=display_name,
130
+ phone_number=phone_number,
131
+ email_verified=email_verified,
132
+ disabled=disabled
133
+ )
134
+ )
135
+
136
+ self.logger.info(f"Successfully updated Firebase Auth user: {user_uid}")
137
+ return user_record
138
+
139
+ except auth.UserNotFoundError:
140
+ raise UserAuthError(
141
+ detail=f"Firebase Auth user not found",
142
+ user_uid=user_uid,
143
+ operation="update_userauth"
144
+ )
145
+ except Exception as e:
146
+ self.logger.error(f"Failed to update Firebase Auth user {user_uid}: {e}", exc_info=True)
147
+ raise UserAuthError(
148
+ detail=f"Failed to update Firebase Auth user: {str(e)}",
149
+ user_uid=user_uid,
150
+ operation="update_userauth",
151
+ original_error=e
152
+ )
153
+
154
+ # Firebase Auth Custom Claims
155
+
156
+ def generate_firebase_custom_claims(
157
+ self,
158
+ primary_usertype: str,
159
+ secondary_usertypes: Optional[List[str]] = None,
160
+ organizations_uids: Optional[List[str]] = None,
161
+ user_approval_status: str = "pending"
162
+ ) -> Dict[str, Any]:
163
+ """Generate Firebase custom claims with minimal required fields"""
164
+ try:
165
+ claims = {
166
+ "primary_usertype": primary_usertype,
167
+ "secondary_usertypes": secondary_usertypes or [],
168
+ "organizations_uids": organizations_uids or [],
169
+ "user_approval_status": user_approval_status,
170
+ }
171
+ self.logger.info(f"Generated Firebase custom claims for usertype {primary_usertype}")
172
+ return claims
173
+ except Exception as e:
174
+ self.logger.error(f"Error generating Firebase custom claims: {e}", exc_info=True)
175
+ raise UserAuthError(
176
+ detail=f"Failed to generate Firebase custom claims: {str(e)}",
177
+ operation="generate_firebase_custom_claims",
178
+ original_error=e
179
+ )
180
+
181
+ async def set_userauth_custom_claims(
182
+ self,
183
+ user_uid: str,
184
+ custom_claims: Dict[str, Any],
185
+ merge_with_existing: bool = False
186
+ ) -> bool:
187
+ """Set Firebase Auth custom claims for a user with optional merging"""
188
+ try:
189
+ if merge_with_existing:
190
+ # Get existing claims and merge
191
+ user_record = await self.get_userauth(user_uid)
192
+ if user_record and user_record.custom_claims:
193
+ existing_claims = user_record.custom_claims.copy()
194
+ existing_claims.update(custom_claims)
195
+ custom_claims = existing_claims
196
+
197
+ loop = asyncio.get_event_loop()
198
+ await loop.run_in_executor(
199
+ None,
200
+ auth.set_custom_user_claims,
201
+ user_uid,
202
+ custom_claims
203
+ )
204
+
205
+ self.logger.info(f"Successfully set Firebase custom claims for user: {user_uid}")
206
+ return True
207
+
208
+ except auth.UserNotFoundError:
209
+ raise UserAuthError(
210
+ detail=f"Firebase Auth user not found",
211
+ user_uid=user_uid,
212
+ operation="set_userauth_custom_claims"
213
+ )
214
+ except Exception as e:
215
+ self.logger.error(f"Failed to set Firebase custom claims for user {user_uid}: {e}", exc_info=True)
216
+ raise UserAuthError(
217
+ detail=f"Failed to set Firebase custom claims: {str(e)}",
218
+ user_uid=user_uid,
219
+ operation="set_userauth_custom_claims",
220
+ original_error=e
221
+ )
222
+
223
+ async def get_userauth_custom_claims(self, user_uid: str) -> Optional[Dict[str, Any]]:
224
+ """Get Firebase Auth custom claims for a user"""
225
+ try:
226
+ user_record = await self.get_userauth(user_uid)
227
+ return user_record.custom_claims if user_record else None
228
+ except Exception as e:
229
+ self.logger.error(f"Failed to get Firebase custom claims for user {user_uid}: {e}", exc_info=True)
230
+ raise UserAuthError(
231
+ detail=f"Failed to get Firebase custom claims: {str(e)}",
232
+ user_uid=user_uid,
233
+ operation="get_userauth_custom_claims",
234
+ original_error=e
235
+ )
236
+
237
+ # Firebase Auth User Deletion
238
+
239
+ async def delete_userauth(self, user_uid: str) -> bool:
240
+ """Delete Firebase Auth user"""
241
+ try:
242
+ loop = asyncio.get_event_loop()
243
+ await loop.run_in_executor(
244
+ None,
245
+ auth.delete_user,
246
+ user_uid
247
+ )
248
+
249
+ self.logger.info(f"Successfully deleted Firebase Auth user: {user_uid}")
250
+ return True
251
+
252
+ except auth.UserNotFoundError:
253
+ self.logger.warning(f"Firebase Auth user {user_uid} not found during deletion")
254
+ return True # Consider non-existent user as successfully deleted
255
+ except Exception as e:
256
+ self.logger.error(f"Failed to delete Firebase Auth user {user_uid}: {e}", exc_info=True)
257
+ raise UserAuthError(
258
+ detail=f"Failed to delete Firebase Auth user: {str(e)}",
259
+ user_uid=user_uid,
260
+ operation="delete_userauth",
261
+ original_error=e
262
+ )
263
+
264
+ # Utility Methods
265
+
266
+ async def userauth_exists(self, user_uid: str) -> bool:
267
+ """Check if Firebase Auth user exists"""
268
+ user_record = await self.get_userauth(user_uid)
269
+ return user_record is not None
270
+
271
+ async def userauth_exists_by_email(self, email: str) -> bool:
272
+ """Check if Firebase Auth user exists by email"""
273
+ user_record = await self.get_userauth_by_email(email)
274
+ return user_record is not None
275
+
276
+ async def validate_userauth(self, user_uid: str) -> bool:
277
+ """Validate that Firebase Auth user exists and is not disabled"""
278
+ try:
279
+ user_record = await self.get_userauth(user_uid)
280
+ if not user_record:
281
+ return False
282
+ return not user_record.disabled
283
+ except Exception:
284
+ return False
285
+
286
+ async def list_userauth(
287
+ self,
288
+ page_token: Optional[str] = None,
289
+ max_results: int = 1000
290
+ ) -> auth.ListUsersPage:
291
+ """List Firebase Auth users with pagination"""
292
+ try:
293
+ loop = asyncio.get_event_loop()
294
+ page = await loop.run_in_executor(
295
+ None,
296
+ lambda: auth.list_users(page_token=page_token, max_results=max_results)
297
+ )
298
+ return page
299
+ except Exception as e:
300
+ self.logger.error(f"Failed to list Firebase Auth users: {e}", exc_info=True)
301
+ raise UserAuthError(
302
+ detail=f"Failed to list Firebase Auth users: {str(e)}",
303
+ operation="list_userauth",
304
+ original_error=e
305
+ )