Skip to content

[US-11.10 / OBT-239] Expose the authenticated user's managed project IDs - #93

Open
levigtri wants to merge 9 commits into
mainfrom
levigft/obt-239-us-1110-expose-the-authenticated-users-managed-project-ids
Open

[US-11.10 / OBT-239] Expose the authenticated user's managed project IDs#93
levigtri wants to merge 9 commits into
mainfrom
levigft/obt-239-us-1110-expose-the-authenticated-users-managed-project-ids

Conversation

@levigtri

@levigtri levigtri commented Jul 4, 2026

Copy link
Copy Markdown
Member

[US-11.10 / OBT-239] Expose the authenticated user's managed project IDs

Summary

Adds GET /api/auth/my-managed-projects returning the projects the current user manages, so the console can derive manager status consistently with the backend's per-project scoping (US-12.9).

Changes

1. Response schema

app/models/auth.py — new MyManagedProjectsResponse (managed_project_ids: list[str]).

2. Endpoint

app/api/auth.pyGET /api/auth/my-managed-projects protected by get_current_user, returning get_managed_project_ids(db, user.id). Mirrors my-managed-orgs.

Type of Change

  • Feature (new read-only endpoint)

Testing

  • Auth user → { managed_project_ids: [...] }; unauth → 401. Covered by tests/test_console_scoping.py.

Summary by CodeRabbit

  • New Features
    • Added an authenticated My Managed Projects endpoint and response model.
    • Introduced an admin-or-manager guard for console listings of projects, organizations, languages, and phases (admins still see all).
  • Bug Fixes
    • Updated authorization to base project access checks on project manager role scope.
    • Scoping now consistently filters organizations, languages, and phases to managed projects for non-admins.
    • Restricted project access-management updates to platform administrators.
  • Tests
    • Added and updated tests for managed-project scoping, empty-input behavior, and manager-only authorization rules.

@levigtri levigtri self-assigned this Jul 4, 2026
levigtri added 4 commits July 4, 2026 17:30
Non-admin users receive only the data tied to the projects they manage (ProjectUserAccess.role
== "manager"), instead of the full dataset: organizations linked to those projects,
the languages of those projects, and the phases attached to them. Platform admins are
unaffected and continue to see everything.

Adds get_managed_project_ids and per-domain "by projects" services
(list_organizations_by_projects, list_languages_by_projects, list_phases_by_projects and
list_phases_with_deps_by_projects), replacing the earlier organization-based scoping to align
with the 2026-07 per-project manager model. Wires them into the organizations, languages and
phases list endpoints.
…project manager rule

Adds require_admin_or_manager and applies it to the console content routers (organizations,
projects, languages, phases), so users who are neither platform admins nor managers of any
organization or project now receive 403 instead of an empty 200 list.

Enforces the 2026-07 per-project manager rule on the projects surface: a non-admin may only view
and manage the projects on which they hold the manager role. list_projects_for_user returns only
the caller's managed projects and assert_project_access denies project detail, access and phase
sub-routes for projects outside that set. Reuses get_managed_project_ids (US-11.6) and adds the
is_project_manager and list_projects_by_ids services. Updates the affected tests.
The project Access-tab role update endpoint (PATCH /api/projects/{project_id}/access/users/
{user_id}) now requires platform admin. Organization/project managers and other users who
merely have access to the project receive 403; unauthenticated requests still receive 401.

