DGSoft 93b98cfb5c Initial commit: Team Chat System with Code Snippet Library
- Complete chat application similar to Microsoft Teams
- Code snippet library with syntax highlighting
- Real-time messaging with WebSockets
- File upload with Office integration
- Department-based permissions
- Dark/Light theme support
- Production deployment with SSL/Reverse Proxy
- Docker containerization
- PostgreSQL database with SQLModel ORM
2025-12-09 22:25:03 +01:00

164 lines
5.5 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File
from sqlmodel import Session, select
from datetime import timedelta
import os
import uuid
from pathlib import Path
from app.database import get_session
from app.models import User
from app.schemas import UserCreate, UserResponse, UserLogin, Token
from app.auth import get_password_hash, authenticate_user, create_access_token, get_current_user
from app.config import get_settings
router = APIRouter(prefix="/auth", tags=["Authentication"])
settings = get_settings()
@router.post("/register", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
def register(user_data: UserCreate, session: Session = Depends(get_session)):
"""Register a new user"""
# Check if username already exists
statement = select(User).where(User.username == user_data.username)
existing_user = session.exec(statement).first()
if existing_user:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Username already registered"
)
# Check if email already exists
statement = select(User).where(User.email == user_data.email)
existing_email = session.exec(statement).first()
if existing_email:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Email already registered"
)
# Create new user
hashed_password = get_password_hash(user_data.password)
new_user = User(
username=user_data.username,
email=user_data.email,
full_name=user_data.full_name,
hashed_password=hashed_password
)
session.add(new_user)
session.commit()
session.refresh(new_user)
return new_user
@router.post("/login", response_model=Token)
def login(login_data: UserLogin, session: Session = Depends(get_session)):
"""Login and get access token"""
user = authenticate_user(session, login_data.username, login_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)
access_token_expires = timedelta(minutes=settings.access_token_expire_minutes)
access_token = create_access_token(
data={"sub": user.username}, expires_delta=access_token_expires
)
return {"access_token": access_token, "token_type": "bearer"}
@router.get("/me", response_model=UserResponse)
def get_current_user_info(current_user: User = Depends(get_current_user)):
"""Get current user information"""
return current_user
@router.put("/me", response_model=UserResponse)
def update_profile(
profile_data: dict,
current_user: User = Depends(get_current_user),
session: Session = Depends(get_session)
):
"""Update current user profile"""
# Check if email is being changed and if it already exists
if "email" in profile_data and profile_data["email"] != current_user.email:
statement = select(User).where(User.email == profile_data["email"])
existing_email = session.exec(statement).first()
if existing_email:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Email already registered"
)
current_user.email = profile_data["email"]
# Update full_name if provided
if "full_name" in profile_data:
current_user.full_name = profile_data["full_name"]
# Update password if provided
if "password" in profile_data and profile_data["password"]:
current_user.hashed_password = get_password_hash(profile_data["password"])
# Update profile_picture if provided
if "profile_picture" in profile_data:
current_user.profile_picture = profile_data["profile_picture"]
# Update theme if provided
if "theme" in profile_data:
if profile_data["theme"] in ["light", "dark"]:
current_user.theme = profile_data["theme"]
session.add(current_user)
session.commit()
session.refresh(current_user)
return current_user
@router.post("/me/profile-picture", response_model=UserResponse)
async def upload_profile_picture(
file: UploadFile = File(...),
current_user: User = Depends(get_current_user),
session: Session = Depends(get_session)
):
"""Upload profile picture"""
# Validate file type
if not file.content_type or not file.content_type.startswith('image/'):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Only image files are allowed"
)
# Create uploads directory if it doesn't exist
upload_dir = Path("uploads/profile_pictures")
upload_dir.mkdir(parents=True, exist_ok=True)
# Generate unique filename
file_extension = os.path.splitext(file.filename)[1]
unique_filename = f"{uuid.uuid4()}{file_extension}"
file_path = upload_dir / unique_filename
# Save file
with open(file_path, "wb") as buffer:
content = await file.read()
buffer.write(content)
# Delete old profile picture if exists
if current_user.profile_picture:
old_file_path = Path(current_user.profile_picture)
if old_file_path.exists():
old_file_path.unlink()
# Update user profile picture path
current_user.profile_picture = str(file_path)
session.add(current_user)
session.commit()
session.refresh(current_user)
return current_user