Skip to content

Bug 2071907 - Migrate Product REST resource to native Mojo API - #2762

Merged
dklawren merged 2 commits into
mozilla:masterfrom
Xzzz:bug-2071907
Sep 24, 2026
Merged

dklawren merged 2 commits into
mozilla:masterfrom
Xzzz:bug-2071907

Conversation

@Xzzz

@Xzzz Xzzz commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Ports Bugzilla::WebService::Product's get/create/get_accessible_products/get_enterable_products/get_selectable_products methods into a native Bugzilla::API::V1::Product Mojo controller, mirroring the pattern already used for Classification/Component/Teams/Reminders/Configuration/Bugzilla (system info)/BugUserLastVisit.

This is a child bug of 2057358, see there for details.

Changes

  • Add Bugzilla/API/V1/Product.pm: GET /rest/product_accessible, /rest/product_enterable, /rest/product_selectable, GET /rest/product, GET /rest/product/<id_or_name> and POST /rest/product (login + editcomponents required for create), same JSON response shape as the legacy endpoints
  • Delete Bugzilla/WebService/Product.pm and Bugzilla/WebService/Server/REST/Resources/Product.pm
  • Remove the Product entry from WS_DISPATCH in Bugzilla/WebService/Constants.pm, the corresponding use line in Bugzilla/WebService/Server/REST.pm, and the POD entry in Bugzilla/WebService.pm. Also repoint a POD link in Bugzilla/WebService/Bug.pm that referenced Bugzilla::WebService::Product/get_accessible_products
  • get() declares ids, names, type, include_fields and exclude_fields as list parameters to the shared merge_request_params, so ?ids=1&ids=2 returns every product asked for rather than only the last. include_fields/exclude_fields also accept a comma-separated list. A malformed JSON body is reported as rest_malformed_json
  • create() coerces is_open, has_unconfirmed and create_series from query-string/form values (true/false/1/0, case-insensitive) and rejects anything else with invalid_params. Without this, ?is_open=false would create an open product, since the string "false" is truthy in Perl. JSON booleans are unchanged
  • get() and the three id lists return login_required for anonymous requests when the requirelogin parameter is on. The legacy dispatcher's Bugzilla->login() enforced this, but the native Mojo login helper does not for REST requests. Anonymous access is still allowed when requirelogin is off, matching the legacy behaviour
  • The allowed methods for OPTIONS come from the route, so /rest/product advertises GET, POST and the other routes advertise GET. Access-Control-Allow-Methods follows the same value
  • The /rest/product/<id_or_name> placeholder is #id_or_name, so product names containing a dot are matched in full
  • qa/t/rest_product.t: cover lookup by id and by name in the path, include_fields=id,name, the missing-params and invalid-type errors, and OPTIONS. qa/t/rest_product_create.t: cover query-string booleans and an invalid boolean value

Breaking change: removing the WS_DISPATCH entry also removes Product.get/create/get_accessible_products/get_enterable_products/get_selectable_products (and the Product.get_products alias) from JSON-RPC and XML-RPC, not just the legacy REST dispatcher, since all three share that table. Native Mojo routes only serve REST. This matches the same tradeoff already made in the Classification, Bugzilla (system-info), BugUserLastVisit and Group migrations earlier in this series.

Not ported: PUT /rest/product/<id_or_name> is documented in docs/en/rst/api/core/v1/product.rst, and the legacy REST resource routed it to an update method, but Bugzilla::WebService::Product never had one. The endpoint has never worked on BMO; it now returns 404 instead of an error.

Test plan

  • GET /rest/product_accessible / _enterable / _selectable as admin, unprivileged and logged-out users
  • GET /rest/product?ids=<id>&ids=<id> / GET /rest/product?names=<name> / GET /rest/product?type=accessible
  • GET /rest/product/<id> / GET /rest/product/<name>
  • GET /rest/product/<id>?include_fields=id,name
  • GET /rest/product with no parameters, expecting params_required
  • GET /rest/product?type=bogus, expecting get_products_invalid_type
  • POST /rest/product (logged out, unprivileged, missing/empty/too-long/duplicate name, missing description, all optional arguments)
  • POST /rest/product?...&is_open=false&has_unconfirmed=false, expecting a closed product without UNCONFIRMED, and is_open=maybe rejected
  • OPTIONS /rest/product returns Allow: GET, POST
  • qa/t/rest_product.t and qa/t/rest_product_create.t pass

References

@dklawren dklawren left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM r=dkl

@dklawren
dklawren merged commit 8bcd8c2 into mozilla:master Sep 24, 2026
8 checks passed
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