zioinfo-mail/workspace/guardia-itsm/routers/shell_scripts.py
DESKTOP-TKLFCPR\ython cfe2901a55 refactor(structure): consolidate all projects under workspace/
- itsm/    -> workspace/guardia-itsm/
- manager/ -> workspace/guardia-manager/
- app/     -> workspace/guardia-messenger/
- manual/  -> workspace/guardia-docs/

workspace/zioinfo-web/ unchanged.
git mv preserves full commit history.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 23:50:56 +09:00

140 lines
4.8 KiB
Python

"""쉘 스크립트 라이브러리 CRUD 엔드포인트."""
from datetime import datetime
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy import select, or_
from sqlalchemy.ext.asyncio import AsyncSession
from core.auth import get_current_user
from database import get_db
from models import (
ShellScript, ShellScriptCreate, ShellScriptOut, ShellScriptUpdate,
User, UserRole,
)
router = APIRouter(prefix="/api/shell-scripts", tags=["shell-scripts"])
@router.get("", response_model=List[ShellScriptOut])
async def list_scripts(
category: Optional[str] = Query(None),
target_layer: Optional[str] = Query(None),
os_type: Optional[str] = Query(None),
keyword: Optional[str] = Query(None),
inst_id: Optional[int] = Query(None),
include_public: bool = Query(True),
skip: int = 0,
limit: int = 100,
db: AsyncSession = Depends(get_db),
_u: User = Depends(get_current_user),
):
q = select(ShellScript).where(ShellScript.is_active == True)
# inst_id 필터: 해당 기관 전용 + 공용(NULL) 포함 가능
if inst_id is not None:
if include_public:
q = q.where(or_(ShellScript.inst_id == inst_id, ShellScript.inst_id == None))
else:
q = q.where(ShellScript.inst_id == inst_id)
if category:
q = q.where(ShellScript.category == category)
if target_layer:
q = q.where(or_(ShellScript.target_layer == target_layer, ShellScript.target_layer == "ALL"))
if os_type:
q = q.where(or_(ShellScript.os_type == os_type, ShellScript.os_type == "ALL"))
if keyword:
q = q.where(
or_(
ShellScript.script_name.contains(keyword),
ShellScript.description.contains(keyword),
ShellScript.tags.contains(keyword),
)
)
q = q.order_by(ShellScript.category, ShellScript.script_name).offset(skip).limit(limit)
result = await db.execute(q)
return result.scalars().all()
@router.get("/{script_id}", response_model=ShellScriptOut)
async def get_script(
script_id: int,
db: AsyncSession = Depends(get_db),
_u: User = Depends(get_current_user),
):
r = await db.execute(select(ShellScript).where(ShellScript.id == script_id))
script = r.scalars().first()
if not script:
raise HTTPException(404, "스크립트를 찾을 수 없습니다.")
return script
@router.post("", response_model=ShellScriptOut, status_code=201)
async def create_script(
payload: ShellScriptCreate,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
if current_user.role not in (UserRole.ADMIN, UserRole.PM, UserRole.ENGINEER):
raise HTTPException(403, "권한이 없습니다.")
data = payload.model_dump()
data["author"] = data.get("author") or current_user.username
script = ShellScript(**data)
db.add(script)
await db.commit()
await db.refresh(script)
return script
@router.patch("/{script_id}", response_model=ShellScriptOut)
async def update_script(
script_id: int,
payload: ShellScriptUpdate,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
if current_user.role not in (UserRole.ADMIN, UserRole.PM, UserRole.ENGINEER):
raise HTTPException(403, "권한이 없습니다.")
r = await db.execute(select(ShellScript).where(ShellScript.id == script_id))
script = r.scalars().first()
if not script:
raise HTTPException(404, "스크립트를 찾을 수 없습니다.")
for k, v in payload.model_dump(exclude_unset=True).items():
setattr(script, k, v)
script.updated_at = datetime.now()
await db.commit()
await db.refresh(script)
return script
@router.delete("/{script_id}", status_code=204)
async def delete_script(
script_id: int,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
if current_user.role not in (UserRole.ADMIN, UserRole.PM):
raise HTTPException(403, "ADMIN 또는 PM 권한이 필요합니다.")
r = await db.execute(select(ShellScript).where(ShellScript.id == script_id))
script = r.scalars().first()
if not script:
raise HTTPException(404, "스크립트를 찾을 수 없습니다.")
script.is_active = False
script.updated_at = datetime.now()
await db.commit()
@router.post("/{script_id}/increment-use", status_code=204)
async def increment_use_count(
script_id: int,
db: AsyncSession = Depends(get_db),
_u: User = Depends(get_current_user),
):
"""스크립트 사용 횟수 증가 (타임테이블 연계 시 호출)."""
r = await db.execute(select(ShellScript).where(ShellScript.id == script_id))
script = r.scalars().first()
if script:
script.use_count = (script.use_count or 0) + 1
await db.commit()