summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGervase Markham <gerv@mozilla.com>2012-04-04 19:00:01 +0200
committerDave Lawrence <dlawrence@mozilla.com>2012-04-04 19:00:01 +0200
commit49495810ea07c10504c894fbf979568af7363f14 (patch)
tree442153a76948d89d139ce544e2b92ae07868e2f9
parentab94d342547caaf0335a54d843a5251ba23fedae (diff)
downloadbugzilla-49495810ea07c10504c894fbf979568af7363f14.tar.gz
bugzilla-49495810ea07c10504c894fbf979568af7363f14.tar.xz
Bug 672841 - Make BMO support BrowserID
r=dkl
-rw-r--r--extensions/BrowserID/Config.pm43
-rw-r--r--extensions/BrowserID/Extension.pm52
-rw-r--r--extensions/BrowserID/TODO19
-rw-r--r--extensions/BrowserID/lib/Login.pm122
-rw-r--r--extensions/BrowserID/template/en/default/hook/account/auth/login-additional_methods.html.tmpl23
-rw-r--r--extensions/BrowserID/template/en/default/hook/account/auth/login-small-additional_methods.html.tmpl20
-rw-r--r--extensions/ComponentWatching/Extension.pm.orig345
-rw-r--r--template/en/default/account/auth/login-small.html.tmpl3
-rw-r--r--template/en/default/account/auth/login.html.tmpl2
9 files changed, 284 insertions, 345 deletions
diff --git a/extensions/BrowserID/Config.pm b/extensions/BrowserID/Config.pm
new file mode 100644
index 000000000..a55ea8ff0
--- /dev/null
+++ b/extensions/BrowserID/Config.pm
@@ -0,0 +1,43 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the BrowserID Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is the Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Gervase Markham <gerv@gerv.net>
+
+package Bugzilla::Extension::BrowserID;
+use strict;
+
+use constant NAME => 'BrowserID';
+
+use constant REQUIRED_MODULES => [
+ {
+ package => 'JSON',
+ module => 'JSON',
+ version => 0,
+ },
+ {
+ package => 'libwww-perl',
+ module => 'LWP::UserAgent',
+ version => 0,
+ },
+];
+
+use constant OPTIONAL_MODULES => [
+];
+
+__PACKAGE__->NAME;
diff --git a/extensions/BrowserID/Extension.pm b/extensions/BrowserID/Extension.pm
new file mode 100644
index 000000000..b132ea503
--- /dev/null
+++ b/extensions/BrowserID/Extension.pm
@@ -0,0 +1,52 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the BrowserID Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is the Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Gervase Markham <gerv@gerv.net>
+
+package Bugzilla::Extension::BrowserID;
+use strict;
+use base qw(Bugzilla::Extension);
+
+our $VERSION = '0.01';
+
+sub auth_login_methods {
+ my ($self, $args) = @_;
+ my $modules = $args->{'modules'};
+ if (exists($modules->{'BrowserID'})) {
+ $modules->{'BrowserID'} = 'Bugzilla/Extension/BrowserID/Login.pm';
+ }
+}
+
+sub config_modify_panels {
+ my ($self, $args) = @_;
+ my $panels = $args->{'panels'};
+ my $auth_panel_params = $panels->{'auth'}->{'params'};
+
+ my ($user_info_class) =
+ grep { $_->{'name'} eq 'user_info_class' } @$auth_panel_params;
+
+ if ($user_info_class) {
+ # XXX Bugzilla::Auth::Login::Stack doesn't let a hard failure stop the
+ # login process :-(( We put it in both ways round for now, for testing.
+ push(@{ $user_info_class->{'choices'} }, "CGI,BrowserID");
+ push(@{ $user_info_class->{'choices'} }, "BrowserID,CGI");
+ }
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/BrowserID/TODO b/extensions/BrowserID/TODO
new file mode 100644
index 000000000..ac94a3c42
--- /dev/null
+++ b/extensions/BrowserID/TODO
@@ -0,0 +1,19 @@
+ToDo:
+
+* Cache the LWP::UserAgent in Login.pm?
+
+* Fix Bugzilla::Auth::Login::Stack to allow failure part way down the chain
+ (currently, it seems that both CGI and BrowserID have to be last in order
+ to report login failures correctly.)
+
+* JS inclusions noticeably slow page load. Do we want a local copy of
+ browserid.js? Do the browserid folks object to that? How can we get good
+ performance? How can we avoid including it in every logged-in page? Can we
+ do demand loading onclick, and/or load-on-reveal?
+
+* Fix -8px margin-bottom hack in login-small-additional_methods.html.tmpl
+
+
+
+
+
diff --git a/extensions/BrowserID/lib/Login.pm b/extensions/BrowserID/lib/Login.pm
new file mode 100644
index 000000000..eedc85d09
--- /dev/null
+++ b/extensions/BrowserID/lib/Login.pm
@@ -0,0 +1,122 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the BrowserID Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is the Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Gervase Markham <gerv@gerv.net>
+
+package Bugzilla::Extension::BrowserID::Login;
+use strict;
+use base qw(Bugzilla::Auth::Login);
+
+use Bugzilla::Constants;
+use Bugzilla::Util;
+
+use JSON;
+use LWP::UserAgent;
+
+use constant requires_verification => 0;
+use constant is_automatic => 1;
+
+sub get_login_info {
+ my ($self) = @_;
+
+ my $cgi = Bugzilla->cgi;
+ my $assertion = $cgi->param("browserid_assertion");
+ # Avoid the assertion being copied into any 'echoes' of the current URL
+ # in the page.
+ $cgi->delete('browserid_assertion');
+
+ if (!$assertion) {
+ return { failure => AUTH_NODATA };
+ }
+
+ my $urlbase = new URI(correct_urlbase());
+ my $audience = $urlbase->scheme . "://" . $urlbase->host_port;
+
+ my $ua = new LWP::UserAgent();
+
+ my $info = { 'status' => 'browserid-server-broken' };
+ eval {
+ my $response = $ua->post("https://browserid.org/verify",
+ [assertion => $assertion,
+ audience => $audience]);
+
+ $info = decode_json($response->content());
+ };
+
+ # XXX Add 120 secs because 'expires' is currently broken in deployed
+ # BrowserID server - it returns exact current time, so is immediately
+ # expired! This should be fixed soon.
+ if ($info->{'status'} eq "okay" &&
+ $info->{'audience'} eq $audience &&
+ (($info->{'expires'} / 1000) + 120) > time())
+ {
+ my $login_data = {
+ 'username' => $info->{'email'}
+ };
+
+ my $result =
+ Bugzilla::Auth::Verify->create_or_update_user($login_data);
+ return $result if $result->{'failure'};
+
+ my $user = $result->{'user'};
+
+ # BrowserID logins are currently restricted to less powerful accounts -
+ # the most you can have is 'editbugs'. This is while the technology
+ # is maturing. So we need to check that the user doesn't have 'too
+ # many permissions' to log in this way.
+ #
+ # If a newly-created account has too many permissions, this code will
+ # create an account for them and then fail their login. Which isn't
+ # great, but they can still use normal-Bugzilla-login password
+ # recovery.
+ my @safe_groups = ('everyone', 'canconfirm', 'editbugs');
+ foreach my $group (@{ $user->groups() }) {
+ if (!grep { $group->name eq $_ } @safe_groups) {
+ return { failure => AUTH_LOGINFAILED };
+ }
+ }
+
+ $login_data->{'user'} = $user;
+ $login_data->{'user_id'} = $user->id;
+
+ return $login_data;
+ }
+ else {
+ return { failure => AUTH_LOGINFAILED };
+ }
+}
+
+# Pinched from Bugzilla::Auth::Login::CGI
+sub fail_nodata {
+ my ($self) = @_;
+ my $cgi = Bugzilla->cgi;
+ my $template = Bugzilla->template;
+
+ if (Bugzilla->usage_mode != USAGE_MODE_BROWSER) {
+ ThrowUserError('login_required');
+ }
+
+ print $cgi->header();
+ $template->process("account/auth/login.html.tmpl",
+ { 'target' => $cgi->url(-relative=>1) })
+ || ThrowTemplateError($template->error());
+ exit;
+}
+
+1;
diff --git a/extensions/BrowserID/template/en/default/hook/account/auth/login-additional_methods.html.tmpl b/extensions/BrowserID/template/en/default/hook/account/auth/login-additional_methods.html.tmpl
new file mode 100644
index 000000000..4d8d8d3f0
--- /dev/null
+++ b/extensions/BrowserID/template/en/default/hook/account/auth/login-additional_methods.html.tmpl
@@ -0,0 +1,23 @@
+[% IF Param('user_info_class').split(',').contains('BrowserID') %]
+<script src="https://browserid.org/include.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+function browserid_sign_in() {
+ navigator.id.getVerifiedEmail(function(assertion) {
+ if (assertion) {
+ // This code will be invoked once the user has successfully
+ // selected an email address they control to sign in with.
+ window.location.href = "[% target FILTER none %]index.cgi?browserid_assertion=" + assertion;
+ } else {
+ // something went wrong! the user isn't logged in.
+ alert("Oh no! Something went wrong...");
+ }
+ });
+}
+</script>
+
+<p>
+Or, you could login using BrowserID:
+<img src="extensions/BrowserID/web/sign_in_orange.png" onclick="browserid_sign_in()">
+</p>
+[% END %] \ No newline at end of file
diff --git a/extensions/BrowserID/template/en/default/hook/account/auth/login-small-additional_methods.html.tmpl b/extensions/BrowserID/template/en/default/hook/account/auth/login-small-additional_methods.html.tmpl
new file mode 100644
index 000000000..12bff015b
--- /dev/null
+++ b/extensions/BrowserID/template/en/default/hook/account/auth/login-small-additional_methods.html.tmpl
@@ -0,0 +1,20 @@
+[% IF Param('user_info_class').split(',').contains('BrowserID') %]
+<script src="https://browserid.org/include.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+function browserid_sign_in() {
+ navigator.id.getVerifiedEmail(function(assertion) {
+ if (assertion) {
+ // This code will be invoked once the user has successfully
+ // selected an email address they control to sign in with.
+ window.location.href = "[% login_target FILTER none %]?browserid_assertion=" + assertion;
+ } else {
+ // something went wrong! the user isn't logged in.
+ alert("Oh no! Something went wrong...");
+ }
+ });
+}
+</script>
+
+<img src="extensions/BrowserID/web/sign_in_orange.png" onclick="browserid_sign_in()" style="margin-bottom: -8px"> or
+[% END %] \ No newline at end of file
diff --git a/extensions/ComponentWatching/Extension.pm.orig b/extensions/ComponentWatching/Extension.pm.orig
deleted file mode 100644
index d39d9cd55..000000000
--- a/extensions/ComponentWatching/Extension.pm.orig
+++ /dev/null
@@ -1,345 +0,0 @@
-# -*- Mode: perl; indent-tabs-mode: nil -*-
-#
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-#
-# The Original Code is the Component Watching Extension
-#
-# The Initial Developer of the Original Code is the Mozilla Foundation
-# Portions created by the Initial Developers are Copyright (C) 2011 the
-# Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-# Byron Jones <bjones@mozilla.com>
-
-package Bugzilla::Extension::ComponentWatching;
-use strict;
-use base qw(Bugzilla::Extension);
-
-use Bugzilla::Constants;
-use Bugzilla::Error;
-use Bugzilla::Group;
-use Bugzilla::User;
-use Bugzilla::User::Setting;
-
-our $VERSION = '1.1';
-
-use constant REL_COMPONENT_WATCHER => 15;
-
-#
-# installation
-#
-
-sub db_schema_abstract_schema {
- my ($self, $args) = @_;
- $args->{'schema'}->{'component_watch'} = {
- FIELDS => [
- user_id => {
- TYPE => 'INT3',
- NOTNULL => 1,
- REFERENCES => {
- TABLE => 'profiles',
- COLUMN => 'userid',
- DELETE => 'CASCADE',
- }
- },
- component_id => {
- TYPE => 'INT2',
- NOTNULL => 0,
- REFERENCES => {
- TABLE => 'components',
- COLUMN => 'id',
- DELETE => 'CASCADE',
- }
- },
- product_id => {
- TYPE => 'INT2',
- NOTNULL => 0,
- REFERENCES => {
- TABLE => 'products',
- COLUMN => 'id',
- DELETE => 'CASCADE',
- }
- },
- ],
- };
-}
-
-#
-# templates
-#
-
-sub template_before_create {
- my ($self, $args) = @_;
- my $config = $args->{config};
- my $constants = $config->{CONSTANTS};
- $constants->{REL_COMPONENT_WATCHER} = REL_COMPONENT_WATCHER;
-}
-
-#
-# preferences
-#
-
-sub user_preferences {
- my ($self, $args) = @_;
- my $tab = $args->{'current_tab'};
- return unless $tab eq 'component_watch';
-
- my $save = $args->{'save_changes'};
- my $handled = $args->{'handled'};
- my $user = Bugzilla->user;
-
- if ($save) {
- my ($sth, $sthAdd, $sthDel);
-
- if (Bugzilla->input_params->{'add'}) {
- # add watch
-
- my $productName = Bugzilla->input_params->{'add_product'};
- my $ra_componentNames = Bugzilla->input_params->{'add_component'};
- $ra_componentNames = [$ra_componentNames] unless ref($ra_componentNames);
-
- # load product and verify access
- my $product = Bugzilla::Product->new({ name => $productName });
- unless ($product && $user->can_access_product($product)) {
- ThrowUserError('product_access_denied', { product => $productName });
- }
-
- if (grep { $_ eq '' } @$ra_componentNames) {
- # watching a product
- _addProductWatch($user, $product);
-
- } else {
- # watching specific components
- foreach my $componentName (@$ra_componentNames) {
- my $component = Bugzilla::Component->new({ name => $componentName, product => $product });
- unless ($component) {
- ThrowUserError('product_access_denied', { product => $productName });
- }
- _addComponentWatch($user, $component);
- }
- }
-
- _addDefaultSettings($user);
-
- } else {
- # remove watch(s)
-
- foreach my $name (keys %{Bugzilla->input_params}) {
- if ($name =~ /^del_(\d+)$/) {
- _deleteProductWatch($user, $1);
- } elsif ($name =~ /^del_(\d+)_(\d+)$/) {
- _deleteComponentWatch($user, $1, $2);
- }
- }
- }
- }
-
- $args->{'vars'}->{'watches'} = _getWatches($user);
-
- $$handled = 1;
-}
-
-#
-# bugmail
-#
-
-sub bugmail_recipients {
- my ($self, $args) = @_;
- my $bug = $args->{'bug'};
- my $recipients = $args->{'recipients'};
- my $diffs = $args->{'diffs'};
-
- my ($oldProductId, $newProductId) = ($bug->product_id, $bug->product_id);
- my ($oldComponentId, $newComponentId) = ($bug->component_id, $bug->component_id);
-
- # notify when the product/component is switch from one being watched
- if (@$diffs) {
- # we need the product to process the component, so scan for that first
- my $product;
- foreach my $ra (@$diffs) {
- next if !(exists $ra->{'old'}
- && exists $ra->{'field_name'});
- if ($ra->{'field_name'} eq 'product') {
- $product = Bugzilla::Product->new({ name => $ra->{'old'} });
- $oldProductId = $product->id;
- }
- }
- if (!$product) {
- $product = Bugzilla::Product->new($oldProductId);
- }
- foreach my $ra (@$diffs) {
- next if !(exists $ra->{'old'}
- && exists $ra->{'field_name'});
- if ($ra->{'field_name'} eq 'component') {
- my $component = Bugzilla::Component->new({ name => $ra->{'old'}, product => $product });
- $oldComponentId = $component->id;
- }
- }
- }
-
- my $dbh = Bugzilla->dbh;
- my $sth = $dbh->prepare("
- SELECT user_id
- FROM component_watch
- WHERE ((product_id = ? OR product_id = ?) AND component_id IS NULL)
- OR (component_id = ? OR component_id = ?)
- ");
- $sth->execute($oldProductId, $newProductId, $oldComponentId, $newComponentId);
- while (my ($uid) = $sth->fetchrow_array) {
- if (!exists $recipients->{$uid}) {
- $recipients->{$uid}->{+REL_COMPONENT_WATCHER} = Bugzilla::BugMail::BIT_WATCHING();
- }
- }
-}
-
-sub bugmail_relationships {
- my ($self, $args) = @_;
- my $relationships = $args->{relationships};
- $relationships->{+REL_COMPONENT_WATCHER} = 'Component-Watcher';
-}
-
-#
-# db
-#
-
-sub _getWatches {
- my ($user) = @_;
- my $dbh = Bugzilla->dbh;
-
- my $sth = $dbh->prepare("
- SELECT product_id, component_id
- FROM component_watch
- WHERE user_id = ?
- ");
- $sth->execute($user->id);
- my @watches;
- while (my ($productId, $componentId) = $sth->fetchrow_array) {
- my $product = Bugzilla::Product->new($productId);
- next unless $product && $user->can_access_product($product);
-
- my %watch = ( product => $product );
- if ($componentId) {
- my $component = Bugzilla::Component->new($componentId);
- next unless $component;
- $watch{'component'} = $component;
- }
-
- push @watches, \%watch;
- }
-
- @watches = sort {
- $a->{'product'}->name cmp $b->{'product'}->name
- || $a->{'component'}->name cmp $b->{'component'}->name
- } @watches;
-
- return \@watches;
-}
-
-sub _addProductWatch {
- my ($user, $product) = @_;
- my $dbh = Bugzilla->dbh;
-
- my $sth = $dbh->prepare("
- SELECT 1
- FROM component_watch
- WHERE user_id = ? AND product_id = ? AND component_id IS NULL
- ");
- $sth->execute($user->id, $product->id);
- return if $sth->fetchrow_array;
-
- $sth = $dbh->prepare("
- DELETE FROM component_watch
- WHERE user_id = ? AND product_id = ?
- ");
- $sth->execute($user->id, $product->id);
-
- $sth = $dbh->prepare("
- INSERT INTO component_watch(user_id, product_id)
- VALUES (?, ?)
- ");
- $sth->execute($user->id, $product->id);
-}
-
-sub _addComponentWatch {
- my ($user, $component) = @_;
- my $dbh = Bugzilla->dbh;
-
- my $sth = $dbh->prepare("
- SELECT 1
- FROM component_watch
- WHERE user_id = ?
- AND (component_id = ? OR (product_id = ? AND component_id IS NULL))
- ");
- $sth->execute($user->id, $component->id, $component->product_id);
- return if $sth->fetchrow_array;
-
- $sth = $dbh->prepare("
- INSERT INTO component_watch(user_id, product_id, component_id)
- VALUES (?, ?, ?)
- ");
- $sth->execute($user->id, $component->product_id, $component->id);
-}
-
-sub _deleteProductWatch {
- my ($user, $productId) = @_;
- my $dbh = Bugzilla->dbh;
-
- my $sth = $dbh->prepare("
- DELETE FROM component_watch
- WHERE user_id = ? AND product_id = ? AND component_id IS NULL
- ");
- $sth->execute($user->id, $productId);
-}
-
-sub _deleteComponentWatch {
- my ($user, $productId, $componentId) = @_;
- my $dbh = Bugzilla->dbh;
-
- my $sth = $dbh->prepare("
- DELETE FROM component_watch
- WHERE user_id = ? AND product_id = ? AND component_id = ?
- ");
- $sth->execute($user->id, $productId, $componentId);
-}
-
-sub _addDefaultSettings {
- my ($user) = @_;
- my $dbh = Bugzilla->dbh;
-
- my $sth = $dbh->prepare("
- SELECT 1
- FROM email_setting
- WHERE user_id = ? AND relationship = ?
- ");
- $sth->execute($user->id, REL_COMPONENT_WATCHER);
- return if $sth->fetchrow_array;
-
- my @defaultEvents = (
- EVT_OTHER,
- EVT_COMMENT,
- EVT_ATTACHMENT,
- EVT_ATTACHMENT_DATA,
- EVT_PROJ_MANAGEMENT,
- EVT_OPENED_CLOSED,
- EVT_KEYWORD,
- EVT_DEPEND_BLOCK,
- EVT_BUG_CREATED,
- );
- foreach my $event (@defaultEvents) {
- $dbh->do(
- "INSERT INTO email_setting(user_id,relationship,event) VALUES (?,?,?)",
- undef,
- $user->id, REL_COMPONENT_WATCHER, $event
- );
- }
-}
-
-__PACKAGE__->NAME;
diff --git a/template/en/default/account/auth/login-small.html.tmpl b/template/en/default/account/auth/login-small.html.tmpl
index b073c79cc..21bd10117 100644
--- a/template/en/default/account/auth/login-small.html.tmpl
+++ b/template/en/default/account/auth/login-small.html.tmpl
@@ -47,6 +47,9 @@
id="mini_login[% qs_suffix FILTER html %]"
onsubmit="return check_mini_login_fields( '[% qs_suffix FILTER html %]' );"
>
+
+ [% Hook.process('additional_methods') %]
+
<input id="Bugzilla_login[% qs_suffix FILTER html %]"
class="bz_login"
name="Bugzilla_login"
diff --git a/template/en/default/account/auth/login.html.tmpl b/template/en/default/account/auth/login.html.tmpl
index ec8c11e24..a3b075578 100644
--- a/template/en/default/account/auth/login.html.tmpl
+++ b/template/en/default/account/auth/login.html.tmpl
@@ -97,6 +97,8 @@
# their password, assuming that our auth method allows that.
#%]
+ [% Hook.process('additional_methods') %]
+
[% IF Param("createemailregexp") && user.authorizer.user_can_create_account %]
<hr>