읽기 전용 옵저버 역할 추가. 신고 현황 확인만 가능하며 모든 쓰기 동작 차단. - auth.py: require_viewer(admin+observer) 의존성 추가 - auth_router.py: register 엔드포인트에 role 파라미터 추가 (mechanic/observer) - login.html: 회원가입 시 정비사/옵저버 역할 카드 선택 UI, 역할별 안내문구 - 로그인 후 observer → /pages/observer/dashboard.html 라우팅 - observer/dashboard.html: 통계 카드(상태별 건수) + 신고 현황 테이블(읽기전용) - observer/reports.html: 상태·충전기ID·충전소명 필터 신고 목록 - accounts.html: 옵저버 필터·생성·승인 대기 역할 표시 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
67 lines
2.4 KiB
Python
67 lines
2.4 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, Form
|
|
from fastapi.security import OAuth2PasswordRequestForm
|
|
from sqlalchemy.orm import Session
|
|
from typing import Optional
|
|
from database import get_db
|
|
import models
|
|
from auth import verify_password, create_access_token, get_current_user, hash_password
|
|
|
|
router = APIRouter(prefix="/api/auth", tags=["auth"])
|
|
|
|
@router.post("/login")
|
|
def login(form: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)):
|
|
user = db.query(models.User).filter(
|
|
models.User.username == form.username
|
|
).first()
|
|
if not user or not verify_password(form.password, user.password_hash):
|
|
raise HTTPException(status_code=401, detail="아이디 또는 비밀번호가 올바르지 않습니다.")
|
|
if getattr(user, 'is_pending', False):
|
|
raise HTTPException(status_code=403, detail="가입 승인 대기 중입니다. 관리자 승인 후 이용 가능합니다.")
|
|
if not user.is_active:
|
|
raise HTTPException(status_code=403, detail="비활성화된 계정입니다. 관리자에게 문의하세요.")
|
|
token = create_access_token({"sub": str(user.id)})
|
|
return {
|
|
"access_token": token,
|
|
"token_type": "bearer",
|
|
"role": user.role,
|
|
"name": user.name,
|
|
"user_id": user.id
|
|
}
|
|
|
|
@router.post("/register")
|
|
def register(
|
|
username: str = Form(...),
|
|
password: str = Form(...),
|
|
name: str = Form(...),
|
|
phone: str = Form(""),
|
|
company: str = Form(""),
|
|
role: str = Form("mechanic"), # mechanic | observer
|
|
db: Session = Depends(get_db)
|
|
):
|
|
if role not in ("mechanic", "observer"):
|
|
role = "mechanic"
|
|
if db.query(models.User).filter_by(username=username).first():
|
|
raise HTTPException(400, "이미 사용 중인 아이디입니다.")
|
|
user = models.User(
|
|
username=username,
|
|
password_hash=hash_password(password),
|
|
role=role,
|
|
name=name,
|
|
phone=phone or None,
|
|
company=company or None,
|
|
is_active=False,
|
|
is_pending=True,
|
|
)
|
|
db.add(user); db.commit()
|
|
return {"ok": True}
|
|
|
|
@router.get("/me")
|
|
def me(current_user: models.User = Depends(get_current_user)):
|
|
return {
|
|
"id": current_user.id,
|
|
"username": current_user.username,
|
|
"role": current_user.role,
|
|
"name": current_user.name,
|
|
"company": current_user.company,
|
|
}
|