diff options
| author | Daniel Friesel <derf@finalrewind.org> | 2019-03-06 20:48:21 +0100 | 
|---|---|---|
| committer | Daniel Friesel <derf@finalrewind.org> | 2019-03-06 20:48:21 +0100 | 
| commit | ba6b517e5b6986609996339eae109bb2c279ee5f (patch) | |
| tree | efec089485b659bf42d33bdb08ebc72a1867a30c | |
| parent | 4ae0217662c0ba1e35b81c720ccb82e3863dd9dd (diff) | |
working registration and verification
| -rwxr-xr-x | index.pl | 182 | ||||
| -rw-r--r-- | templates/login.html.ep | 26 | ||||
| -rw-r--r-- | templates/register.html.ep | 4 | 
3 files changed, 181 insertions, 31 deletions
| @@ -12,6 +12,7 @@ use Email::Simple;  use Geo::Distance;  use List::Util qw(first);  use List::MoreUtils qw(after_incl before_incl); +use UUID::Tiny qw(:std);  use Travel::Status::DE::IRIS;  use Travel::Status::DE::IRIS::Stations; @@ -44,18 +45,24 @@ app->plugin(  		autoload_user => 1,  		session_key   => 'foodor',  		load_user     => sub { -			my ( $app, $uid ) = @_; -			if ( $uid == 1 ) { -				return { -					name => 'dev', -				}; +			my ( $self, $uid ) = @_; +			my $data = $self->get_user_data($uid); +			if ($data) { +				return { name => $data->{name} };  			}  			return undef;  		},  		validate_user => sub { -			my ( $c, $username, $password, $extradata ) = @_; -			if ( $username eq 'dev' and $password eq 'ohai' ) { -				return 1; +			my ( $self, $username, $password, $extradata ) = @_; +			my $user_info = $self->get_user_password($username); +			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;  		}, @@ -90,10 +97,32 @@ 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(  	add_mail_query => sub {  		my ($self) = @_; -		return $sefl->app->dbh->prepare( +		return $self->app->dbh->prepare(  			qq{  				insert into pending_mails (  					email, num_tries, last_try @@ -103,6 +132,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(  	checkin_query => sub {  		my ($self) = @_; @@ -211,6 +251,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(  	get_stationid_by_ds100_query => sub {  		my ($self) = @_; @@ -245,7 +311,7 @@ app->attr(  sub hash_password {  	my ($password) = @_;  	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 );  } @@ -260,7 +326,7 @@ sub check_password {  }  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 { @@ -499,10 +565,22 @@ helper 'get_station_id' => sub {  	}  }; +helper 'get_user_token' => sub { +	my ( $self, $uid ) = @_; + +	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) = @_; +	my ( $self, $uid ) = @_; -	my $uid   = $self->get_user_id; +	$uid //= $self->get_user_id;  	my $query = $self->app->get_user_query;  	$query->execute($uid);  	my $rows = $query->fetchall_arrayref; @@ -528,6 +606,23 @@ helper 'get_user_data' => sub {  	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 {  	my ($self) = @_; @@ -537,7 +632,7 @@ helper 'get_user_name' => 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; @@ -606,11 +701,20 @@ helper 'get_user_id' => sub {  	my $rows = $self->app->get_userid_query->fetchall_arrayref;  	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 {  		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 );  		$self->app->get_userid_query->execute($user_name);  		$rows = $self->app->get_userid_query->fetchall_arrayref; @@ -1059,7 +1163,8 @@ post '/x/register' => sub {  		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' );  		return;  	} @@ -1083,8 +1188,7 @@ post '/x/register' => sub {  	$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/confirm/${user_id}/${token}\n"; +	$body .= "https://travelynx.finalrewind.org/x/reg/${user_id}/${token}\n";  	$body .= "freischalten.\n\n";  	$body  	  .= "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 .= "Impressum: https://travelynx.finalrewind.org/x/impressum\n"; -	# TODO create user object -  	my $reg_mail = Email::Simple->create(  		header => [  			To             => $email, @@ -1110,16 +1212,36 @@ post '/x/register' => sub {  		body => encode( 'utf-8', $body ),  	); -	# TODO re-enable once remaining registration code is complete -	#my $success = try_to_sendmail($reg_mail); -	#if ($success) { -	#	$self->render( 'login', from => 'register' ); -	#} -	#else { -	#	$self->render( 'register', invalid => 'sendmail' ); -	#} +	my $success = try_to_sendmail($reg_mail); +	if ($success) { +		$self->render( 'login', from => 'register' ); +	} +	else { +		$self->render( 'register', invalid => 'sendmail' ); +	} +}; + +get '/x/reg/:id/:token' => sub { +	my ($self) = @_; -	$self->render( 'register', invalid => 'not implemented yet' ); +	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 { diff --git a/templates/login.html.ep b/templates/login.html.ep index 4e9b1c2..37afacc 100644 --- a/templates/login.html.ep +++ b/templates/login.html.ep @@ -28,7 +28,7 @@  					% }  					% elsif ($invalid eq 'credentials') {  						<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 {  						<span class="card-title">Unbekannter Fehler</span> @@ -39,6 +39,30 @@  		</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">  	%= form_for '/x/login' => (class => 'col s12', method => 'POST') => begin  		%= csrf_field diff --git a/templates/register.html.ep b/templates/register.html.ep index 48afddf..a227e6f 100644 --- a/templates/register.html.ep +++ b/templates/register.html.ep @@ -45,6 +45,10 @@  						<p>Die Bestätigungsmail konnte nicht verschickt werden.  							Ü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 {  						<span class="card-title">Unbekannter Fehler</span>  						<p>„<%= $invalid %>“</p> | 
