feat: 전문적이고 모던한 OAuth 로그인 UI 구현

- AiMond Authorization 브랜딩 적용
- 다크모드 기반 글래스모피즘 디자인
- 애니메이션 효과 (플로팅, 그라디언트, 포커스)
- React Router 기반 라우팅 구조
- AuthContext를 통한 인증 상태 관리
- 대시보드 및 관리 페이지 기본 구조
- Backend API 엔드포인트 구조 개선
- pymongo 호환성 문제 수정

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Claude
2025-08-31 11:07:06 +09:00
parent c03619bdb6
commit b773ef1b3c
20 changed files with 1130 additions and 83 deletions

View File

@ -0,0 +1,25 @@
from fastapi import APIRouter, Depends, HTTPException
from typing import List
from app.core.security import get_current_user, require_admin
from app.models.user import User
router = APIRouter()
@router.get("/users", dependencies=[Depends(require_admin)])
async def get_all_users():
# TODO: Implement get all users logic
return {"users": []}
@router.get("/stats", dependencies=[Depends(require_admin)])
async def get_system_stats():
# TODO: Implement system statistics logic
return {
"total_users": 0,
"total_applications": 0,
"active_sessions": 0
}
@router.post("/users/{user_id}/role", dependencies=[Depends(require_admin)])
async def update_user_role(user_id: str, role: str):
# TODO: Implement role update logic
return {"message": f"User {user_id} role updated to {role}"}

View File

@ -0,0 +1,37 @@
from fastapi import APIRouter, Depends, HTTPException
from typing import List
from app.core.security import get_current_user
from app.models.user import User
from app.models.application import Application
router = APIRouter()
@router.get("/", response_model=List[Application])
async def get_applications(current_user: User = Depends(get_current_user)):
# TODO: Implement application list logic
return []
@router.post("/", response_model=Application)
async def create_application(
app_data: dict,
current_user: User = Depends(get_current_user)
):
# TODO: Implement application creation logic
return {"message": "Application created"}
@router.put("/{app_id}")
async def update_application(
app_id: str,
app_data: dict,
current_user: User = Depends(get_current_user)
):
# TODO: Implement application update logic
return {"message": f"Application {app_id} updated"}
@router.delete("/{app_id}")
async def delete_application(
app_id: str,
current_user: User = Depends(get_current_user)
):
# TODO: Implement application deletion logic
return {"message": f"Application {app_id} deleted"}

View File

@ -0,0 +1,38 @@
from fastapi import APIRouter, HTTPException, Depends, status
from fastapi.security import OAuth2PasswordRequestForm
from app.core.security import create_access_token, get_current_user
from app.models.user import User
from app.core.config import settings
router = APIRouter()
@router.post("/login")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
# TODO: Implement actual authentication
return {
"access_token": create_access_token({"sub": form_data.username}),
"token_type": "bearer"
}
@router.post("/logout")
async def logout(current_user: User = Depends(get_current_user)):
# TODO: Implement logout logic
return {"message": "Logged out successfully"}
@router.post("/refresh")
async def refresh_token(current_user: User = Depends(get_current_user)):
# TODO: Implement token refresh logic
return {
"access_token": create_access_token({"sub": current_user.email}),
"token_type": "bearer"
}
@router.get("/authorize")
async def authorize():
# TODO: Implement OAuth authorization
return {"message": "Authorization endpoint"}
@router.post("/token")
async def token():
# TODO: Implement OAuth token endpoint
return {"message": "Token endpoint"}

View File

@ -0,0 +1,25 @@
from fastapi import APIRouter, Depends, HTTPException
from app.core.security import get_current_user
from app.models.user import User
router = APIRouter()
@router.get("/me")
async def get_me(current_user: User = Depends(get_current_user)):
return current_user
@router.put("/me")
async def update_me(
user_update: dict,
current_user: User = Depends(get_current_user)
):
# TODO: Implement user update logic
return {"message": "User updated", "user": current_user}
@router.post("/me/password")
async def change_password(
password_data: dict,
current_user: User = Depends(get_current_user)
):
# TODO: Implement password change logic
return {"message": "Password changed successfully"}

View File

@ -0,0 +1,51 @@
from datetime import datetime, timedelta
from typing import Optional, Dict, Any
from jose import JWTError, jwt
from passlib.context import CryptContext
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from app.core.config import settings
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login")
def verify_password(plain_password: str, hashed_password: str) -> bool:
return pwd_context.verify(plain_password, hashed_password)
def get_password_hash(password: str) -> str:
return pwd_context.hash(password)
def create_access_token(data: Dict[str, Any], expires_delta: Optional[timedelta] = None) -> str:
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
return encoded_jwt
async def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
except JWTError:
raise credentials_exception
# TODO: Get user from database
return {"email": username, "role": "user"}
async def require_admin(current_user = Depends(get_current_user)):
if current_user.get("role") != "system_admin":
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Not enough permissions"
)
return current_user