Loading lib/Travelynx.pm +11 −1 Original line number Diff line number Diff line Loading @@ -583,7 +583,8 @@ qq{select * from pending_mails where email = ? and num_tries > 1;} elsif ( $user->{cancelled} ) { # Same $self->checkout($station, 1, $self->app->action_type->{cancelled_to}); $self->checkout( $station, 1, $self->app->action_type->{cancelled_to} ); } my $success = $self->app->action_query->execute( Loading Loading @@ -876,6 +877,13 @@ qq{select * from pending_mails where email = ? and num_tries > 1;} } ); $self->helper( 'set_user_password' => sub { my ( $self, $uid, $password ) = @_; $self->app->set_password_query->execute( $password, $uid ); } ); $self->helper( 'check_if_user_name_exists' => sub { my ( $self, $user_name ) = @_; Loading Loading @@ -1322,12 +1330,14 @@ qq{select * from pending_mails where email = ? and num_tries > 1;} ); $authed_r->get('/account')->to('account#account'); $authed_r->get('/change_password')->to('account#password_form'); $authed_r->get('/export.json')->to('account#json_export'); $authed_r->get('/history')->to('traveling#history'); $authed_r->get('/history/:year/:month')->to('traveling#monthly_history'); $authed_r->get('/history.json')->to('traveling#json_history'); $authed_r->get('/journey/:id')->to('traveling#journey_details'); $authed_r->get('/s/*station')->to('traveling#station'); $authed_r->post('/change_password')->to('account#change_password'); $authed_r->post('/delete')->to('account#delete'); $authed_r->post('/logout')->to('account#do_logout'); $authed_r->post('/set_token')->to('api#set_token'); Loading lib/Travelynx/Controller/Account.pm +75 −6 Original line number Diff line number Diff line Loading @@ -136,11 +136,12 @@ sub register { .= "werden wir sie dauerhaft sperren und keine Mails mehr dorthin schicken.\n\n"; $body .= "Daten zur Registrierung:\n"; $body .= " * Datum: ${date}\n"; $body .= " * Verwendete IP: ${ip}\n"; $body .= " * Verwendeter Browser gemäß User Agent: ${ua}\n\n\n"; $body .= " * Client: ${ip}\n"; $body .= " * UserAgent: ${ua}\n\n\n"; $body .= "Impressum: ${imprint_url}\n"; my $success = $self->sendmail->custom($email, 'Registrierung bei travelynx', $body); my $success = $self->sendmail->custom( $email, 'Registrierung bei travelynx', $body ); if ($success) { $self->app->dbh->commit; $self->render( 'login', from => 'register' ); Loading Loading @@ -214,6 +215,73 @@ sub do_logout { $self->redirect_to('/login'); } sub password_form { my ($self) = @_; $self->render('change_password'); } sub change_password { my ($self) = @_; my $old_password = $self->req->param('oldpw'); my $password = $self->req->param('newpw'); my $password2 = $self->req->param('newpw2'); if ( $self->validation->csrf_protect->has_error('csrf_token') ) { $self->render( 'change_password', invalid => 'csrf' ); return; } if ( $password ne $password2 ) { $self->render( 'change_password', invalid => 'password_notequal' ); return; } if ( length($password) < 8 ) { $self->render( 'change_password', invalid => 'password_short' ); return; } if ( not $self->authenticate( $self->current_user->{name}, $self->param('oldpw') ) ) { $self->render( 'change_password', invalid => 'password' ); return; } my $pw_hash = hash_password($password); $self->set_user_password( $self->current_user->{id}, $pw_hash ); $self->redirect_to('account'); my $user = $self->current_user->{name}; my $email = $self->current_user->{email}; my $ip = $self->req->headers->header('X-Forwarded-For'); my $ua = $self->req->headers->user_agent; my $date = DateTime->now( time_zone => 'Europe/Berlin' ) ->strftime('%d.%m.%Y %H:%M:%S %z'); # In case Mojolicious is not running behind a reverse proxy $ip //= sprintf( '%s:%s', $self->tx->remote_address, $self->tx->remote_port ); my $imprint_url = $self->url_for('impressum')->to_abs->scheme('https'); my $body = "Hallo ${user},\n\n"; $body .= "Das Passwort deines travelynx-Accounts wurde soeben geändert.\n\n"; $body .= "Daten zur Änderung:\n"; $body .= " * Datum: ${date}\n"; $body .= " * Client: ${ip}\n"; $body .= " * UserAgent: ${ua}\n\n\n"; $body .= "Impressum: ${imprint_url}\n"; $self->sendmail->custom( $email, 'travelynx: Passwort geändert', $body ); } sub account { my ($self) = @_; Loading @@ -231,9 +299,10 @@ sub json_export { while ( my @row = $query->fetchrow_array ) { my ( $action_id, $action, $raw_ts, $ds100, $name, $train_type, $train_line, $train_no, $train_id, $raw_sched_ts, $raw_real_ts, $raw_route, $raw_messages $action_id, $action, $raw_ts, $ds100, $name, $train_type, $train_line, $train_no, $train_id, $raw_sched_ts, $raw_real_ts, $raw_route, $raw_messages ) = @row; push( Loading templates/account.html.ep +5 −5 Original line number Diff line number Diff line Loading @@ -38,6 +38,10 @@ <th scope="row">Mail</th> <td><%= $acc->{email} %></td> </tr> <tr> <th scope="row">Passwort</th> <td><a href="/change_password" class="waves-effect waves-light btn">ändern</a></td> </tr> <tr> <th scope="row">Registriert am</th> <td><%= $acc->{registered_at}->strftime('%d.%m.%Y %H:%M') %></td> Loading @@ -46,9 +50,7 @@ </div> </div> <div class="row"> <div class="col s1 m1 l3"> </div> <div class="col s10 m10 l6 center-align"> <div class="col s12 m12 l12 center-align"> %= form_for 'logout' => begin %= csrf_field <button class="btn waves-effect waves-light" type="submit" name="action" value="logout"> Loading @@ -56,8 +58,6 @@ </button> %= end </div> <div class="col s1 m1 l3"> </div> </div> % my $token = get_api_token(); Loading templates/change_password.html.ep 0 → 100644 +69 −0 Original line number Diff line number Diff line % if (my $invalid = stash('invalid')) { <div class="row"> <div class="col s12"> <div class="card red darken-4"> <div class="card-content white-text"> % if ($invalid eq 'csrf') { <span class="card-title">Ungültiger CSRF-Token</span> <p>Sind Cookies aktiviert? Ansonsten könnte es sich um einen Fall von <a href="https://de.wikipedia.org/wiki/Cross-Site-Request-Forgery">CSRF</a> handeln.</p> % } % elsif ($invalid eq 'password_notequal') { <span class="card-title">Passwort ungültig</span> <p>Die angegebenen neuen Passwörter sind nicht identisch.</p> % } % elsif ($invalid eq 'password_short') { <span class="card-title">Passwort zu kurz</span> <p>Das neue Passwort muss mindestens acht Zeichen lang sein.</p> % } % elsif ($invalid eq 'password') { <span class="card-title">Ungültiges Passwort</span> <p>Das aktuelle Passwort wurde nicht korrekt eingegeben.</p> % } % else { <span class="card-title">Unbekannter Fehler</span> <p>„<%= $invalid %>“</p> % } </div> </div> </div> </div> % } <h1>Passwort ändern</h1> %= form_for '/change_password' => (method => 'POST') => begin %= csrf_field <div class="row"> <div class="input-field col s12"> <i class="material-icons prefix">lock</i> %= password_field 'oldpw', id => 'oldpassword', class => 'validate', required => undef, autocomplete => 'current-password' <label for="oldpassword">Aktuelles Passwort</label> </div> </div> <div class="row"> <div class="input-field col l6 m12 s12"> <i class="material-icons prefix">lock</i> %= password_field 'newpw', id => 'password', class => 'validate', required => undef, minlength => 8, autocomplete => 'new-password' <label for="password">Neues Passwort</label> </div> <div class="input-field col l6 m12 s12"> <i class="material-icons prefix">lock</i> %= password_field 'newpw2', id => 'password2', class => 'validate', required => undef, minlength => 8, autocomplete => 'new-password' <label for="password2">Passwort wiederholen</label> </div> </div> <div class="row"> <div class="col s3 m3 l3"> </div> <div class="col s6 m6 l6 center-align"> <button class="btn waves-effect waves-light" type="submit" name="action" value="login"> Ändern <i class="material-icons right">send</i> </button> </div> <div class="col s3 m3 l3"> </div> </div> %= end Loading
lib/Travelynx.pm +11 −1 Original line number Diff line number Diff line Loading @@ -583,7 +583,8 @@ qq{select * from pending_mails where email = ? and num_tries > 1;} elsif ( $user->{cancelled} ) { # Same $self->checkout($station, 1, $self->app->action_type->{cancelled_to}); $self->checkout( $station, 1, $self->app->action_type->{cancelled_to} ); } my $success = $self->app->action_query->execute( Loading Loading @@ -876,6 +877,13 @@ qq{select * from pending_mails where email = ? and num_tries > 1;} } ); $self->helper( 'set_user_password' => sub { my ( $self, $uid, $password ) = @_; $self->app->set_password_query->execute( $password, $uid ); } ); $self->helper( 'check_if_user_name_exists' => sub { my ( $self, $user_name ) = @_; Loading Loading @@ -1322,12 +1330,14 @@ qq{select * from pending_mails where email = ? and num_tries > 1;} ); $authed_r->get('/account')->to('account#account'); $authed_r->get('/change_password')->to('account#password_form'); $authed_r->get('/export.json')->to('account#json_export'); $authed_r->get('/history')->to('traveling#history'); $authed_r->get('/history/:year/:month')->to('traveling#monthly_history'); $authed_r->get('/history.json')->to('traveling#json_history'); $authed_r->get('/journey/:id')->to('traveling#journey_details'); $authed_r->get('/s/*station')->to('traveling#station'); $authed_r->post('/change_password')->to('account#change_password'); $authed_r->post('/delete')->to('account#delete'); $authed_r->post('/logout')->to('account#do_logout'); $authed_r->post('/set_token')->to('api#set_token'); Loading
lib/Travelynx/Controller/Account.pm +75 −6 Original line number Diff line number Diff line Loading @@ -136,11 +136,12 @@ sub register { .= "werden wir sie dauerhaft sperren und keine Mails mehr dorthin schicken.\n\n"; $body .= "Daten zur Registrierung:\n"; $body .= " * Datum: ${date}\n"; $body .= " * Verwendete IP: ${ip}\n"; $body .= " * Verwendeter Browser gemäß User Agent: ${ua}\n\n\n"; $body .= " * Client: ${ip}\n"; $body .= " * UserAgent: ${ua}\n\n\n"; $body .= "Impressum: ${imprint_url}\n"; my $success = $self->sendmail->custom($email, 'Registrierung bei travelynx', $body); my $success = $self->sendmail->custom( $email, 'Registrierung bei travelynx', $body ); if ($success) { $self->app->dbh->commit; $self->render( 'login', from => 'register' ); Loading Loading @@ -214,6 +215,73 @@ sub do_logout { $self->redirect_to('/login'); } sub password_form { my ($self) = @_; $self->render('change_password'); } sub change_password { my ($self) = @_; my $old_password = $self->req->param('oldpw'); my $password = $self->req->param('newpw'); my $password2 = $self->req->param('newpw2'); if ( $self->validation->csrf_protect->has_error('csrf_token') ) { $self->render( 'change_password', invalid => 'csrf' ); return; } if ( $password ne $password2 ) { $self->render( 'change_password', invalid => 'password_notequal' ); return; } if ( length($password) < 8 ) { $self->render( 'change_password', invalid => 'password_short' ); return; } if ( not $self->authenticate( $self->current_user->{name}, $self->param('oldpw') ) ) { $self->render( 'change_password', invalid => 'password' ); return; } my $pw_hash = hash_password($password); $self->set_user_password( $self->current_user->{id}, $pw_hash ); $self->redirect_to('account'); my $user = $self->current_user->{name}; my $email = $self->current_user->{email}; my $ip = $self->req->headers->header('X-Forwarded-For'); my $ua = $self->req->headers->user_agent; my $date = DateTime->now( time_zone => 'Europe/Berlin' ) ->strftime('%d.%m.%Y %H:%M:%S %z'); # In case Mojolicious is not running behind a reverse proxy $ip //= sprintf( '%s:%s', $self->tx->remote_address, $self->tx->remote_port ); my $imprint_url = $self->url_for('impressum')->to_abs->scheme('https'); my $body = "Hallo ${user},\n\n"; $body .= "Das Passwort deines travelynx-Accounts wurde soeben geändert.\n\n"; $body .= "Daten zur Änderung:\n"; $body .= " * Datum: ${date}\n"; $body .= " * Client: ${ip}\n"; $body .= " * UserAgent: ${ua}\n\n\n"; $body .= "Impressum: ${imprint_url}\n"; $self->sendmail->custom( $email, 'travelynx: Passwort geändert', $body ); } sub account { my ($self) = @_; Loading @@ -231,9 +299,10 @@ sub json_export { while ( my @row = $query->fetchrow_array ) { my ( $action_id, $action, $raw_ts, $ds100, $name, $train_type, $train_line, $train_no, $train_id, $raw_sched_ts, $raw_real_ts, $raw_route, $raw_messages $action_id, $action, $raw_ts, $ds100, $name, $train_type, $train_line, $train_no, $train_id, $raw_sched_ts, $raw_real_ts, $raw_route, $raw_messages ) = @row; push( Loading
templates/account.html.ep +5 −5 Original line number Diff line number Diff line Loading @@ -38,6 +38,10 @@ <th scope="row">Mail</th> <td><%= $acc->{email} %></td> </tr> <tr> <th scope="row">Passwort</th> <td><a href="/change_password" class="waves-effect waves-light btn">ändern</a></td> </tr> <tr> <th scope="row">Registriert am</th> <td><%= $acc->{registered_at}->strftime('%d.%m.%Y %H:%M') %></td> Loading @@ -46,9 +50,7 @@ </div> </div> <div class="row"> <div class="col s1 m1 l3"> </div> <div class="col s10 m10 l6 center-align"> <div class="col s12 m12 l12 center-align"> %= form_for 'logout' => begin %= csrf_field <button class="btn waves-effect waves-light" type="submit" name="action" value="logout"> Loading @@ -56,8 +58,6 @@ </button> %= end </div> <div class="col s1 m1 l3"> </div> </div> % my $token = get_api_token(); Loading
templates/change_password.html.ep 0 → 100644 +69 −0 Original line number Diff line number Diff line % if (my $invalid = stash('invalid')) { <div class="row"> <div class="col s12"> <div class="card red darken-4"> <div class="card-content white-text"> % if ($invalid eq 'csrf') { <span class="card-title">Ungültiger CSRF-Token</span> <p>Sind Cookies aktiviert? Ansonsten könnte es sich um einen Fall von <a href="https://de.wikipedia.org/wiki/Cross-Site-Request-Forgery">CSRF</a> handeln.</p> % } % elsif ($invalid eq 'password_notequal') { <span class="card-title">Passwort ungültig</span> <p>Die angegebenen neuen Passwörter sind nicht identisch.</p> % } % elsif ($invalid eq 'password_short') { <span class="card-title">Passwort zu kurz</span> <p>Das neue Passwort muss mindestens acht Zeichen lang sein.</p> % } % elsif ($invalid eq 'password') { <span class="card-title">Ungültiges Passwort</span> <p>Das aktuelle Passwort wurde nicht korrekt eingegeben.</p> % } % else { <span class="card-title">Unbekannter Fehler</span> <p>„<%= $invalid %>“</p> % } </div> </div> </div> </div> % } <h1>Passwort ändern</h1> %= form_for '/change_password' => (method => 'POST') => begin %= csrf_field <div class="row"> <div class="input-field col s12"> <i class="material-icons prefix">lock</i> %= password_field 'oldpw', id => 'oldpassword', class => 'validate', required => undef, autocomplete => 'current-password' <label for="oldpassword">Aktuelles Passwort</label> </div> </div> <div class="row"> <div class="input-field col l6 m12 s12"> <i class="material-icons prefix">lock</i> %= password_field 'newpw', id => 'password', class => 'validate', required => undef, minlength => 8, autocomplete => 'new-password' <label for="password">Neues Passwort</label> </div> <div class="input-field col l6 m12 s12"> <i class="material-icons prefix">lock</i> %= password_field 'newpw2', id => 'password2', class => 'validate', required => undef, minlength => 8, autocomplete => 'new-password' <label for="password2">Passwort wiederholen</label> </div> </div> <div class="row"> <div class="col s3 m3 l3"> </div> <div class="col s6 m6 l6 center-align"> <button class="btn waves-effect waves-light" type="submit" name="action" value="login"> Ändern <i class="material-icons right">send</i> </button> </div> <div class="col s3 m3 l3"> </div> </div> %= end