Files
Aislo/resources/tester/test_706_1_share_request.py
T
eomsangdonandClaude Opus 5.5 74352ec6b8 feat(회사에 올리기): 요청 장부 · 요청 · 목록 · 승인 · 거절 · 알림 봄 길 + 임시 storage 시험 (PLAN 706-1)
- 회사 층 폴더 올리기요청.json 하나 · DB 안 바꿈
- 승인 = 「회사로 복사…」와 같은 길(구조물 = 붙여넣기 · 사전조합 = 서고 복사 + 폴더 자리) · 원본 개인 것 그대로
- 권한 = M02_Layer_Access 재사용 · 일반 승인 403 · 다른 회사 장부 안 봄 · 같은 것 다시 요청 409

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 14:52:30 +09:00

130 lines
6.4 KiB
Python

"""회사에 올리기 요청 · 승인(PLAN 706-1 · `M02_Share_Request`) — 임시 storage.
① 일반 사용자 요청(구조물 항목 · 사전조합) → 장부 한 줄 · 같은 것 다시 = 409 「요청 중」.
② 회사 관리자 승인 = 회사 층 고른 폴더에 사본(원본 개인 것 그대로) · 거절 = 사유 · 요청자 알림 → 봄.
③ 권한 — 일반 승인 403 · 다른 회사 관리자는 그 요청을 못 봄(404) · 남의 회사 장부 안 봄 ·
목록은 자기 것만.
"""
from __future__ import annotations
import json
from typing import Any
from fastapi import FastAPI
from fastapi.testclient import TestClient
from common_util.common_util_auth import verify_session
from M02_MasterTemplete import M02_Labor_Router as labor_router
from M02_MasterTemplete import M02_MasterTemplete_Router_Items as items_router
from M02_MasterTemplete import M02_MasterTemplete_Router_Layers as layers_router
from M02_MasterTemplete import M02_Share_Request as share
from resources.tester import test_m02_tree as base
from resources.tester.test_m02_tree import Tree
world = base.world # 같은 임시 storage 판
URL = "/api/m02/share-requests"
def _client(world: dict[str, Any]) -> TestClient:
app = FastAPI()
for one in (layers_router, items_router, labor_router, share):
app.include_router(one.router)
app.dependency_overrides[verify_session] = lambda: world["session"]
return TestClient(app)
def _as(world: dict[str, Any], role: str = "USER", user: int = 42, company: int = 7) -> None:
world["session"].update(role=role, user_id=user, company_id=company, name=f"사람{user}")
def _mine(world: dict[str, Any], client: TestClient) -> tuple[str, str]:
"""일반 사용자 42 개인 층 — 항목 「배수/sub7임시」 · 사전조합 하나 → (항목 키, 사전조합 키)."""
_as(world)
t = Tree(client, "personal")
t.do(op="add-folder", 경로=[], 이름="배수")
t.do(op="add-item", 경로=["배수"], 이름="sub7임시", 단위="m")
doc = {
"문서": {"이름": "sub7임시 사전", "구분": "C 사면안정", "상세구분": "옹벽", "담은로직": []}
}
pre = client.post("/api/m02/layers/personal/library/precombo", json=doc).json()["이름"]
return t.item(["배수", "sub7임시"])["key"], pre
def test_요청_승인_거절_알림(world):
client = _client(world)
item, pre = _mine(world, client)
got = client.post(URL, json={"종류": "item", "키": item, "글": " 회사 공용으로 "})
assert got.status_code == 200, got.text
one = got.json()
assert (one["이름"], one["경로"], one["주인"], one["글"]) == (
"sub7임시",
["배수"],
"7/42",
"회사 공용으로",
)
assert client.post(URL, json={"종류": "item", "키": item}).status_code == 409 # 요청 중
two = client.post(URL, json={"종류": "precombo", "키": pre}).json()
assert client.post(URL, json={"종류": "item", "키": "SP42-999999"}).status_code == 404
assert client.post(URL, json={"종류": "precombo", "키": "SC-999999"}).status_code == 404
mine = client.get(URL).json()
assert mine["관리"] is False and [r["id"] for r in mine["줄"]] == [one["id"], two["id"]]
_as(world, "ADMIN", user=50) # 회사 7 관리자
company = Tree(client, "company")
company.do(op="add-folder", 경로=[], 이름="공용")
boss = client.get(URL).json()
assert boss["관리"] is True and len(boss["줄"]) == 2
ok = client.post(f"{URL}/{one['id']}/approve", json={"경로": ["공용"]})
assert ok.status_code == 200, ok.text
assert ok.json()["상태"] == "승인" and ok.json()["봄"] is False
company = Tree(client, "company")
assert ["공용", "sub7임시"] in company.paths() # 고른 폴더에 사본
again = client.post(f"{URL}/{one['id']}/approve", json={"경로": []})
assert again.status_code == 409 # 이미 승인
no = client.post(f"{URL}/{two['id']}/reject", json={"사유": "이름 다시"})
assert no.json()["상태"] == "거절" and no.json()["사유"] == "이름 다시"
_as(world) # 요청자 — 원본 그대로 · 결과 둘 · 봄 뒤 0
assert ["배수", "sub7임시"] in Tree(client, "personal").paths()
rows = client.get(URL).json()["줄"]
assert [(r["상태"], r["봄"]) for r in rows] == [("승인", False), ("거절", False)]
assert client.post(f"{URL}/seen").json() == {"봄": 2}
assert client.post(f"{URL}/seen").json() == {"봄": 0}
# 거절된 것은 다시 요청할 수 있음
assert client.post(URL, json={"종류": "precombo", "키": pre}).status_code == 200
def test_사전조합_승인_폴더_자리(world):
client = _client(world)
_, pre = _mine(world, client)
rid = client.post(URL, json={"종류": "precombo", "키": pre}).json()["id"]
_as(world, "ADMIN", user=50)
tree_url = "/api/m02/layers/company/precombo-tree"
now = client.get(tree_url).json()
client.post(tree_url, json={"op": "add-folder", "경로": [], "이름": "옹벽", "판": now["판"]})
made = client.post(f"{URL}/{rid}/approve", json={"경로": ["옹벽"]}).json()["사본"]
assert client.get(tree_url).json()["자리"] == {made: ["옹벽"]}
doc = client.get(f"/api/m02/layers/company/templates/precombo/{made}").json()["문서"]
assert doc["이름"] == "sub7임시 사전"
assert doc["본뜬"]["주인"] == "7/42" # 원본 표시
def test_권한_일반_승인_403_다른_회사(world):
client = _client(world)
item, _ = _mine(world, client)
rid = client.post(URL, json={"종류": "item", "키": item}).json()["id"]
assert client.post(f"{URL}/{rid}/approve", json={}).status_code == 403 # 일반 = 승인 못 함
assert client.post(f"{URL}/{rid}/reject", json={}).status_code == 403
_as(world, "USER", user=43) # 같은 회사 다른 일반 — 남의 요청 안 보임
assert client.get(URL).json()["줄"] == []
_as(world, "ADMIN", user=90, company=9) # 다른 회사 관리자
assert client.get(URL).json()["줄"] == []
assert client.post(f"{URL}/{rid}/approve", json={}).status_code == 404 # 자기 장부에 없음
assert client.get(URL, params={"company": "7"}).json()["회사"] == "9" # 남의 회사 고르기 무시
_as(world, "SYSTEM_ADMIN", user=1, company=None)
assert len(client.get(URL, params={"company": "7"}).json()["줄"]) == 1
ledger = world["storage"] / "7" / "templates" / share.FILE
assert json.loads(ledger.read_bytes())["줄"][0]["상태"] == "요청"