|
from fastapi import APIRouter, HTTPException, status |
|
from .Schema import ( |
|
RegisterUserRequest, |
|
LoginUserRequest, |
|
AccessTokenResponse, |
|
ForgotPasswordRequest, |
|
VerifyResetTokenRequest, |
|
ResetPasswordRequest, |
|
BaseResponse, |
|
UserResponse, |
|
) |
|
from .Model import User |
|
from jose import jwt |
|
from typing import List |
|
from datetime import datetime, timedelta |
|
from App.Android.Android import AndroidClient |
|
from App.Android.Schema import RegisterUserRequest as AndroidRegister |
|
from App.Templates.Templates import MessageTemplate |
|
|
|
|
|
SECRET_KEY = "your_secret_key_here" |
|
ALGORITHM = "HS256" |
|
ACCESS_TOKEN_EXPIRE_MINUTES = 30 |
|
user_router = APIRouter(tags=["User"]) |
|
client = AndroidClient() |
|
templates = MessageTemplate() |
|
|
|
|
|
def create_access_token(data: dict, expires_delta: timedelta = None): |
|
to_encode = data.copy() |
|
expire = datetime.utcnow() + ( |
|
expires_delta or timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) |
|
) |
|
to_encode.update({"exp": expire}) |
|
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@user_router.post( |
|
"/user/register", response_model=BaseResponse, status_code=status.HTTP_201_CREATED |
|
) |
|
async def register_user(request: RegisterUserRequest): |
|
existing_user = await User.filter(phoneNumber=request.phoneNumber).first() |
|
if existing_user: |
|
raise HTTPException( |
|
status_code=status.HTTP_400_BAD_REQUEST, detail="User already exists." |
|
) |
|
|
|
new_user = await User.create_user(request.dict()) |
|
return BaseResponse( |
|
code=200, message="User created successfully", payload={"user_id": new_user.id} |
|
) |
|
|
|
|
|
@user_router.post( |
|
"/user/login", response_model=AccessTokenResponse, status_code=status.HTTP_200_OK |
|
) |
|
async def login_user(request: LoginUserRequest): |
|
db_user = await User.filter(phoneNumber=request.phoneNumber).first() |
|
if db_user and db_user.verify_password(request.password): |
|
access_token = create_access_token(data={"sub": db_user.phoneNumber}) |
|
return AccessTokenResponse(access_token=access_token, token_type="bearer") |
|
raise HTTPException( |
|
status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials" |
|
) |
|
|
|
|
|
@user_router.post( |
|
"/user/forgot-password", response_model=BaseResponse, status_code=status.HTTP_200_OK |
|
) |
|
async def forgot_password(request: ForgotPasswordRequest): |
|
user = await User.filter(phoneNumber=request.phoneNumber).first() |
|
if not user: |
|
raise HTTPException( |
|
status_code=status.HTTP_404_NOT_FOUND, detail="User not found." |
|
) |
|
await user.initiate_password_reset() |
|
return BaseResponse(code=200, message="Password reset token sent to your phone.") |
|
|
|
|
|
@user_router.post( |
|
"/user/verify-reset-token", |
|
response_model=BaseResponse, |
|
status_code=status.HTTP_200_OK, |
|
) |
|
async def verify_reset_token(request: VerifyResetTokenRequest): |
|
user = await User.filter( |
|
phoneNumber=request.phoneNumber, reset_token=request.reset_token |
|
).first() |
|
if not user or datetime.utcnow() > user.reset_token_expiration: |
|
raise HTTPException( |
|
status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid or expired token." |
|
) |
|
return BaseResponse(code=200, message="Token verified. Proceed to reset password.") |
|
|
|
|
|
@user_router.post( |
|
"/user/reset-password", response_model=BaseResponse, status_code=status.HTTP_200_OK |
|
) |
|
async def reset_password(request: ResetPasswordRequest): |
|
user = await User.filter(phoneNumber=request.phoneNumber).first() |
|
if not user: |
|
raise HTTPException( |
|
status_code=status.HTTP_404_NOT_FOUND, detail="User not found." |
|
) |
|
if not await user.reset_password(request.reset_token, request.new_password): |
|
raise HTTPException( |
|
status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid or expired token." |
|
) |
|
return BaseResponse(code=200, message="Password has been reset successfully.") |
|
|
|
|
|
@user_router.get( |
|
"/user/all", response_model=List[UserResponse], status_code=status.HTTP_200_OK |
|
) |
|
async def get_all_users(): |
|
users = await User.all() |
|
return [UserResponse.from_orm(user) for user in users] |
|
|
|
|
|
@user_router.delete( |
|
"/user/{user_id}", response_model=BaseResponse, status_code=status.HTTP_200_OK |
|
) |
|
async def delete_user(user_id: str): |
|
user = await User.filter(id=user_id).first() |
|
if not user: |
|
raise HTTPException( |
|
status_code=status.HTTP_404_NOT_FOUND, detail="User not found." |
|
) |
|
await user.delete() |
|
return BaseResponse(code=200, message="User deleted successfully.") |
|
|
|
|
|
@user_router.put( |
|
"/user/toggle_status/{user_id}", |
|
response_model=BaseResponse, |
|
status_code=status.HTTP_200_OK, |
|
) |
|
async def toggle_user_status(user_id: str): |
|
user = await User.filter(id=user_id).first() |
|
if not user: |
|
raise HTTPException( |
|
status_code=status.HTTP_404_NOT_FOUND, detail="User not found." |
|
) |
|
user.account_locked = not user.account_locked |
|
await user.save() |
|
message = ( |
|
"User disabled successfully." |
|
if user.account_locked |
|
else "User enabled successfully." |
|
) |
|
return BaseResponse(code=200, message=message) |
|
|