diff --git a/handler/routes.go b/handler/routes.go index b103c08..dd8cde4 100644 --- a/handler/routes.go +++ b/handler/routes.go @@ -139,6 +139,39 @@ func NewClient() echo.HandlerFunc { } } +// SetClientStatus handler to enable / disable a client +func SetClientStatus() echo.HandlerFunc { + return func(c echo.Context) error { + data := make(map[string]interface{}) + err := json.NewDecoder(c.Request().Body).Decode(&data) + + if err != nil { + return c.JSON(http.StatusBadRequest, jsonHTTPResponse{false, "Bad post data"}) + } + + clientID := data["id"].(string) + status := data["status"].(bool) + + // initialize database directory + dir := "./db" + db, err := scribble.New(dir, nil) + if err != nil { + log.Error("Cannot initialize the database: ", err) + } + + client := model.Client{} + if err := db.Read("clients", clientID, &client); err != nil { + log.Error("Cannot fetch server interface config from database: ", err) + } + + client.Enabled = status + db.Write("clients", clientID, &client) + log.Infof("Change client %s to status %b", client.ID, status) + + return c.JSON(http.StatusOK, jsonHTTPResponse{true, "ok"}) + } +} + // RemoveClient handler func RemoveClient() echo.HandlerFunc { return func(c echo.Context) error { diff --git a/main.go b/main.go index df6f7b1..bcd4056 100644 --- a/main.go +++ b/main.go @@ -10,6 +10,7 @@ func main() { app.GET("/", handler.WireGuardClients()) app.POST("/new-client", handler.NewClient()) + app.POST("/client/set-status", handler.SetClientStatus()) app.POST("/remove-client", handler.RemoveClient()) app.GET("/wg-server", handler.WireGuardServer()) app.POST("wg-server/interfaces", handler.WireGuardServerInterfaces()) diff --git a/templates/base.html b/templates/base.html index 5b1e923..28d1705 100644 --- a/templates/base.html +++ b/templates/base.html @@ -25,6 +25,10 @@ <link rel="stylesheet" href="static/dist/css/adminlte.min.css"> <!-- Google Font: Source Sans Pro --> <link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700" rel="stylesheet"> + + <!-- START: On page css --> + {{template "top_css" .}} + <!-- END: On page css --> </head> <body class="hold-transition sidebar-mini"> diff --git a/templates/clients.html b/templates/clients.html index 3faf054..2d8d25d 100644 --- a/templates/clients.html +++ b/templates/clients.html @@ -2,6 +2,16 @@ Wireguard Clients {{end}} +{{define "top_css"}} +<style> + .paused-client { + transition: transform .2s; + cursor: pointer; + } + i[class^="paused-client"]:hover { transform: scale(1.5); } +</style> +{{end}} + {{define "username"}} Admin {{end}} @@ -18,14 +28,21 @@ Wireguard Clients {{range .clientDataList}} <div class="col-sm-6"> <div class="info-box"> + <div class="overlay" id="paused_{{.Client.ID}}" {{if eq .Client.Enabled true}}style="display: none;"{{end}}> + <i class="paused-client fas fa-3x fa-play" onclick="resumeClient('{{.Client.ID}}')"></i> + </div> <img src="{{ .QRCode }}" /> <div class="info-box-content"> <div class="btn-group"> <button type="button" class="btn btn-outline-success btn-sm">Download</button> <button type="button" class="btn btn-outline-primary btn-sm">Edit</button> - <button type="button" class="btn btn-outline-warning btn-sm">Disable</button> - <button type="button" class="btn btn-outline-danger btn-sm" data-toggle="modal" data-target="#modal_remove_client" data-clientid="{{ .Client.ID }}" data-clientname="{{ .Client.Name }}">Remove</button> + <button type="button" class="btn btn-outline-warning btn-sm" data-toggle="modal" + data-target="#modal_pause_client" data-clientid="{{ .Client.ID }}" + data-clientname="{{ .Client.Name }}">Disable</button> + <button type="button" class="btn btn-outline-danger btn-sm" data-toggle="modal" + data-target="#modal_remove_client" data-clientid="{{ .Client.ID }}" + data-clientname="{{ .Client.Name }}">Remove</button> </div> <hr> <span class="info-box-text"><i class="fas fa-user"></i> {{ .Client.Name }}</span> @@ -54,6 +71,28 @@ Wireguard Clients </div> </section> +<div class="modal fade" id="modal_pause_client"> + <div class="modal-dialog"> + <div class="modal-content bg-warning"> + <div class="modal-header"> + <h4 class="modal-title">Disable</h4> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">×</span> + </button> + </div> + <div class="modal-body"> + </div> + <div class="modal-footer justify-content-between"> + <button type="button" class="btn btn-outline-dark" data-dismiss="modal">Cancel</button> + <button type="button" class="btn btn-outline-dark" id="pause_client_confirm">Apply</button> + </div> + </div> + <!-- /.modal-content --> + </div> + <!-- /.modal-dialog --> +</div> +<!-- /.modal --> + <div class="modal fade" id="modal_remove_client"> <div class="modal-dialog"> <div class="modal-content bg-danger"> @@ -66,8 +105,8 @@ Wireguard Clients <div class="modal-body"> </div> <div class="modal-footer justify-content-between"> - <button type="button" class="btn btn-outline-light" data-dismiss="modal">Cancel</button> - <button type="button" class="btn btn-outline-light" id="remove_client_confirm">Apply</button> + <button type="button" class="btn btn-outline-dark" data-dismiss="modal">Cancel</button> + <button type="button" class="btn btn-outline-dark" id="remove_client_confirm">Apply</button> </div> </div> <!-- /.modal-content --> @@ -79,6 +118,57 @@ Wireguard Clients {{define "bottom_js"}} <script> + function setClientStatus(clientID, status) { + var data = {"id": clientID, "status": status} + $.ajax({ + cache: false, + method: 'POST', + url: '/client/set-status', + dataType: 'json', + contentType: "application/json", + data: JSON.stringify(data), + success: function (data) { + console.log("Set client " + clientID + " status to " + status) + }, + error: function (jqXHR, exception) { + var responseJson = jQuery.parseJSON(jqXHR.responseText); + toastr.error(responseJson['message']); + } + }); + } + + function resumeClient(clientID) { + setClientStatus(clientID, true); + var divElement = document.getElementById("paused_" + clientID); + divElement.style.display = "none"; + } + + function pauseClient(clientID) { + setClientStatus(clientID, false); + var divElement = document.getElementById("paused_" + clientID); + divElement.style.display = "block"; + } + </script> + <script> + // modal_pause_client modal event + $('#modal_pause_client').on('show.bs.modal', function (event) { + var button = $(event.relatedTarget); + var client_id = button.data('clientid'); + var client_name = button.data('clientname'); + var modal = $(this); + modal.find('.modal-body').text("You are about to disable client " + client_name); + modal.find('#pause_client_confirm').val(client_id); + }) + + // pause_client_confirm button event + $(document).ready(function () { + $('#pause_client_confirm').click(function () { + var client_id = $(this).val(); + pauseClient(client_id); + $('#modal_pause_client').modal('hide'); + }); + }); + // modal_remove_client modal event $('#modal_remove_client').on('show.bs.modal', function (event) { var button = $(event.relatedTarget); diff --git a/templates/global_settings.html b/templates/global_settings.html index 8d612d4..59a13c1 100644 --- a/templates/global_settings.html +++ b/templates/global_settings.html @@ -2,6 +2,9 @@ Global Settings {{end}} +{{define "top_css"}} +{{end}} + {{define "username"}} Admin {{end}} diff --git a/templates/server.html b/templates/server.html index 4abeb6e..cabcc13 100644 --- a/templates/server.html +++ b/templates/server.html @@ -2,6 +2,9 @@ Wireguard Server {{end}} +{{define "top_css"}} +{{end}} + {{define "username"}} Admin {{end}}