package db import ( "database/sql" "iter" ) type TX interface { Exec(query string, args ...any) (sql.Result, error) Query(query string, args ...any) (*sql.Rows, error) QueryRow(query string, args ...any) *sql.Row } // ---------------------------------------------------------------------------- // Table: config // ---------------------------------------------------------------------------- type Config struct { ConfigID int64 HubAddress string VPNNetwork []byte Password []byte } const Config_SelectQuery = "SELECT ConfigID,HubAddress,VPNNetwork,Password FROM config" func Config_Insert( tx TX, row *Config, ) (err error) { Config_Sanitize(row) if err = Config_Validate(row); err != nil { return err } _, err = tx.Exec("INSERT INTO config(ConfigID,HubAddress,VPNNetwork,Password) VALUES(?,?,?,?)", row.ConfigID, row.HubAddress, row.VPNNetwork, row.Password) return err } func Config_Update( tx TX, row *Config, ) (err error) { Config_Sanitize(row) if err = Config_Validate(row); err != nil { return err } result, err := tx.Exec("UPDATE config SET HubAddress=?,VPNNetwork=? WHERE ConfigID=?", row.HubAddress, row.VPNNetwork, row.ConfigID) if err != nil { return err } n, err := result.RowsAffected() if err != nil { panic(err) } switch n { case 0: return sql.ErrNoRows case 1: return nil default: panic("multiple rows updated") } } func Config_UpdateFull( tx TX, row *Config, ) (err error) { Config_Sanitize(row) if err = Config_Validate(row); err != nil { return err } result, err := tx.Exec("UPDATE config SET HubAddress=?,VPNNetwork=?,Password=? WHERE ConfigID=?", row.HubAddress, row.VPNNetwork, row.Password, row.ConfigID) if err != nil { return err } n, err := result.RowsAffected() if err != nil { panic(err) } switch n { case 0: return sql.ErrNoRows case 1: return nil default: panic("multiple rows updated") } } func Config_Delete( tx TX, ConfigID int64, ) (err error) { result, err := tx.Exec("DELETE FROM config WHERE ConfigID=?", ConfigID) if err != nil { return err } n, err := result.RowsAffected() if err != nil { panic(err) } switch n { case 0: return sql.ErrNoRows case 1: return nil default: panic("multiple rows deleted") } } func Config_Get( tx TX, ConfigID int64, ) ( row *Config, err error, ) { row = &Config{} r := tx.QueryRow("SELECT ConfigID,HubAddress,VPNNetwork,Password FROM config WHERE ConfigID=?", ConfigID) err = r.Scan(&row.ConfigID, &row.HubAddress, &row.VPNNetwork, &row.Password) return } func Config_GetWhere( tx TX, query string, args ...any, ) ( row *Config, err error, ) { row = &Config{} r := tx.QueryRow(query, args...) err = r.Scan(&row.ConfigID, &row.HubAddress, &row.VPNNetwork, &row.Password) return } func Config_Iterate( tx TX, query string, args ...any, ) iter.Seq2[*Config, error] { rows, err := tx.Query(query, args...) if err != nil { return func(yield func(*Config, error) bool) { yield(nil, err) } } return func(yield func(*Config, error) bool) { defer rows.Close() for rows.Next() { row := &Config{} err := rows.Scan(&row.ConfigID, &row.HubAddress, &row.VPNNetwork, &row.Password) if !yield(row, err) { return } } } } func Config_List( tx TX, query string, args ...any, ) ( l []*Config, err error, ) { for row, err := range Config_Iterate(tx, query, args...) { if err != nil { return nil, err } l = append(l, row) } return l, nil } // ---------------------------------------------------------------------------- // Table: sessions // ---------------------------------------------------------------------------- type Session struct { SessionID string CSRF string SignedIn bool CreatedAt int64 LastSeenAt int64 } const Session_SelectQuery = "SELECT SessionID,CSRF,SignedIn,CreatedAt,LastSeenAt FROM sessions" func Session_Insert( tx TX, row *Session, ) (err error) { Session_Sanitize(row) if err = Session_Validate(row); err != nil { return err } _, err = tx.Exec("INSERT INTO sessions(SessionID,CSRF,SignedIn,CreatedAt,LastSeenAt) VALUES(?,?,?,?,?)", row.SessionID, row.CSRF, row.SignedIn, row.CreatedAt, row.LastSeenAt) return err } func Session_Delete( tx TX, SessionID string, ) (err error) { result, err := tx.Exec("DELETE FROM sessions WHERE SessionID=?", SessionID) if err != nil { return err } n, err := result.RowsAffected() if err != nil { panic(err) } switch n { case 0: return sql.ErrNoRows case 1: return nil default: panic("multiple rows deleted") } } func Session_Get( tx TX, SessionID string, ) ( row *Session, err error, ) { row = &Session{} r := tx.QueryRow("SELECT SessionID,CSRF,SignedIn,CreatedAt,LastSeenAt FROM sessions WHERE SessionID=?", SessionID) err = r.Scan(&row.SessionID, &row.CSRF, &row.SignedIn, &row.CreatedAt, &row.LastSeenAt) return } func Session_GetWhere( tx TX, query string, args ...any, ) ( row *Session, err error, ) { row = &Session{} r := tx.QueryRow(query, args...) err = r.Scan(&row.SessionID, &row.CSRF, &row.SignedIn, &row.CreatedAt, &row.LastSeenAt) return } func Session_Iterate( tx TX, query string, args ...any, ) iter.Seq2[*Session, error] { rows, err := tx.Query(query, args...) if err != nil { return func(yield func(*Session, error) bool) { yield(nil, err) } } return func(yield func(*Session, error) bool) { defer rows.Close() for rows.Next() { row := &Session{} err := rows.Scan(&row.SessionID, &row.CSRF, &row.SignedIn, &row.CreatedAt, &row.LastSeenAt) if !yield(row, err) { return } } } } func Session_List( tx TX, query string, args ...any, ) ( l []*Session, err error, ) { for row, err := range Session_Iterate(tx, query, args...) { if err != nil { return nil, err } l = append(l, row) } return l, nil } // ---------------------------------------------------------------------------- // Table: peers // ---------------------------------------------------------------------------- type Peer struct { PeerIP byte Version int64 APIKey string Name string PublicIP []byte Port uint16 Relay bool PubKey []byte } const Peer_SelectQuery = "SELECT PeerIP,Version,APIKey,Name,PublicIP,Port,Relay,PubKey FROM peers" func Peer_Insert( tx TX, row *Peer, ) (err error) { Peer_Sanitize(row) if err = Peer_Validate(row); err != nil { return err } _, err = tx.Exec("INSERT INTO peers(PeerIP,Version,APIKey,Name,PublicIP,Port,Relay,PubKey) VALUES(?,?,?,?,?,?,?,?)", row.PeerIP, row.Version, row.APIKey, row.Name, row.PublicIP, row.Port, row.Relay, row.PubKey) return err } func Peer_Update( tx TX, row *Peer, ) (err error) { Peer_Sanitize(row) if err = Peer_Validate(row); err != nil { return err } result, err := tx.Exec("UPDATE peers SET Version=?,Name=?,PublicIP=?,Port=?,Relay=? WHERE PeerIP=?", row.Version, row.Name, row.PublicIP, row.Port, row.Relay, row.PeerIP) if err != nil { return err } n, err := result.RowsAffected() if err != nil { panic(err) } switch n { case 0: return sql.ErrNoRows case 1: return nil default: panic("multiple rows updated") } } func Peer_UpdateFull( tx TX, row *Peer, ) (err error) { Peer_Sanitize(row) if err = Peer_Validate(row); err != nil { return err } result, err := tx.Exec("UPDATE peers SET Version=?,APIKey=?,Name=?,PublicIP=?,Port=?,Relay=?,PubKey=? WHERE PeerIP=?", row.Version, row.APIKey, row.Name, row.PublicIP, row.Port, row.Relay, row.PubKey, row.PeerIP) if err != nil { return err } n, err := result.RowsAffected() if err != nil { panic(err) } switch n { case 0: return sql.ErrNoRows case 1: return nil default: panic("multiple rows updated") } } func Peer_Delete( tx TX, PeerIP byte, ) (err error) { result, err := tx.Exec("DELETE FROM peers WHERE PeerIP=?", PeerIP) if err != nil { return err } n, err := result.RowsAffected() if err != nil { panic(err) } switch n { case 0: return sql.ErrNoRows case 1: return nil default: panic("multiple rows deleted") } } func Peer_Get( tx TX, PeerIP byte, ) ( row *Peer, err error, ) { row = &Peer{} r := tx.QueryRow("SELECT PeerIP,Version,APIKey,Name,PublicIP,Port,Relay,PubKey FROM peers WHERE PeerIP=?", PeerIP) err = r.Scan(&row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP, &row.Port, &row.Relay, &row.PubKey) return } func Peer_GetWhere( tx TX, query string, args ...any, ) ( row *Peer, err error, ) { row = &Peer{} r := tx.QueryRow(query, args...) err = r.Scan(&row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP, &row.Port, &row.Relay, &row.PubKey) return } func Peer_Iterate( tx TX, query string, args ...any, ) iter.Seq2[*Peer, error] { rows, err := tx.Query(query, args...) if err != nil { return func(yield func(*Peer, error) bool) { yield(nil, err) } } return func(yield func(*Peer, error) bool) { defer rows.Close() for rows.Next() { row := &Peer{} err := rows.Scan(&row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP, &row.Port, &row.Relay, &row.PubKey) if !yield(row, err) { return } } } } func Peer_List( tx TX, query string, args ...any, ) ( l []*Peer, err error, ) { for row, err := range Peer_Iterate(tx, query, args...) { if err != nil { return nil, err } l = append(l, row) } return l, nil }