From 484c0d4aeb2f7381b7b99a25f084927d1c65beac Mon Sep 17 00:00:00 2001 From: timmy Date: Fri, 7 Aug 2026 05:52:28 +0000 Subject: [PATCH] perf: bound My Work authorization requests (#171) --- src/gitea_proxy.py | 52 +++++++++++++-------- tests/test_gitea_work_search.py | 80 +++++++++++++++++++++------------ 2 files changed, 85 insertions(+), 47 deletions(-) diff --git a/src/gitea_proxy.py b/src/gitea_proxy.py index 8f86b9b..1216cd3 100644 --- a/src/gitea_proxy.py +++ b/src/gitea_proxy.py @@ -544,25 +544,29 @@ async def issue_detail(repository: str, number: int) -> dict: } -async def _work_contains(stream: str, repository: str, number: int) -> bool: - page = 1 - while page <= 100: - result = await work_page(stream, page) - if any( - item.get("number") == number - and isinstance(item.get("repository"), dict) - and item["repository"].get("full_name") == repository - for item in result["items"] - ): - return True - if not result["has_more"]: - return False - page += 1 - return False +async def _current_login_and_target(path: str) -> tuple[str, dict]: + user, target = await asyncio.gather(current_user(), fetch(path)) + login = user.get("login") if isinstance(user, dict) else None + if not isinstance(login, str) or not login or not isinstance(target, dict): + return "", {} + return login, target + + +def _login_in_users(login: str, value: object) -> bool: + return isinstance(value, list) and any( + isinstance(user, dict) and user.get("login") == login for user in value + ) async def is_assigned_issue(repository: str, number: int) -> bool: - return await _work_contains("issue", repository, number) + login, issue = await _current_login_and_target( + f"repos/{repository}/issues/{number}" + ) + return ( + issue.get("state") == "open" + and not isinstance(issue.get("pull_request"), dict) + and _login_in_users(login, issue.get("assignees")) + ) async def pull_requests() -> WorkItems: @@ -592,11 +596,23 @@ async def pull_requests() -> WorkItems: async def is_requested_review(repository: str, number: int) -> bool: - return await _work_contains("review", repository, number) + login, pull = await _current_login_and_target( + f"repos/{repository}/pulls/{number}" + ) + return ( + pull.get("state") == "open" + and _login_in_users(login, pull.get("requested_reviewers")) + ) async def is_assigned_pull(repository: str, number: int) -> bool: - return await _work_contains("pull", repository, number) + login, pull = await _current_login_and_target( + f"repos/{repository}/pulls/{number}" + ) + return ( + pull.get("state") == "open" + and _login_in_users(login, pull.get("assignees")) + ) async def pull_completion_detail(repository: str, number: int) -> dict: diff --git a/tests/test_gitea_work_search.py b/tests/test_gitea_work_search.py index 86a0989..14353c5 100644 --- a/tests/test_gitea_work_search.py +++ b/tests/test_gitea_work_search.py @@ -142,53 +142,75 @@ async def test_pull_request_searches_start_concurrently(monkeypatch): @pytest.mark.anyio -async def test_requested_review_guard_uses_only_dedicated_review_search(monkeypatch): +async def test_requested_review_guard_uses_direct_pull_and_current_user(monkeypatch): requested = [] - async def fake_page(stream, page=1, limit=50): - requested.append((stream, page)) - items = [] if page == 1 else [{ - "number": 77, - "repository": {"full_name": "stackchain/api"}, - }] + async def fake_fetch(path): + requested.append(path) + if path == "user": + return {"login": "timmy"} + assert path == "repos/stackchain/api/pulls/77" return { - "stream": stream, "items": items, "page": page, - "total": 51, "has_more": page == 1, + "state": "open", + "requested_reviewers": [{"login": "timmy"}], } - monkeypatch.setattr(gitea_proxy, "work_page", fake_page) + async def reject_search(*args, **kwargs): + raise AssertionError("authorization must not scan review search pages") + + monkeypatch.setattr(gitea_proxy, "fetch", fake_fetch) + monkeypatch.setattr(gitea_proxy, "work_page", reject_search) assert await gitea_proxy.is_requested_review("stackchain/api", 77) is True - assert await gitea_proxy.is_requested_review("stackchain/api", 9) is False - assert requested == [ - ("review", 1), ("review", 2), - ("review", 1), ("review", 2), - ] + assert sorted(requested) == ["repos/stackchain/api/pulls/77", "user"] @pytest.mark.anyio -async def test_assignment_guards_find_eligible_items_beyond_first_page(monkeypatch): +async def test_assigned_issue_guard_uses_direct_target_and_current_user(monkeypatch): requested = [] - async def fake_page(stream, page=1, limit=50): - requested.append((stream, page)) + async def fake_fetch(path): + requested.append(path) + if path == "user": + return {"login": "timmy"} + assert path == "repos/stackchain/api/issues/77" return { - "stream": stream, - "items": [] if page == 1 else [{ - "number": 77, - "repository": {"full_name": "stackchain/api"}, - }], - "page": page, "total": 51, "has_more": page == 1, + "state": "open", + "assignees": [{"login": "timmy"}], } - monkeypatch.setattr(gitea_proxy, "work_page", fake_page) + async def reject_search(*args, **kwargs): + raise AssertionError("authorization must not scan work search pages") + + monkeypatch.setattr(gitea_proxy, "fetch", fake_fetch) + monkeypatch.setattr(gitea_proxy, "work_page", reject_search) assert await gitea_proxy.is_assigned_issue("stackchain/api", 77) is True + assert sorted(requested) == ["repos/stackchain/api/issues/77", "user"] + + +@pytest.mark.anyio +async def test_assigned_pull_guard_uses_direct_target_and_current_user(monkeypatch): + requested = [] + + async def fake_fetch(path): + requested.append(path) + if path == "user": + return {"login": "timmy"} + assert path == "repos/stackchain/api/pulls/77" + return { + "state": "open", + "assignees": [{"login": "timmy"}], + } + + async def reject_search(*args, **kwargs): + raise AssertionError("authorization must not scan work search pages") + + monkeypatch.setattr(gitea_proxy, "fetch", fake_fetch) + monkeypatch.setattr(gitea_proxy, "work_page", reject_search) + assert await gitea_proxy.is_assigned_pull("stackchain/api", 77) is True - assert requested == [ - ("issue", 1), ("issue", 2), - ("pull", 1), ("pull", 2), - ] + assert sorted(requested) == ["repos/stackchain/api/pulls/77", "user"] @pytest.mark.anyio