blob: 557a996f87bb3d5d51272f22ee5ce39ef620e9b1 [file] [log] [blame]
# 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::Constants;
use 5.10.1;
use strict;
use warnings;
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
);
# This maps the error names in global/*-error.html.tmpl to numbers.
# Generally, transient errors should have a number above 0, and
# fatal errors should have a number below 0.
#
# This hash should generally contain any error that could be thrown
# by the WebService interface. If it's extremely unlikely that the
# error could be thrown (like some CodeErrors), it doesn't have to
# be listed here.
#
# "Transient" means "If you resubmit that request with different data,
# it may work."
#
# "Fatal" means, "There's something wrong with Bugzilla, probably
# something an administrator would have to fix."
#
# NOTE: Numbers must never be recycled. If you remove a number, leave a
# comment that it was retired. Also, if an error changes its name, you'll
# have to fix it here.
use constant WS_ERROR_CODE => {
# Generic errors (Bugzilla::Object and others) are 50-99.
object_not_specified => 50,
reassign_to_empty => 50,
param_required => 50,
params_required => 50,
undefined_field => 50,
object_does_not_exist => 51,
param_must_be_numeric => 52,
number_not_numeric => 52,
param_invalid => 53,
number_too_large => 54,
number_too_small => 55,
illegal_date => 56,
param_integer_required => 57,
param_scalar_array_required => 58,
# Bug errors usually occupy the 100-200 range.
improper_bug_id_field_value => 100,
bug_id_does_not_exist => 101,
bug_access_denied => 102,
bug_access_query => 102,
# These all mean "invalid alias"
alias_too_long => 103,
alias_in_use => 103,
alias_is_numeric => 103,
alias_has_comma_or_space => 103,
multiple_alias_not_allowed => 103,
# Misc. bug field errors
illegal_field => 104,
freetext_too_long => 104,
# Component errors
require_component => 105,
component_name_too_long => 105,
product_unknown_component => 105,
# Invalid Product
no_products => 106,
entry_access_denied => 106,
product_access_denied => 106,
product_disabled => 106,
# Invalid Summary
require_summary => 107,
# Invalid field name
invalid_field_name => 108,
# Not authorized to edit the bug
product_edit_denied => 109,
# Comment-related errors
comment_is_private => 110,
comment_id_invalid => 111,
comment_too_long => 114,
comment_invalid_isprivate => 117,
# Comment tagging
comment_tag_disabled => 125,
comment_tag_invalid => 126,
comment_tag_too_long => 127,
comment_tag_too_short => 128,
# See Also errors
bug_url_invalid => 112,
bug_url_too_long => 112,
# Insidergroup Errors
user_not_insider => 113,
# Note: 114 is above in the Comment-related section.
# Bug update errors
illegal_change => 115,
# Dependency errors
dependency_loop_single => 116,
dependency_loop_multi => 116,
# Note: 117 is above in the Comment-related section.
# Dup errors
dupe_loop_detected => 118,
dupe_id_required => 119,
# Bug-related group errors
group_invalid_removal => 120,
group_restriction_not_allowed => 120,
# Status/Resolution errors
missing_resolution => 121,
resolution_not_allowed => 122,
illegal_bug_status_transition => 123,
# Flag errors
flag_status_invalid => 129,
flag_update_denied => 130,
flag_type_requestee_disabled => 131,
flag_not_unique => 132,
flag_type_not_unique => 133,
flag_type_inactive => 134,
# Authentication errors are usually 300-400.
invalid_login_or_password => 300,
account_disabled => 301,
auth_invalid_email => 302,
extern_id_conflict => -303,
auth_failure => 304,
password_too_short => 305,
password_not_complex => 305,
api_key_not_valid => 306,
api_key_revoked => 306,
auth_invalid_token => 307,
# Except, historically, AUTH_NODATA, which is 410.
login_required => 410,
# User errors are 500-600.
account_exists => 500,
illegal_email_address => 501,
auth_cant_create_account => 501,
account_creation_disabled => 501,
account_creation_restricted => 501,
password_too_short => 502,
# Error 503 password_too_long no longer exists.
invalid_username => 504,
# This is from strict_isolation, but it also basically means
# "invalid user."
invalid_user_group => 504,
user_access_by_id_denied => 505,
user_access_by_match_denied => 505,
# Attachment errors are 600-700.
file_too_large => 600,
invalid_content_type => 601,
# Error 602 attachment_illegal_url no longer exists.
file_not_specified => 603,
missing_attachment_description => 604,
# Error 605 attachment_url_disabled no longer exists.
zero_length_file => 606,
# Product erros are 700-800
product_blank_name => 700,
product_name_too_long => 701,
product_name_already_in_use => 702,
product_name_diff_in_case => 702,
product_must_have_description => 703,
product_must_have_version => 704,
product_must_define_defaultmilestone => 705,
# Group errors are 800-900
empty_group_name => 800,
group_exists => 801,
empty_group_description => 802,
invalid_regexp => 803,
invalid_group_name => 804,
group_cannot_view => 805,
# Classification errors are 900-1000
auth_classification_not_enabled => 900,
# Search errors are 1000-1100
buglist_parameters_required => 1000,
# Flag type errors are 1100-1200
flag_type_name_invalid => 1101,
flag_type_description_invalid => 1102,
flag_type_cc_list_invalid => 1103,
flag_type_sortkey_invalid => 1104,
flag_type_not_editable => 1105,
# Component errors are 1200-1300
component_already_exists => 1200,
component_is_last => 1201,
component_has_bugs => 1202,
# Errors thrown by the WebService itself. The ones that are negative
# conform to http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php
xmlrpc_invalid_value => -32600,
unknown_method => -32601,
json_rpc_post_only => 32610,
json_rpc_invalid_callback => 32611,
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.
sub REST_STATUS_CODE_MAP {
my $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,
32614 => STATUS_NOT_FOUND,
_default => STATUS_BAD_REQUEST
};
Bugzilla::Hook::process('webservice_status_code_map',
{ status_code_map => $status_code_map });
return $status_code_map;
};
# These are the fallback defaults for errors not in ERROR_CODE.
use constant ERROR_UNKNOWN_FATAL => -32000;
use constant ERROR_UNKNOWN_TRANSIENT => 32000;
use constant ERROR_GENERAL => 999;
use constant XMLRPC_CONTENT_TYPE_WHITELIST => qw(
text/xml
application/xml
);
# The first content type specified is used as the default.
use constant REST_CONTENT_TYPE_WHITELIST => qw(
application/json
application/javascript
text/javascript
text/html
);
sub WS_DISPATCH {
# We "require" here instead of "use" above to avoid a dependency loop.
require Bugzilla::Hook;
my %hook_dispatch;
Bugzilla::Hook::process('webservice', { dispatch => \%hook_dispatch });
my $dispatch = {
'Bugzilla' => 'Bugzilla::WebService::Bugzilla',
'Bug' => 'Bugzilla::WebService::Bug',
'Classification' => 'Bugzilla::WebService::Classification',
'Component' => 'Bugzilla::WebService::Component',
'FlagType' => 'Bugzilla::WebService::FlagType',
'Group' => 'Bugzilla::WebService::Group',
'Product' => 'Bugzilla::WebService::Product',
'User' => 'Bugzilla::WebService::User',
'BugUserLastVisit' => 'Bugzilla::WebService::BugUserLastVisit',
%hook_dispatch
};
return $dispatch;
};
1;
=head1 B<Methods in need of POD>
=over
=item REST_STATUS_CODE_MAP
=item WS_DISPATCH
=back