Publish ITWorx Pulse source
Public source validation / validate (push) Failing after 3m8s

This commit is contained in:
ITWorx Pulse release export
2026-09-03 02:09:19 +02:00
commit bd774932d5
614 changed files with 77116 additions and 0 deletions
+98
View File
@@ -0,0 +1,98 @@
package backupapi
import (
"context"
"encoding/json"
"errors"
"net/http"
"time"
"github.com/itworx/pulse/internal/auth"
"github.com/itworx/pulse/internal/backup"
)
type Handler struct {
Manager *backup.Manager
Audit func(context.Context, string, string) error
// OnCreated invalidates derived status caches after the archive and its
// checksum have both been written successfully.
OnCreated func()
}
type publicResult struct {
BackupID string `json:"backupId"`
SHA256 string `json:"sha256"`
Bytes int64 `json:"bytes"`
Rows int64 `json:"rows"`
Created time.Time `json:"createdAt"`
}
func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if h.Manager == nil {
writeError(w, http.StatusServiceUnavailable, "BACKUP_UNAVAILABLE", "Backup is not configured")
return
}
switch r.Method {
case http.MethodGet:
if r.URL.Path != "/api/v1/system/backups" {
writeError(w, http.StatusNotFound, "NOT_FOUND", "Not found")
return
}
result, err := h.Manager.List(r.Context())
if err != nil {
writeError(w, http.StatusServiceUnavailable, "BACKUP_UNAVAILABLE", "Backups are not available")
return
}
public := make([]publicResult, 0, len(result))
for _, item := range result {
public = append(public, toPublic(item))
}
writeJSON(w, http.StatusOK, map[string]any{"backups": public})
case http.MethodPost:
if r.URL.Path != "/api/v1/system/backups" {
writeError(w, http.StatusNotFound, "NOT_FOUND", "Not found")
return
}
result, err := h.Manager.Create(r.Context())
principal, _ := auth.PrincipalFromContext(r.Context())
if err != nil {
if h.Audit != nil {
_ = h.Audit(r.Context(), principal.Subject, "failure")
}
status := http.StatusInternalServerError
code := "BACKUP_FAILED"
if errors.Is(err, backup.ErrNotConfigured) {
status = http.StatusServiceUnavailable
code = "BACKUP_UNAVAILABLE"
}
writeError(w, status, code, "Backup could not be created")
return
}
if h.Audit != nil {
_ = h.Audit(r.Context(), principal.Subject, "success")
}
if h.OnCreated != nil {
h.OnCreated()
}
writeJSON(w, http.StatusCreated, toPublic(result))
default:
writeError(w, http.StatusMethodNotAllowed, "METHOD_NOT_ALLOWED", "Method not allowed")
}
}
func toPublic(result backup.Result) publicResult {
return publicResult{BackupID: result.BackupID, SHA256: result.SHA256, Bytes: result.Bytes, Rows: result.Rows, Created: result.Created}
}
func writeJSON(w http.ResponseWriter, status int, value any) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Cache-Control", "private, no-store")
w.WriteHeader(status)
_ = json.NewEncoder(w).Encode(value)
}
func writeError(w http.ResponseWriter, status int, code, detail string) {
writeJSON(w, status, map[string]string{"code": code, "detail": detail})
}
var _ http.Handler = Handler{}
+44
View File
@@ -0,0 +1,44 @@
package backupapi
import (
"encoding/json"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/itworx/pulse/internal/backup"
)
func TestHandlerRejectsUnconfiguredBackupWithoutDisclosure(t *testing.T) {
handler := Handler{}
request := httptest.NewRequest(http.MethodPost, "/api/v1/system/backups", nil)
response := httptest.NewRecorder()
handler.ServeHTTP(response, request)
if response.Code != http.StatusServiceUnavailable || !strings.Contains(response.Body.String(), "BACKUP_UNAVAILABLE") {
t.Fatalf("response = %d %s", response.Code, response.Body.String())
}
if strings.Contains(response.Body.String(), "PULSE_") || strings.Contains(response.Body.String(), "password") {
t.Fatal("configuration detail leaked")
}
}
func TestHandlerRejectsUnsupportedMethod(t *testing.T) {
handler := Handler{Manager: &backup.Manager{}}
request := httptest.NewRequest(http.MethodDelete, "/api/v1/system/backups", nil)
response := httptest.NewRecorder()
handler.ServeHTTP(response, request)
if response.Code != http.StatusMethodNotAllowed {
t.Fatalf("response = %d, want method not allowed", response.Code)
}
}
func TestPublicResultOmitsServerPath(t *testing.T) {
payload, err := json.Marshal(toPublic(backup.Result{BackupID: "id", Path: "C:/private/backups/pulse.zip", SHA256: "checksum"}))
if err != nil {
t.Fatal(err)
}
if strings.Contains(string(payload), "private/backups") || strings.Contains(string(payload), "path") {
t.Fatalf("server path leaked: %s", payload)
}
}