From 23ba337de24e88c6aaf6ceb37507997f5c5f4920 Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Sat, 2 Apr 2016 01:09:45 -0400 Subject: fully working edit dialog --- data/stuff/js/util.js | 4 ++ data/stuff/test/auth.js | 97 +++++++++++++++++++++++++++------ src/guff/api/methods.cr | 42 +++++++++++++++ src/guff/api/test.cr | 10 ++-- src/guff/handlers/api.cr | 1 + src/guff/models/user.cr | 111 ++++++++++++++++++++++++++------------ src/guff/views/ecrs/test/auth.ecr | 4 +- 7 files changed, 215 insertions(+), 54 deletions(-) diff --git a/data/stuff/js/util.js b/data/stuff/js/util.js index a6826db..c021499 100644 --- a/data/stuff/js/util.js +++ b/data/stuff/js/util.js @@ -9,4 +9,8 @@ jQuery(function($) { data: args, }); }; + + LuigiTemplate.FILTERS.json = function(val) { + return JSON.stringify(val); + }; }); diff --git a/data/stuff/test/auth.js b/data/stuff/test/auth.js index 5876a41..0776bfd 100644 --- a/data/stuff/test/auth.js +++ b/data/stuff/test/auth.js @@ -5,8 +5,8 @@ jQuery(function($) { "", "", "", @@ -51,7 +51,7 @@ jQuery(function($) { }).done(function(r) { list.html($.map(r.users, function(row) { return TEMPLATES.run('user', $.extend({}, row, { - css: (r.user_id == row.user_id) ? 'active' : '', + row: row, })); }).join('')); }); @@ -74,20 +74,10 @@ jQuery(function($) { var me = $(this); // update highlight - var last = $('#users .active').removeClass('active'); + $('#users .active').removeClass('active'); me.addClass('active'); - // show spinner - me.addClass('disabled').find('.loading').toggleClass('hidden'); - - set_user(me.data('user_id')).always(function() { - // hide spinner - me.removeClass('disabled').find('.loading').toggleClass('hidden'); - }).fail(function(r) { - // restore old highlight - me.removeClass('active'); - last.addClass('active'); - }); + $('#edit-dialog').data('row', me.data('row')).modal('show'); // stop event return false; @@ -100,6 +90,21 @@ jQuery(function($) { $('#add-role').val('guest'); }); + $('#add-dialog').on('shown.bs.modal', function() { + $('#add-name').focus(); + }); + + $('#add-name, #add-email, #add-password').keydown(function(ev) { + if (ev.which == 13) { + setTimeout(function() { + $('#add-confirm').click(); + }, 10); + + // stop event + return false; + } + }); + $('#add-confirm').click(function() { var me = $(this); @@ -130,6 +135,68 @@ jQuery(function($) { return false; }); + $('#edit-dialog').on('show.bs.modal', function() { + var row = $(this).data('row'); + + $.each({ + name: 'user_name', + email: 'email', + role: 'role_name', + }, function(id, col) { + $('#edit-' + id).val(row[col]); + }); + }); + + $('#edit-dialog').on('shown.bs.modal', function() { + $('#edit-name').focus(); + }); + + $('#edit-dialog').on('hide.bs.modal', function() { + // clear highlight + $('#users .active').removeClass('active'); + }); + + $('#edit-name, #edit-email').keydown(function(ev) { + if (ev.which == 13) { + setTimeout(function() { + $('#edit-confirm').click(); + }, 10); + + // stop event + return false; + } + }); + + $('#edit-confirm').click(function() { + var me = $(this), + user_id = $('#edit-dialog').data('row').user_id; + + if (me.hasClass('disabled')) + return false; + + // toggle loading + me.toggleClass('disabled').find('.loading').toggleClass('hidden'); + + send('test/edit_user', { + user_id: user_id, + name: $('#edit-name').val(), + email: $('#edit-email').val(), + role: $('#edit-role').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); + reload(); + $('#edit-dialog').modal('hide'); + }); + + // stop event + return false; + }); + $('#login').click(function() { var me = $(this); diff --git a/src/guff/api/methods.cr b/src/guff/api/methods.cr index fce6911..9b8aa3b 100644 --- a/src/guff/api/methods.cr +++ b/src/guff/api/methods.cr @@ -403,6 +403,48 @@ module Guff }, }, + "edit_user": { + text: "Test edit user", + + args: { + "user_id": { + text: "User ID", + type: :int, + required: true, + }, + + "name": { + text: "Name of user", + type: :text, + required: false, + }, + + "active": { + text: "Is this user active?", + type: :bool, + required: false, + }, + + "role": { + text: "Role of user", + type: :text, + required: false, + }, + + "email": { + text: "Email address of user", + type: :text, + required: false, + }, + + "password": { + text: "Password of user", + type: :text, + required: false, + }, + }, + }, + "login": { text: "Test user login.", diff --git a/src/guff/api/test.cr b/src/guff/api/test.cr index decc5ec..91a729c 100644 --- a/src/guff/api/test.cr +++ b/src/guff/api/test.cr @@ -65,14 +65,16 @@ module Guff::API::TestAPI { "ok": true, "user_id": user_id } end - private def do_test_update_user( + private def do_test_edit_user( context : HTTP::Server::Context, args : Hash(String, String) ) - @models.user.update_user(args["user_id"].to_i64, - name: args["name"]? ? args["name"] : nil, + @models.user.edit_user(args["user_id"].to_i64, + name: args["name"]?, active: args["active"]? ? args["active"] == "t" : nil, - role: args["role"]? ? args["role"] : nil + role: args["role"]?, + email: args["email"]?, + password: args["password"]?, ) { "ok": true } diff --git a/src/guff/handlers/api.cr b/src/guff/handlers/api.cr index d9208b1..523f2f2 100644 --- a/src/guff/handlers/api.cr +++ b/src/guff/handlers/api.cr @@ -139,6 +139,7 @@ class Guff::Handlers::APIHandler < Guff::Handler get_users, set_user, add_user, + edit_user, login, ], }) diff --git a/src/guff/models/user.cr b/src/guff/models/user.cr index bdbb0de..d440c5c 100644 --- a/src/guff/models/user.cr +++ b/src/guff/models/user.cr @@ -23,7 +23,7 @@ class Guff::UserModel < Guff::Model INSERT INTO users(user_name) VALUES (:user_name) ", - update_user: " + edit_user: " UPDATE users SET %{sets} WHERE user_id = :user_id @@ -38,6 +38,12 @@ class Guff::UserModel < Guff::Model (:user_id, :email, :pass_hash) ", + edit_login: " + UPDATE user_logins + SET %{sets} + WHERE user_id = :user_id + ", + login: " SELECT a.user_id, a.pass_hash @@ -92,7 +98,7 @@ class Guff::UserModel < Guff::Model # set active and/or role if active || role - update_user(user_id, + edit_user(user_id, active: active, role: role, ) @@ -111,38 +117,46 @@ class Guff::UserModel < Guff::Model user_id end - def update_user( - user_id : Int64, - name : String? = nil, - active : Bool? = nil, - role : String? = nil, + def edit_user( + user_id : Int64, + name : String? = nil, + active : Bool? = nil, + role : String? = nil, + email : String? = nil, + password : String? = nil, ) - sets = [] of String - args = { "user_id": user_id.to_s } + transaction do + sets = [] of String + args = { "user_id": user_id.to_s } - if name != nil - args["name"] = name.not_nil! - sets << "user_name = :name" - end + if name != nil + args["name"] = name.not_nil! + sets << "user_name = :name" + end - if active != nil - args["is_active"] = active.not_nil! ? "1" : "0" - sets << "is_active = :is_active" - end + if active != nil + args["is_active"] = active.not_nil! ? "1" : "0" + sets << "is_active = :is_active" + end - if role != nil - args["role"] = role.not_nil! - sets << " - role_id = (SELECT role_id - FROM roles - WHERE role_name = :role) - " - end + if role != nil + args["role"] = role.not_nil! + sets << " + role_id = (SELECT role_id + FROM roles + WHERE role_name = :role) + " + end - # exec query - query(:update_user, args, { - "sets": sets.join(", "), - }) if sets.size > 0 + # exec query + query(:edit_user, args, { + "sets": sets.join(", "), + }) if sets.size > 0 + + if email != nil || password != nil + edit_login(user_id, email, password) + end + end end def delete_login(user_id : Int64) @@ -156,11 +170,8 @@ class Guff::UserModel < Guff::Model email : String, password : String, ) - # TODO: check password strength - raise "password too short" if password.size < 4 - # hash password - pass_hash = Crypto::Bcrypt::Password.create(password, cost: 10).to_s + pass_hash = hash_password(password) transaction do # clear old credentials @@ -175,6 +186,32 @@ class Guff::UserModel < Guff::Model end end + private def edit_login( + user_id : Int64, + email : String? = nil, + password : String? = nil, + ) + transaction do + sets = [] of String + args = { "user_id": user_id.to_s } + + if email != nil + args["email"] = email.not_nil! + sets << "email = :email" + end + + if password != nil + args["pass_hash"] = hash_password(password.not_nil!) + sets << "pass_hash = :pass_hash" + end + + # exec query + query(:edit_login, args, { + "sets": sets.join(", "), + }) if sets.size > 0 + end + end + def login( email : String, password : String @@ -198,4 +235,12 @@ class Guff::UserModel < Guff::Model # return user id row["user_id"] as Int64 end + + private def hash_password(password : String) + # TODO: check password strength + raise "password too short" if password.size < 4 + + # hash password + Crypto::Bcrypt::Password.create(password, cost: 10).to_s + end end diff --git a/src/guff/views/ecrs/test/auth.ecr b/src/guff/views/ecrs/test/auth.ecr index b683c5c..ab9f552 100644 --- a/src/guff/views/ecrs/test/auth.ecr +++ b/src/guff/views/ecrs/test/auth.ecr @@ -228,7 +228,7 @@ -