perl dancer tips
perl cpan dancer
Dancer2
- Return to previous page after login (return_url)
cpanm install Dancer2::Plugin::Auth::Tiny
- In config.yml plugin can be configured for the logged_in_key (optional). Indentation is very important. Set logged_in_key value (logged_in) as true in POST ‘/login’ route if username and password matches.
# for Dancer2::Plugin::Auth::Tiny Auth::Tiny: logged_in_key: logged_in
- In the lib/project.pm
# login get '/login' => sub { # put 'return_url' in a hidden form field #print "================>Thsi is the return url" . params->{'return_url'} . "\n"; template 'login.tt' => { return_url => params->{'return_url'}, }; }; post '/login' => sub { my $err; if ( request->method() eq "POST" ) { # process form input if ( params->{'username'} ne setting('username') ) { $err = "Invalid username"; } elsif ( params->{'password'} ne setting('password') ) { $err = "Invalid password"; } else { session 'logged_in' => true; set_flash('You are logged in.'); #print "================>Thsi is the return url" . params->{'return_url'} . "\n"; return redirect params->{return_url} || '/'; # return to previous page prior to login #return redirect '/'; } } # display login form template 'login.tt', { 'err' => $err, }; };
- In views/login.tt (The “return_url” parameter is needed)
[% INCLUDE header.tt %] <ul class=entries> <h2>Login</h2> [% IF err %]<p class=error><strong>Error:</strong> [% err %][% END %] <form action="[% login_url %]" method=post> <dl> <dt>Username: <input type=text name=username><br><br> <dt>Password: <input type=password name=password><br><br> <!--<dt>Return: is [% return_url %]--> <input type=hidden name=return_url value=[% return_url %]><br><br><!-- return to pre login page --> <dd><input type=submit value=Login> </dl> </form> </ul>
- protected route requiring login. In lib/project.pm (The “needs login” is needed)
get '/private' => needs login => sub { your code here };
- encrypted password stored in config.yml
cpanm Dancer2::Plugin::Auth::Extensible
- In config.yml plugin can be configured. Indentation is important.
plugins: Auth::Extensible: realms: config: provider: Config users: - user: dave pass: supersecret roles: - Developer - Manager - BeerDrinker - user: bob pass: '{SSHA512}2QOSf9rnEYz8gAJBBFdAK/xEwrYILmRUraJU0WaTsMvMywfnJO5aM38EDSDPZhusjof1PDtcpWbn6oCaX+WLh8vNXeU=' roles: - Tester
- Generate the salted hash and paste the output in the pass: above
dancer2-generate-crypted-password
- In the lib/myapp.pm add the login code
use Dancer2; use Dancer2::Plugin::Auth::Extensible; get '/' => require_login sub { template 'index' => { 'title' => 'userauth' }; };
- plain text password in mysql db
-
cpanm Dancer2::Plugin::Database cpanm Dancer2::Plugin::Auth::Extensible
- In config.yml plugin can be configured. Indentation is important.
plugins: Database: connections: foo: driver: 'mysql' database: 'userauth' host: 'localhost' port: 3306 username: 'root' password: 'secret' connection_check_threshold: 10 dbi_params: RaiseError: 1 AutoCommit: 1 on_connect_do: ["SET NAMES 'utf8'", "SET CHARACTER SET 'utf8'" ] log_queries: 1 #handle_class: 'My::Super::Sexy::Database::Handle' Auth::Extensible: realms: users: provider: 'Database' db_connection_name: 'foo' disable_roles: 1 users_table: 'active_users' roles_table: 'roles' user_roles_table: 'user_roles' users_id_column: 'id' users_username_column: 'username' users_password_column: 'password' roles_id_column: 'id' roles_role_column: 'role' user_roles_user_id_column: 'user_id' user_roles_role_id_column: 'roles_id'
- Create mysql schema
CREATE TABLE users (id INTEGER PRIMARY KEY AUTO_INCREMENT,username VARCHAR(32) NOT NULL UNIQUE,password VARCHAR(40) NOT NULL,disabled TIMESTAMP NULL ); CREATE TABLE roles (id INTEGER AUTO_INCREMENT PRIMARY KEY,role VARCHAR(32) NOT NULL); CREATE TABLE user_roles (user_id INTEGER NOT NULL,role_id INTEGER NOT NULL,UNIQUE KEY user_role (user_id, role_id)); CREATE VIEW active_users (id, username, password) AS SELECT id, username, password FROM users WHERE disabled IS NULL; INSERT INTO users ( username, password, disabled ) VALUES ( 'Alice', 'test', null), ( 'Bob', 'test', '2017-10-01 10:10:10');
- In the lib/myapp.pm add the login code
use Dancer2; use Dancer2::Plugin::Database; use Dancer2::Plugin::Auth::Extensible; get '/' => require_login sub { template 'index' => { 'title' => 'userauth' }; };
-
- Encrypt password in mysql db
- Install below modules
cpanm Dancer2; cpanm Dancer2::Plugin::Passphrase; #for crypt salt hash password cpanm Data::Dumper; #for debugging cpanm Dancer2::Plugin::Database; #for db connections. cpanm Dancer2::Plugin::Auth::Tiny; #for "needs login" in protected routes
- In config.yml plugin can be configured for the logged_in_key (optional). Indentation is very important. Set logged_in_key value (logged_in) as true in POST ‘/login’ route if username and password matches.
plugins: Database: connections: foo: driver: 'mysql' database: 'userauth' host: 'localhost' port: 3306 username: 'root' password: 'secret' connection_check_threshold: 10 dbi_params: RaiseError: 1 AutoCommit: 1 on_connect_do: ["SET NAMES 'utf8'", "SET CHARACTER SET 'utf8'" ] log_queries: 1 #handle_class: 'My::Super::Sexy::Database::Handle' Auth::Tiny: logged_in_key: 'logged_in'
- Create mysql schema
CREATE TABLE users (id INTEGER PRIMARY KEY AUTO_INCREMENT,username VARCHAR(32) NOT NULL UNIQUE,password VARCHAR(40) NOT NULL,disabled TIMESTAMP NULL ); CREATE TABLE roles (id INTEGER AUTO_INCREMENT PRIMARY KEY,role VARCHAR(32) NOT NULL); CREATE TABLE user_roles (user_id INTEGER NOT NULL,role_id INTEGER NOT NULL,UNIQUE KEY user_role (user_id, role_id)); CREATE VIEW active_users (id, username, password) AS SELECT id, username, password FROM users WHERE disabled IS NULL; INSERT INTO users ( username, password, disabled ) VALUES ( 'Alice', 'test', null), ( 'Bob', 'test', '2017-10-01 10:10:10');
- The lib/userauth.pm file
package userauth; use Dancer2; use Dancer2::Plugin::Passphrase; #for crypt salt hash password use Data::Dumper; use Dancer2::Plugin::Database; #for db connections. #use Dancer2::Plugin::Auth::Extensible; #for automatic /login route etc use Dancer2::Plugin::Auth::Tiny; #for "needs login" in protected routes sub set_flash { my $message = shift; session flash => $message; } hook before_template => sub { my $tokens = shift; $tokens->{'css_url'} = request->base . 'css/style.css'; $tokens->{'login_url'} = uri_for('/login'); $tokens->{'logout_url'} = uri_for('/logout'); }; # mysql db settings. sub connect_db { my $db = DBI->connect('DBI:mysql:userauth', 'root', 'secret') or die $DBI::errstr; return $db; } # subroutine for fetching password from db. sub fetch_password_from_db { my ($username,$password) = @_; my $db = connect_db(); my $sqltransaction = 'select username,password from users where username=(?)'; my $sthtransaction = $db->prepare($sqltransaction) or die $db->errstr; $sthtransaction->execute($username) or die $sthtransaction->errstr; my $sqlresultuserrow = $sthtransaction->fetchrow_hashref; return $sqlresultuserrow; }; # login get '/login' => sub { # put 'return_url' in a hidden form field template 'login.tt' => { return_url => params->{'return_url'}, }; }; post '/login' => sub { my $err; #username and password provided by login form my $username = param('username'); my $password = param('password'); #fetch values from db my $saved_userpass = fetch_password_from_db($username,$password); my $stored_username_string = $saved_userpass->{username}; my $stored_rfc_2307_string = $saved_userpass->{password}; if ( params->{'username'} ne ( $stored_username_string ) ) { #username is ok. $err = "Invalid username"; } elsif ( passphrase( param('password') )->matches( $stored_rfc_2307_string ) ) { # Passphrase matches! print "\nPassphrase matches ========================>>>>>>\n"; session 'logged_in' => true; set_flash('You are logged in.'); redirect params->{'return_url'} || '/'; # return to previous page prior to login } else { print "\nPassphrase does not match ========================>>>>>>\n"; $err = "Invalid password"; } }; #user registeration form. get '/register' => sub { template 'register' => { 'title' => 'registeration form', register_user_url => uri_for('/register'), }; }; #route for inserting in db. post '/register' => sub { my $username = param('username'); my $password = passphrase(param('password'))->generate( { algorithm => 'Bcrypt', Bcrypt => { cost => 04, } } ); # $password is now a hashed password object save_user_in_db( $username, $password->rfc2307 ); #template registered => { success => 1 }; }; # save user and password (crypt salted hash) in db. sub save_user_in_db { my ($username, $password) = @_; my $db = connect_db(); my $sqltransaction = 'insert into users(username, password) values(?, ?)'; my $sthtransaction = $db->prepare($sqltransaction) or die $db->errstr; $sthtransaction->execute($username, $password) or die $sthtransaction->errstr; }; get '/private' => needs login => sub { template 'index' => { 'title' => 'userauth' }; }; get '/logout' => sub { context->destroy_session; set_flash('You are logged out.'); redirect '/'; }; get '/generate_new_password' => sub { return passphrase->generate_random; }; true;
- views/register.tt
<h2>Register</h2> [% IF err %]<p class=error><strong>Error:</strong> [% err %][% END %] <form action="[% register_user_url %]" method=post> <dl> <dt>Username: <dd><input type=text name=username> <dt>Password: <dd><input type=password name=password> <dd><input type=submit value=Login> </dl> </form>
- views/login.tt
[% IF vars.login_failed %] <div class="alert alert-danger"> <strong>Login Failed</strong> Try again <button type="button" class="close" data-dismiss="alert" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> [% END %] <form method = "post" lpformnum="1" class="form-signin"> <h2 class="form-signin-heading">Please sign in</h2> <label for="username" class="sr-only">Username</label> <input type="text" name="username" id="username" class="form-control" placeholder="User name" required autofocus> <label for="password" class="sr-only">Password</label> <input type="password" name="password" id="password" class="form-control" placeholder="Password" required> <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button> <br> <input type="hidden" name="return_url" value="[% return_url %]"> </form>
- Install below modules
- fetchrow_array in lib/xxxxxx.pm
- Select from mysqldb and get the resulting data as an array
# start festival data structure my $sql4='SELECT feast,url,description FROM `festivals` WHERE `date` = CURDATE()'; my $sth4 = $db->prepare($sql4) or die $db->errstr; $sth4->execute or die $sth4->errstr; my $feast; my $url; my $description; ($feast, $url,$description) = $sth4->fetchrow_array(); $sth4->finish; my ($feastnameRef,$urlRef,$descriptionRef) = ($feast,$url,$description); # end festival data structure template 'query5.tt', { 'countryname' => $countrynameRef, 'statename' => $statenameRef, 'cityname' => $citynameRef, 'churchid' => $churchidRef, 'feastname' => $feastnameRef, 'feastdescription' => $descriptionRef, 'url' => $urlRef, 'title' => 'Churches of India', 'request.uri_base' => 'http://localhost/', 'Testing' => "This is text to test to make sure this will come through", # to test, use this like <% Testing %> on your template page };
- Select from mysqldb and get the resulting data as an array
- fetchall_href in lib/xxxxxx.pm
- Select from mysqldb and get the resulting data as a hash
my $db = connect_db(); my $sql='SELECT country_id,country_name FROM country'; my $sth = $db->prepare($sql) or die $db->errstr; $sth->execute or die $sth->errstr; my $countrynameRef = $sth->fetchall_hashref('country_name'); template 'query5.tt', { 'countryname' => $countrynameRef, 'statename' => $statenameRef, 'cityname' => $citynameRef, 'churchid' => $churchidRef, 'feastname' => $feastnameRef, 'feastdescription' => $descriptionRef, 'url' => $urlRef, 'title' => 'Churches of India', 'request.uri_base' => 'http://localhost/', 'Testing' => "This is text to test to make sure this will come through", # to test, use this like <% Testing %> on your template page };
- Another example of Select from mysqldb and get the resulting data as a hash
get '/testarray' => sub { my $db = connect_db(); my $sql='SELECT state_id,state_name FROM state'; my $sth = $db->prepare($sql) or die $db->errstr; $sth->execute or die $sth->errstr; # build data structure my $id; my $name; my %data; while (($id, $name) = $sth->fetchrow_array()) { $data{$id} = { id => $id, name => $name } } $sth->finish; # build city data structure my $sql1='SELECT city_id,city_name FROM city'; my $sth1 = $db->prepare($sql1) or die $db->errstr; $sth1->execute or die $sth1->errstr; my $id1; my $name1; my %data1; while (($id, $name) = $sth1->fetchrow_array()) { $data1{$id} = { cityid => $id, cityname => $name } } $sth1->finish; template 'testarray.tt' => { 'title' => 'church_timing', 'data' => \%data, 'data1' => \%data1 }; };
- Select from mysqldb and get the resulting data as a hash