Files
Task_Reporter/app/modules/auth/services/user_service.py
egg 1d5d4d447d feat: Add mobile responsive layout, open room access, and admin room management
Mobile Responsive Layout:
- Add useMediaQuery, useIsMobile, useIsTablet, useIsDesktop hooks for device detection
- Create MobileHeader component with hamburger menu and action drawer
- Create BottomToolbar for mobile navigation (Files, Members)
- Create SlidePanel component for full-screen mobile sidebars
- Update RoomDetail.tsx with mobile/desktop conditional rendering
- Update RoomList.tsx with single-column grid and touch-friendly buttons
- Add CSS custom properties for safe areas and touch targets (min 44px)
- Add mobile viewport meta tags for notched devices

Open Room Access:
- All authenticated users can view all rooms (not just their own)
- Users can join active rooms they're not members of
- Add is_member field to room responses
- Update room list API to return all rooms by default

Admin Room Management:
- Add permanent delete functionality for system admins
- Add delete confirmation dialog with room title verification
- Broadcast room deletion via WebSocket to connected users
- Add users search API for adding members

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 09:12:10 +08:00

118 lines
3.1 KiB
Python

"""User service for permanent user information storage
This service handles upsert operations for the users table,
which stores display names and metadata for report generation.
"""
from datetime import datetime
from typing import Optional
from sqlalchemy.orm import Session
from app.modules.auth.models import User
def upsert_user(
db: Session,
user_id: str,
display_name: str,
office_location: Optional[str] = None,
job_title: Optional[str] = None,
) -> User:
"""Create or update user record with AD information
This function is called on every successful login to keep
user information up to date. Uses SQLAlchemy merge for
atomic upsert operation.
Args:
db: Database session
user_id: User email address (primary key)
display_name: Display name from AD API
office_location: Office location from AD API (optional)
job_title: Job title from AD API (optional)
Returns:
User: The created or updated user record
"""
# Check if user exists
existing_user = db.query(User).filter(User.user_id == user_id).first()
if existing_user:
# Update existing user
existing_user.display_name = display_name
existing_user.office_location = office_location
existing_user.job_title = job_title
existing_user.last_login_at = datetime.utcnow()
db.commit()
db.refresh(existing_user)
return existing_user
else:
# Create new user
new_user = User(
user_id=user_id,
display_name=display_name,
office_location=office_location,
job_title=job_title,
last_login_at=datetime.utcnow(),
created_at=datetime.utcnow(),
)
db.add(new_user)
db.commit()
db.refresh(new_user)
return new_user
def get_user_by_id(db: Session, user_id: str) -> Optional[User]:
"""Get user by user_id (email)
Args:
db: Database session
user_id: User email address
Returns:
User or None if not found
"""
return db.query(User).filter(User.user_id == user_id).first()
def get_display_name(db: Session, user_id: str) -> str:
"""Get display name for a user, falling back to email if not found
Args:
db: Database session
user_id: User email address
Returns:
Display name or email address as fallback
"""
user = get_user_by_id(db, user_id)
if user:
return user.display_name
return user_id # Fallback to email if user not in database
def search_users(db: Session, query: str, limit: int = 20) -> list[User]:
"""Search users by display_name or user_id (email)
Args:
db: Database session
query: Search query string
limit: Maximum number of results (default 20)
Returns:
List of matching users
"""
from sqlalchemy import or_
search_pattern = f"%{query}%"
return (
db.query(User)
.filter(
or_(
User.display_name.ilike(search_pattern),
User.user_id.ilike(search_pattern)
)
)
.limit(limit)
.all()
)