Bug 525734: Allow WebService clients to authenticate using Bugzilla_login and Bugzilla_password
Patch by Max Kanat-Alexander <mkanat@bugzilla.org> r=dkl, a=mkanat git-svn-id: svn://10.0.0.236/trunk@258941 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -234,6 +234,22 @@ sub cgi {
|
||||
return $class->request_cache->{cgi};
|
||||
}
|
||||
|
||||
sub input_params {
|
||||
my ($class, $params) = @_;
|
||||
my $cache = $class->request_cache;
|
||||
# This is how the WebService and other places set input_params.
|
||||
if (defined $params) {
|
||||
$cache->{input_params} = $params;
|
||||
}
|
||||
return $cache->{input_params} if defined $cache->{input_params};
|
||||
|
||||
# Making this scalar makes it a tied hash to the internals of $cgi,
|
||||
# so if a variable is changed, then it actually changes the $cgi object
|
||||
# as well.
|
||||
$cache->{input_params} = $class->cgi->Vars;
|
||||
return $cache->{input_params};
|
||||
}
|
||||
|
||||
sub localconfig {
|
||||
my $class = shift;
|
||||
$class->request_cache->{localconfig} ||= read_localconfig();
|
||||
@@ -647,6 +663,26 @@ The current C<cgi> object. Note that modules should B<not> be using this in
|
||||
general. Not all Bugzilla actions are cgi requests. Its useful as a convenience
|
||||
method for those scripts/templates which are only use via CGI, though.
|
||||
|
||||
=item C<input_params>
|
||||
|
||||
When running under the WebService, this is a hashref containing the arguments
|
||||
passed to the WebService method that was called. When running in a normal
|
||||
script, this is a hashref containing the contents of the CGI parameters.
|
||||
|
||||
Modifying this hashref will modify the CGI parameters or the WebService
|
||||
arguments (depending on what C<input_params> currently represents).
|
||||
|
||||
This should be used instead of L</cgi> in situations where your code
|
||||
could be being called by either a normal CGI script or a WebService method,
|
||||
such as during a code hook.
|
||||
|
||||
B<Note:> When C<input_params> represents the CGI parameters, any
|
||||
parameter specified more than once (like C<foo=bar&foo=baz>) will appear
|
||||
as an arrayref in the hash, but any value specified only once will appear
|
||||
as a scalar. This means that even if a value I<can> appear multiple times,
|
||||
if it only I<does> appear once, then it will be a scalar in C<input_params>,
|
||||
not an arrayref.
|
||||
|
||||
=item C<user>
|
||||
|
||||
C<undef> if there is no currently logged in user or if the login code has not
|
||||
|
||||
@@ -40,12 +40,10 @@ use Bugzilla::Error;
|
||||
|
||||
sub get_login_info {
|
||||
my ($self) = @_;
|
||||
my $cgi = Bugzilla->cgi;
|
||||
my $params = Bugzilla->input_params;
|
||||
|
||||
my $username = trim($cgi->param("Bugzilla_login"));
|
||||
my $password = $cgi->param("Bugzilla_password");
|
||||
|
||||
$cgi->delete('Bugzilla_login', 'Bugzilla_password');
|
||||
my $username = trim(delete $params->{"Bugzilla_login"});
|
||||
my $password = delete $params->{"Bugzilla_password"};
|
||||
|
||||
if (!defined $username || !defined $password) {
|
||||
return { failure => AUTH_NODATA };
|
||||
|
||||
@@ -48,9 +48,10 @@ sub persist_login {
|
||||
my ($self, $user) = @_;
|
||||
my $dbh = Bugzilla->dbh;
|
||||
my $cgi = Bugzilla->cgi;
|
||||
my $input_params = Bugzilla->input_params;
|
||||
|
||||
my $ip_addr;
|
||||
if ($cgi->param('Bugzilla_restrictlogin')) {
|
||||
if ($input_params->{'Bugzilla_restrictlogin'}) {
|
||||
$ip_addr = $cgi->remote_addr;
|
||||
# The IP address is valid, at least for comparing with itself in a
|
||||
# subsequent login
|
||||
@@ -80,8 +81,8 @@ sub persist_login {
|
||||
# or admin didn't forbid it and user told to remember.
|
||||
if ( Bugzilla->params->{'rememberlogin'} eq 'on' ||
|
||||
(Bugzilla->params->{'rememberlogin'} ne 'off' &&
|
||||
$cgi->param('Bugzilla_remember') &&
|
||||
$cgi->param('Bugzilla_remember') eq 'on') )
|
||||
$input_params->{'Bugzilla_remember'} &&
|
||||
$input_params->{'Bugzilla_remember'} eq 'on') )
|
||||
{
|
||||
# Not a session cookie, so set an infinite expiry
|
||||
$cookieargs{'-expires'} = 'Fri, 01-Jan-2038 00:00:00 GMT';
|
||||
|
||||
@@ -416,6 +416,39 @@ sub url_is_attachment_base {
|
||||
return ($self->self_url =~ $regex) ? 1 : 0;
|
||||
}
|
||||
|
||||
##########################
|
||||
# Vars TIEHASH Interface #
|
||||
##########################
|
||||
|
||||
# Fix the TIEHASH interface (scalar $cgi->Vars) to return and accept
|
||||
# arrayrefs.
|
||||
sub STORE {
|
||||
my $self = shift;
|
||||
my ($param, $value) = @_;
|
||||
if (defined $value and ref $value eq 'ARRAY') {
|
||||
return $self->param(-name => $param, -value => $value);
|
||||
}
|
||||
return $self->SUPER::STORE(@_);
|
||||
}
|
||||
|
||||
sub FETCH {
|
||||
my ($self, $param) = @_;
|
||||
return $self if $param eq 'CGI'; # CGI.pm did this, so we do too.
|
||||
my @result = $self->param($param);
|
||||
return undef if !scalar(@result);
|
||||
return $result[0] if scalar(@result) == 1;
|
||||
return \@result;
|
||||
}
|
||||
|
||||
# For the Vars TIEHASH interface: the normal CGI.pm DELETE doesn't return
|
||||
# the value deleted, but Perl's "delete" expects that value.
|
||||
sub DELETE {
|
||||
my ($self, $param) = @_;
|
||||
my $value = $self->FETCH($param);
|
||||
$self->delete($param);
|
||||
return $value;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
@@ -144,6 +144,9 @@ These params are accessible through L<Bugzilla/hook_args>.
|
||||
That returns a hashref. Very frequently, if you want your
|
||||
hook to do anything, you have to modify these variables.
|
||||
|
||||
You may also want to use L<Bugzilla/input_params> to get parameters
|
||||
that were passed to the current CGI script or WebService method.
|
||||
|
||||
=head2 Versioning Extensions
|
||||
|
||||
Every extension must have a file in its root called F<info.pl>.
|
||||
|
||||
@@ -142,11 +142,51 @@ how this is implemented for those frontends.
|
||||
|
||||
=head1 LOGGING IN
|
||||
|
||||
There are various ways to log in:
|
||||
|
||||
=over
|
||||
|
||||
=item C<User.login>
|
||||
|
||||
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.
|
||||
|
||||
=item C<Bugzilla_login> and C<Bugzilla_password>
|
||||
|
||||
B<Added in Bugzilla 3.6>
|
||||
|
||||
You can specify C<Bugzilla_login> and C<Bugzilla_password> as arguments
|
||||
to any WebService method, and you will be logged in as that user if your
|
||||
credentials are correct. Here are the arguments you can specify to any
|
||||
WebService method to perform a login:
|
||||
|
||||
=over
|
||||
|
||||
=item C<Bugzilla_login> (string) - A user's login name.
|
||||
|
||||
=item C<Bugzilla_password> (string) - That user's password.
|
||||
|
||||
=item C<Bugzilla_restrictlogin> (boolean) - Optional. If true,
|
||||
then your login will only be valid for your IP address.
|
||||
|
||||
=item C<Bugzilla_rememberlogin> (boolean) - Optional. If true,
|
||||
then the cookie sent back to you with the method response will
|
||||
not expire.
|
||||
|
||||
=back
|
||||
|
||||
The C<Bugzilla_restrictlogin> and C<Bugzilla_rememberlogin> options
|
||||
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).
|
||||
|
||||
=back
|
||||
|
||||
=head1 STABLE, EXPERIMENTAL, and UNSTABLE
|
||||
|
||||
Methods are marked B<STABLE> if you can expect their parameters and
|
||||
|
||||
@@ -21,7 +21,8 @@ use strict;
|
||||
sub handle_login {
|
||||
my ($self, $class, $method, $full_method) = @_;
|
||||
eval "require $class";
|
||||
return if $class->login_exempt($method);
|
||||
return if ($class->login_exempt($method)
|
||||
and !defined Bugzilla->input_params->{Bugzilla_login});
|
||||
Bugzilla->login();
|
||||
}
|
||||
|
||||
|
||||
@@ -112,12 +112,6 @@ sub _argument_type_check {
|
||||
my $self = shift;
|
||||
my $params = $self->SUPER::_argument_type_check(@_);
|
||||
|
||||
# This is the best time to do login checks.
|
||||
$self->handle_login();
|
||||
|
||||
# If there are no parameters, we don't need to parse them.
|
||||
return $params if !ref $params;
|
||||
|
||||
# JSON-RPC 1.0 requires all parameters to be passed as an array, so
|
||||
# we just pull out the first item and assume it's an object.
|
||||
if (ref $params eq 'ARRAY') {
|
||||
@@ -144,6 +138,11 @@ sub _argument_type_check {
|
||||
}
|
||||
}
|
||||
|
||||
Bugzilla->input_params($params);
|
||||
|
||||
# This is the best time to do login checks.
|
||||
$self->handle_login();
|
||||
|
||||
# Bugzilla::WebService packages call internal methods like
|
||||
# $self->_some_private_method. So we have to inherit from
|
||||
# that class as well as this Server class.
|
||||
|
||||
@@ -78,6 +78,7 @@ sub deserialize {
|
||||
$som->{_bz_do_taint} = 1;
|
||||
}
|
||||
bless $som, 'Bugzilla::XMLRPC::SOM';
|
||||
Bugzilla->input_params($som->paramsin);
|
||||
return $som;
|
||||
}
|
||||
|
||||
@@ -146,11 +147,13 @@ use Bugzilla::WebService::Util qw(taint_data);
|
||||
|
||||
sub paramsin {
|
||||
my $self = shift;
|
||||
return $self->{bz_params_in} if $self->{bz_params_in};
|
||||
my $params = $self->SUPER::paramsin(@_);
|
||||
if ($self->{_bz_do_taint}) {
|
||||
taint_data($params);
|
||||
}
|
||||
return $params;
|
||||
$self->{bz_params_in} = $params;
|
||||
return $self->{bz_params_in};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
@@ -61,12 +61,12 @@ sub login {
|
||||
}
|
||||
|
||||
# Make sure the CGI user info class works if necessary.
|
||||
my $cgi = Bugzilla->cgi;
|
||||
$cgi->param('Bugzilla_login', $params->{login});
|
||||
$cgi->param('Bugzilla_password', $params->{password});
|
||||
$cgi->param('Bugzilla_remember', $remember);
|
||||
my $input_params = Bugzilla->input_params;
|
||||
$input_params->{'Bugzilla_login'} = $params->{login};
|
||||
$input_params->{'Bugzilla_password'} = $params->{password};
|
||||
$input_params->{'Bugzilla_remember'} = $remember;
|
||||
|
||||
Bugzilla->login;
|
||||
Bugzilla->login();
|
||||
return { id => $self->type('int', Bugzilla->user->id) };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user