Bump version to 1.0.23

This commit is contained in:
2026-07-09 17:33:04 -04:00
parent be7d47c0e1
commit 88cc7e88e6
15 changed files with 632 additions and 381 deletions
+102 -1
View File
@@ -1,16 +1,19 @@
package api
import (
"context"
"database/sql"
"encoding/json"
"log/slog"
"net/http"
"path/filepath"
"regexp"
"strconv"
"time"
"github.com/go-chi/chi/v5"
"github.com/syncserver/internal/models"
"github.com/syncserver/internal/sshmanager"
"github.com/syncserver/internal/syncengine"
"github.com/syncserver/internal/wol"
)
@@ -218,6 +221,103 @@ func (h *MachineHandler) TestWoL(w http.ResponseWriter, r *http.Request) {
writeJSON(w, map[string]interface{}{"ok": true, "sent": 3})
}
func (h *MachineHandler) TestConnection(w http.ResponseWriter, r *http.Request) {
id, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
if err != nil {
writeError(w, http.StatusBadRequest, "invalid id")
return
}
repo := models.NewMachineRepository(h.db)
m, err := repo.GetByID(id)
if err == sql.ErrNoRows {
writeError(w, http.StatusNotFound, "machine not found")
return
}
if err != nil {
slog.Error("failed to fetch machine", "id", id, "error", err)
writeError(w, http.StatusInternalServerError, "failed to fetch machine")
return
}
knownHostsPath, err := sshmanager.EnsureKnownHosts(filepath.Join("/var/lib/syncserver", "ssh"))
if err != nil {
writeError(w, http.StatusInternalServerError, "failed to ensure known_hosts")
return
}
privKeyPath := filepath.Join("/var/lib/syncserver", "ssh", "id_ed25519")
if m.SSHKeyID != nil {
sshKeyRepo := models.NewSSHKeyRepository(h.db)
sshKey, err := sshKeyRepo.GetByID(*m.SSHKeyID)
if err == nil && sshKey.PrivateKeyPath != "" {
privKeyPath = sshKey.PrivateKeyPath
}
}
result, err := sshmanager.TestSSHConnection(
context.Background(),
m.Host, m.Port, m.SSHUser,
privKeyPath, knownHostsPath,
m.FingerprintConfirmed,
)
if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}
writeJSON(w, TestConnectionResponse{
Success: result.Success,
Output: result.Output,
Error: result.Error,
Fingerprint: result.Fingerprint,
})
}
func (h *MachineHandler) ApproveFingerprint(w http.ResponseWriter, r *http.Request) {
id, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
if err != nil {
writeError(w, http.StatusBadRequest, "invalid id")
return
}
repo := models.NewMachineRepository(h.db)
m, err := repo.GetByID(id)
if err == sql.ErrNoRows {
writeError(w, http.StatusNotFound, "machine not found")
return
}
if err != nil {
slog.Error("failed to fetch machine", "id", id, "error", err)
writeError(w, http.StatusInternalServerError, "failed to fetch machine")
return
}
var req struct {
Fingerprint string `json:"fingerprint"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeError(w, http.StatusBadRequest, "invalid request body")
return
}
if req.Fingerprint == "" {
writeError(w, http.StatusBadRequest, "fingerprint is required")
return
}
if err := repo.UpdateFingerprint(id, true, req.Fingerprint); err != nil {
slog.Error("failed to update fingerprint", "id", id, "error", err)
writeError(w, http.StatusInternalServerError, "failed to update fingerprint")
return
}
sshDir := filepath.Join("/var/lib/syncserver", "ssh")
if err := sshmanager.AddKnownHost(sshDir, m.Host, m.Port, []byte(req.Fingerprint)); err != nil {
slog.Warn("failed to add known_host entry", "host", m.Host, "error", err)
}
m.FingerprintConfirmed = true
m.HostKeyFingerprint = &req.Fingerprint
writeJSON(w, machineToResp(*m))
}
func (h *MachineHandler) Refresh(w http.ResponseWriter, r *http.Request) {
if h.engine == nil {
writeError(w, http.StatusInternalServerError, "engine not available")
@@ -269,8 +369,9 @@ func machineToResp(m models.Machine) MachineResponse {
WoLEnabled: m.WoLEnabled,
BroadcastAddr: m.BroadcastAddr,
WakeTimeoutSeconds: m.WakeTimeoutSeconds,
WakeCheckIntervalSeconds: m.WakeCheckIntervalSeconds,
WakeCheckIntervalSeconds: m.WakeCheckIntervalSeconds,
FingerprintConfirmed: m.FingerprintConfirmed,
HostKeyFingerprint: m.HostKeyFingerprint,
Status: status,
}
}