Skip to content

Bug 2072313 - Accept query-string params on Reminders add - #2751

Open
Xzzz wants to merge 5 commits into
mozilla:masterfrom
Xzzz:bug-2072313
Open

Xzzz wants to merge 5 commits into
mozilla:masterfrom
Xzzz:bug-2072313

Conversation

@Xzzz

@Xzzz Xzzz commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

Reminders.pm's add() only read parameters from the JSON POST body. Adds the query-string merge that the REST docs promise, reusing the same merge_request_params helper as bugs 2065171/2065173/2072305.

Depends on 2072305 per the bug dependency (both introduce the same shared helper; will collapse to one copy once either merges).

Changes

  • merge_request_params now returns ($params, $error) instead of a bare hashref, so a request body that fails to decode as JSON is reported back as rest_malformed_json rather than silently ignored
  • merge_request_params: build params from $c->req->params->names/param() instead of ->to_hash, so a repeated query-string key (e.g. ?note=a&note=b) collapses to a scalar instead of an arrayref reaching an unvalidated field
  • Reminders.pm add(): query string + JSON body merge instead of JSON-body-only; returns user_error('rest_malformed_json') if the body doesn't decode
  • qa/t/rest_reminders.t: cover query-string-only reminder creation and malformed-JSON-body rejection

Test plan

  • POST /rest/reminder with bug_id/note/reminder_ts entirely in the query string, no JSON body
  • POST /rest/reminder with a truncated JSON body, expect 400 / rest_malformed_json
  • Existing qa/t/rest_reminders.t cases unaffected

References

  • Bugzilla link: 2072313
  • Depends on 2072305
  • Fixes 2072318: malformed-JSON bodies are now correctly reported via rest_malformed_json instead of being silently treated as empty params

add() only read from the JSON body. Reuse the same merge_request_params helper as
bugs 2065171/2065173/2072305 instead of writing another copy. No whitelist needed here:
create() only reads three named keys, not the whole params hash.
Comment thread Bugzilla/WebService/Util.pm
Comment thread Bugzilla/WebService/Util.pm Outdated
# layer (see fix_credentials/_retrieve_json_params in
# Bugzilla::WebService::Server::REST) and the documented behavior in
# docs/en/rst/api/core/v1/general.rst.
my $params = $c->req->params->to_hash;

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.

to_hash returns an arrayref for any key that appears more than once

POST /rest/reminder?bug_id=123&note=a&note=b&reminder_ts=2024-06-08 makes note ['a','b'], and note has no entry in Bugzilla::Reminder::VALIDATORS, so run_create_validators passes it straight through and the DB gets the literal string ARRAY(0x...)

bug_id and reminder_ts are shielded by their validators, note is not — and since this helper is meant for reuse by 2065171/2065173/2072305, every future caller inherits it

suggest collapsing to scalars, e.g. building the hash from $c->req->params->names plus $c->req->param($_)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good catch. Fixed as sugested: replaced $c->req->params->to_hash with $params->{$_} = $c->req->param($_) for @{$c->req->params->names} so a repeated key collapses to a scalar instead of an arrayref

Comment thread Bugzilla/API/V1/Reminders.pm Outdated
catch {
return $self->user_error('rest_malformed_json');
};
my $params = merge_request_params($self);

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.

this is where the rest_malformed_json response is lost — see the comment on merge_request_params

if the helper keeps swallowing decode errors, this call site needs its own check so a bad JSON body still returns the right error

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed by the merge_request_params change above => add() now does my ($params, $error) = merge_request_params($self); return $self->user_error($error) if $error;, so a malformed body still gets rest_malformed_json.

Comment thread qa/t/rest_reminders.t
my $params = {};
$params->{$_} = $c->req->param($_) for @{$c->req->params->names};

if (length $c->req->body) {

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.

the decode is gated on length $c->req->body, not on the content type, so any non-JSON body is now rejected

POST /rest/reminder?bug_id=123 with Content-Type: application/x-www-form-urlencoded and body note=hello returns rest_malformed_json, because decode_json is handed the raw form string

that contradicts the comment three lines above, which promises $c->req->params "already covers the query string plus, for POST/PUT, an application/x-www-form-urlencoded or multipart body" — the helper collects those params and then rejects the request they came from. same for multipart

the legacy layer doesn't have this problem: CGI.pm only populates POSTDATA/PUTDATA for non-form content types, so _retrieve_json_params never tries to decode a form body

and since 2065171/2065173/2072305 all reuse this helper, every future caller inherits it

suggest gating the decode on the content type — only decode when $c->req->headers->content_type matches application/json — or skipping it when $c->req->body_params->names is non-empty

Comment thread Bugzilla/Util.pm
return $usage_mode == USAGE_MODE_JSON || $usage_mode == USAGE_MODE_REST;
return $usage_mode == USAGE_MODE_JSON
|| $usage_mode == USAGE_MODE_REST
|| $usage_mode == USAGE_MODE_MOJO_REST;

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.

this is a real bug and worth fixing — without it every native Mojo REST error message over 72 chars gets \ns injected by the error_message filter in Bugzilla/Template.pm:866, which is exactly what the new test would trip over — but it doesn't belong in bug 2072313

i_am_webservice has 14 call sites and this flips all of them for every USAGE_MODE_MOJO_REST endpoint at once, not just Reminders

most are unreachable under MOJO_REST — native REST auth goes through Bugzilla/App/Plugin/Login.pm, not Bugzilla::Auth::Login::Cookie/APIKey — so the practical risk is low. but extensions/RestrictComments/Extension.pm:58 does change: object_end_of_set_all fires for Bugzilla/API/V1/Github.pm:364 and extensions/PhabBugz/lib/API/V1/PhabBugz.pm:235, and will now stop force-clearing restrict_comments on those updates. that's arguably the correct behavior, but it's untested and unrelated to this bug

suggest either splitting it into its own bug, or dropping the commit here and relaxing the new assertion to json_like so the test doesn't depend on the wrapping

This branch has not been deployed

No deployments
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