]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 1497343 - Add some rudimentary type checking to Bugzilla::WebServe::Util::validate()
authorDylan William Hardison <dylan@hardison.net>
Tue, 9 Oct 2018 21:06:18 +0000 (17:06 -0400)
committerGitHub <noreply@github.com>
Tue, 9 Oct 2018 21:06:18 +0000 (17:06 -0400)
Bugzilla/WebService/Bug.pm
Bugzilla/WebService/Util.pm
template/en/default/global/user-error.html.tmpl

index 9003f3480714df6a94c1dbe8c57b3b8fc551e5a2..61a95e07dcc023fee78dbc2774271b881310d048 100644 (file)
@@ -1462,7 +1462,8 @@ sub _bug_to_hash {
         elsif ($field->type == FIELD_TYPE_DATETIME
                || $field->type == FIELD_TYPE_DATE)
         {
-            $item{$name} = $self->type('dateTime', $bug->$name);
+            my $value = $bug->$name;
+            $item{$name} = defined($value) ? $self->type('dateTime', $value) : undef;
         }
         elsif ($field->type == FIELD_TYPE_MULTI_SELECT) {
             my @values = map { $self->type('string', $_) } @{ $bug->$name };
index d462c884a7e88af96d17efa8fbe26c242a84a461..ce55869119d06b51f6a50990494d5ad17377163b 100644 (file)
@@ -11,6 +11,7 @@ use 5.10.1;
 use strict;
 use warnings;
 
+use Bugzilla::Logging;
 use Bugzilla::Flag;
 use Bugzilla::FlagType;
 use Bugzilla::Error;
@@ -18,6 +19,8 @@ use Bugzilla::WebService::Constants;
 
 use Storable qw(dclone);
 use URI::Escape qw(uri_unescape);
+use Type::Params qw( compile );
+use Types::Standard -all;
 
 use base qw(Exporter);
 
@@ -217,6 +220,17 @@ sub _delete_bad_keys {
 
 sub validate  {
     my ($self, $params, @keys) = @_;
+    my $cache_key = join('|', (caller(1))[3], sort @keys);
+    # Type->of() is the same as Type[], used here because it is easier
+    # to chain with plus_coercions.
+    state $array_of_nonrefs = ArrayRef->of(Maybe[Value])->plus_coercions(
+        Maybe[Value], q{ [ $_ ] },
+    );
+    state $type_cache = {};
+    my $params_type = $type_cache->{$cache_key} //= do {
+        my %fields = map { $_ => Optional[$array_of_nonrefs] } @keys;
+        Maybe[ Dict[%fields, slurpy Any] ];
+    };
 
     # If $params is defined but not a reference, then we weren't
     # sent any parameters at all, and we're getting @keys where
@@ -226,12 +240,10 @@ sub validate  {
     # If @keys is not empty then we convert any named
     # parameters that have scalar values to arrayrefs
     # that match.
-    foreach my $key (@keys) {
-        if (exists $params->{$key}) {
-            $params->{$key} = ref $params->{$key}
-                              ? $params->{$key}
-                              : [ $params->{$key} ];
-        }
+    $params = $params_type->coerce($params);
+    if (my $type_error = $params_type->validate($params)) {
+        FATAL("validate() found type error: $type_error");
+        ThrowUserError('invalid_params', { type_error => $type_error } ) if $type_error;
     }
 
     return ($self, $params);
index 9b058300905517ea67cf2019c1911426e90b2cfb..53de6a420bdfe53553ed1ce2fed882de5897c5d3 100644 (file)
     [% title = "Invalid Authentication Method" %]
     API key authentication is required.
 
+  [% ELSIF error == "invalid_params" %]
+    [% title = "Invalid Params" %]
+    API method received invalid params: [% type_error FILTER html %]
+
   [% ELSIF error == "bug_id_does_not_exist" %]
     [% title = BLOCK %]Invalid [% terms.Bug %] ID[% END %]
     [% terms.Bug %] [%= bug_id FILTER html %] does not exist.