summaryrefslogtreecommitdiffstats
path: root/Bugzilla/WebService/Constants.pm
blob: 71fcccd6ebf072d7b1ac321d146a82a6a616a039 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
# 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 base 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

  API_AUTH_HEADERS
);

# 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,

  # 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,

  # 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_username_or_password => 300,
  account_disabled             => 301,
  auth_invalid_email           => 302,
  extern_id_conflict           => -303,
  auth_failure                 => 304,
  password_insecure            => 305,
  api_key_not_valid            => 306,
  api_key_revoked              => 306,
  auth_invalid_token           => 307,
  invalid_cookies_or_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,

  # Error 502 password_too_short no longer exists.
  # 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,

  # Search errors are 1000-1100
  buglist_parameters_required => 1000,

  # BugUserLastVisited errors
  user_not_involved => 1300,

  # Job queue errors 1400-1500
  jobqueue_status_error => 1400,

  # 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',
    'User'             => 'Bugzilla::WebService::User',
    'Product'          => 'Bugzilla::WebService::Product',
    'Group'            => 'Bugzilla::WebService::Group',
    'BugUserLastVisit' => 'Bugzilla::WebService::BugUserLastVisit',
    'Elastic'          => 'Bugzilla::WebService::Elastic',
    %hook_dispatch
  };
  return $dispatch;
}

# Custom HTTP headers that can be used for API authentication rather than
# passing as URL parameters. This is useful if you do not want sensitive
# information to show up in webserver log files.
use constant API_AUTH_HEADERS => {
  X_BUGZILLA_LOGIN    => 'Bugzilla_login',
  X_BUGZILLA_PASSWORD => 'Bugzilla_password',
  X_BUGZILLA_API_KEY  => 'Bugzilla_api_key',
  X_BUGZILLA_TOKEN    => 'Bugzilla_token',
};

1;