File size: 9,533 Bytes
41eef54 9e798a1 f30e75c b856986 8450c71 b856986 f30e75c 9e798a1 39fc4b3 f30e75c 7875b25 41eef54 8450c71 9e798a1 b856986 41eef54 8450c71 7875b25 8450c71 9e798a1 b856986 9e798a1 b856986 9e798a1 7875b25 9e798a1 b856986 9e798a1 7875b25 9e798a1 b856986 9e798a1 39fc4b3 6a3e1a1 41eef54 a4d5446 39fc4b3 a4d5446 6a3e1a1 39fc4b3 4aa1d81 39fc4b3 e0be833 84b44a7 41eef54 3931352 84b44a7 39fc4b3 84b44a7 b856986 39fc4b3 b856986 9e798a1 b856986 9e798a1 b856986 9e798a1 b856986 9e798a1 b856986 9e798a1 b856986 9e798a1 b856986 f30e75c 41eef54 f30e75c 41eef54 f30e75c 57ab719 41eef54 6c582f0 427d907 6c582f0 427d907 6c582f0 41eef54 fbeb0b0 7c11a75 4aa1d81 41eef54 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
from fastapi import APIRouter, HTTPException, status, Depends, Query
from fastapi.responses import JSONResponse
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.Subscriptions.Model import Subscription
from App.Android.Android import AndroidClient
from App.Android.Schema import RegisterUserRequest as AndroidRegister
from App.Templates.Templates import MessageTemplate
from .dependencies import get_current_active_user, get_admin_user
from App.Android.Schema import APIResponse
# JWT Configurations
SECRET_KEY = "your_secret_key_here"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 300
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)
# The user registers
# It sends userdetails to the router
# It sends the user a message to welcome the user
@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):
# Find user by phone number
db_user: User = await User.filter(phoneNumber=request.phoneNumber).first()
# Raise an error if the user does not exist
if db_user is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="User not found."
)
valid_password = await db_user.verify_password(request.password)
# Check if user exists and password is correct
if db_user and valid_password:
# Fetch active subscription if it exists
subscription = await Subscription.filter(user=db_user, active=True).first()
# Handle case when no active subscription is found
subscription_end = (
subscription.expiration_time.isoformat() if subscription else None
)
is_active = await db_user.is_active()
if is_active:
await db_user.remover_user_session()
access_token = create_access_token(
data={
"user_type": db_user.user_type,
"user_name": db_user.name,
"sub": db_user.phoneNumber,
"locked": db_user.account_locked,
"userId": db_user.id,
"subscription_end": subscription_end,
}
)
return AccessTokenResponse(access_token=access_token, token_type="bearer")
# Raise an error if credentials are invalid
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(admin: User = Depends(get_admin_user)):
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, admin: User = Depends(get_current_active_user)):
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."
)
await user.toggle_status()
message = (
"User disabled successfully."
if user.account_locked
else "User enabled successfully."
)
return BaseResponse(code=200, message=message)
@user_router.get(
"/user/me", response_model=UserResponse, status_code=status.HTTP_200_OK
)
async def get_user_details(current_user: User = Depends(get_current_active_user)):
"""
Get the current user's details and balance.
"""
return UserResponse.from_orm(current_user)
@user_router.post("/user/{user_id}/activate", response_model=BaseResponse)
async def activate_user(user_id: str):
user = await User.get_or_none(id=user_id)
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="User not found."
)
if await user.activate_user():
return BaseResponse(code=200, message="User activated successfully.")
else:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, detail="Failed to activate user."
)
@user_router.get(
"/users/active", response_model=List[str]
) # Change response model to List[str]
async def get_active_users():
# Fetch all active users using the Android client
api_response: APIResponse = await client.get_active_users()
active_users = api_response.active_users
if not api_response or not active_users:
return JSONResponse(content={"status": 200, "message": "no users online"})
# Collect phone numbers from active users
active_phone_numbers = [user["phone"] for user in active_users]
# Filter users from the database using the collected phone numbers
users_in_db = await User.filter(phoneNumber__in=active_phone_numbers).all()
# Extract usernames from the matched users
usernames = [
{"name": user.name, "phone": user.phoneNumber} for user in users_in_db
] # Assuming 'name' is the field for username in the User model
if not usernames:
return JSONResponse(
content={"status": 200, "message": "No matching active users found."}
)
return JSONResponse(
content={
"status": 200,
"message": f"Found {len(usernames)} active",
"payload": usernames,
}
)
@user_router.get("/user/active", response_model=List[UserResponse])
async def get_active_user(phone_numbers: List[str] = Query(...)):
# Fetch all active users using the Android client
api_response: APIResponse = await client.get_active_users()
active_users = api_response.active_users
if not api_response or not api_response.active_users:
return JSONResponse(content={"status": 200, "message": "no users online"})
# Filter active users by matching phone numbers
matched_users = [
UserResponse.from_orm(user)
for user in active_users
if user["phone"] in phone_numbers
]
if not matched_users:
return JSONResponse(
content={"status": 200, "message": "No matching active users found."}
)
return matched_users
|