Repository navigation
Conversation
Error messages from native-Mojo REST controllers were being word-wrapped at 72 columns, introducing literal newlines that broke message-content assertions like rest_group_create.t.
…failure The 'auth_failure' error template only has a branch for 'groups' (plural), 'group' fell through to the empty default, so the unauthorized-user message read "...not authorized to add new ." with the object word missing.
_request_params duplicated the same query-string/JSON-body merge logic already written for BugUserLastVisit.pm (bug 2065171). Now call a single shared merge_request_params helper, so it's a one-place change to drop later if query-string-on-POST support is ever removed. Please note that BugUserLastVisit.pm (bug 2065171) is being updated separately to call the same helper instead of its own copy.
|
Pushed a follow-up commit extracting |
can_bless() takes a group id, not a Group object. Passing the object made every entry falsy, and the next line's ->id call on that died. Reachable by bless-privileged users without can_see_groups. Was ported faithfully from legacy as a described no-op, although it's actually a genuine crash, so fixing it here.
…/ids set_all() throws unknown_method for any stray key without a matching set_<key> method. Cookie-authenticated PUT hit this via Bugzilla_api_token (legacy deleted it before the method ran, the Mojo cookie-auth path doesn't), include_fields/exclude_fields hit it too. Whitelist the update fields instead.
|
|
||
| if (length $c->req->body) { | ||
| my $body_params; | ||
| try { $body_params = decode_json($c->req->body); } |
There was a problem hiding this comment.
swallowing the decode error is a regression from the legacy layer. _retrieve_json_params in Bugzilla/WebService/Server/REST.pm:343 did ThrowUserError('json_rpc_invalid_params', {err_msg => $@})
so POST /rest/group with a truncated body now reports You must enter a name instead of telling the client its JSON is broken
suggest rethrowing as json_rpc_invalid_params when the body is non-empty and looks like JSON. separately, the length $c->req->body guard has no method check, so a GET with a body gets its JSON merged in too - legacy only did this for non-GET
There was a problem hiding this comment.
The first half is fixed. Since #2751 landed, the shared merge_request_params in master returns ($params, $error) and raises rest_malformed_json instead of swallowing the decode failure, and create/update/get now unpack both and report it, so a truncated body no longer surfaces as You must enter a name.
The second half is still open, and I would rather have your call than decide it here. You are right that the guard has no method check: it is length $body && !@{$c->req->body_params->names}, so a GET carrying a JSON body still gets it merged, while legacy only merged the body for non-GET requests (Bugzilla/WebService/Server/REST.pm:337).
The catch is that the guard now lives in master and is shared by BugUserLastVisit, Group, Component and Reminders, so fixing it here would put a cross-cutting change back inside a migration PR, which is what you asked me to avoid on the i_am_webservice one. Three options as I see them:
- fold it into Bug 2065171 - Migrate BugUserLastVisit REST resource to native Mojo API #2743, which already touches that helper and is waiting on review
- give it its own bug the way we did for 2074854
- leave it and I will file it separately
Which would you prefer?
The shared helper landed in master with a two-element return, so calling it in scalar context assigned the error rather than the params. create/update/get now unpack both and report a malformed JSON body via user_error.
Whitelisting the documented fields made a typo or an unsupported field a silent no-op returning 200 with empty changes. Delete the request-level keys and pass the rest to set_all(), which still raises unknown_method.
Both OPTIONS routes shared one Allow value, so /rest/group advertised PUT and /rest/group/<id> advertised POST, neither of which exists. The allowed methods now come from the route, which also fixes Access-Control-Allow-Methods.
The legacy code mapped rather than grepped can_bless($group_object), so every element became 0 and _group_to_hash called ->id on it: a 500 for a blesser without can_see_groups, not the no-op the comment claimed.
An empty arrayref is truthy, so the group_not_visible check passed and the membership query became a bare SELECT with an ' AND ...' appended, which is a SQL error. Carried over from the legacy code.
merge_request_params collapses parameters to scalars unless the caller says otherwise, so ?ids=1&ids=2 returned only the last group. update() and get() now declare both list parameters; create() takes only scalar fields and is left alone. Covers the repeated form, which no test exercised.
# Conflicts: # Bugzilla/WebService.pm # Bugzilla/WebService/Constants.pm # Bugzilla/WebService/Server/REST.pm
| my %values = %$params; | ||
| delete @values{ | ||
| qw(ids names include_fields exclude_fields | ||
| Bugzilla_api_key Bugzilla_api_token Bugzilla_login Bugzilla_password |
There was a problem hiding this comment.
Bugzilla_token (and Bugzilla_restrictlogin/restrictlogin) are not dropped here, so a client still sending a legacy token param now gets unknown_method from set_all() where the old code stripped it during login
Looking back on other PRs that we do this and will do for others in the future, maybe we should make this a utility method for Util.pm and backfill the other migration code to use it as well. Bonus points to put the delete list in a constant maybe in Util.pm.
Summary
Ports
Bugzilla::WebService::Group'screate/update/getmethods into a nativeBugzilla::API::V1::GroupMojo controller, mirroring the pattern already used for Classification/Component/Teams/Reminders/Configuration/Bugzilla (system info)/BugUserLastVisit/Product.This is a child bug of 2057358, see there for details.
Master has been merged in now that #2751, #2756 and #2743 have landed, so the branch no longer carries its own copy of
merge_request_paramsor thei_am_webservicechange; both come from master andBugzilla/Util.pmhas dropped out of this diff. TheWS_DISPATCHconflict with #2743 is resolved by dropping both entries: master removedBugUserLastVisit, this PR removesGroup.Master was merged in again after #2762 (Product) landed: the same conflict in
WS_DISPATCH,REST.pm's use list andWebService.pm's POD is resolved by dropping both entries,Product(master) andGroup(this PR).Changes
Bugzilla/API/V1/Group.pm:GET/POST /rest/groupandGET/PUT /rest/group/<id_or_name>(login +creategroupsrequired for create/update), same JSON response shape as the legacy endpointsBugzilla/WebService/Group.pmandBugzilla/WebService/Server/REST/Resources/Group.pmGroupentry fromWS_DISPATCHinBugzilla/WebService/Constants.pm, the correspondinguseline inBugzilla/WebService/Server/REST.pm, and the POD entry inBugzilla/WebService.pmcreate/update/getunpack($params, $error)from the sharedmerge_request_paramsand report a malformed JSON body asrest_malformed_json, instead of the decode error being swallowedupdate()andget()declareidsandnamesas list parameters, so?ids=1&ids=2returns every group asked for rather than only the last.create()takes only scalar fields and is left aloneupdate()deletes the request-level keys (ids,names,include_fields,exclude_fields,Bugzilla_api_key,Bugzilla_api_token,Bugzilla_login,Bugzilla_password) and passes the rest toset_all(), so an unrecognized field still raisesunknown_methodrather than being silently droppedOPTIONScome from the route, so/rest/groupadvertisesGET, POSTand/rest/group/<id_or_name>advertisesGET, PUT, rather than one sharedGET, POST, PUTfor both.Access-Control-Allow-Methodsfollows the same value_get_group_membership(): normalise an emptyvisible_groups_inheritedtoundef. An empty arrayref is truthy, so thegroup_not_visiblecheck passed and the query becameSELECT userid FROM profiles AND ugm.group_id IN (...), a SQL error. Carried over from the legacy codeqa/t/rest_group_get.t: cover a repeatedidsparameter, and a user who can bless one group and requests anotherBreaking change: removing the
WS_DISPATCHentry also removesGroup.create/update/getfrom 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 Product migrations earlier in this series.Pre-existing bug, fixed here:
get()'s "filter by blessability" step for non-can_see_groupsusers. An earlier revision of this description claimed the legacy code was a no-op filter preserved as-is; both halves of that were wrong. Legacy ran[map { $user->can_bless($_) } @{$groups}](amap, not agrep) andcan_blessexpects a group id, so passing the object numified the ref and returned 0 for every element._group_to_hashthen called->idon 0, meaningGET /rest/group/<id>as a blesser withoutcan_see_groupsreturned a 500. Passing$_->idto agrepfilters the list as the comment always claimed. This is a real behaviour change: those users now get a filtered list instead of an error, andqa/t/rest_group_get.tcovers it.Test plan
GET /rest/group/GET /rest/group?ids=1&ids=2/GET /rest/group?names=adminGET /rest/group/<id>/GET /rest/group/<name>GET /rest/group/<id>?membership=1GET /rest/group/<id>as a user who can bless a different group, expecting a filtered list rather than a 500POST /rest/group(name/description required, duplicate name, invaliduser_regexp)POST/PUTwith a malformed JSON body, expectingrest_malformed_jsonPUT /rest/group/<id_or_name>with an unrecognized field, expectingunknown_methodrather than an emptychangesPUT /rest/group/<id_or_name>(protectedadmin/insider group rejected for non-admins, perqa/t/rest_group_update_protected.t)OPTIONS /rest/groupreturnsAllow: GET, POST,OPTIONS /rest/group/<id_or_name>returnsAllow: GET, PUTqa/t/rest_group_create.tandqa/t/rest_group_update_protected.tpass unchanged;qa/t/rest_group_get.tgains the repeated-ids and blessability casesReferences
i_am_webservicechange and the list-parameter support both come from master