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.
| # object, so this filter is a no-op that leaves $groups untouched in | ||
| # practice rather than actually filtering by blessability. | ||
| if (!$can_see_groups) { | ||
| $groups = [map { $user->can_bless($_) } @{$groups}]; |
There was a problem hiding this comment.
this filter isn't a no-op — the comment above is wrong about what happens
can_bless returns 0/1 (Bugzilla/User.pm:2116), so map replaces each Bugzilla::Group object with a plain scalar. the next line then calls ->id on 0 and dies
reachable: a user not in can_see_groups but with bless privileges passes the guard at line 147, gets $groups = $user->bless_groups, and GET /rest/group returns a 500 instead of their blessable groups. admins never hit it, which is why the qa tests are green
the line is a faithful copy of the legacy code so it's pre-existing, but since the PR documents it as harmless it's worth fixing here instead:
$groups = [grep { $user->can_bless($_->id) } @$groups];that matches how _get_group_membership already calls it on line 239
There was a problem hiding this comment.
You right, my comment was wrong: this isn't a harmless no-op, it crashes.
Fixed with $user->can_bless($_->id), matching _get_group_membership's usage.
=> Fixed in "Bug 2065173 - Fix crash filtering groups by blessability"
| $group->check_can_be_edited(); | ||
| } | ||
|
|
||
| my %values = %$params; |
There was a problem hiding this comment.
cookie-authenticated PUT breaks here
_request_params returns $self->req->params->to_hash unfiltered, and Bugzilla/App/Plugin/Login.pm:68 reads Bugzilla_api_token without deleting it. so it survives into %values → set_all → set_Bugzilla_api_token → ThrowCodeError('unknown_method')
legacy worked because Bugzilla::Auth::Login::Cookie did delete Bugzilla->input_params->{Bugzilla_api_token} before the method ran. that path isn't used by Mojo controllers, so this is a new regression
include_fields/exclude_fields hit the same wall. suggest whitelisting the documented fields (name, description, user_regexp, is_active, icon_url) before set_all
There was a problem hiding this comment.
Good catch. As suggested, switched to whitelisting the five documented update fields (name, description, user_regexp, is_active, icon_url) instead of blacklisting names/ids, so stray keys like Bugzilla_api_token or include_fields/exclude_fields no longer reach set_all().
=> Fixed in "Bug 2065173 - Whitelist update() fields instead of blacklisting names/ids"
| my $routes = $r->under( | ||
| '/group' => sub { Bugzilla->usage_mode(USAGE_MODE_MOJO_REST); }); | ||
| $routes->get('/')->to('V1::Group#get'); | ||
| $routes->get('/:id')->to('V1::Group#get'); |
There was a problem hiding this comment.
:id won't match a group name containing a dot — the : placeholder stops at ., while the legacy resource regex was qr{^/group/([^/]+)$}
GET /rest/group/my.group and PUT /rest/group/my.group would return an HTML 404 instead of JSON. Bugzilla::Group::_check_name only checks for emptiness and uniqueness, so dotted names are allowed
use the relaxed placeholder '/#id' on lines 30, 32 and 34, same as Bugzilla/API/V1/Classification.pm:21. a qa case with a dotted name would lock it in
There was a problem hiding this comment.
As suggested, switched to relaxed #id placeholder (same as Classification.pm).
=> Fixed in "Bug 2065173 - Use relaxed #id placeholder to allow dots in group names"
| foreach my $field (keys %{$changes{$group->id}}) { | ||
| my $change = $changes{$group->id}->{$field}; | ||
| $hash{changes}{$field} | ||
| = {removed => "$change->[0]", added => "$change->[1]"}; |
There was a problem hiding this comment.
interpolating $change->[0] turns a legit undef into "" and logs an uninitialized-value warning
legacy used $self->type('string', ...), which passed undef through as JSON null. Bugzilla::Object::update supports transitions from or to undef (e.g. icon_url going from NULL), so this changes the response shape
removed => defined $change->[0] ? "$change->[0]" : undef,
added => defined $change->[1] ? "$change->[1]" : undef,There was a problem hiding this comment.
Fixed as suggested, Thanks!
=> Fixed in "Bug 2065173 - Preserve null in changes when a field goes to/from undef"
_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.
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.This is a child bug of 2057358, see there for details.
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.pmBreaking 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), and BugUserLastVisit migrations earlier in this series.Known pre-existing bug, preserved, not fixed:
get()'s "filter by blessability" step for non-can_see_groupsusers calls$user->can_bless($group)with aGroupobject wherecan_blessexpects a group id, so the filter is a no-op in both the legacy and new code. Flagging for review rather than silently fixing it in a migration PR.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=1POST /rest/group(name/description required, duplicate name, invaliduser_regexp)PUT /rest/group/<id_or_name>(protectedadmin/insider group rejected for non-admins, perqa/t/rest_group_update_protected.t)OPTIONSon both routes returnsAllow: GET, POST, PUTqa/t/rest_group_get.t,qa/t/rest_group_create.t,qa/t/rest_group_update_protected.tshould pass unchangedReferences