Commit 384d1d25 authored by Dave Lawrence's avatar Dave Lawrence

Bug 866927 - Enhance Bugzilla WebServices to allow data access using REST

r=glob,a=justdave
parent 8a2ac056
......@@ -26,3 +26,9 @@ Options -Indexes
</IfModule>
</IfModule>
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /866927/
RewriteRule ^rest/(.*)$ rest.cgi/$1 [NE]
</IfModule>
......@@ -469,6 +469,9 @@ sub usage_mode {
elsif ($newval == USAGE_MODE_TEST) {
$class->error_mode(ERROR_MODE_TEST);
}
elsif ($newval == USAGE_MODE_REST) {
$class->error_mode(ERROR_MODE_REST);
}
else {
ThrowCodeError('usage_mode_invalid',
{'invalid_usage_mode', $newval});
......
......@@ -56,7 +56,7 @@ sub new {
# the rendering of pages.
my $script = basename($0);
if (my $path_info = $self->path_info) {
my @whitelist;
my @whitelist = ("rest.cgi");
Bugzilla::Hook::process('path_info_whitelist', { whitelist => \@whitelist });
if (!grep($_ eq $script, @whitelist)) {
# IIS includes the full path to the script in PATH_INFO,
......
......@@ -122,12 +122,14 @@ use Memoize;
USAGE_MODE_EMAIL
USAGE_MODE_JSON
USAGE_MODE_TEST
USAGE_MODE_REST
ERROR_MODE_WEBPAGE
ERROR_MODE_DIE
ERROR_MODE_DIE_SOAP_FAULT
ERROR_MODE_JSON_RPC
ERROR_MODE_TEST
ERROR_MODE_REST
COLOR_ERROR
COLOR_SUCCESS
......@@ -459,6 +461,7 @@ use constant USAGE_MODE_XMLRPC => 2;
use constant USAGE_MODE_EMAIL => 3;
use constant USAGE_MODE_JSON => 4;
use constant USAGE_MODE_TEST => 5;
use constant USAGE_MODE_REST => 6;
# Error modes. Default set by Bugzilla->usage_mode (so ERROR_MODE_WEBPAGE
# usually). Use with Bugzilla->error_mode.
......@@ -467,6 +470,7 @@ use constant ERROR_MODE_DIE => 1;
use constant ERROR_MODE_DIE_SOAP_FAULT => 2;
use constant ERROR_MODE_JSON_RPC => 3;
use constant ERROR_MODE_TEST => 4;
use constant ERROR_MODE_REST => 5;
# The ANSI colors of messages that command-line scripts use
use constant COLOR_ERROR => 'red';
......
......@@ -104,7 +104,8 @@ sub _throw_error {
die("$message\n");
}
elsif (Bugzilla->error_mode == ERROR_MODE_DIE_SOAP_FAULT
|| Bugzilla->error_mode == ERROR_MODE_JSON_RPC)
|| Bugzilla->error_mode == ERROR_MODE_JSON_RPC
|| Bugzilla->error_mode == ERROR_MODE_REST)
{
# Clone the hash so we aren't modifying the constant.
my %error_map = %{ WS_ERROR_CODE() };
......@@ -121,13 +122,20 @@ sub _throw_error {
}
else {
my $server = Bugzilla->_json_server;
my $status_code = 0;
if (Bugzilla->error_mode == ERROR_MODE_REST) {
my %status_code_map = %{ REST_STATUS_CODE_MAP() };
$status_code = $status_code_map{$code} || $status_code_map{'_default'};
}
# Technically JSON-RPC isn't allowed to have error numbers
# higher than 999, but we do this to avoid conflicts with
# the internal JSON::RPC error codes.
$server->raise_error(code => 100000 + $code,
message => $message,
id => $server->{_bz_request_id},
version => $server->version);
$server->raise_error(code => 100000 + $code,
status_code => $status_code,
message => $message,
id => $server->{_bz_request_id},
version => $server->version);
# Most JSON-RPC Throw*Error calls happen within an eval inside
# of JSON::RPC. So, in that circumstance, instead of exiting,
# we die with no message. JSON::RPC checks raise_error before
......
......@@ -284,7 +284,7 @@ sub OPTIONAL_MODULES {
package => 'JSON-RPC',
module => 'JSON::RPC',
version => 0,
feature => ['jsonrpc'],
feature => ['jsonrpc', 'rest'],
},
{
package => 'JSON-XS',
......@@ -298,7 +298,7 @@ sub OPTIONAL_MODULES {
module => 'Test::Taint',
# 1.06 no longer throws warnings with Perl 5.10+.
version => 1.06,
feature => ['jsonrpc', 'xmlrpc'],
feature => ['jsonrpc', 'xmlrpc', 'rest'],
},
{
# We need the 'utf8_mode' method of HTML::Parser, for HTML::Scrubber.
......@@ -397,6 +397,7 @@ use constant FEATURE_FILES => (
jsonrpc => ['Bugzilla/WebService/Server/JSONRPC.pm', 'jsonrpc.cgi'],
xmlrpc => ['Bugzilla/WebService/Server/XMLRPC.pm', 'xmlrpc.cgi',
'Bugzilla/WebService.pm', 'Bugzilla/WebService/*.pm'],
rest => ['Bugzilla/WebService/Server/REST.pm', 'rest.cgi'],
moving => ['importxml.pl'],
auth_ldap => ['Bugzilla/Auth/Verify/LDAP.pm'],
auth_radius => ['Bugzilla/Auth/Verify/RADIUS.pm'],
......
......@@ -136,6 +136,8 @@ sub MessageToMTA {
Bugzilla::Hook::process('mailer_before_send',
{ email => $email, mailer_args => \@args });
return if $email->header('to') eq '';
$email->walk_parts(sub {
my ($part) = @_;
return if $part->parts > 1; # Top-level
......
......@@ -45,15 +45,20 @@ This is the standard API for external programs that want to interact
with Bugzilla. It provides various methods in various modules.
You can interact with this API via
L<XML-RPC|Bugzilla::WebService::Server::XMLRPC> or
L<JSON-RPC|Bugzilla::WebService::Server::JSONRPC>.
L<XML-RPC|Bugzilla::WebService::Server::XMLRPC>,
L<JSON-RPC|Bugzilla::WebService::Server::JSONRPC> or
L<REST|Bugzilla::WebService::Server::REST>.
=head1 CALLING METHODS
Methods are grouped into "packages", like C<Bug> for
Methods are grouped into "packages", like C<Bug> for
L<Bugzilla::WebService::Bug>. So, for example,
L<Bugzilla::WebService::Bug/get>, is called as C<Bug.get>.
For REST, the "package" is more determined by the path
used to access the resource. See each relevant method
for specific details on how to access via REST.
=head1 PARAMETERS
The Bugzilla API takes the following various types of parameters:
......@@ -135,7 +140,7 @@ There are various ways to log in:
=item C<User.login>
You can use L<Bugzilla::WebService::User/login> to log in as a Bugzilla
You can use L<Bugzilla::WebService::User/login> to log in as a Bugzilla
user. This issues standard HTTP cookies that you must then use in future
calls, so your client must be capable of receiving and transmitting
cookies.
......@@ -165,13 +170,17 @@ not expire.
=back
The C<Bugzilla_restrictlogin> and C<Bugzilla_rememberlogin> options
are only used when you have also specified C<Bugzilla_login> and
are only used when you have also specified C<Bugzilla_login> and
C<Bugzilla_password>.
Note that Bugzilla will return HTTP cookies along with the method
response when you use these arguments (just like the C<User.login> method
above).
For REST, you may also use the C<username> and C<password> variable
names instead of C<Bugzilla_login> and C<Bugzilla_password> as a
convenience.
=back
=head1 STABLE, EXPERIMENTAL, and UNSTABLE
......@@ -266,6 +275,9 @@ would return something like:
{ users => [{ id => 1, name => 'user@domain.com' }] }
Note for REST, C<include_fields> may instead be a comma delimited string
for GET type requests.
=item C<exclude_fields>
C<array> An array of strings, representing the (case-sensitive) names of
......@@ -295,6 +307,9 @@ would return something like:
{ users => [{ id => 1, real_name => 'John Smith' }] }
Note for REST, C<exclude_fields> may instead be a comma delimited string
for GET type requests.
=back
=head1 SEE ALSO
......
......@@ -1075,6 +1075,10 @@ or get information about bugs that have already been filed.
See L<Bugzilla::WebService> for a description of how parameters are passed,
and what B<STABLE>, B<UNSTABLE>, and B<EXPERIMENTAL> mean.
Although the data input and output is the same for JSONRPC, XMLRPC and REST,
the directions for how to access the data via REST is noted in each method
where applicable.
=head1 Utility Functions
=head2 fields
......@@ -1088,11 +1092,26 @@ B<UNSTABLE>
Get information about valid bug fields, including the lists of legal values
for each field.
=item B<REST>
You have several options for retreiving information about fields. The first
part is the request method and the rest is the related path needed.
To get information about all fields:
GET /field/bug
To get information related to a single field:
GET /field/bug/<id_or_name>
The returned data format is the same as below.
=item B<Params>
You can pass either field ids or field names.
B<Note>: If neither C<ids> nor C<names> is specified, then all
B<Note>: If neither C<ids> nor C<names> is specified, then all
non-obsolete fields will be returned.
In addition to the parameters below, this method also accepts the
......@@ -1288,6 +1307,8 @@ You specified an invalid field name or id.
=item C<is_active> return key for C<values> was added in Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>
=back
=back
......@@ -1303,6 +1324,18 @@ B<DEPRECATED> - Use L</fields> instead.
Tells you what values are allowed for a particular field.
=item B<REST>
To get information on the values for a field based on field name:
GET /field/bug/<field_name>/values
To get information based on field name and a specific product:
GET /field/bug/<field_name>/<product_id>/values
The returned data format is the same as below.
=item B<Params>
=over
......@@ -1335,6 +1368,14 @@ You specified a field that doesn't exist or isn't a drop-down field.
=back
=item B<History>
=over
=item REST API call added in Bugzilla B<5.0>.
=back
=back
=head1 Bug Information
......@@ -1353,6 +1394,18 @@ and/or attachment ids.
B<Note>: Private attachments will only be returned if you are in the
insidergroup or if you are the submitter of the attachment.
=item B<REST>
To get all current attachments for a bug:
GET /bug/<bug_id>/attachment
To get a specific attachment based on attachment ID:
GET /bug/attachment/<attachment_id>
The returned data format is the same as below.
=item B<Params>
B<Note>: At least one of C<ids> or C<attachment_ids> is required.
......@@ -1550,6 +1603,8 @@ C<summary>.
=item The C<flags> array was added in Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
......@@ -1566,6 +1621,18 @@ B<STABLE>
This allows you to get data about comments, given a list of bugs
and/or comment ids.
=item B<REST>
To get all comments for a particular bug using the bug ID or alias:
GET /bug/<id_or_alias>/comment
To get a specific comment based on the comment ID:
GET /bug/comment/<comment_id>
The returned data format is the same as below.
=item B<Params>
B<Note>: At least one of C<ids> or C<comment_ids> is required.
......@@ -1711,6 +1778,8 @@ C<creator>.
=item C<creation_time> was added in Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
......@@ -1728,6 +1797,14 @@ Gets information about particular bugs in the database.
Note: Can also be called as "get_bugs" for compatibilty with Bugzilla 3.0 API.
=item B<REST>
To get information about a particular bug using its ID or alias:
GET /bug/<id_or_alias>
The returned data format is the same as below.
=item B<Params>
In addition to the parameters below, this method also accepts the
......@@ -2060,6 +2137,8 @@ You do not have access to the bug_id you specified.
=item The following properties were added to this method's return values
in Bugzilla B<3.4>:
=item REST API call added in Bugzilla B<5.0>
=over
=item For C<bugs>
......@@ -2117,6 +2196,14 @@ B<EXPERIMENTAL>
Gets the history of changes for particular bugs in the database.
=item B<REST>
To get the history for a specific bug ID:
GET /bug/<bug_id>/history
The returned data format will be the same as below.
=item B<Params>
=over
......@@ -2208,6 +2295,8 @@ The same as L</get>.
consistent with other methods. Since Bugzilla B<4.4>, they now match
names used by L<Bug.update|/"update"> for consistency.
=item REST API call added Bugzilla B<5.0>.
=back
=back
......@@ -2223,6 +2312,14 @@ B<UNSTABLE>
Allows you to search for bugs based on particular criteria.
=item <REST>
To search for bugs:
GET /bug
The URL parameters and the returned data format are the same as below.
=item B<Params>
Unless otherwise specified in the description of a parameter, bugs are
......@@ -2408,6 +2505,8 @@ in Bugzilla B<4.0>.
C<limit> is set equal to zero. Otherwise maximum results returned are limited
by system configuration.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
......@@ -2434,10 +2533,19 @@ The WebService interface may allow you to set things other than those listed
here, but realize that anything undocumented is B<UNSTABLE> and will very
likely change in the future.
=item B<REST>
To create a new bug in Bugzilla:
POST /bug
The params to include in the POST body as well as the returned data format,
are the same as below.
=item B<Params>
Some params must be set, or an error will be thrown. These params are
marked B<Required>.
marked B<Required>.
Some parameters can have defaults set in Bugzilla, by the administrator.
If these parameters have defaults set, you can omit them. These parameters
......@@ -2598,6 +2706,8 @@ loop errors had a generic code of C<32000>.
=item The ability to file new bugs with a C<resolution> was added in
Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
......@@ -2613,6 +2723,16 @@ B<STABLE>
This allows you to add an attachment to a bug in Bugzilla.
=item B<REST>
To create attachment on a current bug:
POST /bug/<bug_id>/attachment
The params to include in the POST body, as well as the returned
data format are the same as below. The C<ids> param will be
overridden as it it pulled from the URL path.
=item B<Params>
=over
......@@ -2710,6 +2830,8 @@ You set the "data" field to an empty string.
=item The return value has changed in Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
......@@ -2725,6 +2847,15 @@ B<STABLE>
This allows you to add a comment to a bug in Bugzilla.
=item B<REST>
To create a comment on a current bug:
POST /bug/<bug_id>/comment
The params to include in the POST body as well as the returned data format,
are the same as below.
=item B<Params>
=over
......@@ -2800,6 +2931,8 @@ purposes if you wish.
=item Before Bugzilla B<3.6>, error 54 and error 114 had a generic error
code of 32000.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
......@@ -2816,6 +2949,16 @@ B<UNSTABLE>
Allows you to update the fields of a bug. Automatically sends emails
out about the changes.
=item B<REST>
To update the fields of a current bug:
PUT /bug/<bug_id>
The params to include in the PUT body as well as the returned data format,
are the same as below. The C<ids> param will be overridden as it is
pulled from the URL path.
=item B<Params>
=over
......@@ -3260,6 +3403,8 @@ rules don't allow that change.
=item Added in Bugzilla B<4.0>.
=item REST API call added Bugzilla B<5.0>.
=back
=back
......
......@@ -121,12 +121,12 @@ sub time {
sub last_audit_time {
my ($self, $params) = validate(@_, 'class');
my $dbh = Bugzilla->dbh;
my $sql_statement = "SELECT MAX(at_time) FROM audit_log";
my $class_values = $params->{class};
my @class_values_quoted;
foreach my $class_value (@$class_values) {
push (@class_values_quoted, $dbh->quote($class_value))
push (@class_values_quoted, $dbh->quote($class_value))
if $class_value =~ /^Bugzilla(::[a-zA-Z0-9_]+)*$/;
}
......@@ -135,11 +135,11 @@ sub last_audit_time {
}
my $last_audit_time = $dbh->selectrow_array("$sql_statement");
# All Webservices return times in UTC; Use UTC here for backwards compat.
# Hardcode values where appropriate
$last_audit_time = datetime_from($last_audit_time, 'UTC');
return {
last_audit_time => $self->type('dateTime', $last_audit_time)
};
......@@ -181,6 +181,10 @@ This provides functions that tell you about Bugzilla in general.
See L<Bugzilla::WebService> for a description of how parameters are passed,
and what B<STABLE>, B<UNSTABLE>, and B<EXPERIMENTAL> mean.
Although the data input and output is the same for JSONRPC, XMLRPC and REST,
the directions for how to access the data via REST is noted in each method
where applicable.
=head2 version
B<STABLE>
......@@ -191,6 +195,12 @@ B<STABLE>
Returns the current version of Bugzilla.
=item B<REST>
GET /version
The returned data format is the same as below.
=item B<Params> (none)
=item B<Returns>
......@@ -200,6 +210,14 @@ string.
=item B<Errors> (none)
=item B<History>
=over
=item REST API call added in Bugzilla B<5.0>.
=back
=back
=head2 extensions
......@@ -213,6 +231,12 @@ B<EXPERIMENTAL>
Gets information about the extensions that are currently installed and enabled
in this Bugzilla.
=item B<REST>
GET /extensions
The returned data format is the same as below.
=item B<Params> (none)
=item B<Returns>
......@@ -243,6 +267,8 @@ The return value looks something like this:
that the extensions define themselves. Before 3.6, the names of the
extensions depended on the directory they were in on the Bugzilla server.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
......@@ -258,6 +284,12 @@ Use L</time> instead.
Returns the timezone that Bugzilla expects dates and times in.
=item B<REST>
GET /timezone
The returned data format is the same as below.
=item B<Params> (none)
=item B<Returns>
......@@ -272,6 +304,8 @@ string in (+/-)XXXX (RFC 2822) format.
=item As of Bugzilla B<3.6>, the timezone returned is always C<+0000>
(the UTC timezone).
=item REST API call added in Bugzilla B<5.0>.
=back
=back
......@@ -288,6 +322,12 @@ B<STABLE>
Gets information about what time the Bugzilla server thinks it is, and
what timezone it's running in.
=item B<REST>
GET /time
The returned data format is the same as below.
=item B<Params> (none)
=item B<Returns>
......@@ -298,7 +338,7 @@ A struct with the following items:
=item C<db_time>
C<dateTime> The current time in UTC, according to the Bugzilla
C<dateTime> The current time in UTC, according to the Bugzilla
I<database server>.
Note that Bugzilla assumes that the database and the webserver are running
......@@ -308,7 +348,7 @@ rely on for doing searches and other input to the WebService.
=item C<web_time>
C<dateTime> This is the current time in UTC, according to Bugzilla's
C<dateTime> This is the current time in UTC, according to Bugzilla's
I<web server>.
This might be different by a second from C<db_time> since this comes from
......@@ -324,7 +364,7 @@ versions of Bugzilla before 3.6.)
=item C<tz_name>
C<string> The literal string C<UTC>. (Exists only for backwards-compatibility
with versions of Bugzilla before 3.6.)
with versions of Bugzilla before 3.6.)
=item C<tz_short_name>
......@@ -348,6 +388,8 @@ with versions of Bugzilla before 3.6.)
were in the UTC timezone, instead of returning information in the server's
local timezone.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
......@@ -362,6 +404,12 @@ B<UNSTABLE>
Returns parameter values currently used in this Bugzilla.
=item B<REST>
GET /parameters
The returned data format is the same as below.
=item B<Params> (none)
=item B<Returns>
......@@ -419,6 +467,8 @@ never be stable.
=item Added in Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
......@@ -433,9 +483,15 @@ B<EXPERIMENTAL>
Gets the latest time of the audit_log table.
=item B<REST>
GET /last_audit_time
The returned data format is the same as below.
=item B<Params>
You can pass the optional parameter C<class> to get the maximum for only
You can pass the optional parameter C<class> to get the maximum for only
the listed classes.
=over
......@@ -460,6 +516,8 @@ at_time from the audit_log.
=item Added in Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
......@@ -86,7 +86,7 @@ Bugzilla::Webservice::Classification - The Classification API
=head1 DESCRIPTION
This part of the Bugzilla API allows you to deal with the available Classifications.
This part of the Bugzilla API allows you to deal with the available Classifications.
You will be able to get information about them as well as manipulate them.
=head1 METHODS
......@@ -94,6 +94,10 @@ You will be able to get information about them as well as manipulate them.
See L<Bugzilla::WebService> for a description of how parameters are passed,
and what B<STABLE>, B<UNSTABLE>, and B<EXPERIMENTAL> mean.
Although the data input and output is the same for JSONRPC, XMLRPC and REST,
the directions for how to access the data via REST is noted in each method
where applicable.
=head1 Classification Retrieval
=head2 get
......@@ -106,13 +110,21 @@ B<EXPERIMENTAL>
Returns a hash containing information about a set of classifications.
=item B<REST>
To return information on a single classification:
GET /classification/<classification_id_or_name>
The returned data format will be the same as below.
=item B<Params>
In addition to the parameters below, this method also accepts the
standard L<include_fields|Bugzilla::WebService/include_fields> and
L<exclude_fields|Bugzilla::WebService/exclude_fields> arguments.
You could get classifications info by supplying their names and/or ids.
You could get classifications info by supplying their names and/or ids.
So, this method accepts the following parameters:
=over
......@@ -127,10 +139,10 @@ An array of classification names.
=back
=item B<Returns>
=item B<Returns>
A hash with the key C<classifications> and an array of hashes as the corresponding value.
Each element of the array represents a classification that the user is authorized to see
Each element of the array represents a classification that the user is authorized to see
and has the following keys:
=over
......@@ -190,6 +202,8 @@ Classification is not enabled on this installation.
=item Added in Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
......
......@@ -14,9 +14,22 @@ use parent qw(Exporter);
our @EXPORT = qw(
WS_ERROR_CODE
STATUS_OK
STATUS_CREATED
STATUS_ACCEPTED
STATUS_NO_CONTENT
STATUS_MULTIPLE_CHOICES
STATUS_BAD_REQUEST
STATUS_NOT_FOUND
STATUS_GONE
REST_STATUS_CODE_MAP
ERROR_UNKNOWN_FATAL
ERROR_UNKNOWN_TRANSIENT
XMLRPC_CONTENT_TYPE_WHITELIST
REST_CONTENT_TYPE_WHITELIST
WS_DISPATCH
);
......@@ -172,8 +185,47 @@ use constant WS_ERROR_CODE => {
unknown_method => -32601,
json_rpc_post_only => 32610,
json_rpc_invalid_callback => 32611,
xmlrpc_illegal_content_type => 32612,
json_rpc_illegal_content_type => 32613,
xmlrpc_illegal_content_type => 32612,
json_rpc_illegal_content_type => 32613,
rest_invalid_resource => 32614,
};
# RESTful webservices use the http status code
# to describe whether a call was successful or
# to describe the type of error that occurred.
use constant STATUS_OK => 200;
use constant STATUS_CREATED => 201;
use constant STATUS_ACCEPTED => 202;
use constant STATUS_NO_CONTENT => 204;
use constant STATUS_MULTIPLE_CHOICES => 300;
use constant STATUS_BAD_REQUEST => 400;
use constant STATUS_NOT_AUTHORIZED => 401;
use constant STATUS_NOT_FOUND => 404;
use constant STATUS_GONE => 410;
# The integer value is the error code above returned by
# the related webvservice call. We choose the appropriate
# http status code based on the error code or use the
# default STATUS_BAD_REQUEST.
use constant REST_STATUS_CODE_MAP => {
51 => STATUS_NOT_FOUND,
101 => STATUS_NOT_FOUND,
102 => STATUS_NOT_AUTHORIZED,
106 => STATUS_NOT_AUTHORIZED,
109 => STATUS_NOT_AUTHORIZED,
110 => STATUS_NOT_AUTHORIZED,
113 => STATUS_NOT_AUTHORIZED,
115 => STATUS_NOT_AUTHORIZED,
120 => STATUS_NOT_AUTHORIZED,
300 => STATUS_NOT_AUTHORIZED,
301 => STATUS_NOT_AUTHORIZED,
302 => STATUS_NOT_AUTHORIZED,
303 => STATUS_NOT_AUTHORIZED,
304 => STATUS_NOT_AUTHORIZED,
410 => STATUS_NOT_AUTHORIZED,
504 => STATUS_NOT_AUTHORIZED,
505 => STATUS_NOT_AUTHORIZED,
_default => STATUS_BAD_REQUEST
};
# These are the fallback defaults for errors not in ERROR_CODE.
......@@ -187,6 +239,13 @@ use constant XMLRPC_CONTENT_TYPE_WHITELIST => qw(
application/xml
);
use constant REST_CONTENT_TYPE_WHITELIST => qw(
text/html
application/javascript
application/json
text/javascript
);
sub WS_DISPATCH {
# We "require" here instead of "use" above to avoid a dependency loop.
require Bugzilla::Hook;
......
......@@ -113,6 +113,10 @@ get information about them.
See L<Bugzilla::WebService> for a description of how parameters are passed,
and what B<STABLE>, B<UNSTABLE>, and B<EXPERIMENTAL> mean.
Although the data input and output is the same for JSONRPC, XMLRPC and REST,
the directions for how to access the data via REST is noted in each method
where applicable.
=head1 Group Creation and Modification
=head2 create
......@@ -125,9 +129,16 @@ B<UNSTABLE>
This allows you to create a new group in Bugzilla.
=item B<Params>
=item B<REST>
POST /group
The params to include in the POST body as well as the returned data format,
are the same as below.
Some params must be set, or an error will be thrown. These params are
=item B<Params>
Some params must be set, or an error will be thrown. These params are
marked B<Required>.
=over
......@@ -148,7 +159,7 @@ name of the group.
C<string> A regular expression. Any user whose Bugzilla username matches
this regular expression will automatically be granted membership in this group.
=item C<is_active>
=item C<is_active>
C<boolean> C<True> if new group can be used for bugs, C<False> if this
is a group that will only contain users and no bugs will be restricted
......@@ -162,7 +173,7 @@ if they are in this group.
=back
=item B<Returns>
=item B<Returns>
A hash with one element, C<id>. This is the id of the newly-created group.
......@@ -188,7 +199,15 @@ You specified an invalid regular expression in the C<user_regexp> field.
=back
=back
=item B<History>
=over
=item REST API call added in Bugzilla B<5.0>.
=back
=back
=head2 update
......@@ -200,6 +219,14 @@ B<UNSTABLE>
This allows you to update a group in Bugzilla.
=item B<REST>
PUT /group/<group_name_or_id>
The params to include in the PUT body as well as the returned data format,
are the same as below. The C<ids> param will be overridden as it is pulled
from the URL path.
=item B<Params>
At least C<ids> or C<names> must be set, or an error will be thrown.
......@@ -278,6 +305,14 @@ comma-and-space-separated list if multiple values were removed.
The same as L</create>.
=item B<History>
=over
=item REST API call added in Bugzilla B<5.0>.
=back
=back
=cut
......@@ -336,6 +336,10 @@ get information about them.
See L<Bugzilla::WebService> for a description of how parameters are passed,
and what B<STABLE>, B<UNSTABLE>, and B<EXPERIMENTAL> mean.
Although the data input and output is the same for JSONRPC, XMLRPC and REST,
the directions for how to access the data via REST is noted in each method
where applicable.
=head1 List Products
=head2 get_selectable_products
......@@ -348,15 +352,29 @@ B<EXPERIMENTAL>
Returns a list of the ids of the products the user can search on.
=item B<REST>
GET /product?type=selectable
the returned data format is same as below.
=item B<Params> (none)
=item B<Returns>
=item B<Returns>
A hash containing one item, C<ids>, that contains an array of product
ids.
=item B<Errors> (none)
=item B<History>
=over
=item REST API call added in Bugzilla B<5.0>.
=back
=back
=head2 get_enterable_products
......@@ -370,6 +388,12 @@ B<EXPERIMENTAL>
Returns a list of the ids of the products the user can enter bugs
against.
=item B<REST>
GET /product?type=enterable
the returned data format is same as below.
=item B<Params> (none)
=item B<Returns>
......@@ -379,6 +403,14 @@ ids.
=item B<Errors> (none)
=item B<History>
=over
=item REST API call added in Bugzilla B<5.0>.
=back
=back
=head2 get_accessible_products
......@@ -392,6 +424,12 @@ B<UNSTABLE>
Returns a list of the ids of the products the user can search or enter
bugs against.
=item B<REST>
GET /product?type=accessible
the returned data format is same as below.
=item B<Params> (none)
=item B<Returns>
......@@ -401,6 +439,14 @@ ids.
=item B<Errors> (none)
=item B<History>
=over
=item REST API call added in Bugzilla B<5.0>.
=back
=back
=head2 get
......@@ -417,6 +463,12 @@ B<Note>: You must at least specify one of C<ids> or C<names>.
B<Note>: Can also be called as "get_products" for compatibilty with Bugzilla 3.0 API.
=item B<REST>
GET /product/<product_id_or_name>
the returned data format is same as below.
=item B<Params>
In addition to the parameters below, this method also accepts the
......@@ -612,6 +664,8 @@ been removed.
=item In Bugzilla B<4.4>, C<flag_types> was added to the fields returned
by C<get>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
......@@ -628,9 +682,16 @@ B<EXPERIMENTAL>
This allows you to create a new product in Bugzilla.
=item B<Params>
=item B<REST>
POST /product
The params to include in the POST body as well as the returned data format,
are the same as below.
Some params must be set, or an error will be thrown. These params are
=item B<Params>
Some params must be set, or an error will be thrown. These params are
marked B<Required>.
=over
......@@ -709,6 +770,14 @@ You must specify a version for this product.
=back
=item B<History>
=over
=item REST API call added in Bugzilla B<5.0>.
=back
=back
=head2 update
......@@ -721,6 +790,14 @@ B<EXPERIMENTAL>
This allows you to update a product in Bugzilla.
=item B<REST>
PUT /product/<product_id_or_name>
The params to include in the PUT body as well as the returned data format,
are the same as below. The C<ids> and C<names> params will be overridden as
it is pulled from the URL path.
=item B<Params>
B<Note:> The following parameters specify which products you are updating.
......@@ -859,6 +936,8 @@ You must define a default milestone.
=item Added in Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
......
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package Bugzilla::WebService::Server::REST::Resources::Bug;
use 5.10.1;
use strict;
use Bugzilla::WebService::Constants;
use Bugzilla::WebService::Bug;
BEGIN {
*Bugzilla::WebService::Bug::rest_resources = \&_rest_resources;
};
sub _rest_resources {
my $rest_resources = [
qr{^/bug$}, {
GET => {
method => 'search',
},
POST => {
method => 'create',
status_code => STATUS_CREATED
}
},
qr{^/bug/([^/]+)$}, {
GET => {
method => 'get',
params => sub {
return { ids => [ $_[0] ] };
}
},
PUT => {
method => 'update',
params => sub {
return { ids => [ $_[0] ] };
}
}
},
qr{^/bug/([^/]+)/comment$}, {
GET => {
method => 'comments',
params => sub {
return { ids => [ $_[0] ] };
}
},
POST => {
method => 'add_comment',
params => sub {
return { id => $_[0] };
},
success_code => STATUS_CREATED
}
},
qr{^/bug/comment/([^/]+)$}, {
GET => {
method => 'comments',
params => sub {
return { comment_ids => [ $_[0] ] };
}
}
},
qr{^/bug/([^/]+)/history$}, {
GET => {
method => 'history',
params => sub {
return { ids => [ $_[0] ] };
},
}
},
qr{^/bug/([^/]+)/attachment$}, {
GET => {
method => 'attachments',
params => sub {
return { ids => [ $_[0] ] };
}
},
POST => {
method => 'add_attachment',
params => sub {
return { ids => [ $_[0] ] };
},
success_code => STATUS_CREATED
}
},
qr{^/bug/attachment/([^/]+)$}, {
GET => {
method => 'attachments',
params => sub {
return { attachment_ids => [ $_[0] ] };
}
}
},
qr{^/field/bug$}, {
GET => {
method => 'fields',
}
},
qr{^/field/bug/([^/]+)$}, {
GET => {
method => 'fields',
params => sub {
my $value = $_[0];
my $param = 'names';
$param = 'ids' if $value =~ /^\d+$/;
return { $param => [ $_[0] ] };
}
}
},
qr{^/field/bug/([^/]+)/values$}, {
GET => {
method => 'legal_values',
params => sub {
return { field => $_[0] };
}
}
},
qr{^/field/bug/([^/]+)/([^/]+)/values$}, {
GET => {
method => 'legal_values',
params => sub {
return { field => $_[0],
product_id => $_[1] };
}
}
},
];
return $rest_resources;
}
1;
__END__
=head1 NAME
Bugzilla::Webservice::Server::REST::Resources::Bug - The REST API for creating,
changing, and getting the details of bugs.
=head1 DESCRIPTION
This part of the Bugzilla REST API allows you to file a new bug in Bugzilla,
or get information about bugs that have already been filed.
See L<Bugzilla::WebService::Bug> for more details on how to use this part of
the REST API.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package Bugzilla::WebService::Server::REST::Resources::Bugzilla;
use 5.10.1;
use strict;
use Bugzilla::WebService::Constants;
use Bugzilla::WebService::Bugzilla;
BEGIN {
*Bugzilla::WebService::Bugzilla::rest_resources = \&_rest_resources;
};
sub _rest_resources {
my $rest_resources = [
qr{^/version$}, {
GET => {
method => 'version'
}
},
qr{^/extensions$}, {
GET => {
method => 'extensions'
}
},
qr{^/timezone$}, {
GET => {
method => 'timezone'
}
},
qr{^/time$}, {
GET => {
method => 'time'
}
},
qr{^/last_audit_time$}, {
GET => {
method => 'last_audit_time'
}
},
qr{^/parameters$}, {
GET => {
method => 'parameters'
}
}
];
return $rest_resources;
}
1;
__END__
=head1 NAME
Bugzilla::WebService::Bugzilla - Global functions for the webservice interface.
=head1 DESCRIPTION
This provides functions that tell you about Bugzilla in general.
See L<Bugzilla::WebService::Bugzilla> for more details on how to use this part
of the REST API.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package Bugzilla::WebService::Server::REST::Resources::Classification;
use 5.10.1;
use strict;
use Bugzilla::WebService::Constants;
use Bugzilla::WebService::Classification;
BEGIN {
*Bugzilla::WebService::Classification::rest_resources = \&_rest_resources;
};
sub _rest_resources {
my $rest_resources = [
qr{^/classification/([^/]+)$}, {
GET => {
method => 'get',
params => sub {
my $param = $_[0] =~ /^\d+$/ ? 'ids' : 'names';
return { $param => [ $_[0] ] };
}
}
}
];
return $rest_resources;
}
1;
__END__
=head1 NAME
Bugzilla::Webservice::Server::REST::Resources::Classification - The Classification REST API
=head1 DESCRIPTION
This part of the Bugzilla REST API allows you to deal with the available Classifications.
You will be able to get information about them as well as manipulate them.
See L<Bugzilla::WebService::Bug> for more details on how to use this part
of the REST API.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package Bugzilla::WebService::Server::REST::Resources::Group;
use 5.10.1;
use strict;
use Bugzilla::WebService::Constants;
use Bugzilla::WebService::Group;
BEGIN {
*Bugzilla::WebService::Group::rest_resources = \&_rest_resources;
};
sub _rest_resources {
my $rest_resources = [
qr{^/group$}, {
POST => {
method => 'create',
success_code => STATUS_CREATED
}
},
qr{^/group/([^/]+)$}, {
PUT => {
method => 'update',
params => sub {
my $param = $_[0] =~ /^\d+$/ ? 'ids' : 'names';
return { $param => [ $_[0] ] };
}
}
}
];
return $rest_resources;
}
1;
__END__
=head1 NAME
Bugzilla::Webservice::Server::REST::Resources::Group - The REST API for
creating, changing, and getting information about Groups.
=head1 DESCRIPTION
This part of the Bugzilla REST API allows you to create Groups and
get information about them.
See L<Bugzilla::WebService::Group> for more details on how to use this part
of the REST API.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package Bugzilla::WebService::Server::REST::Resources::Product;
use 5.10.1;
use strict;
use Bugzilla::WebService::Constants;
use Bugzilla::WebService::Product;
use Bugzilla::Error;
BEGIN {
*Bugzilla::WebService::Product::rest_resources = \&_rest_resources;
};
sub _rest_resources {
my $rest_resources = [
qr{^/product$}, {
GET => {
method => sub {
my $type = Bugzilla->input_params->{type};
return 'get_accessible_products'
if !defined $type || $type eq 'accessible';
return 'get_enterable_products' if $type eq 'enterable';
return 'get_selectable_products' if $type eq 'selectable';
ThrowUserError('rest_get_products_invalid_type',
{ type => $type });
},
},
POST => {
method => 'create',
success_code => STATUS_CREATED
}
},
qr{^/product/([^/]+)$}, {
GET => {
method => 'get',
params => sub {
my $param = $_[0] =~ /^\d+$/ ? 'ids' : 'names';
return { $param => [ $_[0] ] };
}
},
PUT => {
method => 'update',
params => sub {
my $param = $_[0] =~ /^\d+$/ ? 'ids' : 'names';
return { $param => [ $_[0] ] };
}
}
},
];
return $rest_resources;
}
1;
__END__
=head1 NAME
Bugzilla::Webservice::Server::REST::Resources::Product - The Product REST API
=head1 DESCRIPTION
This part of the Bugzilla REST API allows you to list the available Products and
get information about them.
See L<Bugzilla::WebService::Bug> for more details on how to use this part of
the REST API.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package Bugzilla::WebService::Server::REST::Resources::User;
use 5.10.1;
use strict;
use Bugzilla::WebService::Constants;
use Bugzilla::WebService::User;
BEGIN {
*Bugzilla::WebService::User::rest_resources = \&_rest_resources;
};
sub _rest_resources {
my $rest_resources = [
qr{^/user$}, {
GET => {
method => 'get'
},
POST => {
method => 'create',
success_code => STATUS_CREATED
}
},
qr{^/user/([^/]+)$}, {
GET => {
method => 'get',
params => sub {
my $param = $_[0] =~ /^\d+$/ ? 'ids' : 'names';
return { $param => [ $_[0] ] };
}
},
PUT => {
method => 'update',
params => sub {
my $param = $_[0] =~ /^\d+$/ ? 'ids' : 'names';
return { $param => [ $_[0] ] };
}
}
}
];
return $rest_resources;
}
1;
__END__
=head1 NAME
Bugzilla::Webservice::Server::REST::Resources::User - The User Account REST API
=head1 DESCRIPTION
This part of the Bugzilla REST API allows you to get User information as well
as create User Accounts.
See L<Bugzilla::WebService::Bug> for more details on how to use this part of
the REST API.
......@@ -127,7 +127,7 @@ sub create {
# $call = $rpc->call( 'User.get', { ids => [1,2,3],
# names => ['testusera@redhat.com', 'testuserb@redhat.com'] });
sub get {
my ($self, $params) = validate(@_, 'names', 'ids');
my ($self, $params) = validate(@_, 'names', 'ids', 'match', 'group_ids', 'groups');
Bugzilla->switch_to_shadow_db();
......@@ -399,6 +399,10 @@ log in/out using an existing account.
See L<Bugzilla::WebService> for a description of how parameters are passed,
and what B<STABLE>, B<UNSTABLE>, and B<EXPERIMENTAL> mean.
Although the data input and output is the same for JSONRPC, XMLRPC and REST,
the directions for how to access the data via REST is noted in each method
where applicable.
=head1 Logging In and Out
=head2 login
......@@ -417,7 +421,7 @@ etc. This method logs in an user.
=over
=item C<login> (string) - The user's login name.
=item C<login> (string) - The user's login name.
=item C<password> (string) - The user's password.
......@@ -541,6 +545,13 @@ actually receive an email. This function does not check that.
You must be logged in and have the C<editusers> privilege in order to
call this function.
=item B<REST>
POST /user
The params to include in the POST body as well as the returned data format,
are the same as below.
=item B<Params>
=over
......@@ -584,6 +595,8 @@ password is under three characters.)
=item Error 503 (Password Too Long) removed in Bugzilla B<3.6>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
......@@ -598,6 +611,14 @@ B<EXPERIMENTAL>
Updates user accounts in Bugzilla.
=item B<REST>
PUT /user/<user_id_or_name>
The params to include in the PUT body as well as the returned data format,
are the same as below. The C<ids> and C<names> params are overridden as they
are pulled from the URL path.
=item B<Params>
=over
......@@ -684,6 +705,14 @@ Logged-in users are not authorized to edit other users.
=back
=item B<History>
=over
=item REST API call added in Bugzilla B<5.0>.
=back
=back
=head1 User Info
......@@ -698,6 +727,18 @@ B<STABLE>
Gets information about user accounts in Bugzilla.
=item B<REST>
To get information about a single user:
GET /user/<user_id_or_name>
To search for users by name, group using URL params same as below:
GET /user
The returned data format is the same as below.
=item B<Params>
B<Note>: At least one of C<ids>, C<names>, or C<match> must be specified.
......@@ -920,6 +961,8 @@ illegal to pass a group name you don't belong to.
=item C<groups>, C<saved_searches>, and C<saved_reports> were added
in Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
#!/usr/bin/perl -wT
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use lib qw(. lib);
use Bugzilla;
use Bugzilla::Constants;
use Bugzilla::Error;
use Bugzilla::WebService::Constants;
BEGIN {
if (!Bugzilla->feature('rest')
|| !Bugzilla->feature('jsonrpc'))
{
ThrowUserError('feature_disabled', { feature => 'rest' });
}
}
use Bugzilla::WebService::Server::REST;
Bugzilla->usage_mode(USAGE_MODE_REST);
local @INC = (bz_locations()->{extensionsdir}, @INC);
my $server = new Bugzilla::WebService::Server::REST;
$server->version('1.1');
$server->handle();
......@@ -1073,6 +1073,13 @@
For security reasons, you must use HTTP POST to call the
'[% method FILTER html %]' method.
[% ELSIF error == "rest_invalid_resource" %]
A REST API resource was not found for '[% method FILTER html +%] [%+ path FILTER html %]'.
[% ELSIF error == "rest_get_products_invalid_type" %]
The type '[% type FILTER html %]' is invalid for 'GET /product'. Valid choices
are 'accessible' (default if type value is undefined), 'selectable', and 'enterable'.
[% ELSIF error == "keyword_already_exists" %]
[% title = "Keyword Already Exists" %]
A keyword with the name [% name FILTER html %] already exists.
......
[%# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
#%]
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Bugzilla::REST::API</title>
<link href="[% urlbase FILTER none %][% 'skins/standard/global.css' FILTER mtime %]"
rel="stylesheet" type="text/css">
</head>
<body>
<pre>[% result FILTER html %]</pre>
</body>
</html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment