Last active
August 29, 2015 02:46
-
-
Save jberger/2d77bdf4dbb239eafc20 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use Mojolicious::Lite; | |
use DBM::Deep; | |
use Mojo::JWT; | |
plugin 'Bcrypt'; | |
plugin 'Minion' => {File => 'minion.db'}; | |
app->minion->add_task(send_email => sub { | |
my ($job, $address, $subject, $body) = @_; | |
require Email::Sender::Simple; | |
require Email::Simple; | |
require Email::Sender::Transport::Print; | |
my $email = Email::Simple->create( | |
header => [ | |
To => $address, | |
From => 'me@nobody.com', | |
Subject => $subject, | |
], | |
body => $body, | |
); | |
my $transport = Email::Sender::Transport::Print->new; | |
Email::Sender::Simple->send($email, {transport => $transport}); | |
}); | |
helper email => sub { shift->minion->enqueue(send_email => [@_]) }; | |
helper jwt => sub { Mojo::JWT->new(secret => shift->app->secrets->[0] || die) }; | |
helper to_index => sub { | |
my ($c, $msg) = @_; | |
$c->flash(message => $msg) if $msg; | |
$c->redirect_to('index'); | |
}; | |
helper users => sub { DBM::Deep->new('users.db') }; | |
any '/' => sub { | |
my $c = shift; | |
$c->render('logged_in') if $c->session('username'); | |
} => 'index'; | |
any '/logout' => sub { shift->session(expires => 1)->to_index }; | |
post '/sign_in' => sub { | |
my $c = shift; | |
my $username = $c->param('username'); | |
return $c->to_index("Username $username not found") | |
unless my $user = $c->users->{$username}; | |
return $c->to_index("Username $username has not been confirmed") | |
unless $user->{confirmed}; | |
return $c->to_index('Password not correct') | |
unless $c->bcrypt_validate($c->param('password'), $user->{password}); | |
$c->session(username => $username)->to_index; | |
}; | |
post '/sign_up' => sub { | |
my $c = shift; | |
my $username = $c->param('username'); | |
return $c->to_index("Username $username is taken") | |
if $c->users->{$username}; | |
return $c->to_index('Password cannot be blank') | |
unless my $password = $c->param('password'); | |
return $c->to_index('Email cannot be blank') | |
unless my $email = $c->param('email'); | |
$c->users->{$username} = { | |
email => $email, | |
password => $c->bcrypt($password), | |
confirmed => 0, | |
}; | |
my $jwt = $c->jwt->claims({username => $username})->encode; | |
my $url = $c->url_for('confirm')->to_abs->query(jwt => $jwt); | |
$c->email($email, 'Confirm registration', "Please visit $url to confirm"); | |
$c->to_index('registration complete, please confirm via email'); | |
}; | |
post '/forgot' => sub { | |
my $c = shift; | |
my $username = $c->param('username'); | |
return $c->to_index("Username $username not found") | |
unless my $user = $c->users->{$username}; | |
return $c->to_index("User $username has no email listed") | |
unless my $email = $user->{email}; | |
my $jwt = $c->jwt->claims({username => $username})->encode; | |
my $url = $c->url_for('reset')->to_abs->query(jwt => $jwt); | |
$c->email($email, 'Password reset', "Please visit $url to reset password"); | |
$c->to_index('password reset email sent, please follow email instructions'); | |
}; | |
get '/confirm' => sub { | |
my $c = shift; | |
my $username = $c->jwt->decode($c->param('jwt'))->{username}; | |
$c->users->{$username}{confirmed} = 1; | |
$c->to_index('registration confirmed, please log in'); | |
}; | |
any '/reset' => sub { | |
my $c = shift; | |
my $username = $c->jwt->decode($c->param('jwt'))->{username}; | |
return $c->render('reset', username => $username) | |
if $c->req->method eq 'GET'; | |
return $c->to_index("Username $username not found") | |
unless my $user = $c->users->{$username}; | |
return $c->to_index('Password cannot be blank') | |
unless my $password = $c->param('password'); | |
$user->{password} = $c->bcrypt($password); | |
$c->to_index('password changed successfully, please login'); | |
}; | |
app->start; | |
__DATA__ | |
@@ index.html.ep | |
<p>Hello Guest!</p> | |
<p><%= flash('message') || 'Sign in or sign up!' %></p> | |
%= form_for sign_in => begin | |
%= label_for username => 'Username' | |
%= text_field 'username' | |
%= label_for password => 'Password' | |
%= password_field 'password' | |
%= label_for email => 'Email' | |
%= email_field 'email', placeholder => 'new acct only' | |
<br> | |
%= submit_button 'Sign In' | |
%= submit_button 'Sign Up', formaction => url_for('sign_up') | |
%= submit_button 'Forgot Password', formaction => url_for('forgot') | |
% end | |
@@ logged_in.html.ep | |
<p>Welcome back <%= session 'username' %>!</p> | |
<p><%= link_to 'Log out' => 'logout' %> | |
@@ reset.html.ep | |
%= form_for reset => method => POST => begin | |
%= label_for password => "Reset password for $username" | |
%= password_field 'password' | |
%= hidden_field jwt => param 'jwt'; | |
%= submit_button 'Change'; | |
% end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment