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:
parent
3c8923c075
commit
3b1719666f
@ -46,7 +46,10 @@ backend/
|
|||||||
| POST | `/v1/auth/create` | 계정 생성 (pw bcrypt 해시) |
|
| POST | `/v1/auth/create` | 계정 생성 (pw bcrypt 해시) |
|
||||||
| POST | `/v1/auth/login` | 로그인, access/refresh 토큰 발급 |
|
| POST | `/v1/auth/login` | 로그인, access/refresh 토큰 발급 |
|
||||||
| POST | `/v1/auth/refresh_token` | access 토큰 재발급 (refresh 필요) |
|
| POST | `/v1/auth/refresh_token` | access 토큰 재발급 (refresh 필요) |
|
||||||
|
| POST | `/v1/auth/logout` | 로그아웃, 저장 토큰 폐기 (access 토큰 필요) |
|
||||||
| GET | `/v1/auth/me` | 내 정보 (access 토큰 필요) |
|
| GET | `/v1/auth/me` | 내 정보 (access 토큰 필요) |
|
||||||
|
| GET | `/v1/auth/popup/status` | 팝업 '안내 보지 않기' 저장 상태 (access 토큰 필요) |
|
||||||
|
| POST | `/v1/auth/popup/hide` | 팝업 안내 보지 않기 영구 저장 (access 토큰 필요) |
|
||||||
|
|
||||||
## 실행 / 테스트
|
## 실행 / 테스트
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@ -217,7 +217,7 @@ class UserCRUD(IUserCRUD):
|
|||||||
return err_type, None
|
return err_type, None
|
||||||
if len(row_list) != 1:
|
if len(row_list) != 1:
|
||||||
return ErrorType.DB_INVALID_KEY, None
|
return ErrorType.DB_INVALID_KEY, None
|
||||||
return ErrorType.SUCCESS, bool(row_list[0])
|
return ErrorType.SUCCESS, row_list[0]
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
LOG.e_no_callstack(ex)
|
LOG.e_no_callstack(ex)
|
||||||
return ErrorType.DB_RUN_FAILED, None
|
return ErrorType.DB_RUN_FAILED, None
|
||||||
|
|||||||
@ -65,6 +65,20 @@ async def logout(user_info: UserInfo = Depends(IsValidAccessToken), service: Aut
|
|||||||
return RemoveNoneResponse(await service.logout(user_info))
|
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(
|
@router.get(
|
||||||
path="/popup/status",
|
path="/popup/status",
|
||||||
response_model=Res_PopupStatus,
|
response_model=Res_PopupStatus,
|
||||||
@ -92,17 +106,3 @@ async def hide_popup(
|
|||||||
service: AuthService = Depends(),
|
service: AuthService = Depends(),
|
||||||
):
|
):
|
||||||
return RemoveNoneResponse(await service.hide_popup(user_info, credentials.credentials, req.popup_type))
|
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))
|
|
||||||
|
|||||||
@ -371,3 +371,8 @@ async def test_popup_hide_invalid_type(client, account_seed):
|
|||||||
async def test_popup_status_without_token(client):
|
async def test_popup_status_without_token(client):
|
||||||
r = await client.get("/v1/auth/popup/status")
|
r = await client.get("/v1/auth/popup/status")
|
||||||
assert r.status_code in (401, 403)
|
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 가 자격증명 없음을 거부
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user