refactor(auth): popup API 리뷰 개선 + 무토큰 테스트 보강

원작성자 컨벤션 대조 리뷰 반영.

- README 엔드포인트 표에 logout·popup/status·popup/hide 추가(누락분 포함)
- user_crud: get_hide_service_info 의 불필요한 bool() 캐스트 제거
  (execute 가 단일 컬럼 select 에서 이미 스칼라 반환 — get_supplier_name 과 동일)
- account: popup 라우터를 me 뒤로 이동(로그인→계정→토큰→내정보→팝업 흐름)
- test_auth: test_popup_hide_without_token 추가(me 섹션과 무토큰 가드 대칭)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
민헌 2026-07-07 14:36:37 +09:00
parent 3c8923c075
commit 3b1719666f
4 changed files with 23 additions and 15 deletions

View File

@ -46,7 +46,10 @@ backend/
| POST | `/v1/auth/create` | 계정 생성 (pw bcrypt 해시) |
| POST | `/v1/auth/login` | 로그인, access/refresh 토큰 발급 |
| POST | `/v1/auth/refresh_token` | access 토큰 재발급 (refresh 필요) |
| POST | `/v1/auth/logout` | 로그아웃, 저장 토큰 폐기 (access 토큰 필요) |
| GET | `/v1/auth/me` | 내 정보 (access 토큰 필요) |
| GET | `/v1/auth/popup/status` | 팝업 '안내 보지 않기' 저장 상태 (access 토큰 필요) |
| POST | `/v1/auth/popup/hide` | 팝업 안내 보지 않기 영구 저장 (access 토큰 필요) |
## 실행 / 테스트
```bash

View File

@ -217,7 +217,7 @@ class UserCRUD(IUserCRUD):
return err_type, None
if len(row_list) != 1:
return ErrorType.DB_INVALID_KEY, None
return ErrorType.SUCCESS, bool(row_list[0])
return ErrorType.SUCCESS, row_list[0]
except Exception as ex:
LOG.e_no_callstack(ex)
return ErrorType.DB_RUN_FAILED, None

View File

@ -65,6 +65,20 @@ async def logout(user_info: UserInfo = Depends(IsValidAccessToken), service: Aut
return RemoveNoneResponse(await service.logout(user_info))
@router.get(
path="/me",
response_model=Res_Me,
summary="내 정보 (보호된 엔드포인트)",
description="access 토큰 검증(validator) 후 su_id DB 존재/활성 + 저장 토큰 대조를 service 에서 확인해 반환한다.",
)
async def me(
user_info: UserInfo = Depends(IsValidAccessToken),
credentials: HTTPAuthorizationCredentials = Depends(security),
service: AuthService = Depends(),
):
return RemoveNoneResponse(await service.get_me(user_info, credentials.credentials))
@router.get(
path="/popup/status",
response_model=Res_PopupStatus,
@ -92,17 +106,3 @@ async def hide_popup(
service: AuthService = Depends(),
):
return RemoveNoneResponse(await service.hide_popup(user_info, credentials.credentials, req.popup_type))
@router.get(
path="/me",
response_model=Res_Me,
summary="내 정보 (보호된 엔드포인트)",
description="access 토큰 검증(validator) 후 su_id DB 존재/활성 + 저장 토큰 대조를 service 에서 확인해 반환한다.",
)
async def me(
user_info: UserInfo = Depends(IsValidAccessToken),
credentials: HTTPAuthorizationCredentials = Depends(security),
service: AuthService = Depends(),
):
return RemoveNoneResponse(await service.get_me(user_info, credentials.credentials))

View File

@ -371,3 +371,8 @@ async def test_popup_hide_invalid_type(client, account_seed):
async def test_popup_status_without_token(client):
r = await client.get("/v1/auth/popup/status")
assert r.status_code in (401, 403)
async def test_popup_hide_without_token(client):
r = await client.post("/v1/auth/popup/hide", json={"popup_type": "service_info"})
assert r.status_code in (401, 403) # HTTPBearer 가 자격증명 없음을 거부