summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Friesel <derf@finalrewind.org>2019-03-07 18:36:11 +0100
committerDaniel Friesel <derf@finalrewind.org>2019-03-07 18:36:11 +0100
commitfd608391164ddc9e55e2f383620d395b43ae99b7 (patch)
treed7718f37e273918933d42f6d488fa70d78f0b1d6
parentba6b517e5b6986609996339eae109bb2c279ee5f (diff)
switch from HTTP Auth to Cookie Auth
-rwxr-xr-xindex.pl446
-rw-r--r--public/static/js/geolocation.js4
-rw-r--r--public/static/js/geolocation.min.js2
-rw-r--r--public/static/js/travelynx-actions.js2
-rw-r--r--public/static/js/travelynx-actions.min.js2
l---------public/static/v11
-rw-r--r--templates/account.html.ep2
-rw-r--r--templates/landingpage.html.ep137
-rw-r--r--templates/layouts/default.html.ep23
-rw-r--r--templates/login.html.ep4
-rw-r--r--templates/register.html.ep4
11 files changed, 286 insertions, 341 deletions
diff --git a/index.pl b/index.pl
index 51eb158..69d1079 100755
--- a/index.pl
+++ b/index.pl
@@ -44,13 +44,10 @@ app->plugin(
authentication => {
autoload_user => 1,
session_key => 'foodor',
+ fail_render => { template => 'login' },
load_user => sub {
my ( $self, $uid ) = @_;
- my $data = $self->get_user_data($uid);
- if ($data) {
- return { name => $data->{name} };
- }
- return undef;
+ return $self->get_user_data($uid);
},
validate_user => sub {
my ( $self, $username, $password, $extradata ) = @_;
@@ -68,6 +65,7 @@ app->plugin(
},
}
);
+app->sessions->default_expiration( 60 * 60 * 24 * 180 );
app->defaults( layout => 'default' );
@@ -427,7 +425,7 @@ helper 'checkin' => sub {
}
my $success = $self->app->checkin_query->execute(
- $self->get_user_id,
+ $self->current_user->{id},
$self->get_station_id(
ds100 => $status->{station_ds100},
name => $status->{station_name}
@@ -457,7 +455,7 @@ helper 'checkin' => sub {
helper 'undo' => sub {
my ($self) = @_;
- my $uid = $self->get_user_id;
+ my $uid = $self->current_user->{id};
$self->app->get_last_actions_query->execute($uid);
my $rows = $self->app->get_last_actions_query->fetchall_arrayref;
@@ -469,10 +467,10 @@ helper 'undo' => sub {
return 'Repeated undo is not supported';
}
- my $success
- = $self->app->undo_query->execute( $self->get_user_id,
+ my $success = $self->app->undo_query->execute(
+ $self->current_user->{id},
DateTime->now( time_zone => 'Europe/Berlin' )->epoch,
- );
+ );
if ( defined $success ) {
return;
@@ -501,7 +499,7 @@ helper 'checkout' => sub {
if ( not defined $train ) {
if ($force) {
my $success = $self->app->checkout_query->execute(
- $self->get_user_id,
+ $self->current_user->{id},
$self->get_station_id(
ds100 => $status->{station_ds100},
name => $status->{station_name}
@@ -523,7 +521,7 @@ helper 'checkout' => sub {
}
else {
my $success = $self->app->checkout_query->execute(
- $self->get_user_id,
+ $self->current_user->{id},
$self->get_station_id(
ds100 => $status->{station_ds100},
name => $status->{station_name}
@@ -580,7 +578,7 @@ helper 'get_user_token' => sub {
helper 'get_user_data' => sub {
my ( $self, $uid ) = @_;
- $uid //= $self->get_user_id;
+ $uid //= $self->current_user->{id};
my $query = $self->app->get_user_query;
$query->execute($uid);
my $rows = $query->fetchall_arrayref;
@@ -603,7 +601,7 @@ helper 'get_user_data' => sub {
deletion_requested => $row[7]
};
}
- return;
+ return undef;
};
helper 'get_user_password' => sub {
@@ -623,80 +621,9 @@ helper 'get_user_password' => sub {
return;
};
-helper 'get_user_name' => sub {
- my ($self) = @_;
-
- my $user = $self->req->headers->header('X-Remote-User') // 'dev';
-
- return $user;
-};
-
-helper 'get_user_id' => sub {
+helper 'add_user' => sub {
my ( $self, $user_name, $email, $token, $password ) = @_;
- $user_name //= $self->get_user_name;
-
- if ( not -e $dbname ) {
- $self->app->dbh->begin_work;
- $self->app->dbh->do(
- qq{
- create table schema_version (
- version integer primary key
- );
- }
- );
- $self->app->dbh->do(
- qq{
- create table users (
- id integer primary key,
- name char(64) not null unique,
- status int not null,
- public_level bool not null,
- email char(256),
- token char(80),
- password text,
- registered_at datetime not null,
- last_login datetime not null,
- deletion_requested datetime
- )
- }
- );
- $self->app->dbh->do(
- qq{
- create table stations (
- id integer primary key,
- ds100 char(16) not null unique,
- name char(64) not null unique
- )
- }
- );
- $self->app->dbh->do(
- qq{
- create table user_actions (
- user_id int not null,
- action_id int not null,
- station_id int,
- action_time int not null,
- train_type char(16),
- train_line char(16),
- train_no char(16),
- train_id char(128),
- sched_time int,
- real_time int,
- route text,
- messages text,
- primary key (user_id, action_time)
- )
- }
- );
- $self->app->dbh->do(
- qq{
- insert into schema_version (version) values (1);
- }
- );
- $self->app->dbh->commit;
- }
-
$self->app->get_userid_query->execute($user_name);
my $rows = $self->app->get_userid_query->fetchall_arrayref;
@@ -737,7 +664,7 @@ helper 'check_if_user_name_exists' => sub {
helper 'get_user_travels' => sub {
my ( $self, $limit ) = @_;
- my $uid = $self->get_user_id;
+ my $uid = $self->current_user->{id};
my $query = $self->app->get_all_actions_query;
if ($limit) {
$query = $self->app->get_last_actions_query;
@@ -800,7 +727,7 @@ helper 'get_user_travels' => sub {
helper 'get_user_status' => sub {
my ($self) = @_;
- my $uid = $self->get_user_id;
+ my $uid = $self->current_user->{id};
$self->app->get_last_actions_query->execute($uid);
my $rows = $self->app->get_last_actions_query->fetchall_arrayref;
@@ -886,176 +813,33 @@ helper 'navbar_class' => sub {
get '/' => sub {
my ($self) = @_;
- $self->render( 'landingpage', with_geolocation => 1 );
-};
-
-post '/action' => sub {
- my ($self) = @_;
- my $params = $self->req->json;
-
- if ( not exists $params->{action} ) {
- $params = $self->req->params->to_hash;
- }
-
- if ( not $params->{action} ) {
- $self->render(
- json => {
- success => 0,
- error => 'Missing action value',
- },
- status => 400,
- );
- return;
- }
-
- my $station = $params->{station};
-
- if ( $params->{action} eq 'checkin' ) {
-
- my ( $train, $error )
- = $self->checkin( $params->{station}, $params->{train}, );
-
- if ($error) {
- $self->render(
- json => {
- success => 0,
- error => $error,
- },
- );
- }
- else {
- $self->render(
- json => {
- success => 1,
- },
- );
- }
- }
- elsif ( $params->{action} eq 'checkout' ) {
- my $error = $self->checkout( $params->{station}, $params->{force}, );
-
- if ($error) {
- $self->render(
- json => {
- success => 0,
- error => $error,
- },
- );
- }
- else {
- $self->render(
- json => {
- success => 1,
- },
- );
- }
- }
- elsif ( $params->{action} eq 'undo' ) {
- my $error = $self->undo;
- if ($error) {
- $self->render(
- json => {
- success => 0,
- error => $error,
- },
- );
- }
- else {
- $self->render(
- json => {
- success => 1,
- },
- );
- }
+ if ( $self->is_user_authenticated ) {
+ $self->render( 'landingpage', with_geolocation => 1 );
}
else {
- $self->render(
- json => {
- success => 0,
- error => 'invalid action value',
- },
- status => 400,
- );
- }
-};
-
-get '/a/account' => sub {
- my ($self) = @_;
-
- $self->render('account');
-};
-
-get '/a/export.json' => sub {
- my ($self) = @_;
- my $uid = $self->get_user_id;
- my $query = $self->app->get_all_actions_query;
-
- $query->execute($uid);
-
- my @entries;
-
- while ( my @row = $query->fetchrow_array ) {
- my (
- $action, $raw_ts, $ds100, $name,
- $train_type, $train_line, $train_no, $train_id,
- $raw_sched_ts, $raw_real_ts, $raw_route, $raw_messages
- ) = @row;
-
- $name = decode( 'UTF-8', $name );
- $raw_route = decode( 'UTF-8', $raw_route );
- $raw_messages = decode( 'UTF-8', $raw_messages );
- push(
- @entries,
- {
- action => $action_types[ $action - 1 ],
- action_ts => $raw_ts,
- station_ds100 => $ds100,
- station_name => $name,
- train_type => $train_type,
- train_line => $train_line,
- train_no => $train_no,
- train_id => $train_id,
- scheduled_ts => $raw_sched_ts,
- realtime_ts => $raw_real_ts,
- messages => $raw_messages
- ? [ map { [ split(qr{:}) ] } split( qr{[|]}, $raw_messages ) ]
- : undef,
- route => $raw_route ? [ split( qr{[|]}, $raw_route ) ]
- : undef,
- }
- );
+ $self->render( 'landingpage', intro => 1 );
}
-
- $self->render(
- json => [@entries],
- );
};
-get '/a/history' => sub {
- my ($self) = @_;
-
- $self->render('history');
-};
-
-get '/x/about' => sub {
+get '/about' => sub {
my ($self) = @_;
$self->render( 'about', version => $VERSION );
};
-get '/x/impressum' => sub {
+get '/impressum' => sub {
my ($self) = @_;
$self->render('imprint');
};
-get '/x/imprint' => sub {
+get '/imprint' => sub {
my ($self) = @_;
$self->render('imprint');
};
-post '/x/geolocation' => sub {
+post '/geolocation' => sub {
my ($self) = @_;
my $lon = $self->param('lon');
@@ -1085,12 +869,12 @@ post '/x/geolocation' => sub {
};
-get '/x/login' => sub {
+get '/login' => sub {
my ($self) = @_;
$self->render('login');
};
-post '/x/login' => sub {
+post '/login' => sub {
my ($self) = @_;
my $user = $self->req->param('user');
my $password = $self->req->param('password');
@@ -1114,18 +898,12 @@ post '/x/login' => sub {
}
};
-get '/x/logout' => sub {
- my ($self) = @_;
- $self->logout;
- $self->redirect_to('/x/login');
-};
-
-get '/x/register' => sub {
+get '/register' => sub {
my ($self) = @_;
$self->render('register');
};
-post '/x/register' => sub {
+post '/register' => sub {
my ($self) = @_;
my $user = $self->req->param('user');
my $email = $self->req->param('email');
@@ -1163,8 +941,7 @@ post '/x/register' => sub {
return;
}
- #if ( $self->check_if_user_name_exists($user) or $user eq 'dev' ) {
- if ( $user ne $self->get_user_name ) {
+ if ( $self->check_if_user_name_exists($user) ) {
$self->render( 'register', invalid => 'user_collision' );
return;
}
@@ -1181,14 +958,14 @@ post '/x/register' => sub {
my $token = make_token();
my $pw_hash = hash_password($password);
- my $user_id = $self->get_user_id( $user, $email, $token, $pw_hash );
+ my $user_id = $self->add_user( $user, $email, $token, $pw_hash );
my $body = "Hallo, ${user}!\n\n";
$body .= "Mit deiner E-Mail-Adresse (${email}) wurde ein Account auf\n";
$body .= "travelynx.finalrewind.org angelegt.\n\n";
$body
.= "Falls die Registrierung von dir ausging, kannst du den Account unter\n";
- $body .= "https://travelynx.finalrewind.org/x/reg/${user_id}/${token}\n";
+ $body .= "https://travelynx.finalrewind.org/reg/${user_id}/${token}\n";
$body .= "freischalten.\n\n";
$body
.= "Falls nicht, ignoriere diese Mail bitte. Nach 48 Stunden wird deine\n";
@@ -1200,7 +977,7 @@ post '/x/register' => sub {
$body .= " * Datum: ${date}\n";
$body .= " * Verwendete IP: ${ip}\n";
$body .= " * Verwendeter Browser gemäß User Agent: ${ua}\n\n\n";
- $body .= "Impressum: https://travelynx.finalrewind.org/x/impressum\n";
+ $body .= "Impressum: https://travelynx.finalrewind.org/impressum\n";
my $reg_mail = Email::Simple->create(
header => [
@@ -1221,7 +998,7 @@ post '/x/register' => sub {
}
};
-get '/x/reg/:id/:token' => sub {
+get '/reg/:id/:token' => sub {
my ($self) = @_;
my $id = $self->stash('id');
@@ -1244,7 +1021,166 @@ get '/x/reg/:id/:token' => sub {
$self->render( 'login', from => 'verification' );
};
-get '/*station' => sub {
+under sub {
+ my ($self) = @_;
+ return $self->is_user_authenticated;
+};
+
+post '/action' => sub {
+ my ($self) = @_;
+ my $params = $self->req->json;
+
+ if ( not exists $params->{action} ) {
+ $params = $self->req->params->to_hash;
+ }
+
+ if ( not $params->{action} ) {
+ $self->render(
+ json => {
+ success => 0,
+ error => 'Missing action value',
+ },
+ status => 400,
+ );
+ return;
+ }
+
+ my $station = $params->{station};
+
+ if ( $params->{action} eq 'checkin' ) {
+
+ my ( $train, $error )
+ = $self->checkin( $params->{station}, $params->{train}, );
+
+ if ($error) {
+ $self->render(
+ json => {
+ success => 0,
+ error => $error,
+ },
+ );
+ }
+ else {
+ $self->render(
+ json => {
+ success => 1,
+ },
+ );
+ }
+ }
+ elsif ( $params->{action} eq 'checkout' ) {
+ my $error = $self->checkout( $params->{station}, $params->{force}, );
+
+ if ($error) {
+ $self->render(
+ json => {
+ success => 0,
+ error => $error,
+ },
+ );
+ }
+ else {
+ $self->render(
+ json => {
+ success => 1,
+ },
+ );
+ }
+ }
+ elsif ( $params->{action} eq 'undo' ) {
+ my $error = $self->undo;
+ if ($error) {
+ $self->render(
+ json => {
+ success => 0,
+ error => $error,
+ },
+ );
+ }
+ else {
+ $self->render(
+ json => {
+ success => 1,
+ },
+ );
+ }
+ }
+ else {
+ $self->render(
+ json => {
+ success => 0,
+ error => 'invalid action value',
+ },
+ status => 400,
+ );
+ }
+};
+
+get '/account' => sub {
+ my ($self) = @_;
+
+ $self->render('account');
+};
+
+get '/history' => sub {
+ my ($self) = @_;
+
+ $self->render('history');
+};
+
+get '/export.json' => sub {
+ my ($self) = @_;
+ my $uid = $self->current_user->{id};
+ my $query = $self->app->get_all_actions_query;
+
+ $query->execute($uid);
+
+ my @entries;
+
+ while ( my @row = $query->fetchrow_array ) {
+ my (
+ $action, $raw_ts, $ds100, $name,
+ $train_type, $train_line, $train_no, $train_id,
+ $raw_sched_ts, $raw_real_ts, $raw_route, $raw_messages
+ ) = @row;
+
+ $name = decode( 'UTF-8', $name );
+ $raw_route = decode( 'UTF-8', $raw_route );
+ $raw_messages = decode( 'UTF-8', $raw_messages );
+ push(
+ @entries,
+ {
+ action => $action_types[ $action - 1 ],
+ action_ts => $raw_ts,
+ station_ds100 => $ds100,
+ station_name => $name,
+ train_type => $train_type,
+ train_line => $train_line,
+ train_no => $train_no,
+ train_id => $train_id,
+ scheduled_ts => $raw_sched_ts,
+ realtime_ts => $raw_real_ts,
+ messages => $raw_messages
+ ? [ map { [ split(qr{:}) ] } split( qr{[|]}, $raw_messages ) ]
+ : undef,
+ route => $raw_route ? [ split( qr{[|]}, $raw_route ) ]
+ : undef,
+ }
+ );
+ }
+
+ $self->render(
+ json => [@entries],
+ );
+};
+
+post '/logout' => sub {
+ my ($self) = @_;
+ $self->logout;
+ $self->redirect_to('/login');
+};
+
+get '/s/*station' => sub {
my ($self) = @_;
my $station = $self->stash('station');
diff --git a/public/static/js/geolocation.js b/public/static/js/geolocation.js
index 1c881e2..caf2a2a 100644
--- a/public/static/js/geolocation.js
+++ b/public/static/js/geolocation.js
@@ -25,14 +25,14 @@ $(document).ready(function() {
stationlink.attr('href', ds100);
stationlink.text(name);
- resultBody.append('<tr><td><a href="/' + ds100 + '">' + name + '</a></td></tr>');
+ resultBody.append('<tr><td><a href="/s/' + ds100 + '">' + name + '</a></td></tr>');
});
placeholder.replaceWith(resultTable);
}
};
var processLocation = function(loc) {
- $.post('/x/geolocation', {lon: loc.coords.longitude, lat: loc.coords.latitude}, processResult);
+ $.post('/geolocation', {lon: loc.coords.longitude, lat: loc.coords.latitude}, processResult);
};
var processError = function(error) {
diff --git a/public/static/js/geolocation.min.js b/public/static/js/geolocation.min.js
index 50cd010..1bd2c77 100644
--- a/public/static/js/geolocation.min.js
+++ b/public/static/js/geolocation.min.js
@@ -1 +1 @@
-$(document).ready(function(){var e=$("p.geolocationhint"),t=$("div.geolocation div.progress"),o=function(o,a,n){e.remove(),t.remove()},a=function(e){e.error?o(0,e.error):0==e.candidates.length?o():(resultTable=$("<table><tbody></tbody></table>"),resultBody=resultTable.children(),$.each(e.candidates,function(e,t){var o=t.ds100,a=t.name,n=t.distance;n=n.toFixed(1);var r=$(document.createElement("a"));r.attr("href",o),r.text(a),resultBody.append('<tr><td><a href="/'+o+'">'+a+"</a></td></tr>")}),t.replaceWith(resultTable))},n=function(e){$.post("/x/geolocation",{lon:e.coords.longitude,lat:e.coords.latitude},a)},r=function(e){e.code==e.PERMISSION_DENIED?o():e.code==e.POSITION_UNAVAILABLE?o():(e.code,e.TIMEOUT,o())};navigator.geolocation?navigator.geolocation.getCurrentPosition(n,r):o()});
+$(document).ready(function(){var a=$("p.geolocationhint"),n=$("div.geolocation div.progress"),t=function(e,t,o){a.remove(),n.remove()},o=function(e){e.error?t(0,e.error):0==e.candidates.length?t():(resultTable=$("<table><tbody></tbody></table>"),resultBody=resultTable.children(),$.each(e.candidates,function(e,t){var o=t.ds100,a=t.name,n=t.distance;n=n.toFixed(1);var r=$(document.createElement("a"));r.attr("href",o),r.text(a),resultBody.append('<tr><td><a href="/s/'+o+'">'+a+"</a></td></tr>")}),n.replaceWith(resultTable))};navigator.geolocation?navigator.geolocation.getCurrentPosition(function(e){$.post("/geolocation",{lon:e.coords.longitude,lat:e.coords.latitude},o)},function(e){e.code==e.PERMISSION_DENIED||e.code==e.POSITION_UNAVAILABLE||(e.code,e.TIMEOUT),t()}):t()});
diff --git a/public/static/js/travelynx-actions.js b/public/static/js/travelynx-actions.js
index d758a1a..0a3d092 100644
--- a/public/static/js/travelynx-actions.js
+++ b/public/static/js/travelynx-actions.js
@@ -34,7 +34,7 @@ $(document).ready(function() {
station: link.data('station'),
force: link.data('force'),
};
- tvly_run(link, req, '/' + req.station, function() {
+ tvly_run(link, req, '/s/' + req.station, function() {
link.append(' – Ohne Echtzeitdaten auschecken?')
link.data('force', true);
});
diff --git a/public/static/js/travelynx-actions.min.js b/public/static/js/travelynx-actions.min.js
index 156c458..9c37d8d 100644
--- a/public/static/js/travelynx-actions.min.js
+++ b/public/static/js/travelynx-actions.min.js
@@ -1 +1 @@
-function tvly_run(n,t,i,a){var c='<i class="material-icons">error</i>',o=$('<div class="progress"><div class="indeterminate"></div></div>');n.hide(),n.after(o),$.post("/action",t,function(t){t.success?$(location).attr("href",i):(M.toast({html:c+" "+t.error}),o.remove(),a&&a(),n.append(" "+c),n.show())})}$(document).ready(function(){$(".action-checkin").click(function(){var t=$(this);tvly_run(t,{action:"checkin",station:t.data("station"),train:t.data("train")},"/")}),$(".action-checkout").click(function(){var t=$(this),n={action:"checkout",station:t.data("station"),force:t.data("force")};tvly_run(t,n,"/"+n.station,function(){t.append(" – Ohne Echtzeitdaten auschecken?"),t.data("force",!0)})}),$(".action-undo").click(function(){tvly_run($(this),{action:"undo"},window.location.href)})});
+function tvly_run(n,t,i,a){var c='<i class="material-icons">error</i>',o=$('<div class="progress"><div class="indeterminate"></div></div>');n.hide(),n.after(o),$.post("/action",t,function(t){t.success?$(location).attr("href",i):(M.toast({html:c+" "+t.error}),o.remove(),a&&a(),n.append(" "+c),n.show())})}$(document).ready(function(){$(".action-checkin").click(function(){var t=$(this);tvly_run(t,{action:"checkin",station:t.data("station"),train:t.data("train")},"/")}),$(".action-checkout").click(function(){var t=$(this),n={action:"checkout",station:t.data("station"),force:t.data("force")};tvly_run(t,n,"/s/"+n.station,function(){t.append(" – Ohne Echtzeitdaten auschecken?"),t.data("force",!0)})}),$(".action-undo").click(function(){tvly_run($(this),{action:"undo"},window.location.href)})});
diff --git a/public/static/v1 b/public/static/v1
new file mode 120000
index 0000000..945c9b4
--- /dev/null
+++ b/public/static/v1
@@ -0,0 +1 @@
+. \ No newline at end of file
diff --git a/templates/account.html.ep b/templates/account.html.ep
index 9c3a435..c3f24f8 100644
--- a/templates/account.html.ep
+++ b/templates/account.html.ep
@@ -22,7 +22,7 @@
<div class="row">
<div class="col s12">
<ul>
- <li><a href="/a/export.json">Rohdaten</a> (Kein API-Ersatz, das Format kann sich jederzeit ändern)</li>
+ <li><a href="/export.json">Rohdaten</a> (Kein API-Ersatz, das Format kann sich jederzeit ändern)</li>
</ul>
</div>
</div>
diff --git a/templates/landingpage.html.ep b/templates/landingpage.html.ep
index 00a67cc..4c6a8f2 100644
--- a/templates/landingpage.html.ep
+++ b/templates/landingpage.html.ep
@@ -1,72 +1,77 @@
-<div class="row">
- <div class="col s12">
- % my $status = $self->get_user_status;
- % if ($status->{checked_in}) {
- <div class="card green darken-4">
- <div class="card-content white-text">
- <span class="card-title">Hallo, <%= $self->get_user_name %>!</span>
- <p>Du bist gerade eingecheckt in
- <%= $status->{train_type} %> <%= $status->{train_no} %>
- ab <%= $status->{station_name} %>.
- % if ($status->{timestamp_delta} < 3600) {
- <a class="action-undo"><i class="material-icons">undo</i> Rückgängig</a>
- % }
- </p>
- <p>Auschecken?</p>
- <table>
- <tbody>
- % my $is_after = 0;
- % for my $station (@{$status->{route_after}}) {
- <tr><td><a class="action-checkout" data-station="<%= $station %>"><%= $station %></a></td></tr>
+% if (is_user_authenticated()) {
+ <div class="row">
+ <div class="col s12">
+ % my $status = get_user_status();
+ % if ($status->{checked_in}) {
+ <div class="card green darken-4">
+ <div class="card-content white-text">
+ <span class="card-title">Hallo, <%= current_user()->{name} %>!</span>
+ <p>Du bist gerade eingecheckt in
+ <%= $status->{train_type} %> <%= $status->{train_no} %>
+ ab <%= $status->{station_name} %>.
+ % if ($status->{timestamp_delta} < 3600) {
+ <a class="action-undo"><i class="material-icons">undo</i> Rückgängig</a>
% }
- </tbody>
- </table>
+ </p>
+ <p>Auschecken?</p>
+ <table>
+ <tbody>
+ % my $is_after = 0;
+ % for my $station (@{$status->{route_after}}) {
+ <tr><td><a class="action-checkout" data-station="<%= $station %>"><%= $station %></a></td></tr>
+ % }
+ </tbody>
+ </table>
+ </div>
</div>
- </div>
- % }
- % else {
- <div class="card grey darken-4">
- <div class="card-content white-text">
- <span class="card-title">Hallo, <%= $self->get_user_name %>!</span>
- <p>Du bist gerade nicht eingecheckt.</p>
- <p class="geolocationhint">Stationen in der Umgebung:</p>
- <div class="geolocation">
- <div class="progress"><div class="indeterminate"></div></div>
+ % }
+ % else {
+ <div class="card grey darken-4">
+ <div class="card-content white-text">
+ <span class="card-title">Hallo, <%= current_user()->{name} %>!</span>
+ <p>Du bist gerade nicht eingecheckt.</p>
+ <p class="geolocationhint">Stationen in der Umgebung:</p>
+ <div class="geolocation">
+ <div class="progress"><div class="indeterminate"></div></div>
+ </div>
</div>
</div>
- </div>
- % }
+ % }
+ </div>
</div>
-</div>
-<h1>Letzte Fahrten</h1>
-<div class="row">
- <table class="striped">
- <thead>
- <tr>
- <th>Datum</th>
- <th>Zug</th>
- <th>Strecke</th>
- <th>Dauer</th>
- </tr>
- </thead>
- <tbody>
- % for my $travel (get_user_travels(1)) {
- % if ($travel->{completed}) {
- <tr>
- <td><%= $travel->{sched_departure}->strftime('%d.%m.%Y') %></td>
- <td><%= $travel->{type} %> <%= $travel->{line} // $travel->{no} %></td>
- <td><%= $travel->{from_name} %> → <%= $travel->{to_name} %></td>
- % if ($travel->{rt_arrival}->epoch and $travel->{rt_departure}->epoch) {
- <td><%= ($travel->{rt_arrival}->epoch - $travel->{rt_departure}->epoch) / 60 %> min
- </td>
- % } else {
- <td><%= sprintf('%.f', $self->get_travel_distance($travel->{from_name}, $travel->{to_name}, $travel->{route})) %>km
- <i class="material-icons">timer_off</i>
- </td>
- % }
- </tr>
+ <h1>Letzte Fahrten</h1>
+ <div class="row">
+ <table class="striped">
+ <thead>
+ <tr>
+ <th>Datum</th>
+ <th>Zug</th>
+ <th>Strecke</th>
+ <th>Dauer</th>
+ </tr>
+ </thead>
+ <tbody>
+ % for my $travel (get_user_travels(1)) {
+ % if ($travel->{completed}) {
+ <tr>
+ <td><%= $travel->{sched_departure}->strftime('%d.%m.%Y') %></td>
+ <td><%= $travel->{type} %> <%= $travel->{line} // $travel->{no} %></td>
+ <td><%= $travel->{from_name} %> → <%= $travel->{to_name} %></td>
+ % if ($travel->{rt_arrival}->epoch and $travel->{rt_departure}->epoch) {
+ <td><%= ($travel->{rt_arrival}->epoch - $travel->{rt_departure}->epoch) / 60 %> min
+ </td>
+ % } else {
+ <td><%= sprintf('%.f', $self->get_travel_distance($travel->{from_name}, $travel->{to_name}, $travel->{route})) %>km
+ <i class="material-icons">timer_off</i>
+ </td>
+ % }
+ </tr>
+ % }
% }
- % }
- </tbody>
- </tabel>
-</div>
+ </tbody>
+ </tabel>
+ </div>
+% }
+% else {
+Huhu!
+% }
diff --git a/templates/layouts/default.html.ep b/templates/layouts/default.html.ep
index cbe06e3..3fdb075 100644
--- a/templates/layouts/default.html.ep
+++ b/templates/layouts/default.html.ep
@@ -5,14 +5,15 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="#673ab7">
- %= stylesheet '/static/css/materialize.min.css'
- %= stylesheet '/static/css/material-icons.css'
- %= stylesheet '/static/css/local.css'
- %= javascript '/static/js/jquery-2.2.4.min.js'
- %= javascript '/static/js/materialize.min.js'
- %= javascript '/static/js/travelynx-actions.min.js'
+ % my $av = 'v1'; # asset version
+ %= stylesheet "/static/${av}/css/materialize.min.css"
+ %= stylesheet "/static/${av}/css/material-icons.css"
+ %= stylesheet "/static/${av}/css/local.css"
+ %= javascript "/static/${av}/js/jquery-2.2.4.min.js"
+ %= javascript "/static/${av}/js/materialize.min.js"
+ %= javascript "/static/${av}/js/travelynx-actions.min.js"
% if (stash('with_geolocation')) {
- %= javascript '/static/js/geolocation.min.js'
+ %= javascript "/static/${av}/js/geolocation.min.js"
% }
</head>
<body>
@@ -21,9 +22,11 @@
<div class="nav-wrapper container">
<a href="/" class="brand-logo left">travelynx</a>
<ul id="nav-mobile" class="right">
- <li class="<%= navbar_class('/a/history') %>"><a href='/a/history' title="History"><i class="material-icons">history</i></a></li>
- <li class="<%= navbar_class('/a/account') %>"><a href="/a/account" title="Account"><i class="material-icons">account_circle</i></a></li>
- <li class="<%= navbar_class('/x/about') %>"><a href='/x/about' title="About"><i class="material-icons">info_outline</i></a></li>
+ % if (is_user_authenticated()) {
+ <li class="<%= navbar_class('/history') %>"><a href='/history' title="History"><i class="material-icons">history</i></a></li>
+ <li class="<%= navbar_class('/account') %>"><a href="/account" title="Account"><i class="material-icons">account_circle</i></a></li>
+ % }
+ <li class="<%= navbar_class('/about') %>"><a href='/about' title="About"><i class="material-icons">info_outline</i></a></li>
</ul>
</div>
</nav>
diff --git a/templates/login.html.ep b/templates/login.html.ep
index 37afacc..f85ba91 100644
--- a/templates/login.html.ep
+++ b/templates/login.html.ep
@@ -7,7 +7,7 @@
<p>
Du bist bereits angemeldet. Falls du mehrere Accounts hast
und auf einen anderen wechseln möchtest, musst du dich
- vorher <a href="/x/logout">abmelden</a>.
+ vorher <a href="/logout">abmelden</a>.
</p>
</div>
</div>
@@ -64,7 +64,7 @@
</div>
% }
<div class="row">
- %= form_for '/x/login' => (class => 'col s12', method => 'POST') => begin
+ %= form_for '/login' => (class => 'col s12', method => 'POST') => begin
%= csrf_field
<div class="row">
<div class="input-field col s12">
diff --git a/templates/register.html.ep b/templates/register.html.ep
index a227e6f..d1e189d 100644
--- a/templates/register.html.ep
+++ b/templates/register.html.ep
@@ -59,7 +59,7 @@
</div>
% }
<div class="row">
- %= form_for '/x/register' => (class => 'col s12', method => 'POST') => begin
+ %= form_for '/register' => (class => 'col s12', method => 'POST') => begin
%= csrf_field
<div class="row">
<div class="input-field col l6 m12 s12">
@@ -103,7 +103,7 @@
Die Mail-Adresse wird ausschließlich zur Bestätigung der Anmeldung
und für die "Passwort vergessen"-Funktionalität verwendet und nicht
an Dritte weitergegeben. Die <a
- href="/x/impressum">Datenschutzerklärung</a> beschreibt weitere
+ href="/impressum">Datenschutzerklärung</a> beschreibt weitere
erhobene Daten sowie deren Zweck und Speicherfristen.
Accounts werden nach einem Jahr ohne Nutzung automatisch gelöscht.
</p>