diff --git a/pkg/api/user/update_password.go b/pkg/api/user/update_password.go new file mode 100644 index 0000000..e4a3a25 --- /dev/null +++ b/pkg/api/user/update_password.go @@ -0,0 +1,63 @@ +package user + +import ( + "encoding/json" + "log" + "net/http" + "strconv" + + "github.com/Ennovar/gPanel/pkg/database" + "github.com/Ennovar/gPanel/pkg/encryption" +) + +func UpdatePassword(res http.ResponseWriter, req *http.Request, logger *log.Logger, dir string) bool { + if req.Method != "UPDATE" { + logger.Println(req.URL.Path + "::" + req.Method + "::" + strconv.Itoa(http.StatusMethodNotAllowed) + "::" + http.StatusText(http.StatusMethodNotAllowed)) + http.Error(res, req.Method+" HTTP method is unsupported for this API.", http.StatusMethodNotAllowed) + return false + } + + var updatePasswordRequestData struct { + User string `json:"user"` + Pass string `json:"pass"` + } + + err := json.NewDecoder(req.Body).Decode(&updatePasswordRequestData) + if err != nil { + logger.Println(req.URL.Path + "::" + err.Error()) + http.Error(res, err.Error(), http.StatusBadRequest) + return false + } + + ds, err := database.Open(dir + database.DB_MAIN) + if err != nil || ds == nil { + logger.Println(req.URL.Path + "::" + err.Error()) + http.Error(res, err.Error(), http.StatusInternalServerError) + return false + } + defer ds.Close() + + var userDatabaseData struct { + Pass string `json:"pass"` + Secret string `json:"secret"` + } + + userDatabaseData.Pass, err = encryption.HashPassword(updatePasswordRequestData.Pass) + if err != nil { + logger.Println(req.URL.Path + "::" + err.Error()) + http.Error(res, err.Error(), http.StatusInternalServerError) + return false + } + + userDatabaseData.Secret = "" + + err = ds.Put(database.BUCKET_USERS, []byte(updatePasswordRequestData.User), userDatabaseData) + if err != nil { + logger.Println(req.URL.Path + "::" + err.Error()) + http.Error(res, err.Error(), http.StatusInternalServerError) + return false + } + + res.WriteHeader(http.StatusNoContent) + return true +} diff --git a/pkg/gpserver/apihandler.go b/pkg/gpserver/apihandler.go index 8fbb074..8fe994f 100644 --- a/pkg/gpserver/apihandler.go +++ b/pkg/gpserver/apihandler.go @@ -76,6 +76,8 @@ func (con *Controller) apiHandler(res http.ResponseWriter, req *http.Request) (b return true, user.List(res, req, con.APILogger, con.Directory) case "/user/delete": return true, user.Delete(res, req, con.APILogger, con.Directory) + case "/user/update_password": + return true, user.UpdatePassword(res, req, con.APILogger, con.Directory) case "/bundle/create": return true, bundle.Create(res, req, con.APILogger, con.Bundles) case "/bundle/list": diff --git a/server/document_root/assets/js/panelHandlers/users/delete.js b/server/document_root/assets/js/panelHandlers/users/delete.js index a764aac..e7f9c47 100644 --- a/server/document_root/assets/js/panelHandlers/users/delete.js +++ b/server/document_root/assets/js/panelHandlers/users/delete.js @@ -3,6 +3,7 @@ jQuery(document).on('click', '._js_user-management-delete', function(e){ if(!jQuery(this).attr('data') || jQuery(this).attr('data') == "") { alert("An error has occurred, please refresh and try again. If problem persists please contact your administrator."); + return; } var ensure = confirm('Are you sure you want to delete the user "' + jQuery(this).attr('data') + '"?'); diff --git a/server/document_root/assets/js/panelHandlers/users/new.js b/server/document_root/assets/js/panelHandlers/users/new.js index 6f2f1b9..0ff0580 100644 --- a/server/document_root/assets/js/panelHandlers/users/new.js +++ b/server/document_root/assets/js/panelHandlers/users/new.js @@ -43,17 +43,23 @@ jQuery('._js_add-user-form').on('submit', function(e){ jQuery('._js_add-user-generate-password').on('click', function(e){ e.preventDefault(); + + var genpass = generatePassword(); + + toggleShowPassword(true); + passwordInput.prop('value', genpass); + passwordInputRetype.prop('value', genpass); +}); + +function generatePassword() { var gen = ""; var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+-[]:;<>?"; for (var i = 0; i < 32; i++) { gen += chars.charAt(Math.floor(Math.random() * chars.length)); } - - toggleShowPassword(true); - passwordInput.prop('value', gen); - passwordInputRetype.prop('value', gen); -}); + return gen +} jQuery('._js_user-management-show-password').on('change', function(e){ e.preventDefault(); diff --git a/server/document_root/assets/js/panelHandlers/users/new_password.js b/server/document_root/assets/js/panelHandlers/users/new_password.js new file mode 100644 index 0000000..391c545 --- /dev/null +++ b/server/document_root/assets/js/panelHandlers/users/new_password.js @@ -0,0 +1,107 @@ +var userModal = jQuery('.user-management-modal'); +var newPassModal = jQuery('.new-pass-modal'); + +var newPassword = jQuery('#updatePassword'); +var newPasswordRetype = jQuery('#updatePasswordRetype'); +var newPasswordUsername = jQuery('#updatePasswordUsername'); + +jQuery(document).on('click', '._js_user-management-new-password', function(e){ + e.preventDefault(); + + if(!jQuery(this).attr('data') || jQuery(this).attr('data') == "") { + alert("An error has occurred, please refresh and try again. If problem persists please contact your administrator."); + return; + } + + var username = jQuery(this).attr('data'); + newPasswordUsername.attr('value', username); + + newPassModal.find('.modal-title').html('Changing password for "'+username+'"'); + toggleShowPasswordNewPassword(false); + + userModal.modal('hide'); + newPassModal.modal('show'); +}); + +jQuery('._js_back-to-user-management').on('click', function(e){ + e.preventDefault(); + + newPassModal.modal('hide'); + userModal.modal('show'); +}); + +jQuery('._js_update-password-form').on('submit', function(e){ + e.preventDefault(); + + if((newPassword && newPassword.val()) && (newPasswordRetype && newPasswordRetype.val()) && (newPasswordUsername && newPasswordUsername.val())) { + if(newPassword.val() == newPasswordRetype.val()) { + var ensure = confirm("Are you sure you want to change the password of user \"" + newPasswordUsername.val() + "\"?"); + if(ensure) { + var requestData = {}; + requestData["user"] = newPasswordUsername.val(); + requestData["pass"] = newPassword.val(); + + var xhr = new XMLHttpRequest(); + xhr.open(jQuery(this).attr('method'), jQuery(this).attr('action'), true); + xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); + xhr.send(JSON.stringify(requestData)); + + xhr.onloadend = function() { + if(xhr.status == 204) { + alert("Password successfully updated."); + newPassModal.modal('hide'); + userModal.modal('show'); + } + else { + if(xhr.response != undefined && xhr.response.length != 0) { + alert('Error: ' + xhr.response); + } + else { + alert('An error has occurred, refresh and try again. If problem persists please contact your administrator.'); + } + } + } + } + } + else { + alert("Passwords must match."); + } + } + else { + alert("All fields need to be filled out"); + } +}); + +jQuery('._js_update-password-show-password').on('change', function(e){ + e.preventDefault(); + + if(this.checked) { + toggleShowPasswordNewPassword(true); + } + else { + toggleShowPasswordNewPassword(false); + } +}); + +jQuery('._js_update-password-generate-password').on('click', function(e){ + e.preventDefault(); + + var genpass = generatePassword(); + + toggleShowPasswordNewPassword(true); + newPassword.prop('value', genpass); + newPasswordRetype.prop('value', genpass); +}); + +function toggleShowPasswordNewPassword(show) { + if(show) { + jQuery('._js_update-password-show-password').prop('checked', true); + newPassword.attr('type', 'text'); + newPasswordRetype.attr('type', 'text'); + } + else { + jQuery('._js_update-password-show-password').prop('checked', false); + newPassword.attr('type', 'password'); + newPasswordRetype.attr('type', 'password'); + } +} diff --git a/server/document_root/gPanel.html b/server/document_root/gPanel.html index f15de11..386af20 100644 --- a/server/document_root/gPanel.html +++ b/server/document_root/gPanel.html @@ -231,6 +231,53 @@ + + +
@@ -318,6 +365,7 @@ +