Compare commits
11 Commits
c6687ad3f5
...
a7b8116ff7
Author | SHA1 | Date |
---|---|---|
barnold | a7b8116ff7 | |
barnold | dd6ea0a0ba | |
barnold | 595b4be156 | |
barnold | 906055e410 | |
barnold | 85dde076e4 | |
barnold | 76df89a970 | |
barnold | 24fbcf708b | |
barnold | 4c5626c9ef | |
barnold | 4c6d5bf321 | |
barnold | 501736f901 | |
barnold | 5cc21a2e7a |
28
lib/MyApp.pm
28
lib/MyApp.pm
|
@ -82,30 +82,12 @@ sub startup ($self) {
|
|||
|
||||
# Set routes.
|
||||
my $r = $self->routes;
|
||||
# Home gets an explicit name, else its name is an empty string. A
|
||||
# route's default name seems to come from '/path' with the leading
|
||||
# '/' removed.
|
||||
$r->get('/')->to('home#index')->name('home');
|
||||
$r->get('/about')->to('home#about');
|
||||
$r->get('/auth')->to('auth#index');
|
||||
$r->post('/login')->to('auth#login');
|
||||
$r->get('/logout')->to('auth#logout');
|
||||
$r->get('/books/<page_number:num>')->to('book#books')->name('books');
|
||||
$r->get('/authors/<page_number:num>')->to('book#authors')->name('authors');
|
||||
$r->get('/<page_number:num>')->to('book#books', page_number => 1)->name('books');
|
||||
$r->get('/about')->to('book#about')->name('about');
|
||||
$r->get('/authors/<page_number:num>')
|
||||
->to('book#authors', page_number => 1)->name('authors');
|
||||
$r->get('/author/<id:num>/<page_number:num>')->to('book#author')->name('author');
|
||||
|
||||
# Put a route under athentication.
|
||||
my $auth = $r->under(
|
||||
'/' => sub ($c) {
|
||||
return 1 if ($c->logname);
|
||||
$c->flash('naughty' => 1);
|
||||
$c->session('post_login' => $c->current_route);
|
||||
$c->redirect_to('auth');
|
||||
return undef;
|
||||
}
|
||||
);
|
||||
$auth->get('/account')->to('auth#account')->name('account');
|
||||
$auth->post('/preferences')->to('auth#preferences')->name('preferences');
|
||||
$r->post('/set_rpp')->to('book#set_rpp')->name('set_rpp');
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
package MyApp::Controller::Auth;
|
||||
use Mojo::Base 'Mojolicious::Controller', -signatures;
|
||||
use List::Util qw( min max );
|
||||
|
||||
sub index ($self) {
|
||||
my $msg = $self->flash('err');
|
||||
$self->render(name_msg => $msg);
|
||||
}
|
||||
|
||||
sub login ($self) {
|
||||
my $logname = $self->param('logname');
|
||||
if ($logname =~ m/^[[:alpha:]]+$/) {
|
||||
$self->session(logname => $logname);
|
||||
my $post_login = $self->session('post_login');
|
||||
$self->session('post_login' => undef);
|
||||
$self->redirect_to($post_login || 'home');
|
||||
} else {
|
||||
$self->flash(err => "Try again!");
|
||||
$self->flash(attempted_name => $logname);
|
||||
$self->redirect_to('auth');
|
||||
}
|
||||
}
|
||||
|
||||
sub logout ($self) {
|
||||
# "Delete whole session by setting an expiration date in the past"
|
||||
# - from Mojolicious::Controller.
|
||||
$self->session(expiration => 1);
|
||||
$self->redirect_to('home');
|
||||
}
|
||||
|
||||
sub preferences ($self) {
|
||||
my $rpp = $self->accept_posint($self->param('rows_per_page'));
|
||||
if ((!defined $rpp) || $rpp < 1 || $rpp > $self->max_rpp) {
|
||||
$self->redirect_to('not_found');
|
||||
return
|
||||
}
|
||||
$self->session(rows_per_page => $rpp);
|
||||
$self->flash(
|
||||
confirmation => sprintf("Updated rows per page to %s.", $self->rpp)
|
||||
);
|
||||
$self->redirect_to('account');
|
||||
}
|
||||
|
||||
1;
|
|
@ -17,7 +17,9 @@ sub books ($self) {
|
|||
);
|
||||
my $pager = $book_page->pager;
|
||||
if ($page_number > $pager->last_page) {
|
||||
$self->redirect_to('not_found');
|
||||
$self->redirect_to(
|
||||
$self->url_with({ page_number => $pager->last_page })
|
||||
);
|
||||
return;
|
||||
}
|
||||
$self->render(
|
||||
|
@ -41,7 +43,9 @@ sub authors ($self) {
|
|||
);
|
||||
my $pager = $author_page->pager;
|
||||
if ($page_number > $pager->last_page) {
|
||||
$self->redirect_to('not_found');
|
||||
$self->redirect_to(
|
||||
$self->url_with({ page_number => $pager->last_page })
|
||||
);
|
||||
return;
|
||||
}
|
||||
$self->render(
|
||||
|
@ -67,7 +71,9 @@ sub author ($self) {
|
|||
}
|
||||
my $pager = $book_page->pager;
|
||||
if ($page_number > $pager->last_page) {
|
||||
$self->redirect_to('not_found');
|
||||
$self->redirect_to(
|
||||
$self->url_with({ page_number => $pager->last_page })
|
||||
);
|
||||
return;
|
||||
}
|
||||
$self->render(
|
||||
|
@ -77,4 +83,17 @@ sub author ($self) {
|
|||
);
|
||||
}
|
||||
|
||||
sub set_rpp ($self) {
|
||||
my $rpp = $self->accept_posint($self->param('rows_per_page'));
|
||||
if ((!defined $rpp) || $rpp < 1 || $rpp > $self->max_rpp) {
|
||||
$self->redirect_to('not_found');
|
||||
return
|
||||
}
|
||||
$self->session(rows_per_page => $rpp);
|
||||
$self->flash(
|
||||
confirmation => sprintf("Updated rows per page to %s.", $self->rpp)
|
||||
);
|
||||
$self->redirect_to($self->param('target_url'));
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
package MyApp::Controller::Home;
|
||||
use Mojo::Base 'Mojolicious::Controller', -signatures;
|
||||
|
||||
# No need for a method for either 'index' or 'about'.
|
||||
# sub index ($self) {
|
||||
# }
|
||||
|
||||
1;
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
secrets:
|
||||
- 197b9b0060f3285c0909d83598e54f9ec0602151
|
||||
default-rows-per-page: 10
|
||||
default-rows-per-page: 12
|
||||
maximum-rows-per-page: 100
|
||||
|
|
|
@ -1,3 +1,34 @@
|
|||
h1 {
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: medium;
|
||||
}
|
||||
|
||||
form > span {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
ul.top {
|
||||
margin: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
ul.top > li {
|
||||
display: inline-block;
|
||||
padding-right: 1em;
|
||||
min-width: 8ch;
|
||||
}
|
||||
|
||||
div.page-nav {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
div.page-nav > span {
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
div.verbiage {
|
||||
max-width: 40em;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,16 @@
|
|||
#!/usr/bin/env perl
|
||||
#
|
||||
# A note about lighttpd and fastcgi, based on
|
||||
# <https://github.com/mojolicious/mojo/wiki/Deploying-on-Lighttpd-with-FastCGI>
|
||||
# which shows how to start the app via lighttpd. However, it doesn't
|
||||
# show how to start the app yourself, outside of lighttpd, in such
|
||||
# a way that it'll work under fcgi.
|
||||
#
|
||||
# To do this:
|
||||
# Change the lighttpd conf to remove "bin-path" and instead use (e.g.)
|
||||
# "host" => "localhost".
|
||||
# Then to start the app, use 'spawn-fcgi', e.g.
|
||||
# spawn-fcgi -a 127.0.0.1 -p 8080 -- script/my_app fastcgi
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
|
13
t/basic.t
13
t/basic.t
|
@ -1,20 +1,13 @@
|
|||
use Mojo::Base -strict;
|
||||
|
||||
use Test2::V0;
|
||||
use Test2::Plugin::BailOnFail;
|
||||
use Test::Mojo;
|
||||
|
||||
my $t = Test::Mojo->new('MyApp');
|
||||
$t->get_ok('/')->status_is(200)->content_like(qr/home/i);
|
||||
$t->get_ok('/')->status_is(200)->content_like(qr/Books/);
|
||||
$t->get_ok('/about')->status_is(200)->content_like(qr/about/i);
|
||||
# No way to follow the redirect?
|
||||
$t->get_ok('/account')->status_is(302);
|
||||
$t->get_ok('/auth')->status_is(200)->content_like(qr/login/i);
|
||||
$t->post_ok('/login' => form => { logname => 'Dobby' });
|
||||
$t->get_ok('/account')->status_is(200)->content_like(qr/dobby/i);
|
||||
$t->get_ok('/books/1')->status_is(200)->content_like(qr/[[:digit:]] books/i);
|
||||
$t->get_ok('/1')->status_is(200)->content_like(qr/[[:digit:]] books/i);
|
||||
$t->get_ok('/authors/1')->status_is(200)->content_like(qr/[[:digit:]] authors/i);
|
||||
$t->get_ok('/logout')->status_is(302);
|
||||
# Can't do "content_unlike()" so check it offers login now.
|
||||
$t->get_ok('/')->status_is(200)->content_like(qr/login/i);
|
||||
|
||||
done_testing();
|
||||
|
|
16
t/notfound.t
16
t/notfound.t
|
@ -1,24 +1,26 @@
|
|||
use Mojo::Base -strict;
|
||||
|
||||
use Test2::V0;
|
||||
use Test2::Plugin::BailOnFail;
|
||||
use Test::Mojo;
|
||||
|
||||
my $t = Test::Mojo->new('MyApp');
|
||||
|
||||
# Page zero gets a redirect.
|
||||
$t->get_ok('/books/0')->status_is(302);
|
||||
$t->get_ok('/0')->status_is(302);
|
||||
|
||||
# Now follow redirects and verify it's a 404.
|
||||
$t->ua->max_redirects(10);
|
||||
$t->get_ok('/books/0')->status_is(404);
|
||||
$t->get_ok('/0')->status_is(404);
|
||||
|
||||
# Likewise for a too-high page number.
|
||||
$t->get_ok('/books/999?title_like=qxqxqxqx')->status_is(404);
|
||||
# A too-high page number should take us to the last page.
|
||||
$t->get_ok('/999?title_like=qxqxqxqx')->status_is(200)
|
||||
->content_like(qr/0\s+books\s+of\s+0/);
|
||||
|
||||
# Likewise for invalid page numbers.
|
||||
$t->get_ok('/books/x')->status_is(404);
|
||||
$t->get_ok('/books/1.99')->status_is(404);
|
||||
$t->get_ok('/books/-42')->status_is(404);
|
||||
$t->get_ok('/x')->status_is(404);
|
||||
$t->get_ok('/1.99')->status_is(404);
|
||||
$t->get_ok('/-42')->status_is(404);
|
||||
|
||||
# Or non-existent author.
|
||||
$t->get_ok('/author/0/1')->status_is(404);
|
||||
|
|
|
@ -1,15 +1,8 @@
|
|||
<p/>
|
||||
Showing <%= $pager->entries_on_this_page %> <%= $items_name || "items" %>
|
||||
of
|
||||
<%= commify($pager->total_entries) =%>
|
||||
% if ($pager->total_entries <= rpp) {
|
||||
.
|
||||
<% } else { %>
|
||||
on page <%= commify($pager->current_page) %>
|
||||
of <%= commify($pager->last_page) %>.
|
||||
<div class="page-nav">
|
||||
|
||||
<br/>
|
||||
<%= link_to url_with(page_number => 1) => begin %>◄ First<% end %>
|
||||
% if ($pager->total_entries > rpp) {
|
||||
<span>
|
||||
<%= link_to url_with(page_number => 1) => begin %>◄ First<% end %>
|
||||
|
||||
% if (my $prev = $pager->previous_page) {
|
||||
<%= link_to url_with(page_number => $prev) => begin %>◄ Prev<% end %>
|
||||
|
@ -25,3 +18,18 @@ Next ►
|
|||
|
||||
<%= link_to url_with(page_number => $pager->last_page) => begin %>Last ►<% end %>
|
||||
% }
|
||||
</span>
|
||||
% }
|
||||
|
||||
<span>
|
||||
<%= $pager->entries_on_this_page %> <%= $items_name || "items" %>
|
||||
of
|
||||
<%= commify($pager->total_entries) =%>
|
||||
% if ($pager->total_entries <= rpp) {
|
||||
.
|
||||
<% } else { %>
|
||||
on page <%= commify($pager->current_page) %>
|
||||
of <%= commify($pager->last_page) %>.
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
% layout 'default';
|
||||
% title 'Account';
|
||||
<h1><%= logname %>'s account on MyApp</h1>
|
||||
|
||||
%= form_for preferences => begin
|
||||
%= label_for rows_per_page => 'Rows per page'
|
||||
<%= number_field rows_per_page => $c->rpp,
|
||||
min => 1, max => max_rpp, maxlength => 4, size => 4 %>
|
||||
%= submit_button "Update"
|
||||
% end
|
||||
<p/>
|
||||
%= flash('confirmation')
|
|
@ -1,14 +0,0 @@
|
|||
% layout 'default';
|
||||
% title 'Auth';
|
||||
<h1>Auth page</h1>
|
||||
|
||||
<%= "Login to reach " . session('post_login') . " page." if flash('naughty') %>
|
||||
<%= $name_msg %>
|
||||
<p/>
|
||||
<div>
|
||||
%= form_for login => begin
|
||||
%= label_for logname => 'Name (only letters, please)'
|
||||
%= text_field logname => flash('attempted_name')
|
||||
%= submit_button "Login"
|
||||
% end
|
||||
</div>
|
|
@ -2,16 +2,17 @@
|
|||
% title 'Authors';
|
||||
<h1><%= title %></h1>
|
||||
|
||||
<a href="/about#search-help">Search help</a>
|
||||
|
||||
<p/>
|
||||
<%# On a new search, reset the page number to 1. %>
|
||||
%= form_for authors => { page_number => 1 } => begin
|
||||
<span>
|
||||
%= label_for name_like => 'Name like'
|
||||
%= text_field name_like => flash('name_like')
|
||||
</span>
|
||||
<span>
|
||||
%= label_for minimum_book_count => 'Wrote at least'
|
||||
<%= number_field minimum_book_count => 0,
|
||||
min => 0, maxlength => 4, size => 4 %> books.
|
||||
min => 0, maxlength => 4, size => 4 %> books
|
||||
</span>
|
||||
%= submit_button "Search"
|
||||
%= end
|
||||
|
||||
|
|
|
@ -2,15 +2,16 @@
|
|||
% title 'Books';
|
||||
<h1><%= title %></h1>
|
||||
|
||||
<a href="/about#search-help">Search help</a>
|
||||
|
||||
<p/>
|
||||
<%# On a new search, reset the page number to 1. %>
|
||||
%= form_for books => { page_number => 1 } => begin
|
||||
<span>
|
||||
%= label_for title_like => 'Title like'
|
||||
%= text_field title_like => flash('title_like')
|
||||
</span>
|
||||
<span>
|
||||
%= label_for author_like => 'Author like'
|
||||
%= text_field author_like => flash('author_like')
|
||||
</span>
|
||||
%= submit_button "Search"
|
||||
%= end
|
||||
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
% layout 'default';
|
||||
% title 'Home';
|
||||
<h1>Home page</h1>
|
||||
|
||||
<p>Pages that don't require login:</p>
|
||||
|
||||
<p><%= link_to("About" => 'about') %></p>
|
||||
<p><%= link_to("Books" => 'books' => { page_number => 1 }) %></p>
|
||||
<p><%= link_to("Authors" => 'authors' => { page_number => 1 }) %></p>
|
||||
|
||||
<p>For this, you'll need to log in, then MyApp will redirect you:</p>
|
||||
<p><%= link_to("Account" => 'account') %></p>
|
|
@ -2,27 +2,42 @@
|
|||
<html>
|
||||
<head>
|
||||
<title><%= title %></title>
|
||||
<link rel="stylesheet" href="/default.css">
|
||||
%= stylesheet '/default.css'
|
||||
</head>
|
||||
<body>
|
||||
<ul class="top">
|
||||
|
||||
<li>
|
||||
<%= link_to("About" => 'about') %>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<%= link_to("Authors" => 'authors') %>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<%= link_to("Books" => 'books') %>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="<%= url_for('about') . '#search-help' %>">Search help</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
%= form_for set_rpp => begin
|
||||
<%= hidden_field target_url => url_with('current') %>
|
||||
<%= number_field rows_per_page => $c->rpp,
|
||||
min => 1, max => max_rpp, maxlength => 4, size => 4 %>
|
||||
rows per page
|
||||
%= submit_button "Update"
|
||||
% end
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<hr/>
|
||||
<div>
|
||||
<%= content %>
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<%# Provide a link to the home page, unless we're on it. %>
|
||||
<%# I gave the home page route a name, else it's an empty string. %>
|
||||
<% if ('home' ne current_route) { %>
|
||||
<%= link_to("Home" => 'home') %>
|
||||
<% } %>
|
||||
</div>
|
||||
<div>
|
||||
<% if (logname) { %>
|
||||
You are logged in as <%= logname %>.
|
||||
<%= link_to("Logout" => 'logout') %>
|
||||
<% } elsif (current_route ne 'auth') { %>
|
||||
<%= link_to("Login" => 'auth') %>
|
||||
<% } %>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Reference in New Issue