Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug 1675625 - Refactor error handing in Mojolicious to allow for native mojo code to something other than Bugzilla::Error #1655

Merged
merged 41 commits into from
Nov 30, 2020
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
c05319a
Bump version to 20200117.1
dklawren Jan 17, 2020
f66659c
Merge remote-tracking branch 'upstream/master'
dklawren Jan 23, 2020
1457930
Merge remote-tracking branch 'upstream/master'
dklawren Feb 4, 2020
879c02a
Merge remote-tracking branch 'upstream/master'
dklawren Feb 11, 2020
cf08e61
Merge remote-tracking branch 'upstream/master'
dklawren Feb 26, 2020
9c9e237
Merge remote-tracking branch 'upstream/master'
dklawren Feb 26, 2020
0d8cb41
Merge remote-tracking branch 'upstream/master'
dklawren Feb 26, 2020
c48e749
Merge remote-tracking branch 'upstream/master'
dklawren Mar 5, 2020
44f1149
Merge remote-tracking branch 'upstream/master'
dklawren Mar 6, 2020
db980c8
Merge remote-tracking branch 'upstream/master'
dklawren Mar 9, 2020
9bce0ae
Merge remote-tracking branch 'upstream/master'
dklawren Mar 9, 2020
f8194dc
Merge remote-tracking branch 'upstream/master'
Mar 11, 2020
f5e8ed5
Merge remote-tracking branch 'upstream/master'
dklawren Mar 20, 2020
be21ec1
Merge branch 'master' of https://github.com/dklawren/bmo
dklawren Mar 20, 2020
698f56f
Merge remote-tracking branch 'upstream/master'
dklawren Mar 25, 2020
d96a196
Merge remote-tracking branch 'upstream/master'
dklawren Apr 10, 2020
a4ccc14
Merge remote-tracking branch 'upstream/master'
dklawren Apr 27, 2020
e83671b
Merge remote-tracking branch 'upstream/master'
dklawren Apr 29, 2020
52fd38a
Merge remote-tracking branch 'upstream/master'
dklawren May 4, 2020
4175907
Merge remote-tracking branch 'upstream/master'
dklawren May 5, 2020
32293eb
Merge remote-tracking branch 'upstream/master'
dklawren May 22, 2020
b332a70
Merge remote-tracking branch 'upstream/master'
dklawren Jun 9, 2020
61b5a62
Merge remote-tracking branch 'upstream/master'
dklawren Jul 2, 2020
3310020
Merge remote-tracking branch 'upstream/master'
dklawren Jul 8, 2020
1089d75
Merge remote-tracking branch 'upstream/master'
dklawren Jul 20, 2020
a2a2e82
Merge remote-tracking branch 'upstream/master'
dklawren Aug 20, 2020
00d6e6a
Merge remote-tracking branch 'upstream/master'
dklawren Sep 2, 2020
2adfd4c
Merge remote-tracking branch 'upstream/master'
dklawren Sep 16, 2020
96b7356
Merge remote-tracking branch 'upstream/master' into master
dklawren Oct 13, 2020
bb3076f
Merge remote-tracking branch 'upstream/master'
dklawren Oct 16, 2020
e1b2175
Merge remote-tracking branch 'upstream/master'
dklawren Oct 23, 2020
2000ac8
Merge remote-tracking branch 'upstream/master'
dklawren Oct 26, 2020
27acdda
Merge remote-tracking branch 'upstream/master'
dklawren Oct 30, 2020
5bf03d7
Merge remote-tracking branch 'upstream/master'
dklawren Nov 9, 2020
561592d
Bug 1675625 - Refactor error handing in Mojolicious to allow for nati…
dklawren Nov 9, 2020
621632f
- Fixed an issue with oauth2 clients and selecting multiple scopes
dklawren Nov 9, 2020
4a5d168
- Refactoring to allow setting USAGE_MODE_REST for API error reporting
dklawren Nov 9, 2020
e809da4
Merge remote-tracking branch 'upstream/master' into master
dklawren Nov 18, 2020
2c42f09
Merge branch 'mojo-error-handling' of https://github.com/dklawren/bmo…
dklawren Nov 18, 2020
79a6ca6
Update base on review comments.
dklawren Nov 18, 2020
7ae1d0c
Merge branch 'master' into mojo-error-handling
dklawren Nov 19, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions Bugzilla/API/V1/Configuration.pm
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ use Mojo::JSON qw( true false );

