OpenID support

View: New views
4 Messages — Rating Filter:   Alert me  

OpenID support

by Bugzilla from lalinsky@gmail.com :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

I needed a little "fun" project so I started to experiment with adding
OpenID support to mb_server. You can see the work-in-progress patch in
attachment (login/registration works, managing OpenID for existing
accounts doesn't yet).

I've been wondering if we want to support OpenID at all. We obviously
still need passwords for web services, but I'd personally prefer to
use my Google account to login on the website. Another thing are user
names, would it make sense to split "user name" which is used for
login and "display name"? That means that username/password would be
used only for logging in, but both could be empty if there is an
OpenID. This would simplify creating an OpenID account on the website.

--
Lukas Lalinsky
lalinsky@...

[openid.diff]

=== modified file 'Makefile.PL'
--- Makefile.PL (revision 12068)
+++ Makefile.PL (working copy)
@@ -42,6 +42,7 @@
 requires 'Locale::Maketext::Extract::Plugin::TT2';
 requires 'Locale::TextDomain'                          => '1.16';
 requires 'List::MoreUtils'                             => '0.22';
+requires 'LWPx::ParanoidAgent'                         => '1.06';
 requires 'MIME::Lite'                                  => '3.023';
 requires 'Moose'                                       => '0.87';
 requires 'MooseX::AttributeHelpers'                    => '0.17';
@@ -51,6 +52,7 @@
 requires 'MooseX::Types'                               => '0.16';
 requires 'MooseX::Types::Structured'                   => '0.16';
 requires 'MRO::Compat'                                 => '0.10';
+requires 'Net::OpenID::Consumer'                       => '1.03';
 requires 'OSSP::uuid'                                  => '1.060200';
 requires 'Readonly'                                    => '1.03';
 requires 'String::ShellQuote'                          => '1.030';

=== modified file 'admin/sql/CreateIndexes.sql'
--- admin/sql/CreateIndexes.sql (revision 12068)
+++ admin/sql/CreateIndexes.sql (working copy)
@@ -22,6 +22,7 @@
 CREATE INDEX dbmirror_Pending_XID_Index ON dbmirror_Pending (XID);
 
 CREATE UNIQUE INDEX editor_idx_name ON editor (LOWER(name));
+CREATE UNIQUE INDEX editor_idx_openid ON editor (openid);
 CREATE INDEX editor_collection_idx_editor ON editor_collection (editor);
 
 CREATE INDEX editor_subscribe_artist_idx_uniq ON editor_subscribe_artist (editor, artist);

=== modified file 'admin/sql/CreateTables.sql'
--- admin/sql/CreateTables.sql (revision 12068)
+++ admin/sql/CreateTables.sql (working copy)
@@ -105,7 +105,8 @@
 (
     id                  SERIAL,
     name                VARCHAR(64) NOT NULL,
-    password            VARCHAR(64) NOT NULL,
+    password            VARCHAR(64),
+    openid              VARCHAR(255),
     privs               INTEGER DEFAULT 0,
     email               VARCHAR(64) DEFAULT NULL,
     website             VARCHAR(255) DEFAULT NULL,

=== modified file 'admin/sql/DropIndexes.sql'
--- admin/sql/DropIndexes.sql (revision 12068)
+++ admin/sql/DropIndexes.sql (working copy)
@@ -15,6 +15,7 @@
 DROP INDEX dbmirror_Pending_XID_Index;
 DROP INDEX editor_collection_idx_editor;
 DROP INDEX editor_idx_name;
+DROP INDEX editor_idx_openid;
 DROP INDEX editor_subscribe_artist_idx_uniq;
 DROP INDEX editor_subscribe_editor_idx_uniq;
 DROP INDEX editor_subscribe_label_idx_uniq;

=== modified file 'lib/DBDefs.pm.default'
--- lib/DBDefs.pm.default (revision 12068)
+++ lib/DBDefs.pm.default (working copy)
@@ -332,5 +332,9 @@
 # Private, please do not change
 sub _RUNNING_TESTS { 0 }
 
+# OpenID settings
+sub OPENID_SECRET { undef }
+sub OPENID_REALM { undef }
+
 1;
 # eof DBDefs.pm

=== modified file 'lib/MusicBrainz/Server/Authentication/Store.pm'
--- lib/MusicBrainz/Server/Authentication/Store.pm (revision 12068)
+++ lib/MusicBrainz/Server/Authentication/Store.pm (working copy)
@@ -18,8 +18,7 @@
     my $editor = $c->model('Editor')->get_by_name($authinfo->{username});
     if (defined $editor) {
         $c->model('Editor')->load_preferences($editor);
-        my $class = Class::MOP::Class->initialize('MusicBrainz::Server::Authentication::User');
-        return $class->rebless_instance($editor);
+        return MusicBrainz::Server::Authentication::User->new_from_editor($editor);
     }
     return undef;
 }

=== modified file 'lib/MusicBrainz/Server/Controller/Root.pm'
--- lib/MusicBrainz/Server/Controller/Root.pm (revision 12068)
+++ lib/MusicBrainz/Server/Controller/Root.pm (working copy)
@@ -61,6 +61,15 @@
     $c->detach('/error_404');
 }
 
