Skip to content

Add tests for B2B manager permissions#3712

Merged
cp-at-mit merged 2 commits into
mainfrom
b2b-permissions-tests
Jun 30, 2026
Merged

Add tests for B2B manager permissions#3712
cp-at-mit merged 2 commits into
mainfrom
b2b-permissions-tests

Conversation

@cp-at-mit

Copy link
Copy Markdown
Contributor

What are the relevant tickets?

NA

Description (What does it do?)

Introduce a new b2b/permissions_test.py suite for IsOrganizationManager, covering both has_permission and has_object_permission. The tests verify superuser bypass, authenticated manager access, denial for non-managers/other orgs/missing org IDs, and object-level org resolution across organization_id, organization, b2b_contract, and run.b2b_contract relationships.

How can this be tested?

Tests should pass. There weren't any unit tests for this code previously.

Introduce a new `b2b/permissions_test.py` suite for `IsOrganizationManager`, covering both `has_permission` and `has_object_permission`. The tests verify superuser bypass, authenticated manager access, denial for non-managers/other orgs/missing org IDs, and object-level org resolution across `organization_id`, `organization`, `b2b_contract`, and `run.b2b_contract` relationships.
@github-actions

Copy link
Copy Markdown

OpenAPI Changes

Show/hide ## Changes for v0.yaml:
## Changes for v0.yaml:
23 changes: 0 error, 0 warning, 23 info
info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API POST /api/v0/b2b/attach/{enrollment_code}/
		added the required property `items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API GET /api/v0/b2b/contracts/
		added the required property `items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API GET /api/v0/b2b/contracts/{contract_slug}/
		added the required property `integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API GET /api/v0/b2b/manager/organizations/
		added the required property `items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API GET /api/v0/b2b/manager/organizations/{id}/
		added the required property `contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API GET /api/v0/b2b/manager/organizations/{parent_lookup_organization}/contracts/{id}/
		added the required property `integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API GET /api/v0/b2b/organizations/
		added the required property `items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API GET /api/v0/b2b/organizations/{organization_slug}/
		added the required property `contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API GET /api/v0/discounts/{parent_lookup_discount}/assignees/
		added the required property `results/items/user/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API POST /api/v0/discounts/{parent_lookup_discount}/assignees/
		added the required property `user/b2b_organizations/items/contracts/items/integration_type` to the response with the `201` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API GET /api/v0/discounts/{parent_lookup_discount}/assignees/{id}/
		added the required property `user/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API PATCH /api/v0/discounts/{parent_lookup_discount}/assignees/{id}/
		added the required property `user/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API PUT /api/v0/discounts/{parent_lookup_discount}/assignees/{id}/
		added the required property `user/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API GET /api/v0/discounts/{parent_lookup_redeemed_discount}/redemptions/
		added the required property `results/items/redeemed_by/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API POST /api/v0/discounts/{parent_lookup_redeemed_discount}/redemptions/
		added the required property `redeemed_by/b2b_organizations/items/contracts/items/integration_type` to the response with the `201` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API GET /api/v0/discounts/{parent_lookup_redeemed_discount}/redemptions/{id}/
		added the required property `redeemed_by/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API PATCH /api/v0/discounts/{parent_lookup_redeemed_discount}/redemptions/{id}/
		added the required property `redeemed_by/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API PUT /api/v0/discounts/{parent_lookup_redeemed_discount}/redemptions/{id}/
		added the required property `redeemed_by/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API GET /api/v0/userinfo/
		added the required property `b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API GET /api/v0/users/current_user/
		added the required property `b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API PATCH /api/v0/users/current_user/
		added the required property `b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API GET /api/v0/users/me
		added the required property `b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API PATCH /api/v0/users/me
		added the required property `b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status



## Changes for v1.yaml:
23 changes: 0 error, 0 warning, 23 info
info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API POST /api/v0/b2b/attach/{enrollment_code}/
		added the required property `items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API GET /api/v0/b2b/contracts/
		added the required property `items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API GET /api/v0/b2b/contracts/{contract_slug}/
		added the required property `integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API GET /api/v0/b2b/manager/organizations/
		added the required property `items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API GET /api/v0/b2b/manager/organizations/{id}/
		added the required property `contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API GET /api/v0/b2b/manager/organizations/{parent_lookup_organization}/contracts/{id}/
		added the required property `integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API GET /api/v0/b2b/organizations/
		added the required property `items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API GET /api/v0/b2b/organizations/{organization_slug}/
		added the required property `contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API GET /api/v0/discounts/{parent_lookup_discount}/assignees/
		added the required property `results/items/user/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API POST /api/v0/discounts/{parent_lookup_discount}/assignees/
		added the required property `user/b2b_organizations/items/contracts/items/integration_type` to the response with the `201` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API GET /api/v0/discounts/{parent_lookup_discount}/assignees/{id}/
		added the required property `user/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API PATCH /api/v0/discounts/{parent_lookup_discount}/assignees/{id}/
		added the required property `user/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API PUT /api/v0/discounts/{parent_lookup_discount}/assignees/{id}/
		added the required property `user/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API GET /api/v0/discounts/{parent_lookup_redeemed_discount}/redemptions/
		added the required property `results/items/redeemed_by/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API POST /api/v0/discounts/{parent_lookup_redeemed_discount}/redemptions/
		added the required property `redeemed_by/b2b_organizations/items/contracts/items/integration_type` to the response with the `201` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API GET /api/v0/discounts/{parent_lookup_redeemed_discount}/redemptions/{id}/
		added the required property `redeemed_by/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API PATCH /api/v0/discounts/{parent_lookup_redeemed_discount}/redemptions/{id}/
		added the required property `redeemed_by/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API PUT /api/v0/discounts/{parent_lookup_redeemed_discount}/redemptions/{id}/
		added the required property `redeemed_by/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API GET /api/v0/userinfo/
		added the required property `b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API GET /api/v0/users/current_user/
		added the required property `b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API PATCH /api/v0/users/current_user/
		added the required property `b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API GET /api/v0/users/me
		added the required property `b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API PATCH /api/v0/users/me
		added the required property `b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status



