From b06a5f44ac35f92a28498c90292eef1735df6f7d Mon Sep 17 00:00:00 2001 From: Dave Lawrence Date: Tue, 25 Feb 2014 21:43:57 +0000 Subject: Bug 972881 - Add hooks to Bugzilla/WebService/Server/REST.pm to allow for extensions to extend and alter REST data r=glob,a=justdave --- Bugzilla/Hook.pm | 83 ++++++++++++++++++++++++++++++++++++++ Bugzilla/WebService/Server/REST.pm | 15 +++++-- Bugzilla/WebService/Util.pm | 3 ++ extensions/Example/Extension.pm | 52 ++++++++++++++++++++++++ 4 files changed, 150 insertions(+), 3 deletions(-) diff --git a/Bugzilla/Hook.pm b/Bugzilla/Hook.pm index e6a0ba283..811e858d7 100644 --- a/Bugzilla/Hook.pm +++ b/Bugzilla/Hook.pm @@ -1623,6 +1623,89 @@ See L for an example. =back +=head2 webservice_fix_credentials + +This hook allows for altering the credential parameters provided by the client +before authentication actually occurs. For example, this can be used to allow mapping +of custom parameters to the standard Bugzilla_login and Bugzilla_password parameters. + +Params: + +=over + +=item C + +A hash ref containing the parameters passed into the webservice after +they have been obtained from the URL or body of the request. + +=back + +=head2 webservice_rest_request + +This hook allows for altering any of the parameters provided by the client +after authentication has occured. You are able to change things like renaming +of keys, removing values, or adding additional information. + +Params: + +=over + +=item C + +A hash ref containing the parameters passed into the webservice after +they have been obtained from the URL or body of the request. + +=item C + +The current JSONRPC, XMLRPC, or REST object. + +=back + +=head2 webservice_rest_resources + +This hook allows for altering of the REST resources data allowing you to +add additional paths to perform additional operations or to override the +resources already provided by the webservice modules. + +Params: + +=over + +=item C + +A hash returned from each module loaded that is used to determine +which code handler to use based on a regex match of the CGI path. + +=item C + +The current JSONRPC, XMLRPC, or REST object. + +=back + +=head2 webservice_rest_response + +This hook allows for altering the result data or response object +that is being returned by the current REST webservice call. + +Params: + +=over + +=item C + +The HTTP response object generated by JSON-RPC library. You can use this +to add headers, etc. + +=item C + +A reference to a hash that contains the result data. + +=item C + +The current JSONRPC, XMLRPC, or REST object. + +=back + =head1 SEE ALSO L diff --git a/Bugzilla/WebService/Server/REST.pm b/Bugzilla/WebService/Server/REST.pm index f1e59873c..f4bc47c91 100644 --- a/Bugzilla/WebService/Server/REST.pm +++ b/Bugzilla/WebService/Server/REST.pm @@ -15,9 +15,10 @@ use parent qw(Bugzilla::WebService::Server::JSONRPC); use Bugzilla; use Bugzilla::Constants; use Bugzilla::Error; +use Bugzilla::Hook; +use Bugzilla::Util qw(correct_urlbase html_quote); use Bugzilla::WebService::Constants; use Bugzilla::WebService::Util qw(taint_data fix_credentials); -use Bugzilla::Util qw(correct_urlbase html_quote); # Load resource modules use Bugzilla::WebService::Server::REST::Resources::Bug; @@ -124,6 +125,9 @@ sub response { $result = $json_data->{result}; } + Bugzilla::Hook::process('webservice_rest_response', + { rpc => $self, result => \$result, response => $response }); + # Access Control $response->header("Access-Control-Allow-Origin", "*"); $response->header("Access-Control-Allow-Headers", "origin, content-type, accept"); @@ -226,8 +230,6 @@ sub _argument_type_check { taint_data($params); - Bugzilla->input_params($params); - # Now, convert dateTime fields on input. my $method = $self->bz_method_name; my $pkg = $self->{dispatch_path}->{$self->path_info}; @@ -262,6 +264,10 @@ sub _argument_type_check { eval "package $new_class;$isa_string;"; bless $self, $new_class; + # Allow extensions to modify the params post login + Bugzilla::Hook::process('webservice_rest_request', + { rpc => $self, params => $params }); + if ($params_is_array) { $params = [$params]; } @@ -377,6 +383,9 @@ sub _find_resource { $resources->{$module} = $module->rest_resources; } + Bugzilla::Hook::process('webservice_rest_resources', + { rpc => $self, resources => $resources }); + # Use the resources hash from each module loaded earlier to determine # which handler to use based on a regex match of the CGI path. # Also any matches found in the regex will be passed in later to the diff --git a/Bugzilla/WebService/Util.pm b/Bugzilla/WebService/Util.pm index 364783216..7f6d14b59 100644 --- a/Bugzilla/WebService/Util.pm +++ b/Bugzilla/WebService/Util.pm @@ -242,6 +242,9 @@ sub fix_credentials { if (exists $params->{'token'}) { $params->{'Bugzilla_token'} = $params->{'token'}; } + + # Allow extensions to modify the credential data before login + Bugzilla::Hook::process('webservice_fix_credentials', { params => $params }); } __END__ diff --git a/extensions/Example/Extension.pm b/extensions/Example/Extension.pm index e3e9b55f6..790231b89 100644 --- a/extensions/Example/Extension.pm +++ b/extensions/Example/Extension.pm @@ -949,5 +949,57 @@ sub webservice_error_codes { $error_map->{'example_my_error'} = 10001; } +sub webservice_fix_credentials { + my ($self, $args) = @_; + my $rpc = $args->{'rpc'}; + my $params = $args->{'params'}; + # Allow user to pass in username=foo&password=bar + if (exists $params->{'username'} && exists $params->{'password'}) { + $params->{'Bugzilla_login'} = $params->{'username'}; + $params->{'Bugzilla_password'} = $params->{'password'}; + } +} + +sub webservice_rest_request { + my ($self, $args) = @_; + my $rpc = $args->{'rpc'}; + my $params = $args->{'params'}; + # Internally we may have a field called 'cf_test_field' but we allow users + # to use the shorter 'test_field' name. + if (exists $params->{'test_field'}) { + $params->{'test_field'} = delete $params->{'cf_test_field'}; + } +} + +sub webservice_rest_resources { + my ($self, $args) = @_; + my $rpc = $args->{'rpc'}; + my $resources = $args->{'resources'}; + # Add a new resource that allows for /rest/example/hello + # to call Example.hello + $resources->{'Bugzilla::Extension::Example::WebService'} = [ + qr{^/example/hello$}, { + GET => { + method => 'hello', + } + } + ]; +} + +sub webservice_rest_response { + my ($self, $args) = @_; + my $rpc = $args->{'rpc'}; + my $result = $args->{'result'}; + my $response = $args->{'response'}; + # Convert a list of bug hashes to a single bug hash if only one is + # being returned. + if (ref $$result eq 'HASH' + && exists $$result->{'bugs'} + && scalar @{ $$result->{'bugs'} } == 1) + { + $$result = $$result->{'bugs'}->[0]; + } +} + # This must be the last line of your extension. __PACKAGE__->NAME; -- cgit v1.2.3-24-g4f1b