Add missing server delete: handler, route, and UI button

DeleteServer already existed in the store layer (refuses if clients
still reference the server) but was never wired up anywhere, so there
was no way to actually remove a server from the UI or API.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
sysops
2026-07-12 16:38:22 +02:00
co-authored by Claude Sonnet 5
parent 9c90e3f49a
commit 0000643187
3 changed files with 45 additions and 0 deletions
+13
View File
@@ -709,6 +709,19 @@ func CreateServer(db store.IStore) echo.HandlerFunc {
}
}
// RemoveServer handler deletes a server, refusing if any client still
// references it (see store.DeleteServer). Admin-only.
func RemoveServer(db store.IStore) echo.HandlerFunc {
return func(c echo.Context) error {
serverID := c.Param("id")
if err := db.DeleteServer(serverID); err != nil {
return c.JSON(http.StatusBadRequest, jsonHTTPResponse{false, err.Error()})
}
log.Infof("Removed server %s", serverID)
return c.JSON(http.StatusOK, jsonHTTPResponse{true, "Server removed successfully"})
}
}
// NewClient handler
func NewClient(db store.IStore) echo.HandlerFunc {
return func(c echo.Context) error {
+1
View File
@@ -264,6 +264,7 @@ func main() {
app.POST(util.BasePath+"/servers/:id/settings", handler.SaveServerSettingsHandler(db), handler.ValidSession, handler.ContentTypeJson, handler.NeedsAdmin)
app.POST(util.BasePath+"/servers/:id/interface", handler.UpdateServerInterfaceHandler(db), handler.ValidSession, handler.ContentTypeJson, handler.NeedsAdmin)
app.POST(util.BasePath+"/servers/:id/keypair", handler.UpdateServerKeyPairHandler(db), handler.ValidSession, handler.ContentTypeJson, handler.NeedsAdmin)
app.POST(util.BasePath+"/servers/:id/delete", handler.RemoveServer(db), handler.ValidSession, handler.ContentTypeJson, handler.NeedsAdmin)
app.POST(util.BasePath+"/backup/download", handler.DownloadBackup(db), handler.ValidSession, handler.ContentTypeJson, handler.NeedsAdmin)
app.GET(util.BasePath+"/api/clients", handler.GetClients(db), handler.ValidSession)
app.GET(util.BasePath+"/api/client/:id", handler.GetClient(db), handler.ValidSession)
+31
View File
@@ -203,6 +203,9 @@ All Servers
<button type="button" class="btn btn-outline-secondary btn-sm" data-toggle="modal"
data-target="#modal_server_interface" data-serverid="${obj.id}">Interface</button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-outline-danger btn-sm btn-delete-server" data-serverid="${obj.id}" data-servername="${safeName}">Delete</button>
</div>
<hr>
<span class="info-box-text"><i class="fas fa-server"></i> ${safeName}</span>
<span class="info-box-text"><i class="fas fa-fingerprint"></i> ID: ${obj.id}</span>
@@ -470,6 +473,34 @@ All Servers
});
});
// Delete server button: rendered dynamically, use event delegation
$(document).ready(function () {
$('#servers-list').on('click', '.btn-delete-server', function () {
const serverId = $(this).data('serverid');
const serverName = $(this).data('servername');
if (!confirm("Are you sure you want to delete server \"" + serverName + "\" (" + serverId + ")?\n" +
"This only works if no clients are assigned to it anymore.")) {
return;
}
$.ajax({
cache: false,
method: 'POST',
url: '{{.basePath}}/servers/' + serverId + '/delete',
dataType: 'json',
contentType: "application/json",
success: function (data) {
toastr.success("Server deleted successfully");
$('#servers-list').empty();
populateServersList();
},
error: function (jqXHR, exception) {
const responseJson = jQuery.parseJSON(jqXHR.responseText);
toastr.error(responseJson['message']);
}
});
});
});
$(document).ready(function () {
$.validator.setDefaults({
submitHandler: function (form) {