Files
vida180/backend/app/api/admin.py
Sergio Correa f50174f898 feat: Implementar funcionalidades de Tarefas e Saúde
- Criadas APIs para Health (métricas de saúde)
  * Registrar peso, altura, % gordura, medidas
  * Histórico completo de medições
  * Estatísticas e resumo

- Criadas APIs para Tasks (tarefas)
  * Criar, editar e deletar tarefas
  * Filtros por status e data
  * Estatísticas detalhadas
  * Prioridades (baixa, média, alta)

- Frontend implementado:
  * Página Health.tsx - registro de métricas
  * Página Tasks.tsx - gerenciamento de tarefas
  * Página Progress.tsx - visualização de progresso
  * Dashboard integrado com estatísticas reais

- Schemas e modelos atualizados
- Todas as funcionalidades testadas e operacionais
2025-11-22 02:33:15 +00:00

149 lines
4.8 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.orm import Session
from typing import List
from datetime import datetime
from app.core.database import get_db
from app.core.security import decode_access_token, get_password_hash
from app.models.user import User
from app.schemas.admin import UserListResponse, UserUpdateRequest, PasswordChangeRequest
router = APIRouter(prefix="/admin", tags=["admin"])
security = HTTPBearer()
def get_current_superadmin(
credentials: HTTPAuthorizationCredentials = Depends(security),
db: Session = Depends(get_db)
) -> User:
"""Verifica se usuário é superadmin"""
token = credentials.credentials
payload = decode_access_token(token)
if not payload:
raise HTTPException(status_code=401, detail="Token inválido")
user_id = payload.get("sub")
user = db.query(User).filter(User.id == user_id).first()
if not user or not user.is_superadmin:
raise HTTPException(
status_code=403,
detail="Acesso negado. Apenas superadmin."
)
return user
@router.get("/users", response_model=List[UserListResponse])
async def list_all_users(
admin: User = Depends(get_current_superadmin),
db: Session = Depends(get_db)
):
"""Listar todos os usuários (apenas superadmin)"""
users = db.query(User).order_by(User.created_at.desc()).all()
return users
@router.get("/stats")
async def get_admin_stats(
admin: User = Depends(get_current_superadmin),
db: Session = Depends(get_db)
):
"""Estatísticas gerais do sistema"""
from sqlalchemy import func
from app.models.habit import Habit, HabitCompletion
total_users = db.query(func.count(User.id)).scalar()
active_users = db.query(func.count(User.id)).filter(User.is_active == True).scalar()
total_habits = db.query(func.count(Habit.id)).scalar()
total_completions = db.query(func.count(HabitCompletion.id)).scalar()
return {
"total_users": total_users,
"active_users": active_users,
"inactive_users": total_users - active_users,
"total_habits": total_habits,
"total_completions": total_completions
}
@router.patch("/users/{user_id}")
async def update_user(
user_id: str,
data: UserUpdateRequest,
admin: User = Depends(get_current_superadmin),
db: Session = Depends(get_db)
):
"""Atualizar dados de usuário"""
user = db.query(User).filter(User.id == user_id).first()
if not user:
raise HTTPException(status_code=404, detail="Usuário não encontrado")
# Atualizar campos
if data.email is not None:
# Verificar se email já existe
existing = db.query(User).filter(
User.email == data.email,
User.id != user_id
).first()
if existing:
raise HTTPException(status_code=400, detail="Email já em uso")
user.email = data.email
if data.username is not None:
# Verificar se username já existe
existing = db.query(User).filter(
User.username == data.username,
User.id != user_id
).first()
if existing:
raise HTTPException(status_code=400, detail="Username já em uso")
user.username = data.username
if data.full_name is not None:
user.full_name = data.full_name
if data.is_active is not None:
user.is_active = data.is_active
if data.is_verified is not None:
user.is_verified = data.is_verified
db.commit()
db.refresh(user)
return {"message": "Usuário atualizado", "user": user}
@router.delete("/users/{user_id}")
async def delete_user(
user_id: str,
admin: User = Depends(get_current_superadmin),
db: Session = Depends(get_db)
):
"""Deletar usuário (soft delete - apenas desativa)"""
user = db.query(User).filter(User.id == user_id).first()
if not user:
raise HTTPException(status_code=404, detail="Usuário não encontrado")
if user.is_superadmin:
raise HTTPException(status_code=403, detail="Não é possível deletar superadmin")
user.is_active = False
db.commit()
return {"message": "Usuário desativado com sucesso"}
@router.post("/users/{user_id}/reset-password")
async def reset_user_password(
user_id: str,
data: PasswordChangeRequest,
admin: User = Depends(get_current_superadmin),
db: Session = Depends(get_db)
):
"""Resetar senha de usuário"""
user = db.query(User).filter(User.id == user_id).first()
if not user:
raise HTTPException(status_code=404, detail="Usuário não encontrado")
user.password_hash = get_password_hash(data.new_password)
db.commit()
return {"message": "Senha alterada com sucesso"}