The backend becomes the source of truth for the admin-only role rule (the frontend gate lives
in US-12.8). The update_user_access_role service is unchanged; authorization is enforced in the
router per backend guidelines.
Adds GET /api/auth/my-managed-projects returning { "managed_project_ids": [...] } for the current
user, resolved via get_managed_project_ids (projects where the user's access role is manager).
The endpoint mirrors my-managed-orgs and is protected by get_current_user, letting the console
derive manager status consistently with the backend's per-project scoping (US-12.9).
@levigtri
levigtri force-pushed the levigft/obt-239-us-1110-expose-the-authenticated-users-managed-project-ids branch from 48b4335 to 17d9664 Compare July 4, 2026 20:35
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: QUIET

Plan: Pro Plus

Run ID: 924ef501-8408-45c1-85fa-f7088209c001

📥 Commits

Reviewing files that changed from the base of the PR and between 9993213 and fe18be4.

📒 Files selected for processing (2)
  • app/main.py
  • tests/baker.py
💤 Files with no reviewable changes (1)
  • tests/baker.py

📝 Walkthrough

Walkthrough

Changes

Project manager scope is derived from project access roles and applied to console routers, resource listings, project access checks, and project listing endpoints. Platform admins retain unrestricted listing access, while access-role updates require platform-admin authorization. A managed-projects endpoint and scope tests were added.

Console scoping and authorization

Layer / File(s) Summary
Scope and access primitives
app/core/org_scope.py, app/services/project/*
Managed project IDs and project-manager checks use manager-role assignments, with new project service exports.
Project-scoped listing services
app/services/language/*, app/services/org/*, app/services/phase/*, app/services/project/*
Language, organization, phase, and project listings support project-ID filtering; user project listing now starts from managed projects.
Authorization and API wiring
app/core/auth_middleware.py, app/main.py, app/api/languages.py, app/api/organizations.py, app/api/phases.py, app/api/projects/*
Console routers require admin-or-manager scope, listing endpoints branch by admin status, and access-role updates require platform-admin authorization.
Managed-project response endpoint
app/models/auth.py, app/api/auth.py
Adds MyManagedProjectsResponse and an authenticated /my-managed-projects endpoint.
Scope and authorization validation
tests/baker.py, tests/test_console_scoping.py, tests/test_project_org_filter.py
Tests validate manager-only scope, project-filtered listings, project filtering, and access authorization.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant ConsoleRouter
  participant AuthDependency
  participant ScopeHelper
  participant ListingService
  Client->>ConsoleRouter: request console resource list
  ConsoleRouter->>AuthDependency: validate admin or manager
  AuthDependency->>ScopeHelper: resolve managed project IDs
  ScopeHelper-->>AuthDependency: project IDs
  AuthDependency-->>ConsoleRouter: authorized user
  ConsoleRouter->>ListingService: list resources for project IDs
  ListingService-->>Client: scoped response
Loading

Suggested reviewers: caliridaniel, henokteixeira, joaocarvoli

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: exposing the authenticated user's managed project IDs.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch levigft/obt-239-us-1110-expose-the-authenticated-users-managed-project-ids

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
app/services/phase/list_phases_by_projects.py (1)

8-27: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add concise docstrings to the new public service functions. All four newly added public service functions omit the docstrings required by guidelines for app/services/**/*.py.

  • app/services/phase/list_phases_by_projects.py#L8-L27: add a one-line docstring to list_phases_by_projects describing the project-scoped phase listing contract (including the project_id narrowing behavior).
  • app/services/phase/list_phases_by_projects.py#L30-L55: add a one-line docstring to list_phases_with_deps_by_projects describing the scoped dependency-map contract.
  • app/services/org/list_organizations_by_projects.py#L8-L20: add a one-line docstring to list_organizations_by_projects.
  • app/services/project/list_projects_by_ids.py#L7-L12: add a one-line docstring to list_projects_by_ids.

As per coding guidelines, "Keep service functions function-oriented and composable, with concise docstrings on public service functions."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/services/phase/list_phases_by_projects.py` around lines 8 - 27, Add
concise one-line docstrings to all four public service functions:
list_phases_by_projects in app/services/phase/list_phases_by_projects.py (lines
8-27), including its project_id narrowing behavior;
list_phases_with_deps_by_projects in
app/services/phase/list_phases_by_projects.py (lines 30-55), describing its
scoped dependency-map contract; list_organizations_by_projects in
app/services/org/list_organizations_by_projects.py (lines 8-20); and
list_projects_by_ids in app/services/project/list_projects_by_ids.py (lines
7-12). Preserve each function’s existing behavior.

Source: Coding guidelines

app/services/project/is_project_manager.py (1)

8-8: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the new public service functions.

Both functions are correct but omit the concise docstrings required for public service functions.

  • app/services/project/is_project_manager.py#L8-L8: add a concise docstring describing the manager-role check.
  • app/services/language/list_languages_by_projects.py#L8-L8: add a concise docstring describing the project-scoped language listing.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/services/project/is_project_manager.py` at line 8, Add concise docstrings
to the public functions is_project_manager in
app/services/project/is_project_manager.py at lines 8-8 and
list_languages_by_projects in
app/services/language/list_languages_by_projects.py at lines 8-8, describing the
manager-role check and project-scoped language listing respectively.

Source: Coding guidelines

app/core/auth_middleware.py (1)

26-40: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Scope lookups are recomputed per-handler instead of shared via FastAPI's dependency cache. require_admin_or_manager calls get_managed_org_ids/get_managed_project_ids as plain awaited functions rather than through Depends(...), so FastAPI's per-request dependency cache never applies; each guarded listing handler then reissues the same get_managed_project_ids query, and the is_platform_admin branch is duplicated across handlers.

  • app/core/auth_middleware.py#L26-L40: extract the org/project scope lookup into a Depends-based helper so its result can be cached and reused by downstream handlers instead of being called as a bare function.
  • app/api/languages.py#L18-L24: consume the shared scope dependency instead of re-invoking get_managed_project_ids directly.
  • app/api/organizations.py#L27-L33: consume the shared scope dependency instead of re-invoking get_managed_project_ids directly.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/core/auth_middleware.py` around lines 26 - 40, Scope lookups are
duplicated because require_admin_or_manager and guarded handlers call them
directly instead of using FastAPI dependency caching. In
app/core/auth_middleware.py lines 26-40, extract the shared org/project scope
lookup into a Depends-based helper and use it from require_admin_or_manager
while preserving the platform-admin bypass. In app/api/languages.py lines 18-24
and app/api/organizations.py lines 27-33, consume that shared dependency rather
than invoking get_managed_project_ids directly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/api/organizations.py`:
- Line 7: Update list_organizations() to include organization IDs returned by
get_managed_org_ids() alongside the existing get_managed_project_ids() scope
before applying require_admin_or_manager, ensuring users who directly manage an
organization receive it even when they manage no projects.

In `@app/api/phases.py`:
- Around line 40-43: Move the database query behind get_managed_project_ids into
an appropriate function under app/services/, then update all callers to use the
service function: app/api/phases.py lines 40-43 and 54-55, and app/api/auth.py
lines 144-145. Remove direct router usage of the core helper while preserving
the existing managed-project filtering behavior.

In `@app/core/org_scope.py`:
- Around line 12-19: Move the database query out of core function
get_managed_project_ids into a service module under app/services/project,
preserving its filtering and sorted-ID behavior. In app/core/org_scope.py,
re-export or delegate to the service function so existing consumers such as
require_admin_or_manager and routers keep their current import surface
unchanged.

---

Nitpick comments:
In `@app/core/auth_middleware.py`:
- Around line 26-40: Scope lookups are duplicated because
require_admin_or_manager and guarded handlers call them directly instead of
using FastAPI dependency caching. In app/core/auth_middleware.py lines 26-40,
extract the shared org/project scope lookup into a Depends-based helper and use
it from require_admin_or_manager while preserving the platform-admin bypass. In
app/api/languages.py lines 18-24 and app/api/organizations.py lines 27-33,
consume that shared dependency rather than invoking get_managed_project_ids
directly.

In `@app/services/phase/list_phases_by_projects.py`:
- Around line 8-27: Add concise one-line docstrings to all four public service
functions: list_phases_by_projects in
app/services/phase/list_phases_by_projects.py (lines 8-27), including its
project_id narrowing behavior; list_phases_with_deps_by_projects in
app/services/phase/list_phases_by_projects.py (lines 30-55), describing its
scoped dependency-map contract; list_organizations_by_projects in
app/services/org/list_organizations_by_projects.py (lines 8-20); and
list_projects_by_ids in app/services/project/list_projects_by_ids.py (lines
7-12). Preserve each function’s existing behavior.

In `@app/services/project/is_project_manager.py`:
- Line 8: Add concise docstrings to the public functions is_project_manager in
app/services/project/is_project_manager.py at lines 8-8 and
list_languages_by_projects in
app/services/language/list_languages_by_projects.py at lines 8-8, describing the
manager-role check and project-scoped language listing respectively.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: QUIET

Plan: Pro Plus

Run ID: a8d60b5e-35d8-4eac-b60d-83ae8b05ec09

📥 Commits

Reviewing files that changed from the base of the PR and between d669a56 and 5caf07b.

📒 Files selected for processing (23)
  • app/api/auth.py
  • app/api/languages.py
  • app/api/organizations.py
  • app/api/phases.py
  • app/api/projects/_deps.py
  • app/api/projects/access.py
  • app/core/auth_middleware.py
  • app/core/org_scope.py
  • app/main.py
  • app/models/auth.py
  • app/services/language/__init__.py
  • app/services/language/list_languages_by_projects.py
  • app/services/org/__init__.py
  • app/services/org/list_organizations_by_projects.py
  • app/services/phase/__init__.py
  • app/services/phase/list_phases_by_projects.py
  • app/services/project/__init__.py
  • app/services/project/is_project_manager.py
  • app/services/project/list_projects_by_ids.py
  • app/services/project/list_projects_for_user.py
  • tests/baker.py
  • tests/test_console_scoping.py
  • tests/test_project_org_filter.py

Comment thread app/api/organizations.py
from app.core.database import get_db
from app.core.exceptions import AuthorizationError, NotFoundError
from app.core.org_scope import get_managed_org_ids
from app.core.org_scope import get_managed_org_ids, get_managed_project_ids

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== app/api/organizations.py ==\n'
cat -n app/api/organizations.py | sed -n '1,220p'

printf '\n== app/core/auth_middleware.py ==\n'
cat -n app/core/auth_middleware.py | sed -n '1,240p'

printf '\n== app/core/org_scope.py ==\n'
cat -n app/core/org_scope.py | sed -n '1,260p'

printf '\n== search references ==\n'
rg -n "get_managed_org_ids|get_managed_project_ids|list_organizations_by_projects|require_admin_or_manager|list_organizations" app -S

Repository: shemaobt/tripod-api

Length of output: 13753


Include organizations managed directly by the user. list_organizations() only scopes non-admins through get_managed_project_ids(), so users who manage an org directly but no projects pass require_admin_or_manager and still get an empty list. Merge in get_managed_org_ids() here, or let the service accept both scopes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/api/organizations.py` at line 7, Update list_organizations() to include
organization IDs returned by get_managed_org_ids() alongside the existing
get_managed_project_ids() scope before applying require_admin_or_manager,
ensuring users who directly manage an organization receive it even when they
manage no projects.

Comment thread app/api/phases.py
Comment thread app/core/org_scope.py Outdated
@levigtri

Copy link
Copy Markdown
Member Author

@coderabbitai — decisions on this review:

  1. organizations.py (include directly-managed org IDs in list_organizations):
    Won't do. Console scoping is intentionally oriented around managed projects;
    direct organization management is being phased out, so re-introducing an
    org-based path here contradicts the current product direction.

  2. Move get_managed_project_ids DB query out of app/core/org_scope.py into
    app/services/ (with org_scope delegating so the import surface stays stable):
    Will do. Consistent with the layering already applied in this PR — the other
    scope queries were moved into services.

  3. auth_middleware.py (extract a Depends-cached scope helper):
    Won't do (nitpick). Marginal benefit for the added indirection.

  4. Docstring coverage / one-line docstrings on service functions:
    Won't do. Docstrings are intentionally omitted in this codebase.

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@levigtri, thanks for the detailed breakdown — all noted:

  1. organizations.py — understood, won't push on this given the shift away from org-level management toward project-based scoping.
  2. get_managed_project_ids → services layer — sounds good. Happy to take another look once that's moved, to confirm the org_scope delegation keeps the import surface stable.
  3. auth_middleware.py extraction — fair, agreed it's a nitpick with marginal upside.
  4. Docstrings — got it, won't flag this going forward.

Thanks for taking the time to go through these one by one.


✏️ Learnings added
Learnt from: levigtri
URL: https://github.com/shemaobt/tripod-api/pull/93

Timestamp: 2026-07-16T00:32:42.725Z
Learning: In this codebase (tripod-api), console/manager scoping is intentionally oriented around managed *projects*, not organizations. Direct organization-level management (e.g., via managed org IDs) is being phased out in favor of project-based scoping, so review suggestions to reintroduce org-based access paths (e.g., in app/api/organizations.py's list_organizations) should not be made.

Learnt from: levigtri
URL: https://github.com/shemaobt/tripod-api/pull/93

Timestamp: 2026-07-16T00:32:42.725Z
Learning: In this codebase (tripod-api), docstrings are intentionally omitted on service functions (e.g., under app/services/). Do not flag missing docstrings as a review comment.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/main.py (1)

128-153: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Scope console_guard to console-only project routes

app/main.py:128-153 applies require_admin_or_manager to the whole projects_router, but app/api/projects/core.py still exposes project list/read/update endpoints to any authenticated user with project access. This blanket guard will 403 regular project members on /api/projects. Split the console-only routes or move the dependency to those routers only.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/main.py` around lines 128 - 153, Restrict console_guard in the router
registration around projects_router so it applies only to console-only project
endpoints, not the member-accessible project list/read/update routes. Split the
project routes into separate routers or otherwise attach
require_admin_or_manager only to the console-specific router, while preserving
project access for authenticated members.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@app/main.py`:
- Around line 128-153: Restrict console_guard in the router registration around
projects_router so it applies only to console-only project endpoints, not the
member-accessible project list/read/update routes. Split the project routes into
separate routers or otherwise attach require_admin_or_manager only to the
console-specific router, while preserving project access for authenticated
members.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: QUIET

Plan: Pro Plus

Run ID: f5591363-f401-4b80-a7a7-deda918c8147

📥 Commits

Reviewing files that changed from the base of the PR and between 5caf07b and 495b73c.

📒 Files selected for processing (1)
  • app/main.py

@levigtri
levigtri requested review from joaocarvoli and removed request for joaocarvoli July 16, 2026 01:41
… layer; core delegates

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@levigtri

Copy link
Copy Markdown
Member Author

Follow-up on decision 2: done. get_managed_project_ids now lives in app/services/project/get_managed_project_ids.py — the DB query is out of app/core/org_scope.py, which just delegates to it. Existing consumers (require_admin_or_manager, the routers, list_projects_for_user) keep importing from app.core.org_scope unchanged, so there's no churn on the callers or the rest of the 11.x stack.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/services/project/get_managed_project_ids.py`:
- Around line 8-15: Add a concise public-service docstring to
get_managed_project_ids describing that it returns the sorted project IDs
managed by the specified user. Keep the query and return behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: QUIET

Plan: Pro Plus

Run ID: 10465f91-a96b-4cfa-b73d-ce8cdd44cfc0

📥 Commits

Reviewing files that changed from the base of the PR and between 495b73c and 9993213.

📒 Files selected for processing (2)
  • app/core/org_scope.py
  • app/services/project/get_managed_project_ids.py

Comment on lines +8 to +15
async def get_managed_project_ids(db: AsyncSession, user_id: str) -> list[str]:
result = await db.execute(
select(ProjectUserAccess.project_id).where(
ProjectUserAccess.user_id == user_id,
ProjectUserAccess.role == MemberRole.MANAGER,
)
)
return sorted(result.scalars().all())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add the required public service docstring.

This public service function should document that it returns the sorted project IDs managed by the specified user.

Suggested change
 async def get_managed_project_ids(db: AsyncSession, user_id: str) -> list[str]:
+    """Return sorted project IDs managed by the user."""
     result = await db.execute(

As per coding guidelines, public service functions must have concise docstrings.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async def get_managed_project_ids(db: AsyncSession, user_id: str) -> list[str]:
result = await db.execute(
select(ProjectUserAccess.project_id).where(
ProjectUserAccess.user_id == user_id,
ProjectUserAccess.role == MemberRole.MANAGER,
)
)
return sorted(result.scalars().all())
async def get_managed_project_ids(db: AsyncSession, user_id: str) -> list[str]:
"""Return sorted project IDs managed by the user."""
result = await db.execute(
select(ProjectUserAccess.project_id).where(
ProjectUserAccess.user_id == user_id,
ProjectUserAccess.role == MemberRole.MANAGER,
)
)
return sorted(result.scalars().all())
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/services/project/get_managed_project_ids.py` around lines 8 - 15, Add a
concise public-service docstring to get_managed_project_ids describing that it
returns the sorted project IDs managed by the specified user. Keep the query and
return behavior unchanged.

Source: Coding guidelines

@joaocarvoli joaocarvoli left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some comments

Comment thread app/api/projects/_deps.py
return
allowed = await project_service.can_access_project(db, user.id, project_id)
if not allowed:
is_manager = await project_service.is_project_manager(db, user.id, project_id)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can_access_project was true for any access row or via the org membership, is_project_manager only for role == manager. So every plain member and everyone that had access through the org now takes 403 on all the endpoints using this dep, not only the console ones. Is that correct? The PR is only for expose the managed project ids — if it is really intentional the name and the message "You do not have access to this project" are lying now. @levigtri

Comment thread app/main.py
app.include_router(projects_router, prefix="/api/projects", tags=["projects"])
app.include_router(phases_router, prefix="/api/phases", tags=["phases"])
app.include_router(
projects_router,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/api/projects and /api/phases are not consumed only by the console I think, and with this guard anyone that is not manager/admin somewhere takes 403 on the whole surface. Nothing of this is on the PR description ("Type of Change: Feature (new read-only endpoint)"). Just make sure here that this is really the ticket. ps: same access question of _deps.py.

…ed-users-managed-project-ids

# Conflicts:
#	app/main.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants