276 lines
8.7 KiB
Python
276 lines
8.7 KiB
Python
from fastapi import APIRouter, Depends, HTTPException
|
|
from sqlalchemy.orm import Session
|
|
from typing import List
|
|
from app.database import get_db
|
|
from app.schemas.admin import (
|
|
UserCreate, UserUpdate, UserInfo, UserListResponse,
|
|
VMAccessCreate, VMAccessUpdate, VMAccessInfo, VMAccessListResponse,
|
|
AdminResponse
|
|
)
|
|
from app.schemas.auth import CurrentUser
|
|
from app.api.auth import get_current_user
|
|
from app.models.user import User, UserRole
|
|
from app.models.vm import VMAccess
|
|
from app.utils.security import hash_password
|
|
from app.utils.exceptions import PermissionDeniedError, NotFoundError, BadRequestError
|
|
|
|
router = APIRouter()
|
|
|
|
def require_admin(current_user: CurrentUser = Depends(get_current_user)):
|
|
"""관리자 권한 확인"""
|
|
if current_user.role != "admin":
|
|
raise PermissionDeniedError("관리자 권한이 필요합니다")
|
|
return current_user
|
|
|
|
# ==================== 사용자 관리 ====================
|
|
|
|
@router.get("/users", response_model=UserListResponse)
|
|
async def get_users(
|
|
current_user: CurrentUser = Depends(require_admin),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""사용자 목록 조회"""
|
|
users = db.query(User).all()
|
|
|
|
user_list = [
|
|
UserInfo(
|
|
id=user.id,
|
|
username=user.username,
|
|
email=user.email,
|
|
full_name=user.full_name,
|
|
role=user.role.value,
|
|
is_active=user.is_active,
|
|
created_at=user.created_at,
|
|
last_login=user.last_login
|
|
)
|
|
for user in users
|
|
]
|
|
|
|
return UserListResponse(total=len(user_list), users=user_list)
|
|
|
|
@router.post("/users", response_model=AdminResponse)
|
|
async def create_user(
|
|
user_data: UserCreate,
|
|
current_user: CurrentUser = Depends(require_admin),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""사용자 생성"""
|
|
# 중복 확인
|
|
if db.query(User).filter(User.username == user_data.username).first():
|
|
raise BadRequestError("이미 존재하는 사용자명입니다")
|
|
|
|
if db.query(User).filter(User.email == user_data.email).first():
|
|
raise BadRequestError("이미 존재하는 이메일입니다")
|
|
|
|
# 역할 유효성 검사
|
|
if user_data.role not in ["admin", "user"]:
|
|
raise BadRequestError("역할은 'admin' 또는 'user'만 가능합니다")
|
|
|
|
# 사용자 생성
|
|
new_user = User(
|
|
username=user_data.username,
|
|
email=user_data.email,
|
|
hashed_password=hash_password(user_data.password),
|
|
full_name=user_data.full_name,
|
|
role=UserRole.ADMIN if user_data.role == "admin" else UserRole.USER,
|
|
is_active=True
|
|
)
|
|
|
|
db.add(new_user)
|
|
db.commit()
|
|
|
|
return AdminResponse(
|
|
success=True,
|
|
message=f"사용자 '{user_data.username}'이(가) 생성되었습니다"
|
|
)
|
|
|
|
@router.put("/users/{user_id}", response_model=AdminResponse)
|
|
async def update_user(
|
|
user_id: int,
|
|
user_data: UserUpdate,
|
|
current_user: CurrentUser = Depends(require_admin),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""사용자 정보 수정"""
|
|
user = db.query(User).filter(User.id == user_id).first()
|
|
if not user:
|
|
raise NotFoundError("사용자를 찾을 수 없습니다")
|
|
|
|
# 이메일 중복 확인
|
|
if user_data.email and user_data.email != user.email:
|
|
if db.query(User).filter(User.email == user_data.email).first():
|
|
raise BadRequestError("이미 존재하는 이메일입니다")
|
|
user.email = user_data.email
|
|
|
|
# 비밀번호 변경
|
|
if user_data.password:
|
|
user.hashed_password = hash_password(user_data.password)
|
|
|
|
# 기타 정보 업데이트
|
|
if user_data.full_name is not None:
|
|
user.full_name = user_data.full_name
|
|
|
|
if user_data.role:
|
|
if user_data.role not in ["admin", "user"]:
|
|
raise BadRequestError("역할은 'admin' 또는 'user'만 가능합니다")
|
|
user.role = UserRole.ADMIN if user_data.role == "admin" else UserRole.USER
|
|
|
|
if user_data.is_active is not None:
|
|
user.is_active = user_data.is_active
|
|
|
|
db.commit()
|
|
|
|
return AdminResponse(
|
|
success=True,
|
|
message=f"사용자 '{user.username}'의 정보가 수정되었습니다"
|
|
)
|
|
|
|
@router.delete("/users/{user_id}", response_model=AdminResponse)
|
|
async def delete_user(
|
|
user_id: int,
|
|
current_user: CurrentUser = Depends(require_admin),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""사용자 삭제"""
|
|
# 자기 자신은 삭제 불가
|
|
if user_id == current_user.id:
|
|
raise BadRequestError("자기 자신은 삭제할 수 없습니다")
|
|
|
|
user = db.query(User).filter(User.id == user_id).first()
|
|
if not user:
|
|
raise NotFoundError("사용자를 찾을 수 없습니다")
|
|
|
|
username = user.username
|
|
db.delete(user)
|
|
db.commit()
|
|
|
|
return AdminResponse(
|
|
success=True,
|
|
message=f"사용자 '{username}'이(가) 삭제되었습니다"
|
|
)
|
|
|
|
# ==================== VM 접근 권한 관리 ====================
|
|
|
|
@router.get("/vm-access", response_model=VMAccessListResponse)
|
|
async def get_vm_access_list(
|
|
current_user: CurrentUser = Depends(require_admin),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""VM 접근 권한 목록 조회"""
|
|
accesses = db.query(VMAccess).join(User).all()
|
|
|
|
access_list = [
|
|
VMAccessInfo(
|
|
id=access.id,
|
|
user_id=access.user_id,
|
|
username=access.user.username,
|
|
vm_id=access.vm_id,
|
|
node=access.node,
|
|
vm_name=access.vm_name,
|
|
static_ip=access.static_ip,
|
|
rdp_username=access.rdp_username,
|
|
rdp_port=access.rdp_port,
|
|
is_active=access.is_active,
|
|
created_at=access.created_at
|
|
)
|
|
for access in accesses
|
|
]
|
|
|
|
return VMAccessListResponse(total=len(access_list), accesses=access_list)
|
|
|
|
@router.post("/vm-access", response_model=AdminResponse)
|
|
async def create_vm_access(
|
|
access_data: VMAccessCreate,
|
|
current_user: CurrentUser = Depends(require_admin),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""VM 접근 권한 부여"""
|
|
# 사용자 존재 확인
|
|
user = db.query(User).filter(User.id == access_data.user_id).first()
|
|
if not user:
|
|
raise NotFoundError("사용자를 찾을 수 없습니다")
|
|
|
|
# 중복 확인
|
|
existing = db.query(VMAccess).filter(
|
|
VMAccess.user_id == access_data.user_id,
|
|
VMAccess.vm_id == access_data.vm_id
|
|
).first()
|
|
|
|
if existing:
|
|
raise BadRequestError("이미 해당 사용자에게 VM 접근 권한이 있습니다")
|
|
|
|
# 권한 생성
|
|
access = VMAccess(
|
|
user_id=access_data.user_id,
|
|
vm_id=access_data.vm_id,
|
|
node=access_data.node,
|
|
static_ip=access_data.static_ip,
|
|
rdp_username=access_data.rdp_username,
|
|
rdp_password=access_data.rdp_password,
|
|
rdp_port=access_data.rdp_port,
|
|
is_active=True
|
|
)
|
|
|
|
db.add(access)
|
|
db.commit()
|
|
|
|
return AdminResponse(
|
|
success=True,
|
|
message=f"사용자 '{user.username}'에게 VM {access_data.vm_id} 접근 권한이 부여되었습니다"
|
|
)
|
|
|
|
@router.put("/vm-access/{access_id}", response_model=AdminResponse)
|
|
async def update_vm_access(
|
|
access_id: int,
|
|
access_data: VMAccessUpdate,
|
|
current_user: CurrentUser = Depends(require_admin),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""VM 접근 권한 수정"""
|
|
access = db.query(VMAccess).filter(VMAccess.id == access_id).first()
|
|
if not access:
|
|
raise NotFoundError("접근 권한을 찾을 수 없습니다")
|
|
|
|
# 정보 업데이트
|
|
if access_data.static_ip is not None:
|
|
access.static_ip = access_data.static_ip
|
|
|
|
if access_data.rdp_username is not None:
|
|
access.rdp_username = access_data.rdp_username
|
|
|
|
if access_data.rdp_password is not None:
|
|
access.rdp_password = access_data.rdp_password
|
|
|
|
if access_data.rdp_port is not None:
|
|
access.rdp_port = access_data.rdp_port
|
|
|
|
if access_data.is_active is not None:
|
|
access.is_active = access_data.is_active
|
|
|
|
db.commit()
|
|
|
|
return AdminResponse(
|
|
success=True,
|
|
message=f"VM {access.vm_id} 접근 권한이 수정되었습니다"
|
|
)
|
|
|
|
@router.delete("/vm-access/{access_id}", response_model=AdminResponse)
|
|
async def delete_vm_access(
|
|
access_id: int,
|
|
current_user: CurrentUser = Depends(require_admin),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""VM 접근 권한 삭제"""
|
|
access = db.query(VMAccess).filter(VMAccess.id == access_id).first()
|
|
if not access:
|
|
raise NotFoundError("접근 권한을 찾을 수 없습니다")
|
|
|
|
vm_id = access.vm_id
|
|
db.delete(access)
|
|
db.commit()
|
|
|
|
return AdminResponse(
|
|
success=True,
|
|
message=f"VM {vm_id} 접근 권한이 삭제되었습니다"
|
|
)
|