From c08fc6ce1e76ef87cc322fc7880cd435af4bf949 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 8 Jul 2013 23:54:40 +0200 Subject: [PATCH] Add basic Persona support This allows users to sign in to Hydra using Mozilla Persona accounts. When a user first sign in, a row in the Users table for the given Persona identity (an email address) is created automatically. To do: figure out how to deal with legacy accounts. --- src/lib/Hydra/Controller/Root.pm | 2 +- src/lib/Hydra/Controller/User.pm | 39 ++++++++++++++++++++++++++++++++ src/root/layout.tt | 38 ++++++++++++++++++++++++++++++- src/root/login.tt | 4 ++-- src/root/topbar.tt | 10 +++++--- 5 files changed, 86 insertions(+), 7 deletions(-) diff --git a/src/lib/Hydra/Controller/Root.pm b/src/lib/Hydra/Controller/Root.pm index 52ffa653..7f1a28ae 100644 --- a/src/lib/Hydra/Controller/Root.pm +++ b/src/lib/Hydra/Controller/Root.pm @@ -135,7 +135,7 @@ sub machines :Local Args(0) { { order_by => 'stoptime desc', rows => 1 }); ${$machines}{$m}{'idle'} = $idle ? $idle->stoptime : 0; } - + $c->stash->{machines} = $machines; $c->stash->{steps} = [ $c->model('DB::BuildSteps')->search( { finished => 0, 'me.busy' => 1, 'build.busy' => 1, }, diff --git a/src/lib/Hydra/Controller/User.pm b/src/lib/Hydra/Controller/User.pm index 84ec88df..3b9efb0a 100644 --- a/src/lib/Hydra/Controller/User.pm +++ b/src/lib/Hydra/Controller/User.pm @@ -8,6 +8,8 @@ use Crypt::RandPasswd; use Digest::SHA1 qw(sha1_hex); use Hydra::Helper::Nix; use Hydra::Helper::CatalystUtils; +use LWP::UserAgent; +use JSON; __PACKAGE__->config->{namespace} = ''; @@ -70,6 +72,43 @@ sub logout_GET { } +sub persona_login :Path('/persona-login') Args(0) { + my ($self, $c) = @_; + $c->stash->{json} = {}; + die if $c->request->method ne "POST"; + + my $assertion = $c->req->params->{assertion} or die; + + my $ua = new LWP::UserAgent; + my $response = $ua->post( + 'https://verifier.login.persona.org/verify', + { assertion => $assertion, + audience => "http://localhost:3000/" + }); + Catalyst::Exception->throw("Did not get a response from Persona.") unless $response->is_success; + + my $d = decode_json($response->decoded_content) or die; + Catalyst::Exception->throw("Persona says: $d->{reason}") if $d->{status} ne "okay"; + + my $email = $d->{email} or die; + + my $user = $c->find_user({ username => $email }); + + if (!$user) { + $c->model('DB::Users')->create( + { username => $email + , password => "!" + , emailaddress => $email, + }); + $user = $c->find_user({ username => $email }) or die; + } + + $c->set_authenticated($user); + + $c->stash->{json}->{result} = "ok"; +} + + sub captcha :Local Args(0) { my ($self, $c) = @_; $c->create_captcha(); diff --git a/src/root/layout.tt b/src/root/layout.tt index 2337599b..3357726b 100644 --- a/src/root/layout.tt +++ b/src/root/layout.tt @@ -11,6 +11,8 @@ Hydra - [% HTML.escape(title) %] + + @@ -95,13 +97,47 @@ Hydra [% HTML.escape(version) %] (using [% HTML.escape(nixVersion) %]). [% IF c.user_exists %] - You are logged in as [% c.user.username %]. + You are logged in as [% HTML.escape(c.user.username) %]. [% END %] + + + + diff --git a/src/root/login.tt b/src/root/login.tt index 5d69f3ea..bf3ad616 100644 --- a/src/root/login.tt +++ b/src/root/login.tt @@ -13,8 +13,7 @@ You can logout here. c.uri_for('/register') %]">register first.

--> -
- + [% END %] diff --git a/src/root/topbar.tt b/src/root/topbar.tt index fd924615..609fa3c1 100644 --- a/src/root/topbar.tt +++ b/src/root/topbar.tt @@ -1,6 +1,6 @@ [% BLOCK menuItem %]
  • - [% title %] + uri) %]>[% title %]
  • [% END %] @@ -198,9 +198,13 @@ [% IF c.user_exists %] [% INCLUDE menuItem uri = c.uri_for(c.controller('User').action_for('edit'), [c.user.username]) title = "Preferences" %] - [% INCLUDE menuItem uri = c.uri_for(c.controller('Root').action_for('logout')) title = "Sign out" %] +
  • + Sign out +
  • [% ELSE %] - [% INCLUDE menuItem uri = c.uri_for(c.controller('Root').action_for('login')) title = "Sign in" %] +
  • + Sign in +
  • [% END %]