|
from app.schema.response_schema import ResponseSchema
|
|
from app.schema.user_schema import CheckFirstTimeUserSchema
|
|
from app.schema.change_password import PasswordSchema
|
|
from sqlalchemy.exc import SQLAlchemyError
|
|
from sqlalchemy import text
|
|
from app.models.user import User
|
|
from app.models.user_profile import UserProfile
|
|
from app.models.application import Application
|
|
from fastapi import HTTPException, status
|
|
from fastapi.responses import RedirectResponse
|
|
from app.models.onBoarding_profile import OnBoardingProfile
|
|
from app.services.helper.user_service_helper import get_password_hash
|
|
from app.config.env import env
|
|
from app.schema.personal_info import PersonalInfoSchema
|
|
from app.schema.user_schema import Roles
|
|
from app.utils.auth0 import get_access_token
|
|
from sqlalchemy.orm import Session
|
|
import httpx
|
|
from app.utils.communication_service_internal.send_email import send_email
|
|
from app.enums.email_template_enum import EmailTemplateEnum
|
|
from app.enums.role_enum import RoleEnum
|
|
|
|
|
|
class UserService:
|
|
async def get_user_detail(id, db):
|
|
"""
|
|
Retrieves details of a specific user by user ID.
|
|
|
|
Parameters:
|
|
- id: ID of the user to retrieve details for
|
|
- db: SQLAlchemy database session
|
|
|
|
Returns:
|
|
- ResponseSchema: Response object containing user details
|
|
"""
|
|
try:
|
|
user = db.query(User).filter_by(userId=id, isActive="1").first()
|
|
if user:
|
|
|
|
user_data = dict(user.__dict__)
|
|
|
|
user_data.pop("_sa_instance_state", None)
|
|
user_data.pop("password", None)
|
|
return ResponseSchema(
|
|
status=200,
|
|
message="User details fetched successfully!",
|
|
success=True,
|
|
data={"user": user_data},
|
|
)
|
|
else:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="User does not exist!",
|
|
)
|
|
except SQLAlchemyError as e:
|
|
db.rollback()
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST, detail=e.args[0]
|
|
)
|
|
|
|
async def get_loan_officer_details(db: Session, user: any):
|
|
"""
|
|
Retrieves details of loan officer of loggedin user
|
|
|
|
Parameters:
|
|
- db: SQLAlchemy database session
|
|
- user: contains all the info available in token
|
|
|
|
Returns:
|
|
- ResponseSchema: Response object containing loan officer details
|
|
"""
|
|
try:
|
|
user_detail = db.query(User).filter(User.userId == user["user_id"]).first()
|
|
|
|
if not user_detail:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="User details not found",
|
|
)
|
|
|
|
if user_detail.role == RoleEnum.LOAN_OFFICER.value:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Details cannot be provided for a loan officer",
|
|
)
|
|
|
|
if not user_detail.lenderId:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Loan officer details not found",
|
|
)
|
|
|
|
loan_officer = (
|
|
db.query(User).filter(User.userId == user_detail.lenderId).first()
|
|
)
|
|
loan_officer = loan_officer.dict()
|
|
|
|
loan_officer_details = {
|
|
"first_name": loan_officer.get("firstName", None),
|
|
"last_name": loan_officer.get("lastName", None),
|
|
"nmls_id": loan_officer.get("NMLS", None),
|
|
"organization": None,
|
|
"email": loan_officer.get("email", None),
|
|
"mobile": loan_officer.get("phoneNumber", None),
|
|
}
|
|
|
|
return ResponseSchema(
|
|
status=200,
|
|
message="Loan officer details fetched successfully!",
|
|
success=True,
|
|
data=loan_officer_details,
|
|
)
|
|
|
|
except SQLAlchemyError as e:
|
|
db.rollback()
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST, detail=e.args[0]
|
|
)
|
|
|
|
async def get_all_users(limit, offset, db):
|
|
"""
|
|
Retrieves users from the database with pagination.
|
|
|
|
Parameters:
|
|
- limit: Maximum number of users to retrieve
|
|
- offset: Number of users to skip from the beginning
|
|
- db: SQLAlchemy database session
|
|
|
|
Returns:
|
|
- ResponseSchema: Response object containing user data
|
|
"""
|
|
try:
|
|
|
|
users = (
|
|
db.query(User).filter_by(isActive="1").offset(offset).limit(limit).all()
|
|
)
|
|
users_data = []
|
|
for user in users:
|
|
user_data = dict(user.__dict__)
|
|
user_data.pop("_sa_instance_state", None)
|
|
user_data.pop("password", None)
|
|
users_data.append(user_data)
|
|
|
|
return ResponseSchema(
|
|
status=200,
|
|
message="Users fetched successfully!",
|
|
success=True,
|
|
data={"users": users_data},
|
|
)
|
|
except SQLAlchemyError as e:
|
|
db.rollback()
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST, detail=e.args[0]
|
|
)
|
|
|
|
async def get_loan_officers(db):
|
|
"""
|
|
Retrieves loan officers from the database.
|
|
|
|
Parameters:
|
|
- db: SQLAlchemy database session
|
|
|
|
Returns:
|
|
- ResponseSchema: Response object containing loan officer data
|
|
"""
|
|
try:
|
|
users = db.query(User).where(
|
|
User.NMLS != None, User.NMLS != "", User.isActive == "1"
|
|
)
|
|
users_data = []
|
|
for user in users:
|
|
user_data = dict(user.__dict__)
|
|
user_data.pop("_sa_instance_state", None)
|
|
user_data.pop("password", None)
|
|
users_data.append(user_data)
|
|
|
|
return ResponseSchema(
|
|
status=200,
|
|
message="Loan Officers fetched successfully!",
|
|
success=True,
|
|
data={"users": users_data},
|
|
)
|
|
except SQLAlchemyError as e:
|
|
db.rollback()
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST, detail=e.args[0]
|
|
)
|
|
|
|
async def is_first_time_user(user: CheckFirstTimeUserSchema, db):
|
|
"""
|
|
Checks if the user is a first-time user based on provided user data.
|
|
|
|
Parameters:
|
|
- user: CheckFirstTimeUserSchema object containing user information
|
|
- db: SQLAlchemy database session
|
|
|
|
Returns:
|
|
- ResponseSchema: Response object indicating whether the user is a first-time user
|
|
"""
|
|
try:
|
|
|
|
if len(user.user_id) >= 10:
|
|
user_data = (
|
|
db.query(User)
|
|
.filter(User.googleOauthId == user.user_id, User.isActive == "1")
|
|
.first()
|
|
)
|
|
else:
|
|
user_data = (
|
|
db.query(User)
|
|
.filter(User.userId == user.user_id, User.isActive == "1")
|
|
.first()
|
|
)
|
|
|
|
|
|
if user_data:
|
|
user_data = user_data.dict()
|
|
user_id = user_data["userId"]
|
|
user_profile_data = (
|
|
db.query(UserProfile).where(UserProfile.userId == user_id).first()
|
|
)
|
|
|
|
|
|
pending_application_id = (
|
|
db.query(Application)
|
|
.where(Application.applicationStatusId == 1)
|
|
.where(Application.userId == user_id)
|
|
.first()
|
|
)
|
|
|
|
return ResponseSchema(
|
|
status=status.HTTP_200_OK,
|
|
message="User exists",
|
|
success=True,
|
|
data={
|
|
"new_user": 0,
|
|
"user_profile_exists": (
|
|
1 if user_profile_data is not None else 0
|
|
),
|
|
"pending_application_id": (
|
|
pending_application_id.dict()["applicationId"]
|
|
if pending_application_id is not None
|
|
else 0
|
|
),
|
|
"user_id": user_id,
|
|
"first_name": (
|
|
user_data["firstName"] if user_data["firstName"] else None
|
|
),
|
|
"last_name": (
|
|
user_data["lastName"] if user_data["lastName"] else None
|
|
),
|
|
"is_verified": user_data["isVerified"],
|
|
},
|
|
)
|
|
else:
|
|
user = User(
|
|
firstName=user.first_name,
|
|
lastName=user.last_name,
|
|
email=user.email,
|
|
googleOauthId=user.user_id,
|
|
)
|
|
db.add(user)
|
|
db.commit()
|
|
user = user.dict()
|
|
user_id = user["userId"]
|
|
|
|
return ResponseSchema(
|
|
status=status.HTTP_200_OK,
|
|
message="User dosent exist",
|
|
success=True,
|
|
data={
|
|
"new_user": 1,
|
|
"user_profile_exists": 0,
|
|
"pending_application_id": 0,
|
|
"user_id": user_id,
|
|
},
|
|
)
|
|
|
|
except SQLAlchemyError as e:
|
|
db.rollback()
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST, detail=e.args[0]
|
|
)
|
|
|
|
async def get_user_profiles(user_id, db):
|
|
"""
|
|
Retrieves user profiles associated with a given user ID.
|
|
|
|
Parameters:
|
|
- user_id: ID of the user whose profiles are to be retrieved
|
|
- db: SQLAlchemy database session
|
|
|
|
Returns:
|
|
- ResponseSchema: Response object containing user profile data
|
|
"""
|
|
try:
|
|
|
|
all_user_profiles = db.query(UserProfile).where(
|
|
UserProfile.userId == user_id
|
|
)
|
|
users_data = []
|
|
|
|
for user in all_user_profiles:
|
|
user_data = dict(user.__dict__)
|
|
user_data.pop("_sa_instance_state", None)
|
|
users_data.append(user_data)
|
|
|
|
return ResponseSchema(
|
|
status=200,
|
|
message="User Profiles fetched successfully!",
|
|
success=True,
|
|
data={"user_profiles": users_data},
|
|
)
|
|
except SQLAlchemyError as e:
|
|
db.rollback()
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST, detail=e.args[0]
|
|
)
|
|
|
|
async def create_onboarding_profiles(db, onboarding_profile_details, user):
|
|
"""
|
|
Creates a new onboarding profile for a user.
|
|
|
|
Parameters:
|
|
- db: SQLAlchemy database session
|
|
- onboarding_profile_details: Onboarding profile details
|
|
- user: Dictionary containing user information
|
|
|
|
Returns:
|
|
- ResponseSchema: Response object containing the newly created onboarding profile data
|
|
"""
|
|
try:
|
|
item_dict = onboarding_profile_details.model_dump()
|
|
item_dict["userId"] = user["user_id"]
|
|
item_dict["isWorkingWithAnyLoanOfficer"] = str(
|
|
int(onboarding_profile_details.isWorkingWithAnyLoanOfficer)
|
|
)
|
|
new_item = OnBoardingProfile(**item_dict)
|
|
db.add(new_item)
|
|
db.commit()
|
|
return ResponseSchema(
|
|
status=200,
|
|
message="Onboarding data created successfully!",
|
|
success=True,
|
|
data=new_item.dict(),
|
|
)
|
|
except SQLAlchemyError as e:
|
|
db.rollback()
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST, detail=e.args[0]
|
|
)
|
|
|
|
async def update_onboarding_profiles(db, update_fields, user):
|
|
"""
|
|
Updates onboarding profile data for a user.
|
|
|
|
Parameters:
|
|
- db: SQLAlchemy database session
|
|
- update_fields: Dictionary containing fields to be updated
|
|
- user: Dictionary containing user information
|
|
|
|
Returns:
|
|
- ResponseSchema: Response object containing updated onboarding profile data
|
|
"""
|
|
try:
|
|
|
|
data = db.query(OnBoardingProfile).filter_by(userId=user["user_id"]).first()
|
|
|
|
|
|
if not data:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Onboarding data not found",
|
|
)
|
|
|
|
|
|
data_dict = update_fields.dict(exclude_unset=True)
|
|
|
|
|
|
if "lenderId" in data_dict:
|
|
user_instance = (
|
|
db.query(User)
|
|
.filter_by(userId=user["user_id"], isActive="1")
|
|
.first()
|
|
)
|
|
setattr(user_instance, "lenderId", data_dict["lenderId"])
|
|
db.commit()
|
|
|
|
|
|
if "address" in data_dict:
|
|
user_instance = (
|
|
db.query(User)
|
|
.filter_by(userId=user["user_id"], isActive="1")
|
|
.first()
|
|
)
|
|
setattr(user_instance, "address", data_dict["address"])
|
|
db.commit()
|
|
|
|
for field, value in data_dict.items():
|
|
if isinstance(value, bool):
|
|
value = str(int(value))
|
|
|
|
setattr(data, field, value)
|
|
|
|
db.add(data)
|
|
db.commit()
|
|
|
|
return ResponseSchema(
|
|
status=200,
|
|
message="Onboarding data updated successfully!",
|
|
success=True,
|
|
data=data.dict(),
|
|
)
|
|
|
|
except SQLAlchemyError as e:
|
|
db.rollback()
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
|
|
|
async def get_onboarding_profiles(db, user):
|
|
"""
|
|
Retrieves onboarding profile data for a user.
|
|
|
|
Parameters:
|
|
- db: SQLAlchemy database session
|
|
- user: Dictionary containing user information
|
|
|
|
Returns:
|
|
- ResponseSchema: Response object containing onboarding profile data
|
|
"""
|
|
try:
|
|
data = (
|
|
db.query(OnBoardingProfile)
|
|
.filter_by(userId=user.get("user_id", 0))
|
|
.first()
|
|
)
|
|
|
|
if not data:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Onboarding profile data not found",
|
|
)
|
|
|
|
return ResponseSchema(
|
|
status=200,
|
|
message="Onboarding data fetched successfully!",
|
|
success=True,
|
|
data=data.dict(),
|
|
)
|
|
|
|
except SQLAlchemyError as e:
|
|
db.rollback()
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
|
|
|
async def delete_applications(db, user_id):
|
|
"""
|
|
Deletes all application-related data for a user.
|
|
|
|
Parameters:
|
|
- db: SQLAlchemy database session
|
|
- user: Dictionary containing user information with 'user_id' key
|
|
|
|
Returns:
|
|
- ResponseSchema: Response object indicating success or failure of the deletion operation
|
|
"""
|
|
try:
|
|
db.execute(
|
|
text(
|
|
f'DELETE FROM "ApplicationPurchaseHomes" WHERE "userId" = {user_id};'
|
|
)
|
|
)
|
|
db.execute(
|
|
text(
|
|
f'DELETE FROM "UserEmploymentAndIncomes" WHERE "userId" = {user_id};'
|
|
)
|
|
)
|
|
db.execute(
|
|
text(f'DELETE FROM "UserDemographics" WHERE "userId" = {user_id};')
|
|
)
|
|
db.execute(
|
|
text(f'DELETE FROM "UserLiabilities" WHERE "userId" = {user_id};')
|
|
)
|
|
db.execute(text(f'DELETE FROM "UserREOs" WHERE "userId" = {user_id};'))
|
|
db.execute(text(f'DELETE FROM "UserAssets" WHERE "userId" = {user_id};'))
|
|
db.execute(
|
|
text(
|
|
f'DELETE FROM "ApplicationDeclarations" WHERE "userId" = {user_id};'
|
|
)
|
|
)
|
|
db.execute(text(f'DELETE FROM "UserProfiles" WHERE "userId" = {user_id};'))
|
|
db.execute(text(f'DELETE FROM "Applications" WHERE "userId" = {user_id};'))
|
|
db.execute(
|
|
text(f'DELETE FROM "OnboardingProfiles" WHERE "userId" = {user_id};')
|
|
)
|
|
|
|
db.commit()
|
|
|
|
return ResponseSchema(
|
|
status=200,
|
|
message="Application deleted successfully!",
|
|
success=True,
|
|
)
|
|
|
|
except SQLAlchemyError as e:
|
|
db.rollback()
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
|
|
|
async def is_loan_officer(db, user_id):
|
|
"""
|
|
Check if the user is a loan officer.
|
|
|
|
Parameters:
|
|
- db: SQLAlchemy database session
|
|
- user_id: ID of the user
|
|
|
|
Returns:
|
|
- bool: True if the user is a loan officer, False otherwise
|
|
"""
|
|
try:
|
|
data = db.query(User).filter_by(userId=user_id, isActive="1").first()
|
|
|
|
if not data:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="User does not exist",
|
|
)
|
|
is_loan_officer = bool(data.NMLS)
|
|
return is_loan_officer
|
|
|
|
except SQLAlchemyError as e:
|
|
db.rollback()
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
|
|
|
async def change_password(pass_object: PasswordSchema, db):
|
|
"""
|
|
Update the temporary password to the new one
|
|
|
|
Parameters:
|
|
- pass_object: contains user_id, code, and new password
|
|
- db: SQLAlchemy database session
|
|
|
|
Returns:
|
|
- Response: return 200 as success response
|
|
"""
|
|
try:
|
|
data = (
|
|
db.query(User)
|
|
.filter_by(userId=pass_object.user_id, isActive="1")
|
|
.first()
|
|
)
|
|
|
|
if not data:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="User does not exist",
|
|
)
|
|
|
|
if pass_object.code != data.verificationCode:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Invalid passcode",
|
|
)
|
|
|
|
|
|
hashed_password = get_password_hash(pass_object.password)
|
|
|
|
|
|
setattr(data, "password", hashed_password)
|
|
setattr(data, "isVerified", str(int(1)))
|
|
|
|
db.add(data)
|
|
db.commit()
|
|
|
|
return ResponseSchema(
|
|
status=200,
|
|
message="Password changed successfully",
|
|
success=True,
|
|
)
|
|
|
|
except SQLAlchemyError as e:
|
|
db.rollback()
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
|
|
|
async def is_user_verified(db, user_id, code):
|
|
"""
|
|
checking if the user is verified if not will verify it
|
|
|
|
Parameters:
|
|
- db: SQLAlchemy database session
|
|
- user_id: ID of the user
|
|
- code: verification code
|
|
|
|
Returns:
|
|
- Response: return 200 as success response
|
|
"""
|
|
try:
|
|
data = db.query(User).filter_by(userId=user_id, isActive="1").first()
|
|
|
|
if not data:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Users not found",
|
|
)
|
|
|
|
if data.isVerified == "1":
|
|
expired_link = env.PASSWORD_LINK_EXPIRED
|
|
return RedirectResponse(url=expired_link)
|
|
|
|
if code != data.verificationCode:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Invalid passcode",
|
|
)
|
|
|
|
|
|
password_setup_page_url = env.PASSWORD_SETUP_PAGE_URL
|
|
email = data.email
|
|
redirection_url = (
|
|
f"{password_setup_page_url}?user_id={user_id}&code={code}&email={email}"
|
|
)
|
|
|
|
return RedirectResponse(url=redirection_url)
|
|
|
|
except SQLAlchemyError as e:
|
|
db.rollback()
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
|
|
|
async def reset_user_password_via_reset_link(db, user_id, code):
|
|
"""
|
|
It resets the password of the user when user clicks on password reset link
|
|
|
|
Parameters:
|
|
- db: SQLAlchemy database session
|
|
- user_id: ID of the user
|
|
- code: verification code
|
|
|
|
Returns:
|
|
- Response: return 200 as success response
|
|
"""
|
|
try:
|
|
data = db.query(User).filter_by(userId=user_id, isActive="1").first()
|
|
|
|
if not data:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Users not found",
|
|
)
|
|
|
|
if code != data.verificationCode:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Invalid passcode",
|
|
)
|
|
|
|
|
|
password_setup_page_url = env.PASSWORD_SETUP_PAGE_URL
|
|
email = data.email
|
|
redirection_url = (
|
|
f"{password_setup_page_url}?user_id={user_id}&code={code}&email={email}"
|
|
)
|
|
|
|
return RedirectResponse(url=redirection_url)
|
|
|
|
except SQLAlchemyError as e:
|
|
db.rollback()
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
|
|
|
async def update_user_data(
|
|
user_email: str, db: Session, person_info: PersonalInfoSchema, current_user
|
|
) -> dict:
|
|
try:
|
|
"""
|
|
checking if the user with that email exists and update the personal info if it exists
|
|
|
|
Parameters:
|
|
- db: SQLAlchemy database session
|
|
- user_email: email of the user
|
|
- personal_info: User info that needs to updated
|
|
|
|
Returns:
|
|
- Response: return updated user details as response
|
|
"""
|
|
user_details = (
|
|
db.query(User).filter_by(email=user_email, isActive="1").first()
|
|
)
|
|
if not user_details:
|
|
|
|
provider, user_id = current_user["sub"].split("|")
|
|
user_data = User(
|
|
firstName=person_info.firstName,
|
|
lastName=person_info.lastName,
|
|
email=current_user["email"],
|
|
phoneNumber=person_info.phoneNumber,
|
|
isVerified=str(int(1)),
|
|
NMLS=person_info.NMLS,
|
|
organisationNMLS=person_info.organizationNMLS,
|
|
isOrganisation="1" if person_info.isOrganization else "0",
|
|
role=person_info.role,
|
|
googleOauthId=user_id,
|
|
)
|
|
db.add(user_data)
|
|
db.commit()
|
|
return user_data
|
|
user_details.firstName = person_info.firstName
|
|
user_details.lastName = person_info.lastName
|
|
user_details.phoneNumber = person_info.phoneNumber
|
|
user_details.NMLS = person_info.NMLS
|
|
user_details.organisationNMLS = person_info.organizationNMLS
|
|
user_details.isOrganisation = "1" if person_info.isOrganization else "0"
|
|
user_details.role = person_info.role
|
|
db.commit()
|
|
db.refresh(user_details)
|
|
return user_details
|
|
except SQLAlchemyError as e:
|
|
db.rollback()
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
|
|
|
async def update_personal_info(
|
|
user: PersonalInfoSchema,
|
|
db,
|
|
current_user,
|
|
):
|
|
"""
|
|
Update the User info to Auth0 and DB
|
|
|
|
Parameters:
|
|
- db: SQLAlchemy database session
|
|
- user: personal info of the user
|
|
- current_user: info of the user that is trying to log in(coming from session token auth0)
|
|
|
|
Returns:
|
|
- Response: return 200 as success response
|
|
"""
|
|
try:
|
|
id = user.userId
|
|
client_id = (env.CLIENT_ID,)
|
|
client_secret = (env.CLIENT_SECRET,)
|
|
domain = (env.AUTH0_DOMAIN,)
|
|
mgmt_api_token = get_access_token(
|
|
client_id=client_id, client_secret=client_secret, domain=domain
|
|
)
|
|
|
|
domain = (env.AUTH0_DOMAIN,)
|
|
url = f"https://{domain[0]}/api/v2/users/{id}"
|
|
headers = {
|
|
"Authorization": f"Bearer {mgmt_api_token}",
|
|
"Content-Type": "application/json",
|
|
}
|
|
data = {
|
|
"app_metadata": {
|
|
"firstName": user.firstName,
|
|
"lastName": user.lastName,
|
|
"phoneNumber": user.phoneNumber,
|
|
"NMLS": user.NMLS,
|
|
"isOrganization": user.isOrganization,
|
|
"organizationNMLS": user.organizationNMLS,
|
|
"role": user.role,
|
|
}
|
|
}
|
|
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.patch(url, headers=headers, json=data)
|
|
response.raise_for_status()
|
|
await UserService.update_user_data(
|
|
current_user["email"], db, user, current_user
|
|
)
|
|
|
|
|
|
template_name = (
|
|
EmailTemplateEnum.WELCOME_EMAIL_CONSUMER.value
|
|
if user.role == RoleEnum.CONSUMER.value
|
|
else EmailTemplateEnum.WELCOME_EMAIL_LOAN_OFFICER.value
|
|
)
|
|
|
|
|
|
context_data = {"name": user.firstName}
|
|
|
|
await send_email(db, current_user["email"], context_data, template_name)
|
|
|
|
return ResponseSchema(
|
|
status=status.HTTP_200_OK,
|
|
message="Data Updated Successfully",
|
|
success=True,
|
|
data=response.json(),
|
|
)
|
|
except httpx.HTTPStatusError as e:
|
|
raise HTTPException(
|
|
status_code=e.response.status_code,
|
|
detail=f"HTTP error occurred: {e.response.text}",
|
|
)
|
|
except httpx.RequestError as e:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_502_BAD_GATEWAY,
|
|
detail=f"Network error occurred: {e}",
|
|
)
|
|
except Exception as e:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"An unexpected error occurred: {str(e)}",
|
|
)
|
|
|
|
async def resend_mail(db: Session, current_user):
|
|
try:
|
|
user_details = (
|
|
db.query(User)
|
|
.filter_by(email=current_user["email"], isActive="1")
|
|
.first()
|
|
)
|
|
if user_details.isVerified == "1":
|
|
return ResponseSchema(
|
|
status=204,
|
|
message="User already verified",
|
|
success=True,
|
|
)
|
|
id = current_user["sub"]
|
|
client_id = (env.CLIENT_ID,)
|
|
client_secret = (env.CLIENT_SECRET,)
|
|
domain = (env.AUTH0_DOMAIN,)
|
|
mgmt_api_token = get_access_token(
|
|
client_id=client_id, client_secret=client_secret, domain=domain
|
|
)
|
|
|
|
domain = env.AUTH0_DOMAIN
|
|
provider, user_id = id.split("|")
|
|
verify_email_url = f"https://{domain}/api/v2/jobs/verification-email"
|
|
verify_email_payload = {
|
|
"user_id": id,
|
|
"client_id": env.CLIENT_ID,
|
|
"identity": {"user_id": user_id, "provider": provider},
|
|
}
|
|
|
|
headers = {
|
|
"Authorization": f"Bearer {mgmt_api_token}",
|
|
"Content-Type": "application/json",
|
|
}
|
|
|
|
async with httpx.AsyncClient() as client:
|
|
verify_response = await client.post(
|
|
verify_email_url, json=verify_email_payload, headers=headers
|
|
)
|
|
verify_response.raise_for_status()
|
|
return ResponseSchema(
|
|
status=status.HTTP_200_OK,
|
|
message="Verification email sent successfully",
|
|
success=True,
|
|
data=None,
|
|
)
|
|
|
|
except SQLAlchemyError as e:
|
|
db.rollback()
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
|
except httpx.HTTPStatusError as e:
|
|
raise HTTPException(
|
|
status_code=e.response.status_code,
|
|
detail=f"HTTP error occurred: {e.response.text}",
|
|
)
|
|
except httpx.RequestError as e:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_502_BAD_GATEWAY,
|
|
detail=f"Network error occurred: {e}",
|
|
)
|
|
except Exception as e:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"An unexpected error occurred: {str(e)}",
|
|
)
|
|
|
|
async def redirect_user_verification(redirectUrl: str, sessionToken: str):
|
|
"""
|
|
Redirect User without State Token.
|
|
Reason: We can continue with login and get access token if we have state variable in param by redirecting to continue.
|
|
So this will cause the user to skip email verification if he hasn't done already. So for frontend, we need to send only session token
|
|
when the user is redirecting for user verification
|
|
Parameters:
|
|
- redirectUrl: frontend Url that needs to redirected
|
|
- sessionToken: Auth0 session token
|
|
|
|
Returns:
|
|
- Redirect: Redirects the user to redirectUrl
|
|
"""
|
|
try:
|
|
return RedirectResponse(url=f"{redirectUrl}?session_token={sessionToken}")
|
|
except SQLAlchemyError as e:
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
|
|