- 회사 층 폴더 올리기요청.json 하나 · DB 안 바꿈 - 승인 = 「회사로 복사…」와 같은 길(구조물 = 붙여넣기 · 사전조합 = 서고 복사 + 폴더 자리) · 원본 개인 것 그대로 - 권한 = M02_Layer_Access 재사용 · 일반 승인 403 · 다른 회사 장부 안 봄 · 같은 것 다시 요청 409 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
130 lines
6.4 KiB
Python
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]["상태"] == "요청"
|