fix(asana): use project memberships endpoint for project IDs in connector (#13746)

### What problem does this PR solve?

Fixes a bug in the Asana connector where providing `Project IDs` caused
sync to fail with:

`project_membership: Not a recognized ID: <PROJECT_GID>`

Root cause: the connector called `get_project_membership(project_gid)`,
but that API expects a **project membership gid**, not a **project
gid**.
This PR switches to the correct project-scoped API and adds regression
tests.

Fixes: [#13669](https://github.com/infiniflow/ragflow/issues/13669)

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

### Changes made

- Updated `common/data_source/asana_connector.py`:
- Replaced `get_project_membership(pid, ...)` with
`get_project_memberships_for_project(pid, ...)`
- Trimmed and filtered `asana_project_ids` parsing to avoid
empty/whitespace IDs
  - Normalized `asana_team_id` by trimming whitespace
  - Used safer access for membership email extraction (`m.get("user")`)
- Added `test/unit_test/common/test_asana_connector.py`:
  - Verifies the correct project-membership API method is called
  - Verifies empty `project_ids` path returns workspace emails
  - Verifies project/team input normalization behavior

### Compatibility / risk

- Non-breaking bug fix
- No API contract changes
- Existing behavior for empty `Project IDs` remains unchanged
This commit is contained in:
NeedmeFordev
2026-03-24 06:21:31 -06:00
committed by GitHub
parent 7c8927c4fb
commit 840cc8fbe9

View File

@ -288,22 +288,25 @@ class AsanaAPI:
project_emails = set()
for pid in project_ids:
pid = pid.strip()
if not pid:
continue
project = self.project_api.get_project(
pid,
opts={"opt_fields": "team,privacy_setting"}
)
if project["privacy_setting"] == "private":
if project.get("privacy_setting") == "private":
if team_id and project.get("team", {}).get("gid") != team_id:
continue
memberships = self.project_memberships_api.get_project_membership(
memberships = self.project_memberships_api.get_project_memberships_for_project(
pid,
opts={"opt_fields": "user.gid,user.email"}
)
for m in memberships:
email = m["user"].get("email")
email = (m.get("user") or {}).get("email")
if email:
project_emails.add(email)
@ -338,9 +341,11 @@ class AsanaConnector(LoadConnector, PollConnector):
) -> None:
self.workspace_id = asana_workspace_id
self.project_ids_to_index: list[str] | None = (
asana_project_ids.split(",") if asana_project_ids else None
[project_id.strip() for project_id in asana_project_ids.split(",") if project_id.strip()]
if asana_project_ids
else None
)
self.asana_team_id = asana_team_id if asana_team_id else None
self.asana_team_id = asana_team_id.strip() if asana_team_id and asana_team_id.strip() else None
self.batch_size = batch_size
self.continue_on_failure = continue_on_failure
self.size_threshold = None