WIP
This commit is contained in:
@@ -19,8 +19,10 @@ import (
|
|||||||
var migrations embed.FS
|
var migrations embed.FS
|
||||||
|
|
||||||
type API struct {
|
type API struct {
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
|
sessionsMu sync.Mutex
|
||||||
|
sessions map[string]*Session
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(dbPath string) (*API, error) {
|
func New(dbPath string) (*API, error) {
|
||||||
@@ -34,7 +36,8 @@ func New(dbPath string) (*API, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
a := &API{
|
a := &API{
|
||||||
db: sqlDB,
|
db: sqlDB,
|
||||||
|
sessions: make(map[string]*Session),
|
||||||
}
|
}
|
||||||
|
|
||||||
return a, a.ensurePassword()
|
return a, a.ensurePassword()
|
||||||
@@ -75,47 +78,41 @@ func (a *API) Config_Update(conf *Config) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) Session_Delete(sessionID string) error {
|
func (a *API) Session_Delete(sessionID string) error {
|
||||||
return db.Session_Delete(a.db, sessionID)
|
a.sessionsMu.Lock()
|
||||||
|
defer a.sessionsMu.Unlock()
|
||||||
|
delete(a.sessions, sessionID)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) Session_Get(sessionID string) (*Session, error) {
|
func (a *API) Session_Get(sessionID string) (*Session, error) {
|
||||||
if sessionID == "" {
|
a.sessionsMu.Lock()
|
||||||
return a.session_CreatePub()
|
defer a.sessionsMu.Unlock()
|
||||||
}
|
|
||||||
|
|
||||||
session, err := db.Session_Get(a.db, sessionID)
|
if sessionID != "" {
|
||||||
if err != nil {
|
s, ok := a.sessions[sessionID]
|
||||||
return a.session_CreatePub()
|
if ok {
|
||||||
}
|
if timeSince(s.LastSeenAt) <= 86400*21 {
|
||||||
|
if timeSince(s.LastSeenAt) > 86400*7 {
|
||||||
if timeSince(session.LastSeenAt) > 86400*21 {
|
s.LastSeenAt = time.Now().Unix()
|
||||||
return a.session_CreatePub()
|
}
|
||||||
}
|
return s, nil
|
||||||
|
}
|
||||||
if timeSince(session.LastSeenAt) > 86400*7 {
|
delete(a.sessions, sessionID)
|
||||||
session.LastSeenAt = time.Now().Unix()
|
|
||||||
if err := db.Session_UpdateLastSeenAt(a.db, session.SessionID); err != nil {
|
|
||||||
log.Printf("Failed to update session: %v", err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return session, nil
|
return a.session_Create(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) session_CreatePub() (*Session, error) {
|
// caller must hold sessionsMu
|
||||||
|
func (a *API) session_Create() *Session {
|
||||||
s := &Session{
|
s := &Session{
|
||||||
SessionID: idgen.NewToken(),
|
SessionID: idgen.NewToken(),
|
||||||
CSRF: idgen.NewToken(),
|
|
||||||
SignedIn: false,
|
|
||||||
CreatedAt: time.Now().Unix(),
|
CreatedAt: time.Now().Unix(),
|
||||||
LastSeenAt: time.Now().Unix(),
|
LastSeenAt: time.Now().Unix(),
|
||||||
}
|
}
|
||||||
err := db.Session_Insert(a.db, s)
|
a.sessions[s.SessionID] = s
|
||||||
return s, err
|
return s
|
||||||
}
|
|
||||||
|
|
||||||
func (a *API) Session_DeleteBefore(timestamp int64) error {
|
|
||||||
return db.Session_DeleteBefore(a.db, timestamp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) Session_SignIn(s *Session, pwd string) error {
|
func (a *API) Session_SignIn(s *Session, pwd string) error {
|
||||||
@@ -123,8 +120,10 @@ func (a *API) Session_SignIn(s *Session, pwd string) error {
|
|||||||
if err := bcrypt.CompareHashAndPassword(conf.Password, []byte(pwd)); err != nil {
|
if err := bcrypt.CompareHashAndPassword(conf.Password, []byte(pwd)); err != nil {
|
||||||
return ErrNotAuthorized
|
return ErrNotAuthorized
|
||||||
}
|
}
|
||||||
|
a.sessionsMu.Lock()
|
||||||
return db.Session_SetSignedIn(a.db, s.SessionID)
|
s.SignedIn = true
|
||||||
|
a.sessionsMu.Unlock()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) Network_Create(n *Network) error {
|
func (a *API) Network_Create(n *Network) error {
|
||||||
@@ -147,8 +146,7 @@ func (a *API) Network_List() ([]*Network, error) {
|
|||||||
|
|
||||||
func (a *API) Peer_CreateNew(p *Peer) error {
|
func (a *API) Peer_CreateNew(p *Peer) error {
|
||||||
p.Version = idgen.NextID(0)
|
p.Version = idgen.NextID(0)
|
||||||
p.PubKey = []byte{}
|
p.WGPubKey = []byte{}
|
||||||
p.PubSignKey = []byte{}
|
|
||||||
p.APIKey = idgen.NewToken()
|
p.APIKey = idgen.NewToken()
|
||||||
|
|
||||||
return db.Peer_Insert(a.db, p)
|
return db.Peer_Insert(a.db, p)
|
||||||
@@ -159,8 +157,7 @@ func (a *API) Peer_Init(peer *Peer, args m.PeerInitArgs) error {
|
|||||||
defer a.lock.Unlock()
|
defer a.lock.Unlock()
|
||||||
|
|
||||||
peer.Version = idgen.NextID(0)
|
peer.Version = idgen.NextID(0)
|
||||||
peer.PubKey = args.EncPubKey
|
peer.WGPubKey = args.WGPubKey
|
||||||
peer.PubSignKey = args.PubSignKey
|
|
||||||
|
|
||||||
return db.Peer_UpdateFull(a.db, peer)
|
return db.Peer_UpdateFull(a.db, peer)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,7 +123,9 @@ func Config_Get(
|
|||||||
) {
|
) {
|
||||||
row = &Config{}
|
row = &Config{}
|
||||||
r := tx.QueryRow("SELECT ConfigID,Password FROM config WHERE ConfigID=?", ConfigID)
|
r := tx.QueryRow("SELECT ConfigID,Password FROM config WHERE ConfigID=?", ConfigID)
|
||||||
err = r.Scan(&row.ConfigID, &row.Password)
|
if err = r.Scan(&row.ConfigID, &row.Password); err != nil {
|
||||||
|
row = nil
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +139,9 @@ func Config_GetWhere(
|
|||||||
) {
|
) {
|
||||||
row = &Config{}
|
row = &Config{}
|
||||||
r := tx.QueryRow(query, args...)
|
r := tx.QueryRow(query, args...)
|
||||||
err = r.Scan(&row.ConfigID, &row.Password)
|
if err = r.Scan(&row.ConfigID, &row.Password); err != nil {
|
||||||
|
row = nil
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,124 +186,6 @@ func Config_List(
|
|||||||
return l, nil
|
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: networks
|
// Table: networks
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -385,7 +271,9 @@ func Network_Get(
|
|||||||
) {
|
) {
|
||||||
row = &Network{}
|
row = &Network{}
|
||||||
r := tx.QueryRow("SELECT NetworkID,Name,Network FROM networks WHERE NetworkID=?", NetworkID)
|
r := tx.QueryRow("SELECT NetworkID,Name,Network FROM networks WHERE NetworkID=?", NetworkID)
|
||||||
err = r.Scan(&row.NetworkID, &row.Name, &row.Network)
|
if err = r.Scan(&row.NetworkID, &row.Name, &row.Network); err != nil {
|
||||||
|
row = nil
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,7 +287,9 @@ func Network_GetWhere(
|
|||||||
) {
|
) {
|
||||||
row = &Network{}
|
row = &Network{}
|
||||||
r := tx.QueryRow(query, args...)
|
r := tx.QueryRow(query, args...)
|
||||||
err = r.Scan(&row.NetworkID, &row.Name, &row.Network)
|
if err = r.Scan(&row.NetworkID, &row.Name, &row.Network); err != nil {
|
||||||
|
row = nil
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,19 +339,20 @@ func Network_List(
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
type Peer struct {
|
type Peer struct {
|
||||||
NetworkID int64
|
NetworkID int64
|
||||||
PeerIP byte
|
PeerIP byte
|
||||||
Version int64
|
Version int64
|
||||||
APIKey string
|
APIKey string
|
||||||
Name string
|
Name string
|
||||||
PublicIP []byte
|
PublicIP1 []byte
|
||||||
Port uint16
|
Port1 uint16
|
||||||
Relay bool
|
PublicIP2 []byte
|
||||||
PubKey []byte
|
Port2 uint16
|
||||||
PubSignKey []byte
|
Relay bool
|
||||||
|
WGPubKey []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
const Peer_SelectQuery = "SELECT NetworkID,PeerIP,Version,APIKey,Name,PublicIP,Port,Relay,PubKey,PubSignKey FROM peers"
|
const Peer_SelectQuery = "SELECT NetworkID,PeerIP,Version,APIKey,Name,PublicIP1,Port1,PublicIP2,Port2,Relay,WGPubKey FROM peers"
|
||||||
|
|
||||||
func Peer_Insert(
|
func Peer_Insert(
|
||||||
tx TX,
|
tx TX,
|
||||||
@@ -472,7 +363,7 @@ func Peer_Insert(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = tx.Exec("INSERT INTO peers(NetworkID,PeerIP,Version,APIKey,Name,PublicIP,Port,Relay,PubKey,PubSignKey) VALUES(?,?,?,?,?,?,?,?,?,?)", row.NetworkID, row.PeerIP, row.Version, row.APIKey, row.Name, row.PublicIP, row.Port, row.Relay, row.PubKey, row.PubSignKey)
|
_, err = tx.Exec("INSERT INTO peers(NetworkID,PeerIP,Version,APIKey,Name,PublicIP1,Port1,PublicIP2,Port2,Relay,WGPubKey) VALUES(?,?,?,?,?,?,?,?,?,?,?)", row.NetworkID, row.PeerIP, row.Version, row.APIKey, row.Name, row.PublicIP1, row.Port1, row.PublicIP2, row.Port2, row.Relay, row.WGPubKey)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,7 +376,7 @@ func Peer_Update(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := tx.Exec("UPDATE peers SET Version=?,Name=?,PublicIP=?,Port=?,Relay=? WHERE NetworkID=? AND PeerIP=?", row.Version, row.Name, row.PublicIP, row.Port, row.Relay, row.NetworkID, row.PeerIP)
|
result, err := tx.Exec("UPDATE peers SET Version=?,Name=?,PublicIP1=?,Port1=?,PublicIP2=?,Port2=?,Relay=? WHERE NetworkID=? AND PeerIP=?", row.Version, row.Name, row.PublicIP1, row.Port1, row.PublicIP2, row.Port2, row.Relay, row.NetworkID, row.PeerIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -513,7 +404,7 @@ func Peer_UpdateFull(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := tx.Exec("UPDATE peers SET Version=?,APIKey=?,Name=?,PublicIP=?,Port=?,Relay=?,PubKey=?,PubSignKey=? WHERE NetworkID=? AND PeerIP=?", row.Version, row.APIKey, row.Name, row.PublicIP, row.Port, row.Relay, row.PubKey, row.PubSignKey, row.NetworkID, row.PeerIP)
|
result, err := tx.Exec("UPDATE peers SET Version=?,APIKey=?,Name=?,PublicIP1=?,Port1=?,PublicIP2=?,Port2=?,Relay=?,WGPubKey=? WHERE NetworkID=? AND PeerIP=?", row.Version, row.APIKey, row.Name, row.PublicIP1, row.Port1, row.PublicIP2, row.Port2, row.Relay, row.WGPubKey, row.NetworkID, row.PeerIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -565,8 +456,10 @@ func Peer_Get(
|
|||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
row = &Peer{}
|
row = &Peer{}
|
||||||
r := tx.QueryRow("SELECT NetworkID,PeerIP,Version,APIKey,Name,PublicIP,Port,Relay,PubKey,PubSignKey FROM peers WHERE NetworkID=? AND PeerIP=?", NetworkID, PeerIP)
|
r := tx.QueryRow("SELECT NetworkID,PeerIP,Version,APIKey,Name,PublicIP1,Port1,PublicIP2,Port2,Relay,WGPubKey FROM peers WHERE NetworkID=? AND PeerIP=?", NetworkID, PeerIP)
|
||||||
err = r.Scan(&row.NetworkID, &row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP, &row.Port, &row.Relay, &row.PubKey, &row.PubSignKey)
|
if err = r.Scan(&row.NetworkID, &row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP1, &row.Port1, &row.PublicIP2, &row.Port2, &row.Relay, &row.WGPubKey); err != nil {
|
||||||
|
row = nil
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -580,7 +473,9 @@ func Peer_GetWhere(
|
|||||||
) {
|
) {
|
||||||
row = &Peer{}
|
row = &Peer{}
|
||||||
r := tx.QueryRow(query, args...)
|
r := tx.QueryRow(query, args...)
|
||||||
err = r.Scan(&row.NetworkID, &row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP, &row.Port, &row.Relay, &row.PubKey, &row.PubSignKey)
|
if err = r.Scan(&row.NetworkID, &row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP1, &row.Port1, &row.PublicIP2, &row.Port2, &row.Relay, &row.WGPubKey); err != nil {
|
||||||
|
row = nil
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -600,7 +495,7 @@ func Peer_Iterate(
|
|||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
row := &Peer{}
|
row := &Peer{}
|
||||||
err := rows.Scan(&row.NetworkID, &row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP, &row.Port, &row.Relay, &row.PubKey, &row.PubSignKey)
|
err := rows.Scan(&row.NetworkID, &row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP1, &row.Port1, &row.PublicIP2, &row.Port2, &row.Relay, &row.WGPubKey)
|
||||||
if !yield(row, err) {
|
if !yield(row, err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,13 +21,6 @@ func Config_Validate(c *Config) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Session_Sanitize(s *Session) {
|
|
||||||
}
|
|
||||||
|
|
||||||
func Session_Validate(s *Session) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Network_Sanitize(n *Network) {
|
func Network_Sanitize(n *Network) {
|
||||||
n.Name = strings.TrimSpace(n.Name)
|
n.Name = strings.TrimSpace(n.Name)
|
||||||
|
|
||||||
@@ -66,25 +59,39 @@ func Network_Validate(c *Network) error {
|
|||||||
|
|
||||||
func Peer_Sanitize(p *Peer) {
|
func Peer_Sanitize(p *Peer) {
|
||||||
p.Name = strings.TrimSpace(p.Name)
|
p.Name = strings.TrimSpace(p.Name)
|
||||||
if len(p.PublicIP) != 0 {
|
if len(p.PublicIP1) != 0 {
|
||||||
addr, ok := netip.AddrFromSlice(p.PublicIP)
|
if addr, ok := netip.AddrFromSlice(p.PublicIP1); ok {
|
||||||
if ok && addr.Is4() {
|
p.PublicIP1 = addr.AsSlice()
|
||||||
p.PublicIP = addr.AsSlice()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.Port == 0 {
|
if len(p.PublicIP2) != 0 {
|
||||||
p.Port = 456
|
if addr, ok := netip.AddrFromSlice(p.PublicIP2); ok {
|
||||||
|
p.PublicIP2 = addr.AsSlice()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.Port1 == 0 {
|
||||||
|
p.Port1 = 456
|
||||||
|
}
|
||||||
|
if len(p.PublicIP2) != 0 && p.Port2 == 0 {
|
||||||
|
p.Port2 = 456
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Peer_Validate(p *Peer) error {
|
func Peer_Validate(p *Peer) error {
|
||||||
if len(p.PublicIP) > 0 {
|
if len(p.PublicIP1) > 0 {
|
||||||
_, ok := netip.AddrFromSlice(p.PublicIP)
|
if _, ok := netip.AddrFromSlice(p.PublicIP1); !ok {
|
||||||
if !ok {
|
|
||||||
return ErrInvalidIP
|
return ErrInvalidIP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.Port == 0 {
|
if len(p.PublicIP2) > 0 {
|
||||||
|
if _, ok := netip.AddrFromSlice(p.PublicIP2); !ok {
|
||||||
|
return ErrInvalidIP
|
||||||
|
}
|
||||||
|
if p.Port2 == 0 {
|
||||||
|
return ErrInvalidPort
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.Port1 == 0 {
|
||||||
return ErrInvalidPort
|
return ErrInvalidPort
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +105,6 @@ func Peer_Validate(p *Peer) error {
|
|||||||
if c == '.' || c == '-' || c == '_' {
|
if c == '.' || c == '-' || c == '_' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrInvalidPeerName
|
return ErrInvalidPeerName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,14 +3,6 @@ TABLE config OF Config (
|
|||||||
Password []byte
|
Password []byte
|
||||||
);
|
);
|
||||||
|
|
||||||
TABLE sessions OF Session NoUpdate (
|
|
||||||
SessionID string PK,
|
|
||||||
CSRF string,
|
|
||||||
SignedIn bool,
|
|
||||||
CreatedAt int64,
|
|
||||||
LastSeenAt int64
|
|
||||||
);
|
|
||||||
|
|
||||||
TABLE networks OF Network (
|
TABLE networks OF Network (
|
||||||
NetworkID int64 PK,
|
NetworkID int64 PK,
|
||||||
Name string NoUpdate,
|
Name string NoUpdate,
|
||||||
@@ -23,9 +15,10 @@ TABLE peers OF Peer (
|
|||||||
Version int64,
|
Version int64,
|
||||||
APIKey string NoUpdate,
|
APIKey string NoUpdate,
|
||||||
Name string,
|
Name string,
|
||||||
PublicIP []byte,
|
PublicIP1 []byte,
|
||||||
Port uint16,
|
Port1 uint16,
|
||||||
|
PublicIP2 []byte,
|
||||||
|
Port2 uint16,
|
||||||
Relay bool,
|
Relay bool,
|
||||||
PubKey []byte NoUpdate,
|
WGPubKey []byte NoUpdate
|
||||||
PubSignKey []byte NoUpdate
|
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,31 +1,5 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
func Session_UpdateLastSeenAt(
|
|
||||||
tx TX,
|
|
||||||
id string,
|
|
||||||
) (err error) {
|
|
||||||
_, err = tx.Exec("UPDATE sessions SET LastSeenAt=? WHERE SessionID=?", time.Now().Unix(), id)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func Session_SetSignedIn(
|
|
||||||
tx TX,
|
|
||||||
id string,
|
|
||||||
) (err error) {
|
|
||||||
_, err = tx.Exec("UPDATE sessions SET SignedIn=1 WHERE SessionID=?", id)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func Session_DeleteBefore(
|
|
||||||
tx TX,
|
|
||||||
timestamp int64,
|
|
||||||
) (err error) {
|
|
||||||
_, err = tx.Exec("DELETE FROM sessions WHERE LastSeenAt<?", timestamp)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func Peer_ListAll(tx TX, networkID int64) ([]*Peer, error) {
|
func Peer_ListAll(tx TX, networkID int64) ([]*Peer, error) {
|
||||||
const query = Peer_SelectQuery + ` WHERE NetworkID=? ORDER BY PeerIP ASC`
|
const query = Peer_SelectQuery + ` WHERE NetworkID=? ORDER BY PeerIP ASC`
|
||||||
return Peer_List(tx, query, networkID)
|
return Peer_List(tx, query, networkID)
|
||||||
|
|||||||
@@ -3,16 +3,6 @@ CREATE TABLE config (
|
|||||||
Password BLOB NOT NULL -- bcrypt password for web interface
|
Password BLOB NOT NULL -- bcrypt password for web interface
|
||||||
) WITHOUT ROWID;
|
) WITHOUT ROWID;
|
||||||
|
|
||||||
CREATE TABLE sessions (
|
|
||||||
SessionID TEXT NOT NULL PRIMARY KEY,
|
|
||||||
CSRF TEXT NOT NULL,
|
|
||||||
SignedIn INTEGER NOT NULL,
|
|
||||||
CreatedAt INTEGER NOT NULL,
|
|
||||||
LastSeenAt INTEGER NOT NULL
|
|
||||||
) WITHOUT ROWID;
|
|
||||||
|
|
||||||
CREATE INDEX sessions_last_seen_index ON sessions(LastSeenAt);
|
|
||||||
|
|
||||||
CREATE TABLE networks (
|
CREATE TABLE networks (
|
||||||
NetworkID INTEGER NOT NULL PRIMARY KEY,
|
NetworkID INTEGER NOT NULL PRIMARY KEY,
|
||||||
Name TEXT NOT NULL UNIQUE, -- Network/interface name.
|
Name TEXT NOT NULL UNIQUE, -- Network/interface name.
|
||||||
@@ -21,14 +11,15 @@ CREATE TABLE networks (
|
|||||||
|
|
||||||
CREATE TABLE peers (
|
CREATE TABLE peers (
|
||||||
NetworkID INTEGER NOT NULL,
|
NetworkID INTEGER NOT NULL,
|
||||||
PeerIP INTEGER NOT NULL, -- Final byte of IP.
|
PeerIP INTEGER NOT NULL, -- Final byte of IP.
|
||||||
Version INTEGER NOT NULL, -- Changes when updated.
|
Version INTEGER NOT NULL, -- Changes when updated.
|
||||||
APIKey TEXT NOT NULL UNIQUE, -- Peer's secret API key.
|
APIKey TEXT NOT NULL UNIQUE, -- Peer's secret API key.
|
||||||
Name TEXT NOT NULL UNIQUE, -- For humans.
|
Name TEXT NOT NULL UNIQUE, -- For humans.
|
||||||
PublicIP BLOB NOT NULL,
|
PublicIP1 BLOB NOT NULL,
|
||||||
Port INTEGER NOT NULL,
|
Port1 INTEGER NOT NULL,
|
||||||
Relay INTEGER NOT NULL DEFAULT 0, -- Boolean if peer will forward packets. Must also have public address.
|
PublicIP2 BLOB NOT NULL,
|
||||||
PubKey BLOB NOT NULL,
|
Port2 INTEGER NOT NULL,
|
||||||
PubSignKey BLOB NOT NULL,
|
Relay INTEGER NOT NULL DEFAULT 0, -- Boolean if peer will forward packets.
|
||||||
|
WGPubKey BLOB NOT NULL,
|
||||||
PRIMARY KEY(NetworkID, PeerIP)
|
PRIMARY KEY(NetworkID, PeerIP)
|
||||||
) WITHOUT ROWID;
|
) WITHOUT ROWID;
|
||||||
|
|||||||
@@ -3,6 +3,12 @@ package api
|
|||||||
import "vppn/hub/api/db"
|
import "vppn/hub/api/db"
|
||||||
|
|
||||||
type Config = db.Config
|
type Config = db.Config
|
||||||
type Session = db.Session
|
|
||||||
type Network = db.Network
|
type Network = db.Network
|
||||||
type Peer = db.Peer
|
type Peer = db.Peer
|
||||||
|
|
||||||
|
type Session struct {
|
||||||
|
SessionID string
|
||||||
|
SignedIn bool
|
||||||
|
CreatedAt int64
|
||||||
|
LastSeenAt int64
|
||||||
|
}
|
||||||
|
|||||||
18
hub/app.go
18
hub/app.go
@@ -2,6 +2,7 @@ package hub
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
|
"encoding/base64"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -47,6 +48,19 @@ func NewApp(conf Config) (*App, error) {
|
|||||||
return app, nil
|
return app, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var templateFuncs = template.FuncMap{
|
func (app *App) Handler() http.Handler {
|
||||||
"ipToString": ipBytesTostring,
|
cop := http.NewCrossOriginProtection()
|
||||||
|
return cop.Handler(app.mux)
|
||||||
|
}
|
||||||
|
|
||||||
|
var templateFuncs = template.FuncMap{
|
||||||
|
"ipToString": ipBytesTostring,
|
||||||
|
"wgKeyString": wgKeyString,
|
||||||
|
}
|
||||||
|
|
||||||
|
func wgKeyString(key []byte) string {
|
||||||
|
if len(key) == 0 {
|
||||||
|
return "not set"
|
||||||
|
}
|
||||||
|
return base64.StdEncoding.EncodeToString(key)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,11 +26,6 @@ func (app *App) handlePub(pattern string, fn handlerFunc) {
|
|||||||
|
|
||||||
if r.Method == http.MethodPost {
|
if r.Method == http.MethodPost {
|
||||||
r.ParseMultipartForm(64 * 1024)
|
r.ParseMultipartForm(64 * 1024)
|
||||||
if r.FormValue("CSRF") != s.CSRF {
|
|
||||||
log.Printf("%s != %s", r.FormValue("CSRF"), s.CSRF)
|
|
||||||
http.Error(w, "CSRF mismatch", http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
r.ParseForm()
|
r.ParseForm()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,22 +142,27 @@ func (a *App) _adminPeerCreate(s *api.Session, w http.ResponseWriter, r *http.Re
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) _adminPeerCreateSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
func (a *App) _adminPeerCreateSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
var ipStr string
|
var ip1Str, ip2Str string
|
||||||
|
|
||||||
p := &api.Peer{}
|
p := &api.Peer{}
|
||||||
err := webutil.NewFormScanner(r.Form).
|
err := webutil.NewFormScanner(r.Form).
|
||||||
Scan("NetworkID", &p.NetworkID).
|
Scan("NetworkID", &p.NetworkID).
|
||||||
Scan("IP", &p.PeerIP).
|
Scan("IP", &p.PeerIP).
|
||||||
Scan("Name", &p.Name).
|
Scan("Name", &p.Name).
|
||||||
Scan("PublicIP", &ipStr).
|
Scan("PublicIP1", &ip1Str).
|
||||||
Scan("Port", &p.Port).
|
Scan("Port1", &p.Port1).
|
||||||
|
Scan("PublicIP2", &ip2Str).
|
||||||
|
Scan("Port2", &p.Port2).
|
||||||
Scan("Relay", &p.Relay).
|
Scan("Relay", &p.Relay).
|
||||||
Error()
|
Error()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.PublicIP, err = stringToIP(ipStr); err != nil {
|
if p.PublicIP1, err = stringToIP(ip1Str); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if p.PublicIP2, err = stringToIP(ip2Str); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,19 +204,24 @@ func (a *App) _adminPeerEditSubmit(s *api.Session, w http.ResponseWriter, r *htt
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var ipStr string
|
var ip1Str, ip2Str string
|
||||||
|
|
||||||
err = webutil.NewFormScanner(r.Form).
|
err = webutil.NewFormScanner(r.Form).
|
||||||
Scan("Name", &peer.Name).
|
Scan("Name", &peer.Name).
|
||||||
Scan("PublicIP", &ipStr).
|
Scan("PublicIP1", &ip1Str).
|
||||||
Scan("Port", &peer.Port).
|
Scan("Port1", &peer.Port1).
|
||||||
|
Scan("PublicIP2", &ip2Str).
|
||||||
|
Scan("Port2", &peer.Port2).
|
||||||
Scan("Relay", &peer.Relay).
|
Scan("Relay", &peer.Relay).
|
||||||
Error()
|
Error()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if peer.PublicIP, err = stringToIP(ipStr); err != nil {
|
if peer.PublicIP1, err = stringToIP(ip1Str); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if peer.PublicIP2, err = stringToIP(ip2Str); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,6 +305,11 @@ func (a *App) _adminPasswordSubmit(s *api.Session, w http.ResponseWriter, r *htt
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) _peerInit(peer *api.Peer, w http.ResponseWriter, r *http.Request) error {
|
func (a *App) _peerInit(peer *api.Peer, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
if len(peer.WGPubKey) != 0 {
|
||||||
|
http.Error(w, "Already initialized", http.StatusConflict)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
args := m.PeerInitArgs{}
|
args := m.PeerInitArgs{}
|
||||||
if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -338,16 +353,17 @@ func (a *App) peersArray(networkID int64) (peers [256]*m.Peer, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, p := range l {
|
for _, p := range l {
|
||||||
if len(p.PubKey) != 0 {
|
if len(p.WGPubKey) != 0 {
|
||||||
peers[p.PeerIP] = &m.Peer{
|
peers[p.PeerIP] = &m.Peer{
|
||||||
PeerIP: p.PeerIP,
|
PeerIP: p.PeerIP,
|
||||||
Version: p.Version,
|
Version: p.Version,
|
||||||
Name: p.Name,
|
Name: p.Name,
|
||||||
PublicIP: p.PublicIP,
|
PublicIP1: p.PublicIP1,
|
||||||
Port: p.Port,
|
Port1: p.Port1,
|
||||||
Relay: p.Relay,
|
PublicIP2: p.PublicIP2,
|
||||||
PubKey: p.PubKey,
|
Port2: p.Port2,
|
||||||
PubSignKey: p.PubSignKey,
|
Relay: p.Relay,
|
||||||
|
WGPubKey: p.WGPubKey,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ func Main() {
|
|||||||
|
|
||||||
srv := &http.Server{
|
srv := &http.Server{
|
||||||
Addr: conf.ListenAddr,
|
Addr: conf.ListenAddr,
|
||||||
Handler: app.mux,
|
Handler: app.Handler(),
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Fatal(webutil.ListenAndServe(srv))
|
log.Fatal(webutil.ListenAndServe(srv))
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
<h2>Create Network</h2>
|
<h2>Create Network</h2>
|
||||||
|
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<input type="hidden" name="CSRF" value="{{.Session.CSRF}}">
|
<p>
|
||||||
<p>
|
|
||||||
<label>Name</label><br>
|
<label>Name</label><br>
|
||||||
<input type="text" name="Name">
|
<input type="text" name="Name">
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
<h2>Change Password</h2>
|
<h2>Change Password</h2>
|
||||||
|
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<input type="hidden" name="CSRF" value="{{.Session.CSRF}}">
|
<p>
|
||||||
<p>
|
|
||||||
<label>Current Password</label><br>
|
<label>Current Password</label><br>
|
||||||
<input type="password" name="CurrentPassword">
|
<input type="password" name="CurrentPassword">
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
<h2>Sign Out</h2>
|
<h2>Sign Out</h2>
|
||||||
|
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<input type="hidden" name="CSRF" value="{{.Session.CSRF}}">
|
<p>
|
||||||
<p>
|
|
||||||
<button type="submit">Sign Out</button>
|
<button type="submit">Sign Out</button>
|
||||||
<a href="/">Cancel</a>
|
<a href="/">Cancel</a>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -5,8 +5,7 @@
|
|||||||
<p>You must first delete all peers.</p>
|
<p>You must first delete all peers.</p>
|
||||||
{{- else -}}
|
{{- else -}}
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<input type="hidden" name="CSRF" value="{{.Session.CSRF}}">
|
<input type="hidden" name="NetworkID" value="{{.Network.NetworkID}}">
|
||||||
<input type="hidden" name="NetworkID" value="{{.Network.NetworkID}}">
|
|
||||||
<p>
|
<p>
|
||||||
<button type="submit">Delete</button>
|
<button type="submit">Delete</button>
|
||||||
<a href="/admin/network/view/?NetworkID={{.Network.NetworkID}}">Cancel</a>
|
<a href="/admin/network/view/?NetworkID={{.Network.NetworkID}}">Cancel</a>
|
||||||
|
|||||||
@@ -22,8 +22,10 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>PeerIP</th>
|
<th>PeerIP</th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Public IP</th>
|
<th>Public IP 1</th>
|
||||||
<th>Port</th>
|
<th>Port 1</th>
|
||||||
|
<th>Public IP 2</th>
|
||||||
|
<th>Port 2</th>
|
||||||
<th>Relay</th>
|
<th>Relay</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -36,8 +38,10 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>{{.Name}}</td>
|
<td>{{.Name}}</td>
|
||||||
<td>{{ipToString .PublicIP}}</td>
|
<td>{{ipToString .PublicIP1}}</td>
|
||||||
<td>{{.Port}}</td>
|
<td>{{.Port1}}</td>
|
||||||
|
<td>{{ipToString .PublicIP2}}</td>
|
||||||
|
<td>{{.Port2}}</td>
|
||||||
<td>{{if .Relay}}T{{else}}F{{end}}</td>
|
<td>{{if .Relay}}T{{else}}F{{end}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
<h3>New Peer</h3>
|
<h3>New Peer</h3>
|
||||||
|
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<input type="hidden" name="CSRF" value="{{.Session.CSRF}}">
|
|
||||||
<input type="hidden" name="NetworkID" value="{{.Network.NetworkID}}">
|
<input type="hidden" name="NetworkID" value="{{.Network.NetworkID}}">
|
||||||
<p>
|
<p>
|
||||||
<label>IP</label><br>
|
<label>IP</label><br>
|
||||||
@@ -13,12 +12,20 @@
|
|||||||
<input type="text" name="Name">
|
<input type="text" name="Name">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label>Public IP</label><br>
|
<label>Public IP 1</label><br>
|
||||||
<input type="text" name="PublicIP">
|
<input type="text" name="PublicIP1">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label>Port</label><br>
|
<label>Port 1</label><br>
|
||||||
<input type="number" name="Port" value="456">
|
<input type="number" name="Port1" value="456">
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label>Public IP 2 (optional)</label><br>
|
||||||
|
<input type="text" name="PublicIP2">
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label>Port 2</label><br>
|
||||||
|
<input type="number" name="Port2" value="0">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label>
|
<label>
|
||||||
|
|||||||
@@ -3,8 +3,7 @@
|
|||||||
|
|
||||||
{{with .Peer -}}
|
{{with .Peer -}}
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<input type="hidden" name="CSRF" value="{{$.Session.CSRF}}">
|
<input type="hidden" name="NetworkID" value="{{.NetworkID}}">
|
||||||
<input type="hidden" name="NetworkID" value="{{.NetworkID}}">
|
|
||||||
<input type="hidden" name="NetworkID" value="{{.PeerIP}}">
|
<input type="hidden" name="NetworkID" value="{{.PeerIP}}">
|
||||||
<p>
|
<p>
|
||||||
<button type="submit">Delete</button>
|
<button type="submit">Delete</button>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
{{with .Peer -}}
|
{{with .Peer -}}
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<input type="hidden" name="CSRF" value="{{$.Session.CSRF}}">
|
|
||||||
<p>
|
<p>
|
||||||
<label>Peer IP</label><br>
|
<label>Peer IP</label><br>
|
||||||
<input type="text" value="{{.PeerIP}}" disabled>
|
<input type="text" value="{{.PeerIP}}" disabled>
|
||||||
@@ -13,12 +12,20 @@
|
|||||||
<input type="text" name="Name" value="{{.Name}}">
|
<input type="text" name="Name" value="{{.Name}}">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label>Public IP</label><br>
|
<label>Public IP 1</label><br>
|
||||||
<input type="text" name="PublicIP" value="{{ipToString .PublicIP}}">
|
<input type="text" name="PublicIP1" value="{{ipToString .PublicIP1}}">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label>Port</label><br>
|
<label>Port 1</label><br>
|
||||||
<input type="number" name="Port" value="{{.Port}}">
|
<input type="number" name="Port1" value="{{.Port1}}">
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label>Public IP 2 (optional)</label><br>
|
||||||
|
<input type="text" name="PublicIP2" value="{{ipToString .PublicIP2}}">
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label>Port 2</label><br>
|
||||||
|
<input type="number" name="Port2" value="{{.Port2}}">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label>
|
<label>
|
||||||
|
|||||||
@@ -8,10 +8,12 @@
|
|||||||
{{with .Peer -}}
|
{{with .Peer -}}
|
||||||
<table class="def-list">
|
<table class="def-list">
|
||||||
<tr><td>Peer IP</td><td>{{.PeerIP}}</td></tr>
|
<tr><td>Peer IP</td><td>{{.PeerIP}}</td></tr>
|
||||||
<tr><td>Public IP</td><td>{{ipToString .PublicIP}}</td></tr>
|
<tr><td>Public IP 1</td><td>{{ipToString .PublicIP1}}</td></tr>
|
||||||
<tr><td>Port</td><td>{{.Port}}</td></tr>
|
<tr><td>Port 1</td><td>{{.Port1}}</td></tr>
|
||||||
|
<tr><td>Public IP 2</td><td>{{ipToString .PublicIP2}}</td></tr>
|
||||||
|
<tr><td>Port 2</td><td>{{.Port2}}</td></tr>
|
||||||
<tr><td>Relay</td><td>{{if .Relay}}T{{else}}F{{end}}</td></tr>
|
<tr><td>Relay</td><td>{{if .Relay}}T{{else}}F{{end}}</td></tr>
|
||||||
</td></tr>
|
<tr><td>WG Public Key</td><td>{{wgKeyString .WGPubKey}}</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
@@ -19,7 +21,6 @@
|
|||||||
<p>{{.APIKey}}</p>
|
<p>{{.APIKey}}</p>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
<h2>Sign In</h2>
|
<h2>Sign In</h2>
|
||||||
|
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<input type="hidden" name="CSRF" value="{{.Session.CSRF}}">
|
<p>
|
||||||
<p>
|
|
||||||
<label>Password</label><br>
|
<label>Password</label><br>
|
||||||
<input type="password" name="Password">
|
<input type="password" name="Password">
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
20
m/models.go
20
m/models.go
@@ -2,8 +2,7 @@
|
|||||||
package m
|
package m
|
||||||
|
|
||||||
type PeerInitArgs struct {
|
type PeerInitArgs struct {
|
||||||
EncPubKey []byte
|
WGPubKey []byte
|
||||||
PubSignKey []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type PeerInitResp struct {
|
type PeerInitResp struct {
|
||||||
@@ -13,14 +12,15 @@ type PeerInitResp struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Peer struct {
|
type Peer struct {
|
||||||
PeerIP byte
|
PeerIP byte
|
||||||
Version int64
|
Version int64
|
||||||
Name string
|
Name string
|
||||||
PublicIP []byte
|
PublicIP1 []byte
|
||||||
Port uint16
|
Port1 uint16
|
||||||
Relay bool
|
PublicIP2 []byte
|
||||||
PubKey []byte
|
Port2 uint16
|
||||||
PubSignKey []byte
|
Relay bool
|
||||||
|
WGPubKey []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type NetworkState struct {
|
type NetworkState struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user