diff --git a/pkg/api/user/list.go b/pkg/api/user/list.go new file mode 100644 index 0000000..3bd4f25 --- /dev/null +++ b/pkg/api/user/list.go @@ -0,0 +1,50 @@ +package user + +import ( + "encoding/json" + "log" + "net/http" + "strconv" + + "github.com/Ennovar/gPanel/pkg/database" +) + +func List(res http.ResponseWriter, req *http.Request, logger *log.Logger, dir string) bool { + if req.Method != "GET" { + 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 + } + + 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() + + users, err := ds.ListAllUsers() + if err != nil { + logger.Println(req.URL.Path + "::" + err.Error()) + http.Error(res, err.Error(), http.StatusInternalServerError) + return false + } + + if len(users) > 0 { + b, err := json.Marshal(users) + if err != nil { + logger.Println(req.URL.Path + "::" + err.Error()) + http.Error(res, err.Error(), http.StatusInternalServerError) + return false + } + + res.WriteHeader(http.StatusOK) + res.Write(b) + + return true + } + + res.WriteHeader(http.StatusNoContent) + return true +} diff --git a/pkg/database/users.go b/pkg/database/users.go new file mode 100644 index 0000000..be5eb0e --- /dev/null +++ b/pkg/database/users.go @@ -0,0 +1,20 @@ +package database + +import "github.com/boltdb/bolt" + +func (ds *Datastore) ListAllUsers() ([]string, error) { + users := []string{} + + ds.handle.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte(BUCKET_USERS)) + c := b.Cursor() + + for k, _ := c.First(); k != nil; k, _ = c.Next() { + users = append(users, string(k)) + } + + return nil + }) + + return users, nil +} diff --git a/pkg/gpserver/apihandler.go b/pkg/gpserver/apihandler.go index e4c290a..f927457 100644 --- a/pkg/gpserver/apihandler.go +++ b/pkg/gpserver/apihandler.go @@ -72,6 +72,8 @@ func (con *Controller) apiHandler(res http.ResponseWriter, req *http.Request) (b return true, user.Register(res, req, con.APILogger, con.Directory) case "/user/logout": return true, user.Logout(res, req, con.APILogger, con.Directory) + case "/user/list": + return true, user.List(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/new.js b/server/document_root/assets/js/panelHandlers/users/new.js new file mode 100644 index 0000000..6f2f1b9 --- /dev/null +++ b/server/document_root/assets/js/panelHandlers/users/new.js @@ -0,0 +1,80 @@ +var userModal = jQuery('.user-management-modal'); + +var usernameInput = jQuery('#addUserUsername'); +var passwordInput = jQuery('#addUserPassword'); +var passwordInputRetype = jQuery('#addUserPasswordRetype'); + +jQuery('._js_add-user-form').on('submit', function(e){ + e.preventDefault(); + + if((usernameInput && usernameInput.val()) && (passwordInput && passwordInput.val()) && (passwordInputRetype && passwordInputRetype.val())) { + if(passwordInput.val() == passwordInputRetype.val()) { + var requestData = {}; + requestData["user"] = usernameInput.val(); + requestData["pass"] = passwordInput.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) { + listCurrentUsers(); + } + 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('Password fields do not match.'); + } + } + else { + alert('All fields must contain values.'); + } +}); + +jQuery('._js_add-user-generate-password').on('click', function(e){ + e.preventDefault(); + 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); +}); + +jQuery('._js_user-management-show-password').on('change', function(e){ + e.preventDefault(); + + if(this.checked) { + toggleShowPassword(true); + } + else { + toggleShowPassword(false); + } +}); + +function toggleShowPassword(show) { + if(show) { + jQuery('._js_user-management-show-password').prop('checked', true); + passwordInput.attr('type', 'text'); + passwordInputRetype.attr('type', 'text'); + } + else { + jQuery('._js_user-management-show-password').prop('checked', false); + passwordInput.attr('type', 'password'); + passwordInputRetype.attr('type', 'password'); + } +} diff --git a/server/document_root/assets/js/panelHandlers/users/open.js b/server/document_root/assets/js/panelHandlers/users/open.js new file mode 100644 index 0000000..44d5f40 --- /dev/null +++ b/server/document_root/assets/js/panelHandlers/users/open.js @@ -0,0 +1,50 @@ +var userModal = jQuery('.user-management-modal'); + +jQuery('._js_manage-users').on('click', function(e){ + e.preventDefault(); + + jQuery('._js_user-management-show-password').prop('checked', false); + + listCurrentUsers(); + userModal.modal('show'); +}); + +function listCurrentUsers() { + var display = jQuery('._js_current-users'); + display.html(''); + var requestData = {}; + + var xhr = new XMLHttpRequest(); + xhr.open('GET', 'api/user/list', true); + xhr.send(); + + xhr.onloadend = function() { + if(xhr.status == 200) { + if(xhr.response != undefined && xhr.response.length != 0) { + jsonResponse = JSON.parse(xhr.response) + jQuery.each(jsonResponse, function(k, v) { + display.append('

'+v+'

'); + }); + } + else { + display.html('

An error has occurred, please refresh. If problem persists please contact your administrator.

'); + } + } + else if(xhr.status == 204) { + if(xhr.response != undefined && xhr.response.length != 0) { + display.html('

There are no users in the server. This is a problem, this shouldn\'t be like this.

'); + } + else { + display.html('

An error has occurred, please refresh. If problem persists please contact your administrator.

'); + } + } + else { + if(xhr.response != undefined && xhr.response.length != 0) { + display.html('

Error: ' + xhr.response + '

'); + } + else { + display.html('

An error has occurred, please refresh. If problem persists please contact your administrator.

'); + } + } + } +} diff --git a/server/document_root/gPanel.html b/server/document_root/gPanel.html index 2d3ec54..ac4accd 100644 --- a/server/document_root/gPanel.html +++ b/server/document_root/gPanel.html @@ -173,6 +173,64 @@ + + +
@@ -202,6 +260,20 @@
+ +
+
+
+
+

Server Users

+
View, edit, update, and remove users that can access the gPanel Server
+
+ +
+
+
+
+