+sub error_400 : Private
+{
+    my ($self, $c) = @_;
+
+    $c->response->status(400);
+    $c->stash->{template} = 'main/400.tt';
+    $c->detach;
+}
+
 sub error_404 : Private
 {
     my ($self, $c) = @_;

=== modified file 'lib/MusicBrainz/Server/Controller/User.pm'
--- lib/MusicBrainz/Server/Controller/User.pm (revision 12068)
+++ lib/MusicBrainz/Server/Controller/User.pm (working copy)
@@ -8,6 +8,9 @@
 use MusicBrainz::Server::Authentication::User;
 use MusicBrainz::Server::Editor;
 use UserPreference;
+use DBDefs;
+use LWPx::ParanoidAgent;
+use Net::OpenID::Consumer;
 
 use MusicBrainz::Server::Form::User::Login;
 
@@ -31,6 +34,19 @@
 
 =cut
 
+sub _create_openid_consumer
+{
+    my ($self, $c) = @_;
+
+    return Net::OpenID::Consumer->new(
+        ua              => LWPx::ParanoidAgent->new( timeout => 5 ),
+        cache           => $c->cache,
+        args            => $c->req->params,
+        consumer_secret => &DBDefs::OPENID_SECRET,
+        required_root   => $c->req->base,
+    );
+}
+
 sub index : Private
 {
     my ($self, $c) = @_;
@@ -44,39 +60,68 @@
     my ($self, $c) = @_;
     return 1 if $c->user_exists;
 
-    my $form = $c->form(form => 'User::Login');
+    my $form = $c->form( form => 'User::Login' );
+    my $openid_form = $c->form( form => 'User::OpenID' );
+
     my $redirect = defined $c->req->query_params->{uri}
         ? $c->req->query_params->{uri}
         : $c->req->path;
 
-    if ($c->form_posted && $form->process(params => $c->req->params))
-    {
-        if( !$c->authenticate({ username => $form->field("username")->value,
-                                password => $form->field("password")->value }) )
-        {
-            # Bad username / password combo
-            $c->log->info('Invalid username/password');
-            $c->stash( bad_login => 1 );
-        }
-        else
-        {
-            # Logged in OK
-            $c->response->redirect($c->uri_for("/$redirect"));
-            $c->detach;
-        }
+    if ($c->form_posted) {
+
+        # OpenID
+        if ($openid_form->process( params => $c->req->params )) {
+
+            my $csr = $self->_create_openid_consumer($c);
+            my $claimed_identity = $csr->claimed_identity($openid_form->field('openid')->value);
+
+            if (defined $claimed_identity) {
+                my $check_url = $claimed_identity->check_url(
+                    return_to      => $c->uri_for_action("user/login_openid_return", { redirect => $redirect }),
+                    trust_root     => &DBDefs::OPENID_REALM,
+                    delayed_return => 1,
+                );
+                $c->response->redirect($check_url);
+                $c->detach;
+            }
+            else {
+                $openid_form->field('openid')->add_error($c->gettext('Invalid OpenID'));
+            }
+
+        }
+
+        # Standard login
+        if ($form->process( params => $c->req->params )) {
+
+            if( !$c->authenticate({ username => $form->field("username")->value,
+                                    password => $form->field("password")->value }) ) {
+                # Bad username / password combo
+                $c->log->info('Invalid username/password');
+                $c->stash( bad_login => 1 );
+            }
+            else {
+                # Logged in OK
+                $c->response->redirect($c->uri_for("/$redirect"));
+                $c->detach;
+            }
+
+        }
+
     }
 
+
     # Form not even posted
     $c->stash(
         template => 'user/login.tt',
         login_form => $form,
+        openid_form => $openid_form,
         redirect => $redirect,
     );
 
     $c->detach;
 }
 
-sub login : Path('/login')
+sub login : Path('/login') Args(0)
 {
     my ($self, $c) = @_;
 
@@ -89,6 +134,51 @@
     $c->forward('/user/do_login');
 }
 
+sub login_openid_return : Path('/login/openid/return') Args(0)
+{
+    my ($self, $c) = @_;
+
+    my $csr = $self->_create_openid_consumer($c);
+
+    $csr->handle_server_response(
+        not_openid => sub {
+            $c->stash->{message} = "Not an OpenID message.";
+            $c->detach('/error_400');
+        },
+        setup_required => sub {
+            my $setup_url = shift;
+            $c->response->redirect($setup_url);
+        },
+        cancelled => sub {
+            $c->response->redirect($c->uri_for_action("user/login"));
+        },
+        verified => sub {
+            my $verified_identity = shift;
+            my $editor = $c->model('Editor')->get_by_openid($verified_identity->url);
+            if (defined $editor) {
+                my $user = MusicBrainz::Server::Authentication::User->new_from_editor($editor);
+                $c->set_authenticated($user);
+                $c->log->debug("Authenticated " . $user->name . " using OpenID " . $verified_identity->url);
+                my $redirect = defined $c->req->query_params->{redirect}
+                    ? $c->req->query_params->{redirect}
+                    : $c->uri_for_action("/user/profile", $user->name);
+                $c->response->redirect($c->uri_for("/$redirect"));
+            }
+            else {
+                $c->log->debug("No user for OpenID " . $verified_identity->url);
+                $c->response->redirect($c->uri_for_action("/user/login", { bad_openid_login => 1 }));
+            }
+        },
+        error => sub {
+            my $error = shift;
+            $c->log->error("OpenID error " . $error);
+            $c->response->redirect($c->uri_for_action("user/login", { openid_error => 1 }));
+        },
+    );
+
+    $c->detach;
+}
+
 sub logout : Path('/logout')
 {
     my ($self, $c) = @_;
@@ -113,12 +203,110 @@
     my ($self, $c) = @_;
 
     my $form = $c->form(register_form => 'User::Register');
+    my $openid_form = $c->form(openid_form => 'User::OpenID');
+
+    if ($c->form_posted) {
+
+        # OpenID
+        if ($openid_form->submitted_and_valid($c->req->params)) {
+
+            my $csr = $self->_create_openid_consumer($c);
+            my $claimed_identity = $csr->claimed_identity($openid_form->field('openid')->value);
+
+            if (defined $claimed_identity) {
+                my $check_url = $claimed_identity->check_url(
+                    return_to      => $c->uri_for_action("user/register_openid_return"),
+                    trust_root     => &DBDefs::OPENID_REALM,
+                    delayed_return => 1,
+                );
+                $c->response->redirect($check_url);
+                $c->detach;
+            }
+            else {
+                $openid_form->field('openid')->add_error($c->gettext('Invalid OpenID'));
+            }
+
+        }
+
+        # Standard registration
+        if ($form->submitted_and_valid($c->req->params)) {
+
+            my $editor = $c->model('Editor')->insert({
+                name => $form->field('username')->value,
+                password => $form->field('password')->value,
+            });
+
+            my $email = $form->field('email')->value;
+            if ($email) {
+                $self->_send_confirmation_email($c, $editor, $email);
+            }
+
+            my $user = MusicBrainz::Server::Authentication::User->new_from_editor($editor);
+            $c->set_authenticated($user);
+
+            $c->response->redirect($c->uri_for_action('/user/profile', $user->name));
+            $c->detach;
+        }
+
+    }
+
+    $c->stash(
+        register_form => $form,
+        register_openid_form => $openid_form,
+        template => 'user/register.tt',
+    );
+}
+
+sub register_openid_return : Path('/register/openid/return')
+{
+    my ($self, $c) = @_;
+
+    my $csr = $self->_create_openid_consumer($c);
+
+    $csr->handle_server_response(
+        not_openid => sub {
+            $c->stash->{message} = "Not an OpenID message.";
+            $c->detach('/error_400');
+        },
+        setup_required => sub {
+            my $setup_url = shift;
+            $c->response->redirect($setup_url);
+        },
+        cancelled => sub {
+            $c->response->redirect($c->uri_for_action("user/register"));
+        },
+        verified => sub {
+            my $verified_identity = shift;
+            $c->session->{register_openid} = $verified_identity->url;
+            $c->response->redirect($c->uri_for_action("user/register_openid"));
+        },
+        error => sub {
+            my $error = shift;
+            $c->log->error("OpenID error " . $error);
+            $c->response->redirect($c->uri_for_action("user/login", { openid_error => 1 }));
+        },
+    );
+
+    $c->detach;
+}
+
+sub register_openid : Path('/register/openid')
+{
+    my ($self, $c) = @_;
+
+    my $openid = $c->session->{register_openid};
+    unless ($openid) {
+        $c->response->redirect($c->uri_for_action("user/register"));
+        $c->detach;
+    }
+
+    my $form = $c->form(register_form => 'User::RegisterOpenID');
 
     if ($c->form_posted && $form->submitted_and_valid($c->req->params)) {
 
         my $editor = $c->model('Editor')->insert({
             name => $form->field('username')->value,
-            password => $form->field('password')->value,
+            openid => $openid,
         });
 
         my $email = $form->field('email')->value;
@@ -128,14 +316,16 @@
 
         my $user = MusicBrainz::Server::Authentication::User->new_from_editor($editor);
         $c->set_authenticated($user);
+        delete $c->session->{register_openid};
 
         $c->response->redirect($c->uri_for_action('/user/profile', $user->name));
         $c->detach;
     }
 
     $c->stash(
+        openid => $openid,
         register_form => $form,
-        template      => 'user/register.tt',
+        template => 'user/register_openid.tt',
     );
 }
 

=== modified file 'lib/MusicBrainz/Server/Data/Editor.pm'
--- lib/MusicBrainz/Server/Data/Editor.pm (revision 12068)
+++ lib/MusicBrainz/Server/Data/Editor.pm (working copy)
@@ -21,7 +21,7 @@
 
 sub _columns
 {
-    return 'editor.id, name, password, privs, email, website, bio,
+    return 'editor.id, name, password, privs, email, website, bio, openid,
             membersince, emailconfirmdate, lastlogindate, editsaccepted,
             editsrejected, autoeditsaccepted, editsfailed';
 }
@@ -33,6 +33,7 @@
         name                    => 'name',
         email                   => 'email',
         password                => 'password',
+        openid                  => 'openid',
         privileges              => 'privs',
         website                 => 'website',
         biography               => 'bio',
@@ -58,6 +59,13 @@
     return $result[0];
 }
 
+sub get_by_openid
+{
+    my ($self, $openid) = @_;
+    my @result = values %{$self->_get_by_keys('openid', $openid)};
+    return $result[0];
+}
+
 sub find_by_email
 {
     my ($self, $email) = @_;
@@ -87,7 +95,6 @@
         return $self->_entity_class->new(
             id => $sql->InsertRow('editor', $data, 'id'),
             name => $data->{name},
-            password => $data->{password},
             accepted_edits => 0,
             rejected_edits => 0,
             failed_edits => 0,

=== modified file 'lib/MusicBrainz/Server/Entity/Editor.pm'
--- lib/MusicBrainz/Server/Entity/Editor.pm (revision 12068)
+++ lib/MusicBrainz/Server/Entity/Editor.pm (working copy)
@@ -27,6 +27,11 @@
     isa => 'Str',
 );
 
+has 'openid' => (
+    is  => 'rw',
+    isa => 'Str',
+);
+
 has 'privileges' => (
     isa => 'Int',
     is  => 'rw',

=== modified file 'lib/MusicBrainz/Server/Form/Field/URL.pm'
--- lib/MusicBrainz/Server/Form/Field/URL.pm (revision 12068)
+++ lib/MusicBrainz/Server/Form/Field/URL.pm (working copy)
@@ -1,22 +1,17 @@
 package MusicBrainz::Server::Form::Field::URL;
 
-use strict;
-use warnings;
-
-use base 'Form::Processor::Field::Text';
-
-sub validate
-{
-    my $self = shift;
-
-    return unless $self->SUPER::validate;
-
-    my $url = $self->input;
-
-    return $self->add_error('Enter a valid url "e.g. http://google.com/"')
-        unless MusicBrainz::Server::URL->IsLegalURL($url);
-
-    return 1;
-}
-
+use HTML::FormHandler::Moose;
+extends 'HTML::FormHandler::Field::Text';
+
+use MusicBrainz::Server::Validation;
+
+apply([
+    {
+        check   => sub { MusicBrainz::Server::Validation->IsValidURL($_[0]) },
+        message => 'Invalid URL format',
+    }
+]);
+
+__PACKAGE__->meta->make_immutable;
+no HTML::FormHandler::Moose;
 1;

=== modified file 'lib/MusicBrainz/Server/Form/User/EditProfile.pm'
--- lib/MusicBrainz/Server/Form/User/EditProfile.pm (revision 12068)
+++ lib/MusicBrainz/Server/Form/User/EditProfile.pm (working copy)
@@ -12,11 +12,7 @@
 );
 
 has_field 'website' => (
-    type => 'Text',
-    apply => [ {
-        check => sub { MusicBrainz::Server::Validation->IsValidURL($_[0]) },
-        message => 'Invalid URL format',
-    } ],
+    type => '+MusicBrainz::Server::Form::Field::URL',
 );
 
 has_field 'email' => (

=== added file 'lib/MusicBrainz/Server/Form/User/OpenID.pm'
--- lib/MusicBrainz/Server/Form/User/OpenID.pm (revision 0)
+++ lib/MusicBrainz/Server/Form/User/OpenID.pm (working copy)
@@ -0,0 +1,34 @@
+package MusicBrainz::Server::Form::User::OpenID;
+
+use HTML::FormHandler::Moose;
+
+extends 'MusicBrainz::Server::Form';
+
+has '+name' => ( default => 'openid' );
+
+has_field 'openid' => (
+    type => '+MusicBrainz::Server::Form::Field::URL',
+    required => 1,
+);
+
+1;
+
+=head1 COPYRIGHT
+
+Copyright (C) 2009 Lukas Lalinsky
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+=cut

=== added file 'lib/MusicBrainz/Server/Form/User/RegisterOpenID.pm'
--- lib/MusicBrainz/Server/Form/User/RegisterOpenID.pm (revision 0)
+++ lib/MusicBrainz/Server/Form/User/RegisterOpenID.pm (working copy)
@@ -0,0 +1,50 @@
+package MusicBrainz::Server::Form::User::RegisterOpenID;
+
+use HTML::FormHandler::Moose;
+extends 'MusicBrainz::Server::Form';
+
+has '+name' => ( default => 'register' );
+
+has_field 'username' => (
+    type => 'Text',
+    required => 1,
+);
+
+has_field 'email' => (
+    type => 'Email',
+);
+
+sub validate_username
+{
+    my ($self, $field) = @_;
+
+    my $username = $field->value;
+    if ($username) {
+        my $editor = $self->ctx->model('Editor')->get_by_name($username);
+        if (defined $editor) {
+            $field->add_error($self->ctx->gettext('Please choose another username, this one is already taken'));
+        }
+    }
+}
+
+1;
+
+=head1 COPYRIGHT
+
+Copyright (C) 2009 Lukas Lalinsky
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+=cut

=== added file 'root/main/400.tt'
--- root/main/400.tt (revision 0)
+++ root/main/400.tt (working copy)
@@ -0,0 +1,14 @@
+[% WRAPPER "layout.tt" title=l("Error 400: Bad Request") full_width=1 %]
+    <h1>
+        [% l('Ooops!') %]
+    </h1>
+    <h2>
+        [%- l('(<abbr title="HyperText Transfer Protocol">HTTP</abbr> code 400)') -%]
+    </h2>
+    <p>
+        [% l("Sorry, we won't know how to handle this request. The server returned the following error message:") %]
+    </p>
+    <blockquote>
+        [% message | html %]
+    </blockquote>
+[%- END -%]

=== added file 'root/static/images/openid.gif'
Binary files root/static/images/openid.gif (revision 0) and root/static/images/openid.gif (working copy) differ
=== modified file 'root/static/styles/layout.css'
--- root/static/styles/layout.css (revision 12068)
+++ root/static/styles/layout.css (working copy)
@@ -618,3 +618,10 @@
 dl.properties dt {
     line-height: 200%;
 }
+
+span.openid {
+    background: url(../images/openid.gif) 0 50% no-repeat;
+    min-height: 16px;
+    padding-left: 20px;
+    font-style: italic;
+}

=== modified file 'root/user/login.tt'
--- root/user/login.tt (revision 12068)
+++ root/user/login.tt (working copy)
@@ -2,7 +2,6 @@
 
     <h1>[% l("Log In") %]</h1>
 
-    [%- USE r = FormRenderer(login_form) -%]
     <p>
         [% l('Please log in using the form below. Note that the password field <em>is</em> case sensitive.') %]
     </p>
@@ -15,6 +14,11 @@
 the browser cache.', { server => server_details.staging_server }) %]
     </p>
     [% END %]
+
+    <div style="overflow: hidden">
+    <div style="float: left;">
+
+    [%- USE r = FormRenderer(login_form) -%]
     <form action="[% c.req.uri_with({ uri => redirect }) %]" method="post">
         [% IF login_form.has_errors || bad_login -%]
             <p><strong>[% l('Incorrect username or password') %]</strong></p>
@@ -29,6 +33,23 @@
         </p>
         [% form_submit(l('Log in')) %]
     </form>
+
+    </div>
+    <div style="float: left; margin-left: 1em;">
+
+    [%- USE r = FormRenderer(openid_form) -%]
+    <form action="[% c.req.uri %]" method="post" style="margin: 0 auto;">
+        <p>
+            [% r.label('openid', l('OpenID:')) %]
+            [% r.text('openid', { size => 50 }) %]
+            [% form_field_errors(openid_form, 'openid') %]
+        </p>
+        [% form_submit(l('Log in with OpenID')) %]
+    </form>
+
+    </div>
+    </div>
+
     <ul>
         <li>
             [% l('Forgot your {link1|username} or {link2|password}?', {

=== modified file 'root/user/profile.tt'
--- root/user/profile.tt (revision 12068)
+++ root/user/profile.tt (working copy)
@@ -58,6 +58,11 @@
             [% END %]
         [% END %]
 
+        [% IF viewing_own_profile && user.openid %]
+            [% '<span class="openid">' _ html_escape(user.openid) _ '</span>'
+                WRAPPER property name=l("OpenID") %]
+        [% END %]
+
         [% WRAPPER property name=l("User type") %]
             [% types = [] %]
             [% types.push(l('{doc|AutoEditor}', {doc => doc_link('AutoEditor')})) IF user.is_auto_editor %]

=== modified file 'root/user/register.tt'
--- root/user/register.tt (revision 12068)
+++ root/user/register.tt (working copy)
@@ -8,8 +8,11 @@
         [%- create_guideline(l('If you have any questions, please review the {faq|Frequently Asked Questions (FAQ)}, or post it to the appropriate {ml|Mailing List}.', {faq => doc_link('FrequentlyAskedQuestions'), ml => doc_link('MailingList')})) -%]
     [% END %]
 
+    <div style="overflow: hidden">
+
+    <div style="float: left;">
+
     [%- USE r = FormRenderer(register_form) -%]
-
     <form action="[% c.req.uri %]" method="post">
         <p>
             [% r.label('username', l('Username:')) %]
@@ -34,30 +37,24 @@
         [% form_submit(l('Create Account')) %]
     </form>
 
-
-    <h2>[%- l('We respect your privacy') %]</h2>
-
-    <p>
-        [%- l('Rest assured that we will not pass your email address on to anyone, including other MusicBrainz users, without your most explicit consent. At any time you can fill in your email address if it's currently blank, remove it if it's currently filled in or change from one address to another.') %]
-    </p>
-    <p>
-        [%- l('{doc|Read on for the full MusicBrainz Privacy Policy}', {doc => doc_link('MusicBrainzPrivacyPolicy')}) -%]
-    </p>
-
-    <h3>[% l('What your email address will <em>not</em> be used for:') %]</h3>
-    <p>
-        [% l("We won't send you any newsletters, promotional mailings, etc. If you're interested in receiving information from the MusicBrainz staff and communicating with other users, {ml|please subscribe to our mailing lists}.", {ml => doc_link('MailingList')}) %]
-    </p>
-    <h3>[%- l('What your email address <em>will</em> be used for:') -%]</h3>
-    <p>
-        [% l('Because some users, unfortunately, made lots of questionable edits and could not be contacted to fix their mistakes, we now require a confirmed (i.e. working) email address before a user can make edits to the database.') %]
-    </p>
-
-    [%- WRAPPER 'layout/guidelines.tt' -%]
-        [%- create_guideline(l('When you enter your email address, other editors will be able to send messages to you (likewise, you will be able to send messages to them).')) %]
-        [%- create_guideline(l('Any notes attached to your edits will be emailed to you. This enables you to remove, correct or clarify edits which will otherwise be rejected.')) %]
-        [%- create_guideline(l('You may choose to "subscribe" (for free) to your favourite Artists, in which case MusicBrainz will send you a daily list of edits made to the Artists to which you have subscribed.')) %]
-        [%- create_guideline(l('In all cases your email address will not be revealed to other MusicBrainz users.  They will see only your user name.')) %]
-    [% END %]
+    </div>
+
+    <div style="float: left; margin-left: 1em;">
+
+    [%- USE r = FormRenderer(openid_form) -%]
+    <form action="[% c.req.uri %]" method="post" style="margin: 0 auto;">
+        <p>
+            [% r.label('openid', l('OpenID:')) %]
+            [% r.text('openid', { size => 50 }) %]
+            [% form_field_errors(openid_form, 'openid') %]
+        </p>
+        [% form_submit(l('Create Account with OpenID')) %]
+    </form>
+
+    </div>
+
+    </div>
+
+    [% INCLUDE "user/register_footer.tt" %]
 
 [% END %]

=== added file 'root/user/register_footer.tt'
--- root/user/register_footer.tt (revision 0)
+++ root/user/register_footer.tt (working copy)
@@ -0,0 +1,24 @@
+    <h2>[%- l('We respect your privacy') %]</h2>
+
+    <p>
+        [%- l('Rest assured that we will not pass your email address on to anyone, including other MusicBrainz users, without your most explicit consent. At any time you can fill in your email address if it's currently blank, remove it if it's currently filled in or change from one address to another.') %]
+    </p>
+    <p>
+        [%- l('{doc|Read on for the full MusicBrainz Privacy Policy}', {doc => doc_link('MusicBrainzPrivacyPolicy')}) -%]
+    </p>
+
+    <h3>[% l('What your email address will <em>not</em> be used for:') %]</h3>
+    <p>
+        [% l("We won't send you any newsletters, promotional mailings, etc. If you're interested in receiving information from the MusicBrainz staff and communicating with other users, {ml|please subscribe to our mailing lists}.", {ml => doc_link('MailingList')}) %]
+    </p>
+    <h3>[%- l('What your email address <em>will</em> be used for:') -%]</h3>
+    <p>
+        [% l('Because some users, unfortunately, made lots of questionable edits and could not be contacted to fix their mistakes, we now require a confirmed (i.e. working) email address before a user can make edits to the database.') %]
+    </p>
+
+    [%- WRAPPER 'layout/guidelines.tt' -%]
+        [%- create_guideline(l('When you enter your email address, other editors will be able to send messages to you (likewise, you will be able to send messages to them).')) %]
+        [%- create_guideline(l('Any notes attached to your edits will be emailed to you. This enables you to remove, correct or clarify edits which will otherwise be rejected.')) %]
+        [%- create_guideline(l('You may choose to "subscribe" (for free) to your favourite Artists, in which case MusicBrainz will send you a daily list of edits made to the Artists to which you have subscribed.')) %]
+        [%- create_guideline(l('In all cases your email address will not be revealed to other MusicBrainz users.  They will see only your user name.')) %]
+    [% END %]

=== added file 'root/user/register_openid.tt'
--- root/user/register_openid.tt (revision 0)
+++ root/user/register_openid.tt (working copy)
@@ -0,0 +1,33 @@
+[% WRAPPER "layout.tt" title=l("Create an Account with OpenID") full_width=1 %]
+
+    <h1>[% l("Create an Account with OpenID") %]</h1>
+
+    [%- WRAPPER 'layout/guidelines.tt' -%]
+        [%- create_guideline(l('Please fill out the fields below to create a new MusicBrainz account.')) %]
+        [%- create_guideline(l('Before doing so, please read the {coc|MusicBrainz Code of Conduct}', {coc => doc_link('CodeOfConduct')})) -%]
+        [%- create_guideline(l('If you have any questions, please review the {faq|Frequently Asked Questions (FAQ)}, or post it to the appropriate {ml|Mailing List}.', {faq => doc_link('FrequentlyAskedQuestions'), ml => doc_link('MailingList')})) -%]
+    [% END %]
+
+    [%- USE r = FormRenderer(register_form) -%]
+    <form action="[% c.req.uri %]" method="post">
+        <p>
+            <label>[% l('OpenID:') %]</label>
+            <span class="openid">[% openid | html %]</span>
+            [ <a href="[% c.uri_for_action('user/register') %]">[% l('Use another OpenID') %]</a> ]
+        </p>
+        <p>
+            [% r.label('username', l('Username:')) %]
+            [% r.text('username') %]
+            [% form_field_errors(register_form, 'username') %]
+        </p>
+        <p>
+            [% r.label('email', l('Email:')) %]
+            [% r.text('email') %]
+            [% form_field_errors(register_form, 'email') %]
+        </p>
+        [% form_submit(l('Create Account')) %]
+    </form>
+
+    [% INCLUDE "user/register_footer.tt" %]
+
+[% END %]



_______________________________________________
MusicBrainz-devel mailing list
MusicBrainz-devel@...
http://lists.musicbrainz.org/mailman/listinfo/musicbrainz-devel

Re: OpenID support

by Kuno Woudt-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On Sat, Sep 05, 2009 at 03:05:37PM +0200, Lukáš Lalinský wrote:
> I needed a little "fun" project so I started to experiment with adding
> OpenID support to mb_server. You can see the work-in-progress patch in
> attachment (login/registration works, managing OpenID for existing
> accounts doesn't yet).
>
> I've been wondering if we want to support OpenID at all.

For the record, my opinion on openid has reversed (I used to be very
much against it: http://bugs.musicbrainz.org/ticket/3838).  I am now
in favour.

> We obviously
> still need passwords for web services, but I'd personally prefer to
> use my Google account to login on the website. Another thing are user
> names, would it make sense to split "user name" which is used for
> login and "display name"? That means that username/password would be
> used only for logging in, but both could be empty if there is an
> OpenID. This would simplify creating an OpenID account on the website.

Sounds reasonable.  

You've probably thought of this already, but just in case:

Make sure users can move their musicbrainz account from one OpenID
to another (or even better, allow a musicbrainz account to be associated
with multiple OpenID accounts).

-- kuno / warp.


_______________________________________________
MusicBrainz-devel mailing list
MusicBrainz-devel@...
http://lists.musicbrainz.org/mailman/listinfo/musicbrainz-devel

Re: OpenID support

by Sean Goller :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Sat, Sep 5, 2009 at 6:51 AM, Kuno Woudt <kuno@...> wrote:

On Sat, Sep 05, 2009 at 03:05:37PM +0200, Lukáš Lalinský wrote:
> I needed a little "fun" project so I started to experiment with adding
> OpenID support to mb_server. You can see the work-in-progress patch in
> attachment (login/registration works, managing OpenID for existing
> accounts doesn't yet).
>
> I've been wondering if we want to support OpenID at all.

For the record, my opinion on openid has reversed (I used to be very
much against it: http://bugs.musicbrainz.org/ticket/3838).  I am now
in favour.

-- kuno / warp.



So, if I may be so bold as to ask, what changed your mind about OpenID? Personally, if we're going to support any sort of "global" login, I think we should support OpenID. Would it be hard to incorporate RPX ( https://rpxnow.com/ ) into musicbrainz? I would think something like that would give the most flexibility, since presumably they can add more identity sources in the future. I haven't looked at licensing or other issues, just throwing it out there.

-Sean.

_______________________________________________
MusicBrainz-devel mailing list
MusicBrainz-devel@...
http://lists.musicbrainz.org/mailman/listinfo/musicbrainz-devel

Re: OpenID support

by Philipp Wolfer-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Sat, Sep 5, 2009 at 3:51 PM, Kuno Woudt <kuno@...> wrote:

On Sat, Sep 05, 2009 at 03:05:37PM +0200, Lukáš Lalinský wrote:
> I needed a little "fun" project so I started to experiment with adding
> OpenID support to mb_server. You can see the work-in-progress patch in
> attachment (login/registration works, managing OpenID for existing
> accounts doesn't yet).
>
> I've been wondering if we want to support OpenID at all.

For the record, my opinion on openid has reversed (I used to be very
much against it: http://bugs.musicbrainz.org/ticket/3838).  I am now
in favour.

Just out of curiosity: I read your objections and the blog post you linked to in the bug description, but the issues described there did not convince me. The all seemed solvable. I see OpenID with some scepticism, but overall it has a lot of advantages over the username/password approach.

What changed your mind on that issue? 

--
Philipp Wolfer

_______________________________________________
MusicBrainz-devel mailing list
MusicBrainz-devel@...
http://lists.musicbrainz.org/mailman/listinfo/musicbrainz-devel