aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/stuff/test/auth.js40
-rw-r--r--src/guff/api/methods.cr20
-rw-r--r--src/guff/api/test.cr10
-rw-r--r--src/guff/handlers/api.cr2
-rw-r--r--src/guff/models/user.cr37
-rw-r--r--src/guff/views/ecrs/test/auth.ecr66
6 files changed, 168 insertions, 7 deletions
diff --git a/data/stuff/test/auth.js b/data/stuff/test/auth.js
index 1bba095..408010b 100644
--- a/data/stuff/test/auth.js
+++ b/data/stuff/test/auth.js
@@ -91,6 +91,9 @@ jQuery(function($) {
$('#create-user').click(function() {
var me = $(this);
+ if (me.hasClass('disabled'))
+ return false;
+
// toggle loading
me.toggleClass('disabled').find('.loading').toggleClass('hidden');
@@ -113,6 +116,43 @@ jQuery(function($) {
return false;
});
+ $('#login').click(function() {
+ var me = $(this);
+
+ if (me.hasClass('disabled'))
+ return false;
+
+ // toggle loading
+ me.toggleClass('disabled').find('.loading').toggleClass('hidden');
+
+ send('test/login', {
+ email: $('#login-email').val(),
+ password: $('#login-password').val(),
+ }).always(function() {
+ // toggle loading
+ me.toggleClass('disabled').find('.loading').toggleClass('hidden');
+ }).fail(function(r) {
+ alert('Error ' + r.responseText);
+ }).done(function(r) {
+ console.log(r);
+ });
+
+ // stop event
+ return false;
+ });
+
+ $('#login-user, #login-password').keydown(function(ev) {
+ if (ev.which == 13) {
+ setTimeout(function() {
+ // trigger login
+ $('#login').click();
+ }, 10);
+
+ // stop event
+ return false;
+ }
+ });
+
$('#reload').click(reload);
// load users
diff --git a/src/guff/api/methods.cr b/src/guff/api/methods.cr
index 970e41f..fce6911 100644
--- a/src/guff/api/methods.cr
+++ b/src/guff/api/methods.cr
@@ -368,7 +368,7 @@ module Guff
},
"add_user": {
- text: "Add new user",
+ text: "Test add new user",
args: {
"name": {
@@ -402,6 +402,24 @@ module Guff
},
},
},
+
+ "login": {
+ text: "Test user login.",
+
+ args: {
+ "email": {
+ text: "Email address of user",
+ type: :text,
+ required: true,
+ },
+
+ "password": {
+ text: "Password of user",
+ type: :text,
+ required: true,
+ },
+ },
+ },
}
}
diff --git a/src/guff/api/test.cr b/src/guff/api/test.cr
index 059f670..448cadf 100644
--- a/src/guff/api/test.cr
+++ b/src/guff/api/test.cr
@@ -82,7 +82,7 @@ module Guff::API::TestAPI
user_id = @models.user.add_user(args["name"].not_nil!,
active: args["active"]? ? args["active"] == "t" : nil,
role: args["role"]?,
- email: args["name"]?,
+ email: args["email"]?,
password: args["password"]?,
)
{ "ok": true, "user_id": user_id }
@@ -120,4 +120,12 @@ module Guff::API::TestAPI
@models.user.remove_login(args["user_id"].to_i)
{ "ok": true }
end
+
+ private def do_test_login(
+ context : HTTP::Server::Context,
+ args : Hash(String, String)
+ )
+ user_id = @models.user.login(args["email"], args["password"]).to_i
+ { "ok": true, "user_id": user_id }
+ end
end
diff --git a/src/guff/handlers/api.cr b/src/guff/handlers/api.cr
index 0f7f963..d9208b1 100644
--- a/src/guff/handlers/api.cr
+++ b/src/guff/handlers/api.cr
@@ -139,7 +139,7 @@ class Guff::Handlers::APIHandler < Guff::Handler
get_users,
set_user,
add_user,
- update_user,
+ login,
],
})
rescue e
diff --git a/src/guff/models/user.cr b/src/guff/models/user.cr
index 98ae10b..28e317e 100644
--- a/src/guff/models/user.cr
+++ b/src/guff/models/user.cr
@@ -20,6 +20,18 @@ class Guff::UserModel < Guff::Model
INSERT INTO user_logins(user_id, email, pass_hash) VALUES
(:user_id, :email, :pass_hash)
",
+
+ login: "
+ SELECT a.user_id,
+ a.pass_hash
+
+ FROM user_logins a
+ JOIN users b
+ ON (b.user_id = a.user_id AND
+ b.is_active)
+
+ WHERE a.email = :email
+ ",
})
def initialize(models : Models)
@@ -125,6 +137,7 @@ class Guff::UserModel < Guff::Model
# hash password
pass_hash = Crypto::Bcrypt::Password.create(password, cost: 10).to_s
+ # puts "user_id = #{user_id}, email = #{email}, password = #{password}, pass_hash = #{pass_hash}"
transaction do
# clear old credentials
@@ -138,4 +151,28 @@ class Guff::UserModel < Guff::Model
}, nil)
end
end
+
+ def login(
+ email : String,
+ password : String
+ )
+ # map email to user id and pass hash
+ row = row(:login, {
+ "email": email,
+ }, nil)
+
+ raise "invalid login" unless row
+
+ # shut compiler up
+ row = row.not_nil!
+
+ # get pass hash from db
+ pass_hash = Crypto::Bcrypt::Password.new(row["pass_hash"].to_s)
+
+ # compare hash against password
+ raise "invalid login" unless pass_hash == password
+
+ # return user id
+ row["user_id"] as Int64
+ end
end
diff --git a/src/guff/views/ecrs/test/auth.ecr b/src/guff/views/ecrs/test/auth.ecr
index 89d3283..ec6e9a8 100644
--- a/src/guff/views/ecrs/test/auth.ecr
+++ b/src/guff/views/ecrs/test/auth.ecr
@@ -15,7 +15,7 @@
</div><!-- navbar -->
<div class='container'>
- <div class='col-md-8 col-md-offset-2'>
+ <div class='col-md-6'>
<div class='panel panel-default'>
<div class='panel-heading'>
<b>
@@ -46,11 +46,13 @@
</span><!-- list-group-item -->
</div><!-- list-group -->
</div><!-- panel -->
+ </div><!-- col-md-6 -->
+ <div class='col-md-6'>
<div class='panel panel-default'>
<div class='panel-heading'>
<b>
- <i class='fa fa-user'></i>
+ <i class='fa fa-user-plus'></i>
Create User
</b>
</div><!-- panel-heading -->
@@ -123,12 +125,68 @@
</span>
<span class='loading'>
- <i class='fa fa-plus-square'></i>
+ <i class='fa fa-user-plus'></i>
Create User
</span>
</button>
</div><!-- form-group -->
</div><!-- panel-body -->
</div><!-- panel -->
- </div><!-- col-md-8 -->
+
+ <div class='panel panel-default'>
+ <div class='panel-heading'>
+ <b>
+ <i class='fa fa-lock'></i>
+ Login
+ </b>
+ </div><!-- panel-heading -->
+
+ <div class='panel-body'>
+ <div class='form-group'>
+ <label for='login-email'>
+ Email
+ </label>
+
+ <input
+ type='text'
+ id='login-email'
+ class='form-control'
+ title='Enter email address.'
+ placeholder='foo@example.com'
+ />
+ </div><!-- form-group -->
+
+ <div class='form-group'>
+ <label for='login-password'>
+ Password
+ </label>
+
+ <input
+ type='password'
+ id='login-password'
+ class='form-control'
+ title='Enter password.'
+ />
+ </div><!-- form-group -->
+
+ <div class='form-group'>
+ <button
+ id='login'
+ class='btn btn-primary'
+ title='Log in.'
+ >
+ <span class='hidden loading'>
+ <i class='fa fa-spinner fa-spin'></i>
+ Please Wait...
+ </span>
+
+ <span class='loading'>
+ <i class='fa fa-unlock-alt'></i>
+ Log In
+ </span>
+ </button>
+ </div><!-- form-group -->
+ </div><!-- panel-body -->
+ </div><!-- panel -->
+ </div><!-- col-md-6 -->
</div><!-- container -->