diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2017-09-22 12:59:27 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2017-09-22 14:36:28 +0200 |
commit | c990008d564dbaf4f8881458224b7ecaac104f07 (patch) | |
tree | 805cab4728f4170783e63c95efe0b37aa586b188 | |
parent | 0615ed0ff77ba49a919edf9274a8933872f6f403 (diff) | |
download | sourceyard-c990008d564dbaf4f8881458224b7ecaac104f07.tar.gz sourceyard-c990008d564dbaf4f8881458224b7ecaac104f07.tar.bz2 |
Start implementing user personal pages
* lib/Sourceyard.pm: Predeclare user and return_url stash vars.
Route user/ requests.
* lib/Sourceyard/Controller.pm (clone): New method.
* lib/Sourceyard/Controller/Account.pm (login): Redirect to / if
already authenticated.
(user_login): Redirect to return_url, defaulting to /.
* lib/Sourceyard/Controller/Main.pm: Don't use is_logged_in.
* lib/Sourceyard/Controller/User.pm: New file.
* lib/Sourceyard/Schema/Result/User.pm: Load
InflateColumn::DateTime. Index on user_name.
* templates/account/login.html.ep: Move feedback div to
include/feedback.html.ep. Include it.
* templates/include/feedback.html.ep: New file.
* templates/layouts/default.html.ep: Omit div.indexright if
statistics stash var is not defined.
* templates/layouts/user.html.ep: New file.
* templates/menu/anonmenu.html.ep
* templates/menu/leftmenu.html.ep: Use the 'user' stash var instead of
is_logged_in
* templates/menu/topuser.html.ep: New file.
* templates/menu/usermenu.html.ep: Use absolute locations.
* templates/user/admin.html.ep: New file.
-rw-r--r-- | lib/Sourceyard.pm | 14 | ||||
-rw-r--r-- | lib/Sourceyard/Controller.pm | 7 | ||||
-rw-r--r-- | lib/Sourceyard/Controller/Account.pm | 15 | ||||
-rw-r--r-- | lib/Sourceyard/Controller/Main.pm | 7 | ||||
-rw-r--r-- | lib/Sourceyard/Controller/User.pm | 11 | ||||
-rw-r--r-- | lib/Sourceyard/Schema/Result/User.pm | 2 | ||||
-rw-r--r-- | templates/account/login.html.ep | 55 | ||||
-rw-r--r-- | templates/include/feedback.html.ep | 8 | ||||
-rw-r--r-- | templates/layouts/default.html.ep | 4 | ||||
-rw-r--r-- | templates/layouts/user.html.ep | 24 | ||||
-rw-r--r-- | templates/menu/anonmenu.html.ep | 4 | ||||
-rw-r--r-- | templates/menu/leftmenu.html.ep | 17 | ||||
-rw-r--r-- | templates/menu/topuser.html.ep | 38 | ||||
-rw-r--r-- | templates/menu/usermenu.html.ep | 7 | ||||
-rw-r--r-- | templates/user/admin.html.ep | 78 |
15 files changed, 244 insertions, 47 deletions
diff --git a/lib/Sourceyard.pm b/lib/Sourceyard.pm index 7b7d92d..4d1a528 100644 --- a/lib/Sourceyard.pm +++ b/lib/Sourceyard.pm @@ -3,6 +3,7 @@ use Mojo::Base 'Mojolicious'; use FindBin; use Sourceyard::Config; use Sourceyard::Schema; +use Sourceyard::Controller; my @allowed = qw( 193.186.15.43 @@ -34,6 +35,9 @@ sub startup { # FIXME: Documentation browser under "/perldoc" $self->plugin('PODRenderer'); + $self->app->defaults(user => undef); + $self->app->defaults(return_url => undef); + # Router my $r = $self->routes; @@ -41,6 +45,16 @@ sub startup { $r->get('/')->to('main#index'); $r->get('/account/:action')->to(controller => 'account'); $r->post('/account/login')->name('login')->to('account#user_login'); + + my $auth = $r->under('/user' => sub { + my $c = Sourceyard::Controller->clone(shift); + unless ($c->stash('user')) { + $c->render('/account/login', return_url => $c->req->url); + return undef + } + return 1; + }); + $auth->get(':action')->to(controller => 'user'); } 1; diff --git a/lib/Sourceyard/Controller.pm b/lib/Sourceyard/Controller.pm index e7cdd2f..17f887c 100644 --- a/lib/Sourceyard/Controller.pm +++ b/lib/Sourceyard/Controller.pm @@ -13,6 +13,13 @@ sub new { return $self; } +sub clone { + my ($class,$obj) = @_; + my $self = bless $obj, $class; + $self->set_user; + return $self; +} + sub set_user { my ($self, $user) = @_; if (defined($user)) { diff --git a/lib/Sourceyard/Controller/Account.pm b/lib/Sourceyard/Controller/Account.pm index 66cd2ba..fe65008 100644 --- a/lib/Sourceyard/Controller/Account.pm +++ b/lib/Sourceyard/Controller/Account.pm @@ -5,7 +5,12 @@ use Sourceyard::User; sub login { my $self = shift; - $self->render(is_logged_in => 0); + if ($self->stash('user')) { + $self->res->code(302); + $self->redirect_to('/'); + return; + } + $self->render; } sub logout { @@ -31,7 +36,8 @@ sub user_login { my $username = $self->param('username'); my $password = $self->param('password'); my $remember = $self->param('cookie_for_a_year'); - + my $return_url = $self->param('return_url') || '/'; + my $user = new Sourceyard::User($self, $username); if ($user && $self->pwcheck($password, $user->user_pw)) { # FIXME @@ -40,12 +46,9 @@ sub user_login { # $res->update; # } $self->set_user($user); - - $self->res->code(302); - $self->redirect_to('/'); + $self->redirect_to($return_url); } else { $self->render('account/login', - is_logged_in => 0, error_msg => 'Invalid user name or password'); } } diff --git a/lib/Sourceyard/Controller/Main.pm b/lib/Sourceyard/Controller/Main.pm index 64f2565..04a23d7 100644 --- a/lib/Sourceyard/Controller/Main.pm +++ b/lib/Sourceyard/Controller/Main.pm @@ -4,16 +4,13 @@ use Mojo::Base 'Sourceyard::Controller'; # This action will render a template sub index { my $self = shift; - $self->render(msg => 'Welcome', - statistics => $self->statistics, - is_logged_in => $self->session('logged_in'), - ); + statistics => $self->statistics); } sub login { my $self = shift; - $self->render(is_logged_in => 0); + $self->render; } 1; diff --git a/lib/Sourceyard/Controller/User.pm b/lib/Sourceyard/Controller/User.pm new file mode 100644 index 0000000..418fd5a --- /dev/null +++ b/lib/Sourceyard/Controller/User.pm @@ -0,0 +1,11 @@ +package Sourceyard::Controller::User; +use Mojo::Base 'Sourceyard::Controller'; +use Sourceyard::User; + +sub admin { + my $self = shift; + print "ADMIN\n"; + $self->render; +} + +1; diff --git a/lib/Sourceyard/Schema/Result/User.pm b/lib/Sourceyard/Schema/Result/User.pm index adc7120..9210817 100644 --- a/lib/Sourceyard/Schema/Result/User.pm +++ b/lib/Sourceyard/Schema/Result/User.pm @@ -5,6 +5,7 @@ use warnings; use base 'DBIx::Class::Core'; +__PACKAGE__->load_components(qw/ InflateColumn::DateTime Core /); __PACKAGE__->table('user'); __PACKAGE__->add_columns( user_id => { @@ -58,6 +59,7 @@ __PACKAGE__->add_columns( } ); __PACKAGE__->set_primary_key('user_id'); +__PACKAGE__->add_unique_constraint(['user_name']); __PACKAGE__->add_unique_constraint(['user_id','user_name']); __PACKAGE__->add_unique_constraint(['email']); __PACKAGE__->has_many( diff --git a/templates/account/login.html.ep b/templates/account/login.html.ep index 2812001..46e6944 100644 --- a/templates/account/login.html.ep +++ b/templates/account/login.html.ep @@ -1,30 +1,27 @@ % layout 'account'; % title 'Sourceyard Login'; -%= t h2 => (class => 'toptitle') => begin - %= t img => (src => "/images/Savannah.theme/contexts/main.orig.png", width =>48, height => 48, alt => 'main', class => "pageicon") +<h2 class="toptitle"> + <img src="/images/<%= $theme %>.theme/contexts/main.orig.png" + width="48" height="48" alt="main" class="pageicon" /> Login -% end -%= t div => (class => "topmenu", id => "topmenu") => begin - %= t span => (class => "topmenutitle", title => "Site Wide Scope") => begin - Site Wide - % end -% end -% if (my $error_msg = stash 'error_msg') { -<div onclick="document.getElementById('feedback').style.visibility='visible'; document.getElementById('feedbackback').style.visibility='hidden';" id="feedbackback" class="feedbackback"> -Show feedback again -</div> -<div id="feedback" class="feedbackerror" onclick="document.getElementById('feedback').style.visibility='hidden'; document.getElementById('feedbackback').style.visibility='visible';"><span class="feedbackerrortitle"><img src="/images/Savannah.theme/bool/wrong.png" class="feedbackimage" alt="" />Error:</span><br/> -%= $error_msg -</div> -% } +</h2> +<div class="topmenu" id="topmenu"> + <span class="topmenutitle" title="Site Wide Scope"> + Site Wide + </span> +</div> +%= include "include/feedback" <div class="form"> %= form_for 'login' => (method => 'POST') => begin +% if ($return_url) { +%= hidden_field return_url => $return_url +% } <div class="input"> %= label_for username => => (class => 'preinput') => begin Login Name: % end - %= text_field 'username' - %= link_to 'register' => (class => 'smaller') => begin + %= text_field 'username' => (tabindex => 1) + %= link_to 'register' => (class => 'smaller', tabindex => 2) => begin [No account yet?] %= end </div> @@ -32,21 +29,21 @@ Show feedback again %= label_for password => (class => 'preinput') => begin Password: % end - %= password_field 'password' - %= link_to 'lostpw' => (class => 'smaller') => begin + %= password_field 'password' => (tabindex => 1) + %= link_to 'lostpw' => (class => 'smaller', tabindex => 2) => begin [Lost your password?] %= end </div> - <div class="left"> - %= input_tag type => 'cookie_for_a_year', type => 'checkbox' - <span class="preinput">Remember me</span><br /> - <span class="text">For a year, your login information will be stored - in a cookie. Use this only if you are - using your own computer. - </span> - </div> +%# <div class="left"> +%# %= input_tag type => 'cookie_for_a_year', type => 'checkbox' +%# <span class="preinput">Remember me</span><br /> +%# <span class="text">For a year, your login information will be stored +%# in a cookie. Use this only if you are +%# using your own computer. +%# </span> +%# </div> <div class="center"> - %= submit_button 'Login', class => 'btn' + %= submit_button 'Login', (class => 'btn', tabindex => 1) </div> % end </div> diff --git a/templates/include/feedback.html.ep b/templates/include/feedback.html.ep new file mode 100644 index 0000000..41a88e5 --- /dev/null +++ b/templates/include/feedback.html.ep @@ -0,0 +1,8 @@ +% if (my $error_msg = stash 'error_msg') { +<div onclick="document.getElementById('feedback').style.visibility='visible'; document.getElementById('feedbackback').style.visibility='hidden';" id="feedbackback" class="feedbackback"> +Show feedback again +</div> +<div id="feedback" class="feedbackerror" onclick="document.getElementById('feedback').style.visibility='hidden'; document.getElementById('feedbackback').style.visibility='visible';"><span class="feedbackerrortitle"><img src="/images/Savannah.theme/bool/wrong.png" class="feedbackimage" alt="" />Error:</span><br/> +%= $error_msg +</div> +% } diff --git a/templates/layouts/default.html.ep b/templates/layouts/default.html.ep index 110db3a..5d9106f 100644 --- a/templates/layouts/default.html.ep +++ b/templates/layouts/default.html.ep @@ -16,8 +16,8 @@ <div class="main"><a name="top"></a> - <div class="indexright"> % if (my $stat = stash 'statistics') { + <div class="indexright"> <div class="box"> <div class="boxtitle"> <a href="/stats/" class="sortbutton">Statistics</a> @@ -33,8 +33,8 @@ %# </span> %# </div> </div> <!-- box --> -% } </div> <!-- indexright --> +% } <div class="indexcenter"> <%= content %> diff --git a/templates/layouts/user.html.ep b/templates/layouts/user.html.ep new file mode 100644 index 0000000..89fe7e7 --- /dev/null +++ b/templates/layouts/user.html.ep @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE html + PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" + lang="en-US.UTF-8" xml:lang="en-US.UTF-8"> + <head> + <title><%= title %></title> + <meta http-equiv="Content-Script-Type" content="text/javascript" /> + <link rel="stylesheet" type="text/css" href="/css/<%= $theme %>.css" /> + <link rel="icon" type="image/png" href="/images/<%= $theme %>.theme/icon.png" /> + </head> + <body> + <div class="realbody"> +%= include "menu/leftmenu" + <div class="main"><a name="top"></a> +%= include "menu/topuser" + <div id="topmenunooverlap"> </div> + <div id="topmenunooverlapbis"> </div> + <%= content %> + </div> <!-- main --> + </div> <!-- realbody --> + </body> +</html> diff --git a/templates/menu/anonmenu.html.ep b/templates/menu/anonmenu.html.ep index 4be7419..b6ad067 100644 --- a/templates/menu/anonmenu.html.ep +++ b/templates/menu/anonmenu.html.ep @@ -5,9 +5,9 @@ <li class="menuitem"> <span class="error">Not Logged In</span> <li class="menuitem"> - %= link_to Login => 'account/login' + %= link_to Login => '/account/login' </li> <li class="menuitem"> - %= link_to 'New User' => 'account/register' + %= link_to 'New User' => '/account/register' </li> </li> diff --git a/templates/menu/leftmenu.html.ep b/templates/menu/leftmenu.html.ep index f3e981b..f6c8549 100644 --- a/templates/menu/leftmenu.html.ep +++ b/templates/menu/leftmenu.html.ep @@ -6,11 +6,26 @@ height="125" /> </a> </li> -% if ($is_logged_in) { +% if ($user) { %= include "menu/usermenu" % } else { %= include "menu/anonmenu" % } + + <li class="menutitle"> + Search + </li><!-- end menutitle --> + <li class="menusearch"> +%= form_for '/search' => (method => 'POST') => begin +%= text_field 'words' => (size => 15) +<br/> +<em>in</em> +%= select_field type_of_search => [[ Projects => 'projects', selected => 'selected'], [ People => 1]] +<br/> +%= submit_button 'Search', class => 'btn' +% end + </li> + <li class="menutitle"> Related Forges </li> diff --git a/templates/menu/topuser.html.ep b/templates/menu/topuser.html.ep new file mode 100644 index 0000000..11003ce --- /dev/null +++ b/templates/menu/topuser.html.ep @@ -0,0 +1,38 @@ +<h2 class="toptitle"> + <img src="/images/<%= $theme %>.theme/contexts/preferences.orig.png" + width="48" height="48" alt="preferences" class="pageicon" /> + My Account Configuration +</h2> + +<div class="topmenu" id="topmenu"> + <span class="topmenutitle" title="My Scope"> + My + </span><!-- end topmenutitle --> +<div class="topmenuitem"> +<ul id="topmenuitem"> + <li class="topmenuitemmainitem"> + <a href="/user/" class="tabs" title="What's new for me?"> + Incoming Items + </a> + </li><!-- end topmenuitemmainitem --> + + <li class="topmenuitemmainitem"> + <a href="/user/items.php" class="tabs" title="Browse my items (bugs, tasks, bookmarks...)"> + Items + </a> + </li><!-- end topmenuitemmainitem --> + + <li class="topmenuitemmainitem"> + <a href="/user/groups.php" class="tabs" title="List the groups I belong to"> + Group Membership + </a> + </li><!-- end topmenuitemmainitem --> + + <li class="topmenuitemmainitem"> + <a href="/user/admin/" class="tabselect" title="Account configuration: authentication, cosmetics preferences..."> + Account Configuration + </a> + </li><!-- end topmenuitemmainitem --> +</ul> +</div><!-- end topmenuitem --> +</div> diff --git a/templates/menu/usermenu.html.ep b/templates/menu/usermenu.html.ep index 8aed663..326b3a6 100644 --- a/templates/menu/usermenu.html.ep +++ b/templates/menu/usermenu.html.ep @@ -1,6 +1,9 @@ <li class="menutitle"> - Logged in as <%= $self->session('username') %> + Logged in as <%= $user->user_name %> </li> <li class="menuitem"> - %= link_to Logout => 'account/logout' + %= link_to 'My Account Conf' => '/user/admin' +</li> +<li class="menuitem"> + %= link_to Logout => '/account/logout' </li> diff --git a/templates/user/admin.html.ep b/templates/user/admin.html.ep new file mode 100644 index 0000000..2a621b0 --- /dev/null +++ b/templates/user/admin.html.ep @@ -0,0 +1,78 @@ +% layout 'user'; +% title 'My Account Configuration'; +%= include "include/feedback" +<div class="form"> +%= form_for 'admin' => (method => 'POST') => begin + <h3>Significant Arrangements</h3> + <div class="splitleft"> + <div class="box"> + <div class="boxtitle">Identity Record</div> + <div class="boxitem"> + Account #<%= $user->user_id %> + <p class="smaller"> + Your login is <strong><%= $user->user_name %></strong>. + You registered your account on +% $user->add_date->set_time_zone('local'); + <strong><%= $user->add_date->strftime('%a %d %b %Y %I:%M:%S %p %z') %></strong>. + </p> + </div><!-- end ---- boxitem --> + <div class="boxitemalt"> + <a href="change.php?item=realname">Change Real Name</a> + <p class="smaller"> + You are <strong><%= $user->real_name %></strong>. + </p> + </div><!-- end ---- boxitem --> + <div class="boxitem"> + <a href="resume.php">Edit Resume and Skills</a> + <p class="smaller"> + Details about your experience and skills will be available to + logged in users in the hope they will be of interest. + </p> + </div><!-- end ---- boxitem --> + <div class="boxitemalt"> + <a href="/users/gray">View your Public Profile</a> + <p class="smaller"> + Your profile can be viewed by everybody. + </p> + </div><!-- end ---- boxitem --> + </div><!-- end box --> + <br /> + <div class="box"> + <div class="boxtitle">Mail Setup</div> + <div class="boxitem"> + <a href="change.php?item=email"> + Change Email Address + </a> + <p class="smaller"> + Your current address is + <strong><%= $user->email %></strong>. + It is essential to us that this address remains valid. Keep + it up to date. + </p> + </div><!-- end boxitem --> + <div class="boxitemalt"> + <a href="change_notifications.php"> + Edit Personal Notification Settings + </a> + <p class="smaller"> + Configure when the trackers should send email notifications. + It permits also to configure the subject line prefix of sent + mails. + </p> + </div><!-- end ---- boxitem --> + <div class="boxitem"> + <a href="cc.php"> + Cancel Mail Notifications + </a> + <p class="smaller"> + Here, you can cancel all mail notifications. + </p> + </div><!-- end ---- boxitem --> + </div><!-- end box --> + <br /> + </div><!-- end splitleft --> + <div class="center"> + %= submit_button 'Update', (class => 'btn', tabindex => 1) + </div> +% end + |