sub setup_routes {
my ($class, $r) = @_;
$r->get('/latest/configuration')->to('V1::Configuration#configuration');
$r->get('/rest/configuration')->to('V1::Configuration#configuration');
$r->get('/bzapi/configuration')->to('V1::Configuration#configuration');
$r->get('/configuration')->to('V1::Configuration#configuration');
}

sub configuration {
Expand Down
5 changes: 2 additions & 3 deletions Bugzilla/API/V1/User.pm
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ use Mojo::JSON qw( true false );

sub setup_routes {
my ($class, $r) = @_;
$r->get('/api/user/profile')->to('V1::User#user_profile');
$r->get('/rest/user/profile')->to('V1::User#user_profile');
$r->get('/profile')->to('V1::User#user_profile');
dklawren marked this conversation as resolved.
Show resolved Hide resolved
}

sub user_profile {
Expand All @@ -35,7 +34,7 @@ sub user_profile {
);
}
else {
$self->render(status => 401, text => 'Unauthorized');
return $self->user_error('invalid_username');
}
}

Expand Down
1 change: 1 addition & 0 deletions Bugzilla/App.pm
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ sub startup {
$self->plugin('Bugzilla::App::Plugin::BlockIP');
$self->plugin('Bugzilla::App::Plugin::Glue');
$self->plugin('Bugzilla::App::Plugin::Login');
$self->plugin('Bugzilla::App::Plugin::Error');
$self->plugin('Bugzilla::App::Plugin::Hostage')
unless $ENV{BUGZILLA_DISABLE_HOSTAGE};
$self->plugin('Bugzilla::App::Plugin::SizeLimit')
Expand Down
23 changes: 20 additions & 3 deletions Bugzilla/App/API.pm
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@
package Bugzilla::App::API;

use 5.10.1;
use Bugzilla::Logging;
use Module::Runtime qw(require_module);
use Mojo::Base qw( Mojolicious::Controller );

use Mojo::Loader qw( find_modules );
use Module::Runtime qw(require_module);
use Try::Tiny;

use Bugzilla::Constants;
use Bugzilla::Logging;

use constant SUPPORTED_VERSIONS => qw(V1);

sub setup_routes {
Expand All @@ -24,13 +27,27 @@ sub setup_routes {
push @$namespaces, 'Bugzilla::API';
$r->namespaces($namespaces);

# Backwards compat with /api/user/profile which Phabricator
dklawren marked this conversation as resolved.
Show resolved Hide resolved
$r->under('/api' => sub { Bugzilla->usage_mode(USAGE_MODE_REST); })
->get('/user/profile')->to('V1::User#user_profile');

# Other backwards compat routes
$r->under('/latest' => sub { Bugzilla->usage_mode(USAGE_MODE_REST); })
->get('/configuration')->to('V1::Configuration#configuration');
$r->under('/bzapi' => sub { Bugzilla->usage_mode(USAGE_MODE_REST); })
->get('/configuration')->to('V1::Configuration#configuration');

# Set the usage mode for all routes under /rest
my $rest_routes
= $r->under('/rest' => sub { Bugzilla->usage_mode(USAGE_MODE_REST); });

foreach my $version (SUPPORTED_VERSIONS) {
foreach my $module (find_modules("Bugzilla::API::$version")) {
try {
require_module($module);
my $controller = $module->new;
if ($controller->can('setup_routes')) {
$controller->setup_routes($r);
$controller->setup_routes($rest_routes);
}
}
catch {
Expand Down
48 changes: 25 additions & 23 deletions Bugzilla/App/OAuth2/Clients.pm
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ sub setup_routes {
my $client_route = $r->under(
'/admin/oauth' => sub {
my ($c) = @_;
Bugzilla->usage_mode(USAGE_MODE_MOJO);
my $user = $c->bugzilla->login(LOGIN_REQUIRED) || return undef;
$user->in_group('admin')
|| ThrowUserError('auth_failure',
|| return $c->user_error('auth_failure',
{group => 'admin', action => 'edit', object => 'oauth_clients'});
return 1;
}
Expand Down Expand Up @@ -67,31 +68,32 @@ sub create {
my $description = $self->param('description');
my $id = $self->param('id');
my $secret = $self->param('secret');
my @scopes = $self->param('scopes');
$description or ThrowCodeError('param_required', {param => 'description'});
$id or ThrowCodeError('param_required', {param => 'id'});
$secret or ThrowCodeError('param_required', {param => 'secret'});
any { $_ > 0 } @scopes or ThrowCodeError('param_required', {param => 'scopes'});
my $scopes = $self->every_param('scopes');
$description
or return $self->code_error('param_required', {param => 'description'});
$id or return $self->code_error('param_required', {param => 'id'});
$secret or return $self->code_error('param_required', {param => 'secret'});
any { $_ > 0 } @{$scopes}
or return $self->code_error('param_required', {param => 'scopes'});
my $token = $self->param('token');
check_token_data($token, 'create_oauth_client');

$dbh->do('INSERT INTO oauth2_client (client_id, description, secret) VALUES (?, ?, ?)',
$dbh->do(
'INSERT INTO oauth2_client (client_id, description, secret) VALUES (?, ?, ?)',
undef, $id, $description, $secret);

my $client_data
= $dbh->selectrow_hashref('SELECT * FROM oauth2_client WHERE client_id = ?',
undef, $id);

foreach my $scope_id (@scopes) {
foreach my $scope_id (@{$scopes}) {
$scope_id = $dbh->selectrow_array('SELECT id FROM oauth2_scope WHERE id = ?',
undef, $scope_id);
if (!$scope_id) {
ThrowCodeError('param_required', {param => 'scopes'});
return $self->code_error('param_required', {param => 'scopes'});
}
$dbh->do(
'INSERT INTO oauth2_client_scope (client_id, scope_id) VALUES (?, ?)',
undef, $client_data->{id}, $scope_id
);
$dbh->do('INSERT INTO oauth2_client_scope (client_id, scope_id) VALUES (?, ?)',
undef, $client_data->{id}, $scope_id);
}

delete_token($token);
Expand All @@ -114,8 +116,9 @@ sub delete {
my $dbh = Bugzilla->dbh;
my $vars = {};

my $id = $self->param('id');
my $client_data = $dbh->selectrow_hashref('SELECT * FROM oauth2_client WHERE id = ?',
my $id = $self->param('id');
my $client_data
= $dbh->selectrow_hashref('SELECT * FROM oauth2_client WHERE id = ?',
undef, $id);

if (!$self->param('deleteme')) {
Expand Down Expand Up @@ -156,14 +159,15 @@ sub edit {
my $vars = {};
my $id = $self->param('id');

my $client_data = $dbh->selectrow_hashref('SELECT * FROM oauth2_client WHERE id = ?',
my $client_data
= $dbh->selectrow_hashref('SELECT * FROM oauth2_client WHERE id = ?',
undef, $id);
my $client_scopes
= $dbh->selectall_arrayref(
'SELECT scope_id FROM oauth2_client_scope WHERE client_id = ?',
undef, $client_data->{id});
$client_data->{scopes} = [map { $_->[0] } @{$client_scopes}];
$vars->{client} = $client_data;
$vars->{client} = $client_data;

# All scopes
my $all_scopes
Expand All @@ -183,7 +187,7 @@ sub edit {

my $description = $self->param('description');
my $active = $self->param('active');
my @scopes = $self->param('scopes');
my $scopes = $self->every_param('scopes');

if ($description ne $client_data->{description}) {
$dbh->do('UPDATE oauth2_client SET description = ? WHERE id = ?',
Expand All @@ -196,11 +200,9 @@ sub edit {
}

$dbh->do('DELETE FROM oauth2_client_scope WHERE client_id = ?', undef, $id);
foreach my $scope_id (@scopes) {
$dbh->do(
'INSERT INTO oauth2_client_scope (client_id, scope_id) VALUES (?, ?)',
undef, $client_data->{id}, $scope_id
);
foreach my $scope_id (@{$scopes}) {
$dbh->do('INSERT INTO oauth2_client_scope (client_id, scope_id) VALUES (?, ?)',
undef, $client_data->{id}, $scope_id);
}

delete_token($token);
Expand Down
88 changes: 88 additions & 0 deletions Bugzilla/App/Plugin/Error.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# 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::App::Plugin::Error;
use 5.10.1;
use Mojo::Base 'Mojolicious::Plugin';

use Bugzilla::Constants;
use Bugzilla::Logging;
use Bugzilla::WebService::Constants;

sub register {
my ($self, $app) = @_;
$app->helper('code_error' => sub { _render_error('code', @_); });
$app->helper('user_error' => sub { _render_error('user', @_); });
}

sub _render_error {
my ($type, $c, $error, $vars) = @_;
my $logfunc = _make_logfunc(ucfirst($type));

# Errors displayed in a web page
if (Bugzilla->error_mode == ERROR_MODE_MOJO
|| Bugzilla->error_mode == ERROR_MODE_WEBPAGE)
{
$logfunc->("webpage error: $error");

$c->render(
handler => 'bugzilla',
template => "global/$type-error",
format => 'html',
error => $error,
%{$vars}
);
}

# Errors returned in an API request
elsif (Bugzilla->error_mode == ERROR_MODE_REST) {
my %error_map = %{WS_ERROR_CODE()};
my $code = $error_map{$error};

if (!$code) {
$code = ERROR_UNKNOWN_FATAL if $type =~ /code/i;
$code = ERROR_UNKNOWN_TRANSIENT if $type =~ /user/i;
}

my %status_code_map = %{REST_STATUS_CODE_MAP()};
my $status_code = $status_code_map{$code} || $status_code_map{'_default'};

$logfunc->("REST error: $error (HTTP $status_code, internal code $code)");

# Find the full error message
my $message;
$vars->{error} = $error;
my $template = Bugzilla->template;
$template->process("global/$type-error.html.tmpl", $vars, \$message)
|| die $template->error();

my $error = {
error => 1,
code => $code,
message => $message,
documentation => 'https://bmo.readthedocs.io/en/latest/api/',
};

$c->render(json => $error, status => $status_code);
}
}

sub _make_logfunc {
my ($type) = @_;
my $logger = Log::Log4perl->get_logger("Bugzilla.Error.$type");
return sub {
local $Log::Log4perl::caller_depth = $Log::Log4perl::caller_depth + 3;
if ($type eq 'User') {
$logger->warn(@_);
}
else {
$logger->error(@_);
}
};
}

1;
17 changes: 0 additions & 17 deletions Bugzilla/App/Plugin/Glue.pm
Original file line number Diff line number Diff line change
Expand Up @@ -67,23 +67,6 @@ sub register {
}
);

$app->helper(
'bugzilla.error_page' => sub {
my ($c, $error) = @_;
if (blessed $error && $error->isa('Bugzilla::Error::Base')) {
$c->render(
handler => 'bugzilla',
template => $error->template,
error => $error->message,
%{$error->vars}
);
}
else {
$c->reply->exception($error);
}
}
);

$app->helper(
'url_is_attachment_base' => sub {
my ($c, $id) = @_;
Expand Down