ipulse-shared-core-ftredge 23.1.1__tar.gz → 24.2.1__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.
Potentially problematic release.
This version of ipulse-shared-core-ftredge might be problematic. Click here for more details.
- {ipulse_shared_core_ftredge-23.1.1/src/ipulse_shared_core_ftredge.egg-info → ipulse_shared_core_ftredge-24.2.1}/PKG-INFO +2 -2
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/setup.py +2 -2
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/dependencies/auth_firebase_token_validation.py +1 -1
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/models/__init__.py +1 -1
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/models/user/__init__.py +1 -1
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/models/user/user_permissions.py +4 -8
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/models/user/userauth.py +46 -3
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/models/user/userstatus.py +3 -3
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/services/user/user_core_service.py +5 -5
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/services/user/user_multistep_operations.py +7 -7
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/services/user/userauth_operations.py +9 -4
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1/src/ipulse_shared_core_ftredge.egg-info}/PKG-INFO +2 -2
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge.egg-info/requires.txt +1 -1
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/LICENCE +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/README.md +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/pyproject.toml +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/setup.cfg +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/__init__.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/cache/__init__.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/cache/shared_cache.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/dependencies/__init__.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/dependencies/auth_protected_router.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/dependencies/authz_for_apis.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/dependencies/firestore_client.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/exceptions/__init__.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/exceptions/base_exceptions.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/exceptions/user_exceptions.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/models/base_api_response.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/models/base_data_model.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/models/catalog/__init__.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/models/catalog/subscriptionplan.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/models/catalog/usertype.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/models/user/user_subscription.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/models/user/userprofile.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/monitoring/__init__.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/monitoring/tracemon.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/services/__init__.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/services/base/__init__.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/services/base/base_firestore_service.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/services/base/cache_aware_firestore_service.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/services/catalog/__init__.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/services/catalog/catalog_subscriptionplan_service.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/services/catalog/catalog_usertype_service.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/services/charging_processors.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/services/user/__init__.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/services/user/user_permissions_operations.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/services/user/user_subscription_operations.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/services/user/userprofile_operations.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/services/user/userstatus_operations.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/services/user_charging_service.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/utils/__init__.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/utils/custom_json_encoder.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge/utils/json_encoder.py +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge.egg-info/SOURCES.txt +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge.egg-info/dependency_links.txt +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/src/ipulse_shared_core_ftredge.egg-info/top_level.txt +0 -0
- {ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/tests/test_shared_cache.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ipulse_shared_core_ftredge
|
|
3
|
-
Version:
|
|
3
|
+
Version: 24.2.1
|
|
4
4
|
Summary: Shared Core models and Logger util for the Pulse platform project. Using AI for financial advisory and investment management.
|
|
5
5
|
Home-page: https://github.com/TheFutureEdge/ipulse_shared_core
|
|
6
6
|
Author: Russlan Ramdowar
|
|
@@ -12,7 +12,7 @@ License-File: LICENCE
|
|
|
12
12
|
Requires-Dist: pydantic[email]~=2.5
|
|
13
13
|
Requires-Dist: python-dateutil~=2.8
|
|
14
14
|
Requires-Dist: fastapi~=0.115.8
|
|
15
|
-
Requires-Dist: ipulse_shared_base_ftredge==
|
|
15
|
+
Requires-Dist: ipulse_shared_base_ftredge==11.1.1
|
|
16
16
|
Dynamic: author
|
|
17
17
|
Dynamic: classifier
|
|
18
18
|
Dynamic: home-page
|
|
@@ -3,7 +3,7 @@ from setuptools import setup, find_packages
|
|
|
3
3
|
|
|
4
4
|
setup(
|
|
5
5
|
name='ipulse_shared_core_ftredge',
|
|
6
|
-
version='
|
|
6
|
+
version='24.2.1',
|
|
7
7
|
package_dir={'': 'src'}, # Specify the source directory
|
|
8
8
|
packages=find_packages(where='src'), # Look for packages in 'src'
|
|
9
9
|
install_requires=[
|
|
@@ -11,7 +11,7 @@ setup(
|
|
|
11
11
|
'pydantic[email]~=2.5',
|
|
12
12
|
'python-dateutil~=2.8',
|
|
13
13
|
'fastapi~=0.115.8',
|
|
14
|
-
'ipulse_shared_base_ftredge==
|
|
14
|
+
'ipulse_shared_base_ftredge==11.1.1',
|
|
15
15
|
],
|
|
16
16
|
author='Russlan Ramdowar',
|
|
17
17
|
description='Shared Core models and Logger util for the Pulse platform project. Using AI for financial advisory and investment management.',
|
|
@@ -72,7 +72,7 @@ async def verify_firebase_token(
|
|
|
72
72
|
email=email,
|
|
73
73
|
password=None, # No password for token-based auth
|
|
74
74
|
display_name=decoded_token.get('name'),
|
|
75
|
-
|
|
75
|
+
user_uid=decoded_token.get('uid'),
|
|
76
76
|
email_verified=decoded_token.get('email_verified', False),
|
|
77
77
|
custom_claims=decoded_token.get('custom_claims', {}),
|
|
78
78
|
phone_number=decoded_token.get('phone_number'),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
from .base_data_model import BaseDataModel
|
|
2
2
|
from .base_api_response import BaseAPIResponse , CustomJSONResponse, CreditChargeableAPIResponse, UserCreditBalance, UpdatedUserCreditInfo
|
|
3
|
-
from .user import UserProfile, UserSubscription, UserStatus, UserAuth, UserPermission
|
|
3
|
+
from .user import UserProfile, UserSubscription, UserStatus, UserAuth, UserAuthCreateNew, UserPermission
|
|
4
4
|
from .catalog import SubscriptionPlan, ProrationMethod, PlanUpgradePath, UserType
|
|
@@ -28,9 +28,9 @@ class UserPermission(BaseModel):
|
|
|
28
28
|
...,
|
|
29
29
|
description="Source of this assignment (e.g., subscription plan ID, 'manual_grant')"
|
|
30
30
|
)
|
|
31
|
-
expires_at:
|
|
32
|
-
|
|
33
|
-
description="When this assignment expires (
|
|
31
|
+
expires_at: datetime = Field(
|
|
32
|
+
...,
|
|
33
|
+
description="When this assignment expires (mandatory - no permanent permissions)"
|
|
34
34
|
)
|
|
35
35
|
granted_at: datetime = Field(
|
|
36
36
|
default_factory=lambda: datetime.now(timezone.utc),
|
|
@@ -47,9 +47,6 @@ class UserPermission(BaseModel):
|
|
|
47
47
|
|
|
48
48
|
def is_valid(self) -> bool:
|
|
49
49
|
"""Check if the permission is currently valid (not expired)."""
|
|
50
|
-
if self.expires_at is None:
|
|
51
|
-
return True
|
|
52
|
-
|
|
53
50
|
# Ensure both datetimes are timezone-aware for comparison
|
|
54
51
|
current_time = datetime.now(timezone.utc)
|
|
55
52
|
expires_time = self.expires_at
|
|
@@ -62,5 +59,4 @@ class UserPermission(BaseModel):
|
|
|
62
59
|
|
|
63
60
|
def __str__(self) -> str:
|
|
64
61
|
"""Human-readable representation of the permission."""
|
|
65
|
-
|
|
66
|
-
return f"{self.domain}/{self.iam_unit_type}/{self.permission_ref} from {self.source}{expiry}"
|
|
62
|
+
return f"{self.domain}/{self.iam_unit_type}/{self.permission_ref} from {self.source} (expires: {self.expires_at})"
|
|
@@ -2,17 +2,60 @@ from typing import Optional, Dict, Any, List
|
|
|
2
2
|
from datetime import datetime
|
|
3
3
|
from pydantic import BaseModel, Field, EmailStr, ConfigDict, field_validator, model_validator
|
|
4
4
|
|
|
5
|
+
class UserAuthCreateNew(BaseModel):
|
|
6
|
+
"""Model for creating new Firebase Auth users - does not include user_uid"""
|
|
7
|
+
model_config = ConfigDict(extra="forbid")
|
|
8
|
+
|
|
9
|
+
# Core authentication fields for new user creation
|
|
10
|
+
email: EmailStr = Field(..., description="User's email address")
|
|
11
|
+
password: str = Field(..., min_length=6, description="User's password (min 6 characters)")
|
|
12
|
+
display_name: Optional[str] = Field(None, description="User's display name")
|
|
13
|
+
phone_number: Optional[str] = Field(None, description="Phone number in E.164 format (e.g. +1234567890)")
|
|
14
|
+
email_verified: bool = Field(default=False, description="Whether the email is already verified")
|
|
15
|
+
disabled: bool = Field(default=False, description="Whether the user should be disabled on creation")
|
|
16
|
+
|
|
17
|
+
# Custom claims for new user
|
|
18
|
+
custom_claims: Dict[str, Any] = Field(default_factory=dict, description="Firebase custom claims")
|
|
19
|
+
|
|
20
|
+
@field_validator('phone_number')
|
|
21
|
+
@classmethod
|
|
22
|
+
def validate_phone_number(cls, v: Optional[str]) -> Optional[str]:
|
|
23
|
+
"""Validate phone number format if provided"""
|
|
24
|
+
if v is None:
|
|
25
|
+
return v
|
|
26
|
+
# Basic E.164 format validation
|
|
27
|
+
if not v.startswith('+') or not v[1:].isdigit() or len(v) < 8 or len(v) > 16:
|
|
28
|
+
raise ValueError('Phone number must be in E.164 format (+1234567890)')
|
|
29
|
+
return v
|
|
30
|
+
|
|
31
|
+
@field_validator('custom_claims')
|
|
32
|
+
@classmethod
|
|
33
|
+
def validate_custom_claims(cls, v: Dict[str, Any]) -> Dict[str, Any]:
|
|
34
|
+
"""Validate custom claims don't contain reserved Firebase claims"""
|
|
35
|
+
reserved_claims = {
|
|
36
|
+
'iss', 'aud', 'auth_time', 'user_id', 'sub', 'iat', 'exp', 'email',
|
|
37
|
+
'email_verified', 'phone_number', 'name', 'picture', 'firebase'
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
for claim in v.keys():
|
|
41
|
+
if claim in reserved_claims:
|
|
42
|
+
raise ValueError(f'Custom claim "{claim}" is reserved by Firebase')
|
|
43
|
+
|
|
44
|
+
return v
|
|
45
|
+
|
|
5
46
|
class UserAuth(BaseModel):
|
|
6
|
-
"""Comprehensive authentication model for user credentials and auth operations"""
|
|
47
|
+
"""Comprehensive authentication model for existing user credentials and auth operations"""
|
|
7
48
|
model_config = ConfigDict(extra="forbid")
|
|
8
49
|
|
|
50
|
+
# Firebase UID - required for existing users (generated by Firebase when user was created)
|
|
51
|
+
user_uid: str = Field(..., description="Firebase Auth UID - required for existing users")
|
|
52
|
+
|
|
9
53
|
# Core authentication fields
|
|
10
54
|
email: EmailStr = Field(..., description="User's email address")
|
|
11
55
|
display_name: Optional[str] = Field(None, description="User's display name")
|
|
12
|
-
password: Optional[str] = Field(None, min_length=6, description="User's password (for
|
|
56
|
+
password: Optional[str] = Field(None, min_length=6, description="User's password (for updates only)")
|
|
13
57
|
|
|
14
58
|
# Firebase Auth specific fields
|
|
15
|
-
firebase_uid: Optional[str] = Field(default=None, description="Firebase Auth UID")
|
|
16
59
|
provider_id: str = Field(default="password", description="Authentication provider ID")
|
|
17
60
|
email_verified: bool = Field(default=False, description="Whether email is verified")
|
|
18
61
|
disabled: bool = Field(default=False, description="Whether user account is disabled")
|
|
@@ -187,7 +187,7 @@ class UserStatus(BaseDataModel):
|
|
|
187
187
|
iam_unit_type: IAMUnit,
|
|
188
188
|
permission_ref: str,
|
|
189
189
|
source: str,
|
|
190
|
-
expires_at:
|
|
190
|
+
expires_at: datetime,
|
|
191
191
|
granted_by: Optional[str] = None,
|
|
192
192
|
metadata: Optional[Dict[str, Any]] = None
|
|
193
193
|
) -> None:
|
|
@@ -199,7 +199,7 @@ class UserStatus(BaseDataModel):
|
|
|
199
199
|
iam_unit_type: Type of IAM assignment (GROUP, ROLE, etc.)
|
|
200
200
|
permission_ref: The name/identifier of the permission to add
|
|
201
201
|
source: Source identifier for this assignment (e.g., subscription ID)
|
|
202
|
-
expires_at:
|
|
202
|
+
expires_at: Expiration date (mandatory - no permanent permissions)
|
|
203
203
|
granted_by: Who granted this permission
|
|
204
204
|
metadata: Optional metadata for the assignment
|
|
205
205
|
"""
|
|
@@ -329,7 +329,7 @@ class UserStatus(BaseDataModel):
|
|
|
329
329
|
iam_unit_type=permission.iam_unit_type,
|
|
330
330
|
permission_ref=permission.permission_ref,
|
|
331
331
|
source=source,
|
|
332
|
-
expires_at=subscription.
|
|
332
|
+
expires_at=subscription.cycle_end_datetime_safe,
|
|
333
333
|
granted_by=granted_by
|
|
334
334
|
)
|
|
335
335
|
added_count += 1
|
|
@@ -18,7 +18,7 @@ from datetime import datetime
|
|
|
18
18
|
from google.cloud import firestore
|
|
19
19
|
from firebase_admin.auth import UserRecord
|
|
20
20
|
from ipulse_shared_base_ftredge import ApprovalStatus, IAMUnit, IAMUserType
|
|
21
|
-
from ...models import UserProfile, UserStatus, UserAuth, UserSubscription, UserType, SubscriptionPlan, UserPermission
|
|
21
|
+
from ...models import UserProfile, UserStatus, UserAuth, UserAuthCreateNew, UserSubscription, UserType, SubscriptionPlan, UserPermission
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
# Import specialized operation classes
|
|
@@ -132,7 +132,7 @@ class UserCoreService:
|
|
|
132
132
|
self,
|
|
133
133
|
userprofile: UserProfile,
|
|
134
134
|
userstatus: UserStatus,
|
|
135
|
-
userauth: Optional[
|
|
135
|
+
userauth: Optional[UserAuthCreateNew] = None,
|
|
136
136
|
validate_userauth_consistency: bool = False,
|
|
137
137
|
validate_userauth_exists: bool = False
|
|
138
138
|
) -> Tuple[str, UserProfile, UserStatus]:
|
|
@@ -153,7 +153,7 @@ class UserCoreService:
|
|
|
153
153
|
self,
|
|
154
154
|
userprofile: UserProfile,
|
|
155
155
|
usertype: UserType,
|
|
156
|
-
userauth: Optional[
|
|
156
|
+
userauth: Optional[UserAuthCreateNew] = None,
|
|
157
157
|
extra_insight_credits_override: Optional[int] = None,
|
|
158
158
|
voting_credits_override: Optional[int] = None,
|
|
159
159
|
subscriptionplan_id_override: Optional[str] = None,
|
|
@@ -184,7 +184,7 @@ class UserCoreService:
|
|
|
184
184
|
self,
|
|
185
185
|
usertype_id: str,
|
|
186
186
|
userprofile: UserProfile,
|
|
187
|
-
userauth: Optional[
|
|
187
|
+
userauth: Optional[UserAuthCreateNew] = None,
|
|
188
188
|
extra_insight_credits_override: Optional[int] = None,
|
|
189
189
|
voting_credits_override: Optional[int] = None,
|
|
190
190
|
subscriptionplan_id_override: Optional[str] = None,
|
|
@@ -294,7 +294,7 @@ class UserCoreService:
|
|
|
294
294
|
######################### UserAuth Operations ########################
|
|
295
295
|
######################################################################
|
|
296
296
|
|
|
297
|
-
async def create_userauth(self, userauth:
|
|
297
|
+
async def create_userauth(self, userauth: UserAuthCreateNew) -> str:
|
|
298
298
|
"""Create a Firebase Auth user"""
|
|
299
299
|
return await self.userauth_ops.create_userauth(user_auth=userauth)
|
|
300
300
|
|
|
@@ -8,7 +8,7 @@ import asyncio
|
|
|
8
8
|
import logging
|
|
9
9
|
from typing import Dict, Any, Optional, List, Tuple, cast
|
|
10
10
|
from ipulse_shared_base_ftredge.enums import IAMUserType
|
|
11
|
-
from ...models import UserProfile, UserStatus, UserAuth, UserType
|
|
11
|
+
from ...models import UserProfile, UserStatus, UserAuth, UserAuthCreateNew, UserType
|
|
12
12
|
from .userauth_operations import UserauthOperations
|
|
13
13
|
from .userprofile_operations import UserprofileOperations
|
|
14
14
|
from .userstatus_operations import UserstatusOperations
|
|
@@ -130,12 +130,12 @@ class UsermultistepOperations:
|
|
|
130
130
|
self,
|
|
131
131
|
userprofile: UserProfile,
|
|
132
132
|
userstatus: UserStatus,
|
|
133
|
-
userauth: Optional[
|
|
133
|
+
userauth: Optional[UserAuthCreateNew] = None,
|
|
134
134
|
validate_userauth_consistency: bool = False,
|
|
135
135
|
validate_userauth_exists: bool = False
|
|
136
136
|
) -> Tuple[str, UserProfile, UserStatus]:
|
|
137
137
|
"""
|
|
138
|
-
Create a complete user from ready
|
|
138
|
+
Create a complete user from ready UserAuthCreateNew, UserProfile, and UserStatus models.
|
|
139
139
|
|
|
140
140
|
This method efficiently commits pre-configured models to database.
|
|
141
141
|
|
|
@@ -151,7 +151,7 @@ class UsermultistepOperations:
|
|
|
151
151
|
Args:
|
|
152
152
|
userprofile: Complete UserProfile model (template for new user, or ready for existing user)
|
|
153
153
|
userstatus: Complete UserStatus model (template for new user, or ready for existing user)
|
|
154
|
-
userauth: Optional
|
|
154
|
+
userauth: Optional UserAuthCreateNew model. If provided, creates new Firebase Auth user
|
|
155
155
|
validate_userauth_consistency: If True, validates userauth is consistent with userprofile
|
|
156
156
|
validate_userauth_exists: If True, validates userauth exists in Firebase Auth
|
|
157
157
|
|
|
@@ -242,7 +242,7 @@ class UsermultistepOperations:
|
|
|
242
242
|
self,
|
|
243
243
|
userprofile: UserProfile,
|
|
244
244
|
usertype: UserType,
|
|
245
|
-
userauth: Optional[
|
|
245
|
+
userauth: Optional[UserAuthCreateNew] = None,
|
|
246
246
|
extra_insight_credits_override: Optional[int] = None,
|
|
247
247
|
voting_credits_override: Optional[int] = None,
|
|
248
248
|
subscriptionplan_id_override: Optional[str] = None,
|
|
@@ -344,7 +344,7 @@ class UsermultistepOperations:
|
|
|
344
344
|
self,
|
|
345
345
|
usertype_id: str,
|
|
346
346
|
userprofile: UserProfile,
|
|
347
|
-
userauth: Optional[
|
|
347
|
+
userauth: Optional[UserAuthCreateNew] = None,
|
|
348
348
|
extra_insight_credits_override: Optional[int] = None,
|
|
349
349
|
voting_credits_override: Optional[int] = None,
|
|
350
350
|
subscriptionplan_id_override: Optional[str] = None,
|
|
@@ -647,7 +647,7 @@ class UsermultistepOperations:
|
|
|
647
647
|
validation_results["validation_errors"].append("User email is not verified")
|
|
648
648
|
|
|
649
649
|
# 3. UID consistency validation
|
|
650
|
-
auth_uid = getattr(userauth_record, 'uid', None) or getattr(userauth_record, '
|
|
650
|
+
auth_uid = getattr(userauth_record, 'uid', None) or getattr(userauth_record, 'user_uid', None)
|
|
651
651
|
uids_consistent = (
|
|
652
652
|
auth_uid == user_uid and
|
|
653
653
|
userprofile.user_uid == user_uid and
|
|
@@ -9,7 +9,7 @@ from typing import Dict, Any, Optional, Union
|
|
|
9
9
|
from firebase_admin import auth
|
|
10
10
|
from google.cloud import firestore
|
|
11
11
|
from ipulse_shared_base_ftredge.enums import ApprovalStatus
|
|
12
|
-
from ...models import UserAuth
|
|
12
|
+
from ...models import UserAuth, UserAuthCreateNew
|
|
13
13
|
from ...exceptions import UserAuthError
|
|
14
14
|
from ..base import BaseFirestoreService
|
|
15
15
|
|
|
@@ -48,9 +48,14 @@ class UserauthOperations:
|
|
|
48
48
|
|
|
49
49
|
async def create_userauth(
|
|
50
50
|
self,
|
|
51
|
-
user_auth:
|
|
51
|
+
user_auth: UserAuthCreateNew
|
|
52
52
|
) -> str:
|
|
53
|
-
"""
|
|
53
|
+
"""
|
|
54
|
+
Creates a new Firebase Auth user and returns the UID.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
user_auth: UserAuthCreateNew model for new user creation
|
|
58
|
+
"""
|
|
54
59
|
self.logger.info(f"Creating Firebase Auth user for email: {user_auth.email}")
|
|
55
60
|
try:
|
|
56
61
|
# Create user synchronously
|
|
@@ -191,7 +196,7 @@ class UserauthOperations:
|
|
|
191
196
|
userauth_data = {
|
|
192
197
|
"email": user_record.email,
|
|
193
198
|
"display_name": user_record.display_name,
|
|
194
|
-
"
|
|
199
|
+
"user_uid": user_record.uid,
|
|
195
200
|
"email_verified": user_record.email_verified,
|
|
196
201
|
"disabled": user_record.disabled,
|
|
197
202
|
"phone_number": user_record.phone_number,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ipulse_shared_core_ftredge
|
|
3
|
-
Version:
|
|
3
|
+
Version: 24.2.1
|
|
4
4
|
Summary: Shared Core models and Logger util for the Pulse platform project. Using AI for financial advisory and investment management.
|
|
5
5
|
Home-page: https://github.com/TheFutureEdge/ipulse_shared_core
|
|
6
6
|
Author: Russlan Ramdowar
|
|
@@ -12,7 +12,7 @@ License-File: LICENCE
|
|
|
12
12
|
Requires-Dist: pydantic[email]~=2.5
|
|
13
13
|
Requires-Dist: python-dateutil~=2.8
|
|
14
14
|
Requires-Dist: fastapi~=0.115.8
|
|
15
|
-
Requires-Dist: ipulse_shared_base_ftredge==
|
|
15
|
+
Requires-Dist: ipulse_shared_base_ftredge==11.1.1
|
|
16
16
|
Dynamic: author
|
|
17
17
|
Dynamic: classifier
|
|
18
18
|
Dynamic: home-page
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ipulse_shared_core_ftredge-23.1.1 → ipulse_shared_core_ftredge-24.2.1}/tests/test_shared_cache.py
RENAMED
|
File without changes
|