diff --git a/pulp_service/pulp_service/tests/functional/test_lightwell_content_listing_permission.py b/pulp_service/pulp_service/tests/functional/test_lightwell_content_listing_permission.py index 30ebf80c..076d52c3 100644 --- a/pulp_service/pulp_service/tests/functional/test_lightwell_content_listing_permission.py +++ b/pulp_service/pulp_service/tests/functional/test_lightwell_content_listing_permission.py @@ -148,20 +148,32 @@ def test_domain_owner_can_list_content(configure_lightwell_domain): def test_entitled_org_post_denied_on_content_endpoint(configure_lightwell_domain): """A subscribed user cannot POST to a content listing endpoint -- the subscription check only applies to SAFE_METHODS (GET/HEAD/OPTIONS), so the POST falls through to the typed - content-create policy. - - That policy never yields a clean 403 for this request: pulpcore's create conditions - (has_required_repo_perms_on_upload / has_upload_param_model_or_domain_or_obj_perms) call - serializer.is_valid(raise_exception=True) before deciding authorization, so the empty body - 400s during permission evaluation. The assertion is therefore "POST is rejected, not - granted" -- a subscription grant would only ever turn a SAFE read into a 200, never a POST - into a 2xx.""" - content_url, _, _ = configure_lightwell_domain + content-create policy and is denied. + + Send a complete, valid file-upload body (file + relative_path + repository) so the request + clears multipart parsing and pulpcore's create conditions -- which call + serializer.is_valid(raise_exception=True) before deciding authorization -- reach the actual + permission check. The entitled caller holds no role on the target repository, so + has_required_repo_perms_on_upload:file.modify_filerepository denies with a clean 403 rather + than the 400 an empty/JSON body would raise during serializer validation.""" + content_url, repos_url, owner_header = configure_lightwell_domain + # The upload create policy requires a repository; reuse the one the owner created in the + # fixture. The serializer's repository field is backed by Repository.objects.all(), so the + # href resolves for any authenticated caller -- it's the per-repo modify permission the + # entitled-but-unroled caller lacks that produces the 403. + repos = requests.get(repos_url, headers={"x-rh-identity": owner_header}, timeout=30).json() + repo_href = repos["results"][0]["pulp_href"] headers = {"x-rh-identity": _identity_header(LIGHTWELL_ENTITLED_ORG_ID, "entitled-post-user")} - response = requests.post(content_url, headers=headers, json={}, timeout=30) + response = requests.post( + content_url, + headers=headers, + files={"file": ("test.txt", b"test content")}, + data={"relative_path": "test.txt", "repository": repo_href}, + timeout=30, + ) - assert response.status_code in (400, 401, 403) + assert response.status_code == 403 @pytest.fixture