forked from .cyb/cyberman
misc improvements, basic authentication system (no session support yet)
This commit is contained in:
parent
6525ef9f80
commit
7038dc3afa
|
@ -0,0 +1,2 @@
|
|||
*.swp
|
||||
db.sqlite
|
28
config.yml
28
config.yml
|
@ -27,26 +27,8 @@ engines:
|
|||
|
||||
auto_page: 1
|
||||
|
||||
# session engine
|
||||
#
|
||||
# Simple: in-memory session store - Dancer2::Session::Simple
|
||||
# YAML: session stored in YAML files - Dancer2::Session::YAML
|
||||
#
|
||||
# Check out metacpan for other session storage options:
|
||||
# https://metacpan.org/search?q=Dancer2%3A%3ASession&search_type=modules
|
||||
#
|
||||
# Default value for 'cookie_name' is 'dancer.session'. If you run multiple
|
||||
# Dancer apps on the same host then you will need to make sure 'cookie_name'
|
||||
# is different for each app.
|
||||
#
|
||||
#engines:
|
||||
# session:
|
||||
# Simple:
|
||||
# cookie_name: testapp.session
|
||||
#
|
||||
#engines:
|
||||
# session:
|
||||
# YAML:
|
||||
# cookie_name: eshop.session
|
||||
# is_secure: 1
|
||||
# is_http_only: 1
|
||||
plugins:
|
||||
Database:
|
||||
driver: 'SQLite'
|
||||
dbname: 'db.sqlite'
|
||||
log_queries: 1
|
||||
|
|
5
cpanfile
5
cpanfile
|
@ -5,6 +5,11 @@ requires "URL::Encode::XS" => "0";
|
|||
requires "CGI::Deurl::XS" => "0";
|
||||
requires "HTTP::Parser::XS" => "0";
|
||||
requires "Plack::Middleware::Deflater" => "0";
|
||||
requires "Dancer2::Plugin::Database" => "0";
|
||||
requires "DBD::SQLite" => "0";
|
||||
requires "HTML::Entities" => "0";
|
||||
requires "Digest::Bcrypt" => "0";
|
||||
requires "Math::Random::Secure" => "0";
|
||||
|
||||
on "test" => sub {
|
||||
requires "Test::More" => "0";
|
||||
|
|
155
lib/cyberman.pm
155
lib/cyberman.pm
|
@ -1,10 +1,161 @@
|
|||
package cyberman;
|
||||
use Dancer2;
|
||||
use Dancer2::Plugin::Database;
|
||||
use Digest::Bcrypt;
|
||||
use Math::Random::Secure qw(rand irand);
|
||||
|
||||
our $VERSION = '0.1';
|
||||
#####
|
||||
# cyberman.pm
|
||||
# index page and authentication
|
||||
#####
|
||||
|
||||
# misc authentication subs
|
||||
|
||||
sub get_auth {
|
||||
my $uid = shift;
|
||||
my $token = shift;
|
||||
|
||||
my $result = database->quick_select("session", {"uid" => $uid, "token" => $token});
|
||||
|
||||
if ($result) {
|
||||
return $uid;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
sub randstring {
|
||||
my $len = shift;
|
||||
|
||||
my @chars = (0..9, "a".."z", "A".."Z");
|
||||
my $ret;
|
||||
|
||||
for (1..$len) {
|
||||
$ret .= $chars[irand(scalar(@chars))];
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
prefix undef;
|
||||
|
||||
hook 'before' => sub {
|
||||
sub cookieval {
|
||||
my $name = shift;
|
||||
my $cookie = cookie($name);
|
||||
if ($cookie) {
|
||||
return $cookie->value;
|
||||
} else {
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
my $uid = cookieval("token");
|
||||
my $token = cookieval("token");
|
||||
my $auth = 0;
|
||||
if ($uid && $token) {
|
||||
$auth = get_auth($uid, $token);
|
||||
}
|
||||
|
||||
var auth => $auth;
|
||||
};
|
||||
|
||||
get '/' => sub {
|
||||
template 'index' => { 'title' => 'cyberman' };
|
||||
if (!vars->{auth}) {
|
||||
template 'index';
|
||||
}
|
||||
};
|
||||
|
||||
post '/register' => sub {
|
||||
my %errs;
|
||||
|
||||
for my $param ("password", "password2", "email") {
|
||||
if (!param($param)) {
|
||||
$errs{"e_no_$param"} = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists $errs{"e_no_password"} || !exists $errs{"e_no_password2"}) {
|
||||
if (param("password") ne param("password2")) {
|
||||
$errs{"e_pass_match"} = 1;
|
||||
}
|
||||
|
||||
if (length param("password") < 8) {
|
||||
$errs{"e_pass_len"} = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys(%errs)) != 0) {
|
||||
return template 'register' => {
|
||||
error => 1,
|
||||
params,
|
||||
%errs,
|
||||
};
|
||||
}
|
||||
|
||||
# Hash password
|
||||
my $salt = randstring(16);
|
||||
|
||||
my $b = new Digest::Bcrypt;
|
||||
$b->cost(8);
|
||||
$b->salt($salt);
|
||||
$b->add(param "password");
|
||||
|
||||
# Create the account in the database
|
||||
database->quick_insert(
|
||||
"user",
|
||||
{
|
||||
"email" => param("email"),
|
||||
"password" => $b->bcrypt_b64digest,
|
||||
"salt" => $salt,
|
||||
},
|
||||
);
|
||||
|
||||
# TODO: send confirmation email
|
||||
|
||||
template 'login' => {
|
||||
account_created => 1,
|
||||
params,
|
||||
};
|
||||
};
|
||||
|
||||
post '/login' => sub {
|
||||
my %errs;
|
||||
|
||||
my $user = database->quick_select(
|
||||
"user",
|
||||
{
|
||||
"email" => param("email"),
|
||||
},
|
||||
);
|
||||
|
||||
if (!$user) {
|
||||
$errs{"e_no_user"} = 1;
|
||||
}
|
||||
|
||||
if (scalar(keys(%errs)) == 0) {
|
||||
my $b = new Digest::Bcrypt;
|
||||
$b->cost(8);
|
||||
$b->salt($user->{"salt"});
|
||||
$b->add(param "password");
|
||||
|
||||
$errs{"e_pass"} = 1 unless $b->bcrypt_b64digest eq $user->{"password"};
|
||||
}
|
||||
|
||||
if (scalar(keys(%errs)) == 0) {
|
||||
$errs{"e_not_confirmed"} = 1 unless $user->{"active"};
|
||||
}
|
||||
|
||||
if (scalar(keys(%errs)) != 0) {
|
||||
return template 'login' => {
|
||||
error => 1,
|
||||
%errs,
|
||||
params,
|
||||
};
|
||||
}
|
||||
|
||||
# checks finished, we can create a session now
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
true;
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
drop table if exists user;
|
||||
create table user (
|
||||
id integer primary key,
|
||||
email text not null,
|
||||
password text not null,
|
||||
salt text not null,
|
||||
active integer not null default 0
|
||||
);
|
||||
|
||||
drop table if exists session;
|
||||
create table session (
|
||||
id integer primary key,
|
||||
uid text not null,
|
||||
since integer not null,
|
||||
token text not null
|
||||
);
|
|
@ -10,6 +10,7 @@
|
|||
<div class="body">
|
||||
<p>.cyb is a new TLD (top level domain) for anything and everything cyberpunk-related, on the OpenNIC network. To get started, change your computer's DNS settings to use OpenNIC's servers - <a href="https://www.moderntld.com/get-started/">here's how</a>. Registering a .cyb domain is free for everyone.</p>
|
||||
<p>You can <a href="charter">read our charter</a> for more information and details on how to report abuse of cybNIC services.</p>
|
||||
<p>Create or log in to an account in order to register or update .cyb domains.</p>
|
||||
<center>
|
||||
<p>[ <a class="bracketButton" href="login">log in</a> ] [ <a class="bracketButton" href="register">register</a> ]</p>
|
||||
</center>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<title>cybNIC</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
|
@ -22,12 +23,23 @@ p {
|
|||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
a.bracketButton {
|
||||
text-decoration: none;
|
||||
}
|
||||
a.bracketButton:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
form.login>table>tbody>tr>td>label {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.msgBox {
|
||||
border: 1px solid white;
|
||||
display: inline-block;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
<center>
|
||||
<br />
|
||||
<h1>Log in</h1>
|
||||
<br />
|
||||
|
||||
<% IF account_created %>
|
||||
<div class="msgBox">
|
||||
Your account has been created and a confirmation email sent to <% email | html_entity %>. Please confirm your email address, then log in here.
|
||||
</div>
|
||||
<br /><br />
|
||||
<% END %>
|
||||
|
||||
<% IF error %>
|
||||
<div class="msgBox">
|
||||
<% IF e_no_user %>
|
||||
The email address <% email | html_entity %> is not registered.
|
||||
<% END %>
|
||||
<% IF e_pass %>
|
||||
Your password was incorrect, sorry.
|
||||
<% END %>
|
||||
<% IF e_not_confirmed %>
|
||||
Please confirm your email address using the link sent to <% email | html_entity %>.
|
||||
<% END %>
|
||||
</div>
|
||||
<br /><br />
|
||||
<% END %>
|
||||
|
||||
</center>
|
||||
|
||||
<div class="body">
|
||||
<form method=POST class="login" action="login">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="email">Email address:</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="email" name="email" id="email" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="password">Password:</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="password" name="password" id="password" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br />
|
||||
<button action="submit">Log in</button>
|
||||
</form>
|
||||
</div>
|
|
@ -0,0 +1,67 @@
|
|||
<center>
|
||||
<br />
|
||||
<h1>Register</h1>
|
||||
<br />
|
||||
</center>
|
||||
|
||||
<% IF error %>
|
||||
<div style="text-align:center">
|
||||
<div class="msgBox" style="text-align:left">
|
||||
There were some problems with your registration:
|
||||
<br />
|
||||
<ul>
|
||||
<% IF e_no_email %>
|
||||
<li>You need to enter a valid email address.</li>
|
||||
<% END %>
|
||||
<% IF e_no_password %>
|
||||
<li>You need to enter a password.</li>
|
||||
<% END %>
|
||||
<% IF e_pass_len %>
|
||||
<li>Your password must be at least 8 characters!</li>
|
||||
<% END %>
|
||||
<% IF e_no_password2 %>
|
||||
<li>You need to enter a password confirmation.</li>
|
||||
<% END %>
|
||||
<% IF e_pass_match %>
|
||||
<li>The two passwords you entered do not match!</li>
|
||||
<% END %>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<% END %>
|
||||
|
||||
<div class="body">
|
||||
<form class="login" method="POST" action="register">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="email">Email address:</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="email" name="email" id="email" value="<% email | html_entity %>" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="password">Password:</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="password" name="password" id="password" value="<% password | html_entity %>" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="password2">Confirm password:</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="password" name="password2" id="password2" value="<% password2 | html_entity %>" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br />
|
||||
<button action="submit">Register</button>
|
||||
<br /><br />
|
||||
<em>By registering, you agree to be bound by the policies set forward in our <a href="charter">charter</a>.</em>
|
||||
</form>
|
||||
</div>
|
Loading…
Reference in New Issue