Skip to content

Commit fa7ae98

Browse files
committed
Bug 1184332 - Add Restricted API calls for MozReview
1 parent 589ec37 commit fa7ae98

8 files changed

Lines changed: 137 additions & 22 deletions

File tree

Bugzilla/Auth.pm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ sub login {
9696
return $self->_handle_login_result($login_info, $type);
9797
}
9898

99+
sub successful_info_getter {
100+
my ($self) = @_;
101+
102+
return $self->{_info_getter}->{successful};
103+
}
104+
99105
sub can_change_password {
100106
my ($self) = @_;
101107
my $verifier = $self->{_verifier}->{successful};

Bugzilla/Auth/Login/APIKey.pm

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@ use constant requires_verification => 0;
2222
use constant can_login => 0;
2323
use constant can_logout => 0;
2424

25+
use fields qw(app_id);
26+
27+
sub set_app_id {
28+
my ($self, $app_id) = @_;
29+
$self->{app_id} = $app_id;
30+
}
31+
32+
sub app_id {
33+
my ($self) = @_;
34+
return $self->{app_id};
35+
}
36+
2537
# This method is only available to web services. An API key can never
2638
# be used to authenticate a Web request.
2739
sub get_login_info {
@@ -45,6 +57,7 @@ sub get_login_info {
4557
}
4658

4759
$api_key->update_last_used();
60+
$self->set_app_id($api_key->app_id);
4861

4962
return { user_id => $api_key->user_id };
5063
}

Bugzilla/User/APIKey.pm

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use parent qw(Bugzilla::Object);
1414

1515
use Bugzilla::User;
1616
use Bugzilla::Util qw(generate_random_password trim);
17+
use Bugzilla::Error;
1718

1819
#####################################################################
1920
# Overriden Constants that are used as methods
@@ -24,6 +25,7 @@ use constant DB_COLUMNS => qw(
2425
id
2526
user_id
2627
api_key
28+
app_id
2729
description
2830
revoked
2931
last_used
@@ -32,6 +34,7 @@ use constant DB_COLUMNS => qw(
3234
use constant UPDATE_COLUMNS => qw(description revoked last_used);
3335
use constant VALIDATORS => {
3436
api_key => \&_check_api_key,
37+
app_id => \&_check_app_id,
3538
description => \&_check_description,
3639
revoked => \&Bugzilla::Object::check_boolean,
3740
};
@@ -48,6 +51,7 @@ use constant { AUDIT_CREATES => 0,
4851
sub id { return $_[0]->{id} }
4952
sub user_id { return $_[0]->{user_id} }
5053
sub api_key { return $_[0]->{api_key} }
54+
sub app_id { return $_[0]->{app_id} }
5155
sub description { return $_[0]->{description} }
5256
sub revoked { return $_[0]->{revoked} }
5357
sub last_used { return $_[0]->{last_used} }
@@ -74,6 +78,13 @@ sub set_revoked { $_[0]->set('revoked', $_[1]); }
7478
# Validators
7579
sub _check_api_key { return generate_random_password(40); }
7680
sub _check_description { return trim($_[1]) || ''; }
81+
sub _check_app_id {
82+
my ($invocant, $app_id) = @_;
83+
84+
ThrowCodeError("invalid_app_id", { app_id => $app_id }) unless $app_id =~ /^[[:xdigit:]]+$/;
85+
86+
return $app_id;
87+
}
7788
1;
7889

7990
__END__

Bugzilla/WebService/Server/REST.pm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ sub handle_login {
187187
my $class = $self->bz_class_name;
188188
my $method = $self->bz_method_name;
189189
my $full_method = $class . "." . $method;
190+
$full_method =~ s/^Bugzilla::WebService:://;
190191

191192
# Bypass JSONRPC::handle_login
192193
Bugzilla::WebService::Server->handle_login($class, $method, $full_method);

extensions/MozReview/Extension.pm

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,22 @@ use warnings;
1313
use parent qw(Bugzilla::Extension);
1414

1515
use Bugzilla::Attachment;
16-
use Bugzilla::Config::Common;
16+
use Bugzilla::Error;
17+
use List::MoreUtils qw( any );
1718

1819
our $VERSION = '0.01';
1920

21+
my @METHOD_WHITELIST = (
22+
'User.get',
23+
'User.login',
24+
'User.valid_login',
25+
'Bug.add_comment',
26+
'Bug.add_attachment',
27+
'Bug.attachments',
28+
'Bug.get',
29+
'Bug.update_attachment',
30+
);
31+
2032
sub template_before_process {
2133
my ($self, $args) = @_;
2234
my $file = $args->{'file'};
@@ -65,25 +77,32 @@ sub auth_delegation_confirm {
6577
}
6678
}
6779

68-
sub config_modify_panels {
80+
sub config_add_panels {
6981
my ($self, $args) = @_;
70-
push @{ $args->{panels}->{advanced}->{params} }, {
71-
name => 'mozreview_base_url',
72-
type => 't',
73-
default => '',
74-
checker => \&check_urlbase
75-
};
76-
push @{ $args->{panels}->{advanced}->{params} }, {
77-
name => 'mozreview_auth_callback_url',
78-
type => 't',
79-
default => '',
80-
checker => sub {
81-
my ($url) = (@_);
82-
83-
return 'must be an HTTP/HTTPS absolute URL' unless $url =~ m{^https?://};
84-
return '';
82+
my $modules = $args->{panel_modules};
83+
$modules->{MozReview} = "Bugzilla::Extension::MozReview::Config";
84+
}
85+
86+
sub webservice_before_call {
87+
my ($self, $args) = @_;
88+
my ($method, $full_method) = ($args->{method}, $args->{full_method});
89+
my $mozreview_app_id = Bugzilla->params->{mozreview_app_id};
90+
my $user = Bugzilla->user;
91+
92+
return unless $mozreview_app_id;
93+
return unless $user->authorizer;
94+
95+
my $getter = $user->authorizer->successful_info_getter()
96+
or return;
97+
98+
return unless $getter->can("app_id") && $getter->app_id;
99+
100+
my $app_id = $getter->app_id;
101+
if ($app_id eq $mozreview_app_id) {
102+
unless (any { $full_method eq $_ } @METHOD_WHITELIST) {
103+
ThrowCodeError('unknown_method', { method => $full_method });
85104
}
86-
};
105+
}
87106
}
88107

89108
__PACKAGE__->NAME;

extensions/MozReview/lib/Config.pm

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# This Source Code Form is subject to the terms of the Mozilla Public
2+
# License, v. 2.0. If a copy of the MPL was not distributed with this
3+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
4+
#
5+
# This Source Code Form is "Incompatible With Secondary Licenses", as
6+
# defined by the Mozilla Public License, v. 2.0.
7+
8+
package Bugzilla::Extension::MozReview::Config;
9+
10+
use strict;
11+
use warnings;
12+
13+
use Bugzilla::Config::Common;
14+
15+
our $sortkey = 1300;
16+
17+
sub get_param_list {
18+
my ($class) = @_;
19+
20+
my @params = (
21+
{
22+
name => 'mozreview_base_url',
23+
type => 't',
24+
default => '',
25+
checker => \&check_urlbase
26+
},
27+
{
28+
name => 'mozreview_auth_callback_url',
29+
type => 't',
30+
default => '',
31+
checker => sub {
32+
my ($url) = (@_);
33+
34+
return 'must be an HTTP/HTTPS absolute URL' unless $url =~ m{^https?://};
35+
return '';
36+
}
37+
},
38+
{
39+
name => 'mozreview_app_id',
40+
type => 't',
41+
default => '',
42+
checker => sub {
43+
my ($app_id) = (@_);
44+
45+
return 'must be a hex number' unless $app_id =~ /^[[:xdigit:]]+$/;
46+
return '';
47+
},
48+
},
49+
);
50+
51+
return @params;
52+
}
53+
54+
1;

extensions/MozReview/template/en/default/hook/admin/params/editparams-current_panel.html.tmpl renamed to extensions/MozReview/template/en/default/admin/params/mozreview.html.tmpl

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,15 @@
66
# defined by the Mozilla Public License, v. 2.0.
77
#%]
88

9-
[% IF panel.name == "advanced" %]
10-
[% panel.param_descs.mozreview_base_url = 'MozReview Base URL' %]
11-
[% panel.param_descs.mozreview_auth_callback_url = 'MozReview Auth Delegation URL' %]
12-
[% END -%]
9+
[%
10+
title = "MozReview"
11+
desc = "Configure MozReview"
12+
%]
13+
14+
[%
15+
param_descs = {
16+
mozreview_base_url => 'MozReview Base URL',
17+
mozreview_auth_callback_url => 'MozReview Auth Delegation URL',
18+
mozreview_app_id => 'app_id for API Keys delegated to MozReview',
19+
}
20+
%]

template/en/default/global/code-error.html.tmpl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@
207207
[% ELSIF error == "illegal_field" %]
208208
A legal [% field FILTER html %] was not set.
209209

210+
[% ELSIF error == "invalid_app_id" %]
211+
The app_id generated was invalid. [% app_id FILTER html %] is not a hexadecimal string.
212+
210213
[% ELSIF error == "invalid_attach_id_to_obsolete" %]
211214
The attachment number of one of the attachments you wanted to obsolete,
212215
[%+ attach_id FILTER html %], is invalid.

0 commit comments

Comments
 (0)