Add password change form
This commit is contained in:
parent
6630cdcd9e
commit
1405eb6ea3
4 changed files with 160 additions and 12 deletions
|
@ -583,7 +583,8 @@ qq{select * from pending_mails where email = ? and num_tries > 1;}
|
||||||
elsif ( $user->{cancelled} ) {
|
elsif ( $user->{cancelled} ) {
|
||||||
|
|
||||||
# Same
|
# 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(
|
my $success = $self->app->action_query->execute(
|
||||||
|
@ -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(
|
$self->helper(
|
||||||
'check_if_user_name_exists' => sub {
|
'check_if_user_name_exists' => sub {
|
||||||
my ( $self, $user_name ) = @_;
|
my ( $self, $user_name ) = @_;
|
||||||
|
@ -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('/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('/export.json')->to('account#json_export');
|
||||||
$authed_r->get('/history')->to('traveling#history');
|
$authed_r->get('/history')->to('traveling#history');
|
||||||
$authed_r->get('/history/:year/:month')->to('traveling#monthly_history');
|
$authed_r->get('/history/:year/:month')->to('traveling#monthly_history');
|
||||||
$authed_r->get('/history.json')->to('traveling#json_history');
|
$authed_r->get('/history.json')->to('traveling#json_history');
|
||||||
$authed_r->get('/journey/:id')->to('traveling#journey_details');
|
$authed_r->get('/journey/:id')->to('traveling#journey_details');
|
||||||
$authed_r->get('/s/*station')->to('traveling#station');
|
$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('/delete')->to('account#delete');
|
||||||
$authed_r->post('/logout')->to('account#do_logout');
|
$authed_r->post('/logout')->to('account#do_logout');
|
||||||
$authed_r->post('/set_token')->to('api#set_token');
|
$authed_r->post('/set_token')->to('api#set_token');
|
||||||
|
|
|
@ -136,11 +136,12 @@ sub register {
|
||||||
.= "werden wir sie dauerhaft sperren und keine Mails mehr dorthin schicken.\n\n";
|
.= "werden wir sie dauerhaft sperren und keine Mails mehr dorthin schicken.\n\n";
|
||||||
$body .= "Daten zur Registrierung:\n";
|
$body .= "Daten zur Registrierung:\n";
|
||||||
$body .= " * Datum: ${date}\n";
|
$body .= " * Datum: ${date}\n";
|
||||||
$body .= " * Verwendete IP: ${ip}\n";
|
$body .= " * Client: ${ip}\n";
|
||||||
$body .= " * Verwendeter Browser gemäß User Agent: ${ua}\n\n\n";
|
$body .= " * UserAgent: ${ua}\n\n\n";
|
||||||
$body .= "Impressum: ${imprint_url}\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) {
|
if ($success) {
|
||||||
$self->app->dbh->commit;
|
$self->app->dbh->commit;
|
||||||
$self->render( 'login', from => 'register' );
|
$self->render( 'login', from => 'register' );
|
||||||
|
@ -214,6 +215,73 @@ sub do_logout {
|
||||||
$self->redirect_to('/login');
|
$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 {
|
sub account {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
|
|
||||||
|
@ -231,9 +299,10 @@ sub json_export {
|
||||||
|
|
||||||
while ( my @row = $query->fetchrow_array ) {
|
while ( my @row = $query->fetchrow_array ) {
|
||||||
my (
|
my (
|
||||||
$action_id, $action, $raw_ts, $ds100, $name,
|
$action_id, $action, $raw_ts, $ds100,
|
||||||
$train_type, $train_line, $train_no, $train_id,
|
$name, $train_type, $train_line, $train_no,
|
||||||
$raw_sched_ts, $raw_real_ts, $raw_route, $raw_messages
|
$train_id, $raw_sched_ts, $raw_real_ts, $raw_route,
|
||||||
|
$raw_messages
|
||||||
) = @row;
|
) = @row;
|
||||||
|
|
||||||
push(
|
push(
|
||||||
|
|
|
@ -38,6 +38,10 @@
|
||||||
<th scope="row">Mail</th>
|
<th scope="row">Mail</th>
|
||||||
<td><%= $acc->{email} %></td>
|
<td><%= $acc->{email} %></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Passwort</th>
|
||||||
|
<td><a href="/change_password" class="waves-effect waves-light btn">ändern</a></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Registriert am</th>
|
<th scope="row">Registriert am</th>
|
||||||
<td><%= $acc->{registered_at}->strftime('%d.%m.%Y %H:%M') %></td>
|
<td><%= $acc->{registered_at}->strftime('%d.%m.%Y %H:%M') %></td>
|
||||||
|
@ -46,9 +50,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col s1 m1 l3">
|
<div class="col s12 m12 l12 center-align">
|
||||||
</div>
|
|
||||||
<div class="col s10 m10 l6 center-align">
|
|
||||||
%= form_for 'logout' => begin
|
%= form_for 'logout' => begin
|
||||||
%= csrf_field
|
%= csrf_field
|
||||||
<button class="btn waves-effect waves-light" type="submit" name="action" value="logout">
|
<button class="btn waves-effect waves-light" type="submit" name="action" value="logout">
|
||||||
|
@ -56,8 +58,6 @@
|
||||||
</button>
|
</button>
|
||||||
%= end
|
%= end
|
||||||
</div>
|
</div>
|
||||||
<div class="col s1 m1 l3">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
% my $token = get_api_token();
|
% my $token = get_api_token();
|
||||||
|
|
69
templates/change_password.html.ep
Normal file
69
templates/change_password.html.ep
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
% 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…
Reference in a new issue