Added initial admin login page and backend page with authentication
This commit is contained in:
parent
998259f0ae
commit
61d609861a
5 changed files with 116 additions and 1 deletions
|
@ -49,7 +49,8 @@ sub startup {
|
||||||
|
|
||||||
my $r = $self->routes;
|
my $r = $self->routes;
|
||||||
$r->any('/')->to('root#index');
|
$r->any('/')->to('root#index');
|
||||||
$r->any('/admin')->to('admin#index');
|
$r->get('/admin')->to('admin#index');
|
||||||
|
$r->post('/admin')->to('admin#login');
|
||||||
my $api = $r->under('/api' => sub {
|
my $api = $r->under('/api' => sub {
|
||||||
my $c = shift;
|
my $c = shift;
|
||||||
|
|
||||||
|
@ -99,6 +100,8 @@ sub startup {
|
||||||
|
|
||||||
my $admin_routes = $r->under('/admin')->to('admin#under');
|
my $admin_routes = $r->under('/admin')->to('admin#under');
|
||||||
|
|
||||||
|
$admin_routes->get('/home')->to('admin#home');
|
||||||
|
|
||||||
$self->hook( before_dispatch => sub {
|
$self->hook( before_dispatch => sub {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
|
@ -324,6 +327,7 @@ $self->helper(expire_current_session => sub {
|
||||||
$self->helper(check_password_email => sub {
|
$self->helper(check_password_email => sub {
|
||||||
my ( $c, $email, $password ) = @_;
|
my ( $c, $email, $password ) = @_;
|
||||||
my $user = $c->schema->resultset('User')->find({ email => $email });
|
my $user = $c->schema->resultset('User')->find({ email => $email });
|
||||||
|
return undef unless defined $user;
|
||||||
my $ppr = Authen::Passphrase::BlowfishCrypt->from_crypt($user->hashedpassword);
|
my $ppr = Authen::Passphrase::BlowfishCrypt->from_crypt($user->hashedpassword);
|
||||||
return $ppr->match($password);
|
return $ppr->match($password);
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,4 +15,18 @@ sub under {
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub login {
|
||||||
|
my $c = shift;
|
||||||
|
|
||||||
|
if ( $c->authenticate($c->param('email'), $c->param('password')) ) {
|
||||||
|
$c->redirect_to('/admin/home');
|
||||||
|
} else {
|
||||||
|
$c->redirect_to('/admin');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub home {
|
||||||
|
my $c = shift;
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
28
templates/admin/home.html.ep
Normal file
28
templates/admin/home.html.ep
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
% layout 'default';
|
||||||
|
% title 'LocalLoop Admin - Login';
|
||||||
|
% content_for css => begin
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background: whitesmoke;
|
||||||
|
padding-top: 54px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel {
|
||||||
|
background: white;
|
||||||
|
padding: 16px;
|
||||||
|
-webkit-box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.2);
|
||||||
|
-moz-box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.2);
|
||||||
|
box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form {
|
||||||
|
margin-top: 20%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
% end
|
||||||
|
% content_for javascript => begin
|
||||||
|
% end
|
||||||
|
<nav class="navbar fixed-top navbar-inverse bg-primary">
|
||||||
|
<a class="navbar-brand" href="#"><%= title %></a>
|
||||||
|
</nav>
|
||||||
|
<div>Admin Pages</div>
|
49
templates/admin/index.html.ep
Normal file
49
templates/admin/index.html.ep
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
% layout 'default';
|
||||||
|
% title 'LocalLoop Admin - Login';
|
||||||
|
% content_for css => begin
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background: whitesmoke;
|
||||||
|
padding-top: 54px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel {
|
||||||
|
background: white;
|
||||||
|
padding: 16px;
|
||||||
|
-webkit-box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.2);
|
||||||
|
-moz-box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.2);
|
||||||
|
box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form {
|
||||||
|
margin-top: 20%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
% end
|
||||||
|
% content_for javascript => begin
|
||||||
|
% end
|
||||||
|
<nav class="navbar fixed-top navbar-inverse bg-primary">
|
||||||
|
<a class="navbar-brand" href="#"><%= title %></a>
|
||||||
|
</nav>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<!-- Fluid Gird, this login box stay in the middle of screen -->
|
||||||
|
<div class="col-5">
|
||||||
|
|
||||||
|
<div class="login-form panel">
|
||||||
|
<form action="<%= url_for %>" method="post">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="login-email">Email Address</label>
|
||||||
|
<input type="email" id="login-email" class="form-control" name="email" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="login-password">Password</label>
|
||||||
|
<input type="password" id="login-password" class="form-control" name="password" required>
|
||||||
|
</div>
|
||||||
|
<input type="submit" class="btn btn-block btn-primary" value="Sign In">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div><!-- Container fluid-->
|
||||||
|
|
20
templates/layouts/default.html.ep
Normal file
20
templates/layouts/default.html.ep
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title><%= title %></title>
|
||||||
|
|
||||||
|
<!-- Bootstrap and jQuery js -->
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
|
%= content_for 'css';
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%= content %>
|
||||||
|
%= content_for 'javascript';
|
||||||
|
</body>
|
||||||
|
</html>
|
Reference in a new issue