adding base project
This commit is contained in:
@@ -0,0 +1,291 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status, Request, Query, Body
|
||||
from sqlalchemy.orm import Session
|
||||
from typing import List, Optional
|
||||
|
||||
from app.core.deps import get_db, require_current_user, get_current_user_token
|
||||
from app.core.security import verify_password, get_password_hash, create_access_token
|
||||
from app.auth.models import AppUser, Role
|
||||
from app.auth.schemas import (
|
||||
LoginRequest,
|
||||
SessionResponse,
|
||||
SessionItem,
|
||||
RegistrationRequest,
|
||||
SendEmailRequest,
|
||||
EmailExistsRequest,
|
||||
UserResponse
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/token", tags=["Authentication & User Session"])
|
||||
|
||||
@router.post("/session", response_model=SessionResponse)
|
||||
def login_session(login_req: LoginRequest, db: Session = Depends(get_db)):
|
||||
"""
|
||||
Authenticates user and returns the exact SessionResponse expected by Angular Clarity login.service.ts.
|
||||
"""
|
||||
user = db.query(AppUser).filter(AppUser.email == login_req.email).first()
|
||||
if not user or not verify_password(login_req.password, user.password):
|
||||
return SessionResponse(
|
||||
operationStatus="ERROR",
|
||||
operationMessage="Login Failed",
|
||||
item=None
|
||||
)
|
||||
|
||||
# Collect role descriptions / names
|
||||
roles = [r.description or r.name for r in user.roles] if user.roles else ["Admin"]
|
||||
|
||||
# Generate JWT
|
||||
token = create_access_token(
|
||||
subject=user.user_id,
|
||||
extra_claims={
|
||||
"email": user.email,
|
||||
"username": user.username,
|
||||
"roles": roles,
|
||||
"user_grp": user.user_grp_id
|
||||
}
|
||||
)
|
||||
|
||||
session_item = SessionItem(
|
||||
userId=user.user_id,
|
||||
email=user.email,
|
||||
fullname=user.full_name or user.username,
|
||||
firstName=user.first_name or user.full_name or user.username,
|
||||
username=user.username,
|
||||
roles=roles,
|
||||
token=token
|
||||
)
|
||||
|
||||
return SessionResponse(
|
||||
operationStatus="SUCCESS",
|
||||
operationMessage="Login Success",
|
||||
item=session_item
|
||||
)
|
||||
|
||||
@router.post("/generate-token", response_model=SessionResponse)
|
||||
def generate_token(login_req: LoginRequest, db: Session = Depends(get_db)):
|
||||
"""Alias for /token/session."""
|
||||
return login_session(login_req, db)
|
||||
|
||||
@router.get("/logout")
|
||||
@router.post("/logout")
|
||||
def logout_user():
|
||||
"""Logs out the user."""
|
||||
return {"operationStatus": "SUCCESS", "operationMessage": "Logged out successfully"}
|
||||
|
||||
@router.get("/user")
|
||||
def get_current_logged_in_user(
|
||||
db: Session = Depends(get_db),
|
||||
token_payload: dict = Depends(require_current_user)
|
||||
):
|
||||
"""Returns current user details based on the JWT token."""
|
||||
user_id = token_payload.get("user_id") or token_payload.get("sub")
|
||||
user = db.query(AppUser).filter(AppUser.user_id == user_id).first()
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
|
||||
roles = [r.description or r.name for r in user.roles] if user.roles else ["Admin"]
|
||||
return {
|
||||
"userId": user.user_id,
|
||||
"email": user.email,
|
||||
"username": user.username,
|
||||
"fullname": user.full_name,
|
||||
"roles": roles,
|
||||
"status": user.status
|
||||
}
|
||||
|
||||
@router.get("/getuser/{user_id}")
|
||||
def get_user_by_id(user_id: int, db: Session = Depends(get_db)):
|
||||
"""Returns user by ID."""
|
||||
user = db.query(AppUser).filter(AppUser.user_id == user_id).first()
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
|
||||
roles = [r.description or r.name for r in user.roles] if user.roles else ["Admin"]
|
||||
return {
|
||||
"userId": user.user_id,
|
||||
"email": user.email,
|
||||
"username": user.username,
|
||||
"fullname": user.full_name,
|
||||
"roles": roles
|
||||
}
|
||||
|
||||
@router.post("/email-exists")
|
||||
def check_email_exists(req: EmailExistsRequest, db: Session = Depends(get_db)):
|
||||
"""Checks if email already exists."""
|
||||
user = db.query(AppUser).filter(AppUser.email == req.email).first()
|
||||
return {"exists": user is not None}
|
||||
|
||||
@router.post("/users/sysaccount/savesysaccount")
|
||||
@router.post("/savesysaccount")
|
||||
def save_sys_account(data: dict = Body(...)):
|
||||
"""
|
||||
Saves sysaccount during Angular user signup (mirrors Spring Boot SysAccountController /savesysaccount).
|
||||
"""
|
||||
account_id = data.get("account_id") or 1
|
||||
res = dict(data)
|
||||
res["account_id"] = account_id
|
||||
res["mongoid"] = f"acc_{account_id}"
|
||||
return res
|
||||
|
||||
@router.post("/addOneAppUser")
|
||||
def register_user(reg: RegistrationRequest, db: Session = Depends(get_db)):
|
||||
"""
|
||||
Registers a new user or activates a pending user created during OTP step.
|
||||
Mirrors Spring Boot SessionController /addOneAppUser.
|
||||
"""
|
||||
email = reg.email.strip()
|
||||
user = db.query(AppUser).filter(AppUser.email == email).first()
|
||||
|
||||
raw_pwd = reg.new_password or reg.password
|
||||
if not raw_pwd:
|
||||
raise HTTPException(status_code=400, detail="Password is required")
|
||||
|
||||
hashed_pwd = get_password_hash(raw_pwd)
|
||||
first_name = reg.first_name or reg.fullName or email.split("@")[0]
|
||||
last_name = reg.last_name or ""
|
||||
full_name = reg.fullName or f"{first_name} {last_name}".strip()
|
||||
username = reg.username or email.split("@")[0]
|
||||
|
||||
if user:
|
||||
if user.status == "ACTIVE" and user.password:
|
||||
raise HTTPException(status_code=400, detail="Email already exists")
|
||||
# Activate pending user
|
||||
user.password = hashed_pwd
|
||||
user.first_name = first_name
|
||||
user.last_name = last_name
|
||||
user.full_name = full_name
|
||||
user.username = username
|
||||
user.status = "ACTIVE"
|
||||
user.is_active = True
|
||||
else:
|
||||
user = AppUser(
|
||||
email=email,
|
||||
username=username,
|
||||
password=hashed_pwd,
|
||||
full_name=full_name,
|
||||
first_name=first_name,
|
||||
last_name=last_name,
|
||||
status="ACTIVE",
|
||||
user_grp_id=1,
|
||||
is_active=True
|
||||
)
|
||||
db.add(user)
|
||||
|
||||
# Assign Admin role
|
||||
admin_role = db.query(Role).filter(Role.name == "ROLE_ADMIN").first()
|
||||
if admin_role and admin_role not in user.roles:
|
||||
user.roles.append(admin_role)
|
||||
|
||||
db.commit()
|
||||
db.refresh(user)
|
||||
|
||||
return {
|
||||
"userId": user.user_id,
|
||||
"email": user.email,
|
||||
"username": user.username,
|
||||
"fullName": user.full_name,
|
||||
"firstName": user.first_name,
|
||||
"roles": [r.description or r.name for r in user.roles],
|
||||
"message": "User registered successfully"
|
||||
}
|
||||
|
||||
@router.post("/user/send_email")
|
||||
def send_email_for_otp(req: SendEmailRequest, db: Session = Depends(get_db)):
|
||||
"""
|
||||
Sends OTP for email verification (mirrors Spring Boot SessionController /token/user/send_email).
|
||||
"""
|
||||
import random
|
||||
from app.core.email import email_service
|
||||
|
||||
email = req.email.strip()
|
||||
user = db.query(AppUser).filter(AppUser.email == email).first()
|
||||
if user and user.status == "ACTIVE" and user.password: # Already registered active user
|
||||
raise HTTPException(status_code=400, detail=f"{email} already exists")
|
||||
|
||||
otp = str(random.randint(100000, 999999))
|
||||
if not user:
|
||||
username = req.username or email.split("@")[0]
|
||||
user = AppUser(
|
||||
email=email,
|
||||
username=username,
|
||||
password="", # Empty string satisfies NOT NULL constraint until password is set
|
||||
full_name=req.fullName or username,
|
||||
first_name=req.fullName or username,
|
||||
status="PENDING",
|
||||
random_no=otp,
|
||||
is_active=False
|
||||
)
|
||||
db.add(user)
|
||||
else:
|
||||
user.random_no = otp
|
||||
db.commit()
|
||||
|
||||
email_service.adduserviaadmin(email, "Email Verification", otp)
|
||||
return {
|
||||
"operationStatus": "SUCCESS",
|
||||
"operationMessage": "Otp send successfully",
|
||||
"msg": "Otp send successfully",
|
||||
"otp": otp
|
||||
}
|
||||
|
||||
@router.post("/user/resend_otp")
|
||||
def resend_otp(
|
||||
email: Optional[str] = Query(None),
|
||||
db: Session = Depends(get_db),
|
||||
body: Optional[SendEmailRequest] = None
|
||||
):
|
||||
"""
|
||||
Resends OTP for email verification (mirrors Spring Boot SessionController /token/user/resend_otp).
|
||||
Supports query parameter (?email=...) or JSON body.
|
||||
"""
|
||||
import random
|
||||
from app.core.email import email_service
|
||||
|
||||
target_email = email or (body.email if body else None)
|
||||
if not target_email:
|
||||
raise HTTPException(status_code=400, detail="Email is required")
|
||||
|
||||
target_email = target_email.strip()
|
||||
user = db.query(AppUser).filter(AppUser.email == target_email).first()
|
||||
if not user:
|
||||
raise HTTPException(status_code=400, detail=f"{target_email} does not exist")
|
||||
|
||||
otp = str(random.randint(100000, 999999))
|
||||
user.random_no = otp
|
||||
db.commit()
|
||||
|
||||
email_service.adduserviaadmin(target_email, "Email Verification - Resend OTP", otp)
|
||||
return {
|
||||
"operationStatus": "SUCCESS",
|
||||
"operationMessage": "resend Otp send successfully",
|
||||
"msg": "resend Otp send successfully",
|
||||
"otp": otp
|
||||
}
|
||||
|
||||
@router.post("/user/otp_verification")
|
||||
def otp_verification(
|
||||
email: str = Query(...),
|
||||
otp: str = Query(...),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""
|
||||
Verifies OTP entered by user (mirrors Spring Boot SessionController /token/user/otp_verification).
|
||||
Query parameters: ?email=...&otp=...
|
||||
"""
|
||||
email_clean = email.replace(" ", "+").strip()
|
||||
user = db.query(AppUser).filter(AppUser.email == email_clean).first()
|
||||
if not user:
|
||||
raise HTTPException(status_code=400, detail="User not found")
|
||||
|
||||
if user.random_no and user.random_no.strip() == otp.strip():
|
||||
return {
|
||||
"operationStatus": "SUCCESS",
|
||||
"operationMessage": "OTP Verified",
|
||||
"msg": "OTP Verified"
|
||||
}
|
||||
else:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Wrong OTP"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user