feat: tag endpoints for servers

This commit is contained in:
2026-08-04 13:34:22 +01:00
parent fef0b7c7a1
commit e00a0da5d9
+51 -1
View File
@@ -51,6 +51,9 @@ func RegisterRoutes(r *gin.Engine) {
apiGroup.POST("/license", auth.RequireRole("owner"), postLicence)
apiGroup.GET("/servers", listServers)
// Static segment, registered alongside /servers/:id exactly as
// /servers/new already is — gin resolves statics ahead of wildcards.
apiGroup.GET("/servers/tags", listKnownTags)
apiGroup.POST("/servers", createServer)
apiGroup.GET("/servers/new", newServer)
apiGroup.POST("/servers/new", newServer)
@@ -59,6 +62,7 @@ func RegisterRoutes(r *gin.Engine) {
apiGroup.POST("/servers/:id/generate-key", generateKey)
apiGroup.POST("/servers/:id/update-agent", updateAgent)
apiGroup.POST("/servers/:id/apply-updates", applyUpdates)
apiGroup.PUT("/servers/:id/tags", putServerTags)
apiGroup.GET("/agent/latest-version", getLatestAgentVersion)
@@ -119,7 +123,12 @@ func RegisterRoutes(r *gin.Engine) {
}
func listServers(c *gin.Context) {
servers, err := services.ListServers(auth.InstanceID(c))
sel, err := services.ParseTagFilters(c.QueryArray("tag"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
servers, err := services.ListServersFiltered(auth.InstanceID(c), sel)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
@@ -127,6 +136,47 @@ func listServers(c *gin.Context) {
c.JSON(http.StatusOK, servers)
}
func listKnownTags(c *gin.Context) {
tags, err := services.KnownTags(auth.InstanceID(c))
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, tags)
}
func putServerTags(c *gin.Context) {
var body struct {
Tags map[string]string `json:"tags"`
}
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid body"})
return
}
instanceID := auth.InstanceID(c)
serverID := c.Param("id")
before, err := services.GetServer(instanceID, serverID)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "server not found"})
return
}
if err := services.SetServerTags(instanceID, serverID, body.Tags); err != nil {
if errors.Is(err, services.ErrInvalidTag) {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
services.LogEvent(instanceID, "server.tags_updated", actorFromCtx(c), serverID, "",
fmt.Sprintf("tags %v -> %v", before.Tags, body.Tags))
c.JSON(http.StatusOK, gin.H{"tags": body.Tags})
}
func createServer(c *gin.Context) {
s, token, err := services.CreateServer(auth.InstanceID(c))
if err != nil {