## Changes for v2.yaml:
23 changes: 0 error, 0 warning, 23 info
info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API POST /api/v0/b2b/attach/{enrollment_code}/
		added the required property `items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API GET /api/v0/b2b/contracts/
		added the required property `items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API GET /api/v0/b2b/contracts/{contract_slug}/
		added the required property `integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API GET /api/v0/b2b/manager/organizations/
		added the required property `items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API GET /api/v0/b2b/manager/organizations/{id}/
		added the required property `contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API GET /api/v0/b2b/manager/organizations/{parent_lookup_organization}/contracts/{id}/
		added the required property `integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API GET /api/v0/b2b/organizations/
		added the required property `items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API GET /api/v0/b2b/organizations/{organization_slug}/
		added the required property `contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API GET /api/v0/discounts/{parent_lookup_discount}/assignees/
		added the required property `results/items/user/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API POST /api/v0/discounts/{parent_lookup_discount}/assignees/
		added the required property `user/b2b_organizations/items/contracts/items/integration_type` to the response with the `201` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API GET /api/v0/discounts/{parent_lookup_discount}/assignees/{id}/
		added the required property `user/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API PATCH /api/v0/discounts/{parent_lookup_discount}/assignees/{id}/
		added the required property `user/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API PUT /api/v0/discounts/{parent_lookup_discount}/assignees/{id}/
		added the required property `user/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API GET /api/v0/discounts/{parent_lookup_redeemed_discount}/redemptions/
		added the required property `results/items/redeemed_by/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API POST /api/v0/discounts/{parent_lookup_redeemed_discount}/redemptions/
		added the required property `redeemed_by/b2b_organizations/items/contracts/items/integration_type` to the response with the `201` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API GET /api/v0/discounts/{parent_lookup_redeemed_discount}/redemptions/{id}/
		added the required property `redeemed_by/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API PATCH /api/v0/discounts/{parent_lookup_redeemed_discount}/redemptions/{id}/
		added the required property `redeemed_by/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API PUT /api/v0/discounts/{parent_lookup_redeemed_discount}/redemptions/{id}/
		added the required property `redeemed_by/b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API GET /api/v0/userinfo/
		added the required property `b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API GET /api/v0/users/current_user/
		added the required property `b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API PATCH /api/v0/users/current_user/
		added the required property `b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API GET /api/v0/users/me
		added the required property `b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API PATCH /api/v0/users/me
		added the required property `b2b_organizations/items/contracts/items/integration_type` to the response with the `200` status



Unexpected changes? Ensure your branch is up-to-date with main (consider rebasing).

@cp-at-mit cp-at-mit marked this pull request as ready for review June 29, 2026 20:01
@dsubak dsubak self-requested a review June 30, 2026 13:23
@cp-at-mit cp-at-mit merged commit 1e40a64 into main Jun 30, 2026
9 checks passed
@cp-at-mit cp-at-mit deleted the b2b-permissions-tests branch June 30, 2026 18:01
@odlbot odlbot mentioned this pull request Jul 1, 2026
3 tasks
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