fix(packs-lab): 누락된 A1-A3 파일 복구 (Dockerfile + auth + DSM client + tests)

Tasks A1-A3 의 파일이 working tree에 있었으나 git에 stage되지 않은 상태에서
A4 commit이 진행되어 routes.py 의 import (auth, dsm_client)가 깨진 상태였음.
복구: 8 files 일괄 commit.

- packs-lab/Dockerfile
- packs-lab/app/__init__.py
- packs-lab/app/requirements.txt
- packs-lab/app/auth.py (HMAC verify_request_hmac + verify_upload_token)
- packs-lab/app/dsm_client.py (DSM 7.x Sharing.create wrapper)
- packs-lab/tests/{__init__.py, test_auth.py}
- packs-lab/pytest.ini
This commit is contained in:
2026-05-02 08:53:26 +09:00
parent eb547a0367
commit 7a7e3d1ce0
8 changed files with 300 additions and 0 deletions

View File

@@ -0,0 +1 @@
# packs-lab tests

View File

@@ -0,0 +1,85 @@
"""HMAC 인증 단위 테스트.
- verify_request_hmac: Vercel ↔ backend 요청 시그니처 검증
- verify_upload_token: 일회성 업로드 토큰 검증 (jti 단발성)
"""
import json
import os
import time
import uuid
import pytest
from fastapi import HTTPException
# 환경변수 먼저 세팅 (auth import 전)
os.environ["BACKEND_HMAC_SECRET"] = "test-secret-32-bytes-XXXXXXXXXXXX"
from app import auth # noqa: E402
def test_verify_request_hmac_valid():
body = b'{"file_path":"/x"}'
ts = str(int(time.time()))
sig = auth._sign(ts.encode() + b"." + body)
auth.verify_request_hmac(body, ts, sig) # 예외 X
def test_verify_request_hmac_expired():
body = b'{}'
old_ts = str(int(time.time()) - 600) # 10분 전
sig = auth._sign(old_ts.encode() + b"." + body)
with pytest.raises(HTTPException) as exc:
auth.verify_request_hmac(body, old_ts, sig)
assert exc.value.status_code == 401
def test_verify_request_hmac_wrong_sig():
body = b'{}'
ts = str(int(time.time()))
with pytest.raises(HTTPException):
auth.verify_request_hmac(body, ts, "deadbeef")
def test_upload_token_roundtrip():
payload = {
"tier": "master",
"label": "샘플 영상",
"filename": "sample.mp4",
"size_bytes": 1024,
"expires_at": int(time.time()) + 600,
"jti": uuid.uuid4().hex,
}
token = auth.mint_upload_token(payload)
decoded = auth.verify_upload_token(token)
assert decoded["filename"] == "sample.mp4"
assert decoded["jti"] == payload["jti"]
def test_upload_token_replay_rejected():
payload = {
"tier": "starter",
"label": "x",
"filename": "y.pdf",
"size_bytes": 1,
"expires_at": int(time.time()) + 600,
"jti": uuid.uuid4().hex,
}
token = auth.mint_upload_token(payload)
auth.verify_upload_token(token) # 첫 사용 OK
with pytest.raises(HTTPException) as exc:
auth.verify_upload_token(token) # 재사용
assert "이미" in exc.value.detail or "used" in exc.value.detail.lower()
def test_upload_token_expired():
payload = {
"tier": "starter",
"label": "x",
"filename": "y.pdf",
"size_bytes": 1,
"expires_at": int(time.time()) - 100,
"jti": uuid.uuid4().hex,
}
token = auth.mint_upload_token(payload)
with pytest.raises(HTTPException):
auth.verify_upload_token(token)