diff --git a/backend/app/crud/onboarding.py b/backend/app/crud/onboarding.py index 7cfdddb6f..e754414d0 100644 --- a/backend/app/crud/onboarding.py +++ b/backend/app/crud/onboarding.py @@ -9,6 +9,7 @@ get_project_by_name, get_user_by_email, ) +from app.crud.user_project import add_user_to_project from app.models import ( APIKey, Credential, @@ -90,6 +91,19 @@ def onboard_project( session.add(user) session.flush() + _, mapping_status = add_user_to_project( + session=session, + email=user.email, + organization_id=organization.id, + project_id=project.id, + full_name=onboard_in.user_name, + ) + if mapping_status == "different_project": + raise HTTPException( + status_code=409, + detail=(f"User '{user.email}' is already associated with another project"), + ) + raw_key, key_prefix, key_hash = api_key_manager.generate() api_key = APIKey( diff --git a/backend/app/tests/crud/test_onboarding.py b/backend/app/tests/crud/test_onboarding.py index a082fa75e..b9514dbf0 100644 --- a/backend/app/tests/crud/test_onboarding.py +++ b/backend/app/tests/crud/test_onboarding.py @@ -9,6 +9,7 @@ get_user_by_email, get_organization_by_id, ) +from app.crud.user_project import add_user_to_project from app.models import ( OnboardingRequest, OnboardingResponse, @@ -151,6 +152,33 @@ def test_onboard_project_existing_user(db: Session) -> None: assert project is not None +def test_onboard_project_user_already_in_another_project(db: Session) -> None: + """Onboarding must 409 when the user is already mapped to a different project.""" + existing_project = create_test_project(db) + existing_user = create_random_user(db) + + add_user_to_project( + session=db, + email=existing_user.email, + organization_id=existing_project.organization_id, + project_id=existing_project.id, + ) + db.commit() + + onboard_request = OnboardingRequest( + organization_name="TestOrgOnboardDifferent", + project_name="TestProjectOnboardDifferent", + email=existing_user.email, + password=random_lower_string(), + ) + + with pytest.raises(HTTPException) as exc_info: + onboard_project(session=db, onboard_in=onboard_request) + + assert exc_info.value.status_code == 409 + assert "already associated with another project" in str(exc_info.value.detail) + + def test_onboard_project_duplicate_project_name(db: Session) -> None: """Test that onboarding fails when project name already exists in organization.""" # Create existing project