mirror of
https://github.com/Dvorinka/Dash.git
synced 2026-10-28 07:41:27 +00:00
feat: external importers + uptime monitors (merge plan M1)
Two tracks from the Beszel/Domain-Locker merge plan in ROADMAP.md: - Importers: POST /api/import/external sniffs Homepage services.yml, Homarr JSON, and Dashy conf.yml into sections/items; SettingsDialog import now accepts all four formats. - Monitors (M1): monitors + heartbeats schema, pure checkers for http/tcp/ping/dns/keyword/json-query/push, scheduler on app ctx, CRUD + check-now + push ingest API, /monitors + /monitors/:id pages (wouter), monitor board widget, ServiceDialog monitor opt-in. Authored By: TDvorak <[email protected]> Generated with Devin (https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
f428e721fe
commit
1ff1b29ae7
29 files changed
+3050
-98
No files matched your search
@@ -2,6 +2,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"database/sql"
|
||||
"encoding/hex"
|
||||
@@ -12,25 +13,33 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/tdvorak/dash/internal/widget"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Server holds handler dependencies: DB, icon dir, status + widget caches.
|
||||
// Server holds handler dependencies: DB, icon dir, logger, caches.
|
||||
type Server struct {
|
||||
db *sql.DB
|
||||
iconsDir string
|
||||
log *zap.Logger
|
||||
status *statusCache
|
||||
widgets *widgetCache
|
||||
}
|
||||
|
||||
// NewRouter builds the HTTP handler: zap access log, recovery, /api routes.
|
||||
func NewRouter(logger *zap.Logger, db *sql.DB, iconsDir string) *gin.Engine {
|
||||
// A non-nil ctx starts the monitor scheduler; nil keeps it off (tests).
|
||||
func NewRouter(ctx context.Context, logger *zap.Logger, db *sql.DB, iconsDir string) *gin.Engine {
|
||||
s := &Server{
|
||||
db: db,
|
||||
iconsDir: iconsDir,
|
||||
log: logger,
|
||||
status: newStatusCache(60 * time.Second),
|
||||
widgets: newWidgetCache(30 * time.Second),
|
||||
}
|
||||
widget.Register(&monitorWidget{db: db})
|
||||
if ctx != nil {
|
||||
go s.runScheduler(ctx.Done())
|
||||
}
|
||||
|
||||
r := gin.New()
|
||||
r.Use(accessLog(logger), gin.Recovery())
|
||||
@@ -51,6 +60,15 @@ func NewRouter(logger *zap.Logger, db *sql.DB, iconsDir string) *gin.Engine {
|
||||
v1.POST("/items/:id/icon", s.uploadIcon)
|
||||
v1.GET("/icons/:file", s.getIcon)
|
||||
|
||||
v1.GET("/monitors", s.listMonitorsH)
|
||||
v1.POST("/monitors", s.createMonitor)
|
||||
v1.GET("/monitors/:id", s.getMonitor)
|
||||
v1.PATCH("/monitors/:id", s.patchMonitor)
|
||||
v1.DELETE("/monitors/:id", s.deleteMonitor)
|
||||
v1.GET("/monitors/:id/heartbeats", s.monitorHeartbeats)
|
||||
v1.POST("/monitors/:id/check", s.checkNow)
|
||||
v1.Any("/push/:token", s.pushIngest)
|
||||
|
||||
v1.GET("/status", s.getStatus)
|
||||
v1.GET("/widgets/types", s.widgetTypes)
|
||||
v1.GET("/widgets/:id/data", s.widgetData)
|
||||
@@ -58,6 +76,7 @@ func NewRouter(logger *zap.Logger, db *sql.DB, iconsDir string) *gin.Engine {
|
||||
v1.PUT("/settings", s.putSettings)
|
||||
v1.GET("/export", s.exportBoard)
|
||||
v1.POST("/import", s.importBoard)
|
||||
v1.POST("/import/external", s.importExternal)
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user