working registration and verification
This commit is contained in:
parent
4ae0217662
commit
ba6b517e5b
3 changed files with 182 additions and 32 deletions
184
index.pl
184
index.pl
|
@ -12,6 +12,7 @@ use Email::Simple;
|
||||||
use Geo::Distance;
|
use Geo::Distance;
|
||||||
use List::Util qw(first);
|
use List::Util qw(first);
|
||||||
use List::MoreUtils qw(after_incl before_incl);
|
use List::MoreUtils qw(after_incl before_incl);
|
||||||
|
use UUID::Tiny qw(:std);
|
||||||
use Travel::Status::DE::IRIS;
|
use Travel::Status::DE::IRIS;
|
||||||
use Travel::Status::DE::IRIS::Stations;
|
use Travel::Status::DE::IRIS::Stations;
|
||||||
|
|
||||||
|
@ -44,18 +45,24 @@ app->plugin(
|
||||||
autoload_user => 1,
|
autoload_user => 1,
|
||||||
session_key => 'foodor',
|
session_key => 'foodor',
|
||||||
load_user => sub {
|
load_user => sub {
|
||||||
my ( $app, $uid ) = @_;
|
my ( $self, $uid ) = @_;
|
||||||
if ( $uid == 1 ) {
|
my $data = $self->get_user_data($uid);
|
||||||
return {
|
if ($data) {
|
||||||
name => 'dev',
|
return { name => $data->{name} };
|
||||||
};
|
|
||||||
}
|
}
|
||||||
return undef;
|
return undef;
|
||||||
},
|
},
|
||||||
validate_user => sub {
|
validate_user => sub {
|
||||||
my ( $c, $username, $password, $extradata ) = @_;
|
my ( $self, $username, $password, $extradata ) = @_;
|
||||||
if ( $username eq 'dev' and $password eq 'ohai' ) {
|
my $user_info = $self->get_user_password($username);
|
||||||
return 1;
|
if ( not $user_info ) {
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
if ( $user_info->{status} != 1 ) {
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
if ( check_password( $password, $user_info->{password_hash} ) ) {
|
||||||
|
return $user_info->{id};
|
||||||
}
|
}
|
||||||
return undef;
|
return undef;
|
||||||
},
|
},
|
||||||
|
@ -89,11 +96,33 @@ app->attr(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
app->attr(
|
||||||
|
set_email_query => sub {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
return $self->app->dbh->prepare(
|
||||||
|
qq{
|
||||||
|
update users set email = ?, token = ? where id = ?;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
app->attr(
|
||||||
|
set_password_query => sub {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
return $self->app->dbh->prepare(
|
||||||
|
qq{
|
||||||
|
update users set password = ? where id = ?;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
app->attr(
|
app->attr(
|
||||||
add_mail_query => sub {
|
add_mail_query => sub {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
|
|
||||||
return $sefl->app->dbh->prepare(
|
return $self->app->dbh->prepare(
|
||||||
qq{
|
qq{
|
||||||
insert into pending_mails (
|
insert into pending_mails (
|
||||||
email, num_tries, last_try
|
email, num_tries, last_try
|
||||||
|
@ -102,6 +131,17 @@ app->attr(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
app->attr(
|
||||||
|
set_status_query => sub {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
return $self->app->dbh->prepare(
|
||||||
|
qq{
|
||||||
|
update users set status = ? where id = ?;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
app->attr(
|
app->attr(
|
||||||
checkin_query => sub {
|
checkin_query => sub {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
|
@ -210,6 +250,32 @@ app->attr(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
app->attr(
|
||||||
|
get_password_query => sub {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
return $self->app->dbh->prepare(
|
||||||
|
qq{
|
||||||
|
select
|
||||||
|
id, name, status, password
|
||||||
|
from users where name = ?
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
app->attr(
|
||||||
|
get_token_query => sub {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
return $self->app->dbh->prepare(
|
||||||
|
qq{
|
||||||
|
select
|
||||||
|
name, status, token
|
||||||
|
from users where id = ?
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
app->attr(
|
app->attr(
|
||||||
get_stationid_by_ds100_query => sub {
|
get_stationid_by_ds100_query => sub {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
|
@ -245,7 +311,7 @@ app->attr(
|
||||||
sub hash_password {
|
sub hash_password {
|
||||||
my ($password) = @_;
|
my ($password) = @_;
|
||||||
my @salt_bytes = map { int( rand(255) ) + 1 } ( 1 .. 16 );
|
my @salt_bytes = map { int( rand(255) ) + 1 } ( 1 .. 16 );
|
||||||
my $salt = en_base64( pack( 'c[16]', @salt_bytes ) );
|
my $salt = en_base64( pack( 'C[16]', @salt_bytes ) );
|
||||||
|
|
||||||
return bcrypt( $password, '$2a$12$' . $salt );
|
return bcrypt( $password, '$2a$12$' . $salt );
|
||||||
}
|
}
|
||||||
|
@ -260,7 +326,7 @@ sub check_password {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub make_token {
|
sub make_token {
|
||||||
return join( q{}, map { chr( int( rand(26) ) + 97 ) } ( 1 .. 70 ) );
|
return create_uuid_as_string(UUID_V4);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub epoch_to_dt {
|
sub epoch_to_dt {
|
||||||
|
@ -499,10 +565,22 @@ helper 'get_station_id' => sub {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
helper 'get_user_data' => sub {
|
helper 'get_user_token' => sub {
|
||||||
my ($self) = @_;
|
my ( $self, $uid ) = @_;
|
||||||
|
|
||||||
my $uid = $self->get_user_id;
|
my $query = $self->app->get_token_query;
|
||||||
|
$query->execute($uid);
|
||||||
|
my $rows = $query->fetchall_arrayref;
|
||||||
|
if ( @{$rows} ) {
|
||||||
|
return @{ $rows->[0] };
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
helper 'get_user_data' => sub {
|
||||||
|
my ( $self, $uid ) = @_;
|
||||||
|
|
||||||
|
$uid //= $self->get_user_id;
|
||||||
my $query = $self->app->get_user_query;
|
my $query = $self->app->get_user_query;
|
||||||
$query->execute($uid);
|
$query->execute($uid);
|
||||||
my $rows = $query->fetchall_arrayref;
|
my $rows = $query->fetchall_arrayref;
|
||||||
|
@ -528,6 +606,23 @@ helper 'get_user_data' => sub {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
helper 'get_user_password' => sub {
|
||||||
|
my ( $self, $name ) = @_;
|
||||||
|
my $query = $self->app->get_password_query;
|
||||||
|
$query->execute($name);
|
||||||
|
my $rows = $query->fetchall_arrayref;
|
||||||
|
if ( @{$rows} ) {
|
||||||
|
my @row = @{ $rows->[0] };
|
||||||
|
return {
|
||||||
|
id => $row[0],
|
||||||
|
name => $row[1],
|
||||||
|
status => $row[2],
|
||||||
|
password_hash => $row[3],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
helper 'get_user_name' => sub {
|
helper 'get_user_name' => sub {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
|
|
||||||
|
@ -537,7 +632,7 @@ helper 'get_user_name' => sub {
|
||||||
};
|
};
|
||||||
|
|
||||||
helper 'get_user_id' => sub {
|
helper 'get_user_id' => sub {
|
||||||
my ( $self, $user_name, $mail, $token, $password ) = @_;
|
my ( $self, $user_name, $email, $token, $password ) = @_;
|
||||||
|
|
||||||
$user_name //= $self->get_user_name;
|
$user_name //= $self->get_user_name;
|
||||||
|
|
||||||
|
@ -606,11 +701,20 @@ helper 'get_user_id' => sub {
|
||||||
my $rows = $self->app->get_userid_query->fetchall_arrayref;
|
my $rows = $self->app->get_userid_query->fetchall_arrayref;
|
||||||
|
|
||||||
if ( @{$rows} ) {
|
if ( @{$rows} ) {
|
||||||
return $rows->[0][0];
|
my $id = $rows->[0][0];
|
||||||
|
|
||||||
|
# transition code for closed beta account -> normal account
|
||||||
|
if ($email) {
|
||||||
|
$self->app->set_email_query->execute( $email, $token, $id );
|
||||||
|
}
|
||||||
|
if ($password) {
|
||||||
|
$self->app->set_password_query->execute( $password, $id );
|
||||||
|
}
|
||||||
|
return $id;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
my $now = DateTime->now( time_zone => 'Europe/Berlin' )->epoch;
|
my $now = DateTime->now( time_zone => 'Europe/Berlin' )->epoch;
|
||||||
$self->app->add_user_query->execute( $user_name, $mail, $token,
|
$self->app->add_user_query->execute( $user_name, $email, $token,
|
||||||
$password, $now, $now );
|
$password, $now, $now );
|
||||||
$self->app->get_userid_query->execute($user_name);
|
$self->app->get_userid_query->execute($user_name);
|
||||||
$rows = $self->app->get_userid_query->fetchall_arrayref;
|
$rows = $self->app->get_userid_query->fetchall_arrayref;
|
||||||
|
@ -1059,7 +1163,8 @@ post '/x/register' => sub {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $self->check_if_user_name_exists($user) or $user eq 'dev' ) {
|
#if ( $self->check_if_user_name_exists($user) or $user eq 'dev' ) {
|
||||||
|
if ( $user ne $self->get_user_name ) {
|
||||||
$self->render( 'register', invalid => 'user_collision' );
|
$self->render( 'register', invalid => 'user_collision' );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1083,8 +1188,7 @@ post '/x/register' => sub {
|
||||||
$body .= "travelynx.finalrewind.org angelegt.\n\n";
|
$body .= "travelynx.finalrewind.org angelegt.\n\n";
|
||||||
$body
|
$body
|
||||||
.= "Falls die Registrierung von dir ausging, kannst du den Account unter\n";
|
.= "Falls die Registrierung von dir ausging, kannst du den Account unter\n";
|
||||||
$body
|
$body .= "https://travelynx.finalrewind.org/x/reg/${user_id}/${token}\n";
|
||||||
.= "https://travelynx.finalrewind.org/x/confirm/${user_id}/${token}\n";
|
|
||||||
$body .= "freischalten.\n\n";
|
$body .= "freischalten.\n\n";
|
||||||
$body
|
$body
|
||||||
.= "Falls nicht, ignoriere diese Mail bitte. Nach 48 Stunden wird deine\n";
|
.= "Falls nicht, ignoriere diese Mail bitte. Nach 48 Stunden wird deine\n";
|
||||||
|
@ -1098,8 +1202,6 @@ post '/x/register' => sub {
|
||||||
$body .= " * Verwendeter Browser gemäß User Agent: ${ua}\n\n\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/x/impressum\n";
|
||||||
|
|
||||||
# TODO create user object
|
|
||||||
|
|
||||||
my $reg_mail = Email::Simple->create(
|
my $reg_mail = Email::Simple->create(
|
||||||
header => [
|
header => [
|
||||||
To => $email,
|
To => $email,
|
||||||
|
@ -1110,16 +1212,36 @@ post '/x/register' => sub {
|
||||||
body => encode( 'utf-8', $body ),
|
body => encode( 'utf-8', $body ),
|
||||||
);
|
);
|
||||||
|
|
||||||
# TODO re-enable once remaining registration code is complete
|
my $success = try_to_sendmail($reg_mail);
|
||||||
#my $success = try_to_sendmail($reg_mail);
|
if ($success) {
|
||||||
#if ($success) {
|
$self->render( 'login', from => 'register' );
|
||||||
# $self->render( 'login', from => 'register' );
|
}
|
||||||
#}
|
else {
|
||||||
#else {
|
$self->render( 'register', invalid => 'sendmail' );
|
||||||
# $self->render( 'register', invalid => 'sendmail' );
|
}
|
||||||
#}
|
};
|
||||||
|
|
||||||
$self->render( 'register', invalid => 'not implemented yet' );
|
get '/x/reg/:id/:token' => sub {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
my $id = $self->stash('id');
|
||||||
|
my $token = $self->stash('token');
|
||||||
|
|
||||||
|
my @db_user = $self->get_user_token($id);
|
||||||
|
|
||||||
|
if ( not @db_user ) {
|
||||||
|
$self->render( 'register', invalid => 'token' );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my ( $db_name, $db_status, $db_token ) = @db_user;
|
||||||
|
|
||||||
|
if ( not $db_name or $token ne $db_token or $db_status != 0 ) {
|
||||||
|
$self->render( 'register', invalid => 'token' );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$self->app->set_status_query->execute( 1, $id );
|
||||||
|
$self->render( 'login', from => 'verification' );
|
||||||
};
|
};
|
||||||
|
|
||||||
get '/*station' => sub {
|
get '/*station' => sub {
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
% }
|
% }
|
||||||
% elsif ($invalid eq 'credentials') {
|
% elsif ($invalid eq 'credentials') {
|
||||||
<span class="card-title">Ungültige Logindaten</span>
|
<span class="card-title">Ungültige Logindaten</span>
|
||||||
<p>Falscher Account oder falsches Passwort.</p>
|
<p>Falscher (oder noch nicht freigeschalteter) Account oder falsches Passwort.</p>
|
||||||
% }
|
% }
|
||||||
% else {
|
% else {
|
||||||
<span class="card-title">Unbekannter Fehler</span>
|
<span class="card-title">Unbekannter Fehler</span>
|
||||||
|
@ -39,6 +39,30 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
% }
|
% }
|
||||||
|
% if (my $from = stash('from')) {
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s12">
|
||||||
|
% if ($from eq 'register') {
|
||||||
|
<div class="card grey darken-4">
|
||||||
|
<div class="card-content white-text">
|
||||||
|
<span class="card-title">Bitte warten</span>
|
||||||
|
<p>Ein Verifizierungslink wurde an die von dir angegebene
|
||||||
|
Mail-Adresse geschickt. Sobald du diesen angeklickt hast,
|
||||||
|
kannst du dich hier anmelden.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
% }
|
||||||
|
% elsif ($from eq 'verification') {
|
||||||
|
<div class="card green darken-4">
|
||||||
|
<div class="card-content white-text">
|
||||||
|
<span class="card-title">Account freigeschaltet</span>
|
||||||
|
<p>Du kannst dich nun anmelden.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
% }
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
% }
|
||||||
<div class="row">
|
<div class="row">
|
||||||
%= form_for '/x/login' => (class => 'col s12', method => 'POST') => begin
|
%= form_for '/x/login' => (class => 'col s12', method => 'POST') => begin
|
||||||
%= csrf_field
|
%= csrf_field
|
||||||
|
|
|
@ -45,6 +45,10 @@
|
||||||
<p>Die Bestätigungsmail konnte nicht verschickt werden.
|
<p>Die Bestätigungsmail konnte nicht verschickt werden.
|
||||||
Überprüfe bitte, ob die Adresse gültig ist.</p>
|
Überprüfe bitte, ob die Adresse gültig ist.</p>
|
||||||
% }
|
% }
|
||||||
|
% elsif ($invalid eq 'token') {
|
||||||
|
<span class="card-title">Ungültiger Token</span>
|
||||||
|
<p>Die Verifikation deiner Mail-Adresse ist fehlgeschlagen oder du hast den Token schon einmal verwendet.</p>
|
||||||
|
% }
|
||||||
% else {
|
% else {
|
||||||
<span class="card-title">Unbekannter Fehler</span>
|
<span class="card-title">Unbekannter Fehler</span>
|
||||||
<p>„<%= $invalid %>“</p>
|
<p>„<%= $invalid %>“</p>
|
||||||
|
|
Loading…
Reference in a new issue