Initial commit: DSH Web Manager

This commit is contained in:
2026-10-13 09:34:47 +08:00
commit 85332bbc56
135 changed files with 19712 additions and 0 deletions
+131
View File
@@ -0,0 +1,131 @@
package store
import (
"crypto/rand"
"database/sql"
"encoding/hex"
_ "modernc.org/sqlite"
"time"
)
type User struct {
ID string `json:"id"`
Username string `json:"username"`
Admin bool `json:"admin"`
Quota int64 `json:"quota_bytes"`
Created time.Time `json:"created_at"`
}
type Instance struct {
ID string `json:"id"`
UID string `json:"uid"`
Name string `json:"name"`
Version string `json:"version"`
ImageID string `json:"image_id"`
Status string `json:"status"`
ContainerID string `json:"container_id"`
Created time.Time `json:"created_at"`
}
type Store struct{ DB *sql.DB }
func Open(path string) (*Store, error) {
db, e := sql.Open("sqlite", path)
if e != nil {
return nil, e
}
db.SetMaxOpenConns(1)
if _, e = db.Exec("PRAGMA busy_timeout=5000; PRAGMA journal_mode=WAL;"); e != nil {
db.Close()
return nil, e
}
_, e = db.Exec("PRAGMA foreign_keys=ON; CREATE TABLE IF NOT EXISTS users(id TEXT PRIMARY KEY,username TEXT UNIQUE NOT NULL,pass_hash TEXT NOT NULL,admin INTEGER NOT NULL,quota INTEGER NOT NULL,created INTEGER NOT NULL); CREATE TABLE IF NOT EXISTS sessions(id TEXT PRIMARY KEY,uid TEXT NOT NULL,csrf TEXT NOT NULL,expires INTEGER NOT NULL); CREATE TABLE IF NOT EXISTS instances(id TEXT PRIMARY KEY,uid TEXT NOT NULL,name TEXT NOT NULL,version TEXT,image_id TEXT,status TEXT,container_id TEXT,created INTEGER NOT NULL); CREATE TABLE IF NOT EXISTS audit(id INTEGER PRIMARY KEY,uid TEXT,action TEXT,target TEXT,detail TEXT,at INTEGER NOT NULL);")
if e != nil {
db.Close()
return nil, e
}
return &Store{db}, nil
}
func (s *Store) Close() { s.DB.Close() }
func ID() string { b := make([]byte, 16); _, _ = rand.Read(b); return hex.EncodeToString(b) }
func (s *Store) UserByName(n string) (User, error) {
var u User
var a, t int64
e := s.DB.QueryRow("SELECT id,username,admin,quota,created FROM users WHERE username=?", n).Scan(&u.ID, &u.Username, &a, &u.Quota, &t)
u.Admin = a != 0
u.Created = time.Unix(t, 0)
return u, e
}
func (s *Store) UserByID(id string) (User, error) {
var u User
var a, t int64
e := s.DB.QueryRow("SELECT id,username,admin,quota,created FROM users WHERE id=?", id).Scan(&u.ID, &u.Username, &a, &u.Quota, &t)
u.Admin = a != 0
u.Created = time.Unix(t, 0)
return u, e
}
func (s *Store) CreateUser(u User, hash string) error {
_, e := s.DB.Exec("INSERT INTO users(id,username,pass_hash,admin,quota,created) VALUES(?,?,?,?,?,?)", u.ID, u.Username, hash, boolInt(u.Admin), u.Quota, time.Now().Unix())
return e
}
func boolInt(v bool) int {
if v {
return 1
}
return 0
}
func (s *Store) Password(name string) (string, error) {
var p string
e := s.DB.QueryRow("SELECT pass_hash FROM users WHERE username=?", name).Scan(&p)
return p, e
}
func (s *Store) Session(uid string) (string, string, error) {
id, csrf := ID(), ID()
_, e := s.DB.Exec("INSERT INTO sessions VALUES(?,?,?,?)", id, uid, csrf, time.Now().Add(24*time.Hour).Unix())
return id, csrf, e
}
func (s *Store) SessionUser(id string) (User, string, error) {
var uid, csrf string
var exp int64
e := s.DB.QueryRow("SELECT uid,csrf,expires FROM sessions WHERE id=?", id).Scan(&uid, &csrf, &exp)
if e != nil || exp < time.Now().Unix() {
return User{}, "", sql.ErrNoRows
}
u, e := s.UserByID(uid)
return u, csrf, e
}
func (s *Store) DeleteSession(id string) { _, _ = s.DB.Exec("DELETE FROM sessions WHERE id=?", id) }
func (s *Store) AddAudit(uid, a, t, d string) {
_, _ = s.DB.Exec("INSERT INTO audit(uid,action,target,detail,at) VALUES(?,?,?,?,?)", uid, a, t, d, time.Now().Unix())
}
func (s *Store) Instances(uid string) ([]Instance, error) {
rows, e := s.DB.Query("SELECT id,uid,name,version,image_id,status,container_id,created FROM instances WHERE uid=? ORDER BY created", uid)
if e != nil {
return nil, e
}
defer rows.Close()
var out []Instance
for rows.Next() {
var i Instance
var t int64
if e = rows.Scan(&i.ID, &i.UID, &i.Name, &i.Version, &i.ImageID, &i.Status, &i.ContainerID, &t); e != nil {
return nil, e
}
i.Created = time.Unix(t, 0)
out = append(out, i)
}
return out, rows.Err()
}
func (s *Store) AddInstance(i Instance) error {
_, e := s.DB.Exec("INSERT INTO instances VALUES(?,?,?,?,?,?,?,?)", i.ID, i.UID, i.Name, i.Version, i.ImageID, i.Status, i.ContainerID, time.Now().Unix())
return e
}
func (s *Store) GetInstance(id string) (Instance, error) {
var i Instance
var t int64
e := s.DB.QueryRow("SELECT id,uid,name,version,image_id,status,container_id,created FROM instances WHERE id=?", id).Scan(&i.ID, &i.UID, &i.Name, &i.Version, &i.ImageID, &i.Status, &i.ContainerID, &t)
i.Created = time.Unix(t, 0)
return i, e
}
func (s *Store) SetInstance(id, status string) {
_, _ = s.DB.Exec("UPDATE instances SET status=? WHERE id=?", status, id)
}
func (s *Store) DeleteInstance(id string) { _, _ = s.DB.Exec("DELETE FROM instances WHERE id=?", id) }