feat(M02): 조합 키 하나 읽기 /api/m02/combos/key/{키} — 어느 층이든 · 그 층 읽기 권한(PLAN 27-2c 서버)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BU9gbNE3aWFUvE61pS2WGt
This commit is contained in:
@@ -84,6 +84,17 @@ def find(key: str) -> dict[str, Any] | None:
|
||||
return next((r for r in _rows_at(_file(key)) if str(r.get("키")) == key), None)
|
||||
|
||||
|
||||
def where(key: str) -> tuple[str, str | None] | None:
|
||||
"""키의 층 · 주인 — ("system", None) · ("company", "7") · ("personal", "7/42") · 모르면 None."""
|
||||
key = str(key or "")
|
||||
got, path = _HEAD.match(key), _file(key)
|
||||
if key.startswith(MASTER) or path is None or not got:
|
||||
return ("system", None) if key.startswith(MASTER) else None
|
||||
if got[1] == "C":
|
||||
return ("company", got[2])
|
||||
return ("personal", f"{path.parent.parent.parent.name}/{got[2]}") # {회사}/{사용자}/templates
|
||||
|
||||
|
||||
def names() -> dict[str, str]:
|
||||
"""지금 층이 쓸 수 있는 조합 키 → 이름(마스터 · 회사 · 개인)."""
|
||||
out: dict[str, str] = {}
|
||||
|
||||
@@ -67,6 +67,16 @@ def get_all(session: Session = Depends(verify_session)) -> list[dict]:
|
||||
return out
|
||||
|
||||
|
||||
@router.get("/combos/key/{key}")
|
||||
def get_by_key(key: str, session: Session = Depends(verify_session)) -> dict:
|
||||
"""키 하나(어느 층이든 · 그 층 읽기 권한) — `{layer, owner, 판, combo, 줄, …}`."""
|
||||
got = combos.where(key)
|
||||
if got is None:
|
||||
raise HTTPException(status_code=404, detail=f"없는 조합 「{key}」")
|
||||
layer, owner = got
|
||||
return {"layer": layer, "owner": owner, **_call(_root(session, layer, owner), combos.one, key)}
|
||||
|
||||
|
||||
@router.get("/layers/{layer}/combos")
|
||||
def get_combos(layer: Layer, owner: str | None = None, session: Session = Depends(verify_session)):
|
||||
return _call(_root(session, layer, owner), combos.listing)
|
||||
|
||||
@@ -223,6 +223,13 @@ def test_세_층_목록_고르기_남의_층_403_갈라_낸_것은_그_층에(wo
|
||||
assert [r["키"] for r in all_[1]["줄"]] == [uc] and [r["키"] for r in all_[2]["줄"]] == [up]
|
||||
assert combos.find(uc)["이름"] == "회사 조합" and combos.find(up)["이름"] == "내 조합"
|
||||
assert combos.find("UP42-999999") is None and combos.find("엉터리") is None
|
||||
by_key = me.get(f"/api/m02/combos/key/{up}").json()
|
||||
assert (by_key["layer"], by_key["owner"], by_key["combo"]["키"]) == ("personal", "7/42", up)
|
||||
assert me.get(f"/api/m02/combos/key/{uc}").json()["owner"] == "7"
|
||||
assert me.get("/api/m02/combos/key/UP42-999999").status_code == 404
|
||||
world["session"]["company_id"] = 8 # 다른 회사 사람 — 남의 회사 조합은 못 봄
|
||||
assert me.get(f"/api/m02/combos/key/{uc}").status_code == 403
|
||||
world["session"]["company_id"] = 7
|
||||
|
||||
column = me.post(
|
||||
"/api/m02/layers/personal/tree",
|
||||
|
||||
Reference in New Issue
Block a user