mirror of
https://github.com/DeBrosOfficial/network.git
synced 2025-10-06 04:29:07 +00:00
replaced git.debros.io with github.com
This commit is contained in:
parent
82187de96c
commit
ff3b15108d
@ -11,7 +11,7 @@ Thanks for helping improve the network! This guide covers setup, local dev, test
|
|||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://git.debros.io/DeBros/network.git
|
git clone https://github.com/DeBrosOfficial/network.git
|
||||||
cd network
|
cd network
|
||||||
make deps
|
make deps
|
||||||
```
|
```
|
||||||
|
2
Makefile
2
Makefile
@ -33,7 +33,7 @@ build: deps
|
|||||||
go build -ldflags "$(LDFLAGS)" -o bin/node ./cmd/node
|
go build -ldflags "$(LDFLAGS)" -o bin/node ./cmd/node
|
||||||
go build -ldflags "$(LDFLAGS)" -o bin/network-cli cmd/cli/main.go
|
go build -ldflags "$(LDFLAGS)" -o bin/network-cli cmd/cli/main.go
|
||||||
# Inject gateway build metadata via pkg path variables
|
# Inject gateway build metadata via pkg path variables
|
||||||
go build -ldflags "$(LDFLAGS) -X 'git.debros.io/DeBros/network/pkg/gateway.BuildVersion=$(VERSION)' -X 'git.debros.io/DeBros/network/pkg/gateway.BuildCommit=$(COMMIT)' -X 'git.debros.io/DeBros/network/pkg/gateway.BuildTime=$(DATE)'" -o bin/gateway ./cmd/gateway
|
go build -ldflags "$(LDFLAGS) -X 'github.com/DeBrosOfficial/network/pkg/gateway.BuildVersion=$(VERSION)' -X 'github.com/DeBrosOfficial/network/pkg/gateway.BuildCommit=$(COMMIT)' -X 'github.com/DeBrosOfficial/network/pkg/gateway.BuildTime=$(DATE)'" -o bin/gateway ./cmd/gateway
|
||||||
@echo "Build complete! Run ./bin/network-cli version"
|
@echo "Build complete! Run ./bin/network-cli version"
|
||||||
|
|
||||||
# Clean build artifacts
|
# Clean build artifacts
|
||||||
|
10
README.md
10
README.md
@ -94,7 +94,7 @@ A robust, decentralized peer-to-peer network built in Go, providing distributed
|
|||||||
### 1. Clone and Setup
|
### 1. Clone and Setup
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://git.debros.io/DeBros/network.git
|
git clone https://github.com/DeBrosOfficial/network.git
|
||||||
cd network
|
cd network
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ go run ./cmd/node --config configs/node.yaml
|
|||||||
Run the install script for a secure, production-ready setup:
|
Run the install script for a secure, production-ready setup:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -sSL https://git.debros.io/DeBros/network/raw/branch/main/scripts/install-debros-network.sh | sudo bash
|
curl -sSL https://github.com/DeBrosOfficial/network/raw/branch/main/scripts/install-debros-network.sh | sudo bash
|
||||||
```
|
```
|
||||||
|
|
||||||
**What the Script Does:**
|
**What the Script Does:**
|
||||||
@ -279,7 +279,7 @@ logging:
|
|||||||
./bin/network-cli peers # List connected peers
|
./bin/network-cli peers # List connected peers
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Database Operations
|
### Database Operations
|
||||||
|
|
||||||
@ -435,7 +435,7 @@ GET /v1/auth/whoami # Current auth status
|
|||||||
POST /v1/auth/api-key # Generate API key (authenticated)
|
POST /v1/auth/api-key # Generate API key (authenticated)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### Network Operations
|
#### Network Operations
|
||||||
```http
|
```http
|
||||||
@ -542,7 +542,7 @@ curl -X POST http://localhost:8080/v1/auth/verify \
|
|||||||
-d '{"wallet":"0x...","nonce":"...","signature":"0x..."}'
|
-d '{"wallet":"0x...","nonce":"...","signature":"0x..."}'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### Real-time Messaging
|
#### Real-time Messaging
|
||||||
```javascript
|
```javascript
|
||||||
|
@ -12,9 +12,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/anyoneproxy"
|
"github.com/DeBrosOfficial/network/pkg/anyoneproxy"
|
||||||
"git.debros.io/DeBros/network/pkg/auth"
|
"github.com/DeBrosOfficial/network/pkg/auth"
|
||||||
"git.debros.io/DeBros/network/pkg/client"
|
"github.com/DeBrosOfficial/network/pkg/client"
|
||||||
"github.com/libp2p/go-libp2p/core/crypto"
|
"github.com/libp2p/go-libp2p/core/crypto"
|
||||||
"github.com/libp2p/go-libp2p/core/peer"
|
"github.com/libp2p/go-libp2p/core/peer"
|
||||||
)
|
)
|
||||||
|
@ -5,8 +5,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/gateway"
|
"github.com/DeBrosOfficial/network/pkg/gateway"
|
||||||
"git.debros.io/DeBros/network/pkg/logging"
|
"github.com/DeBrosOfficial/network/pkg/logging"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -9,8 +9,8 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/gateway"
|
"github.com/DeBrosOfficial/network/pkg/gateway"
|
||||||
"git.debros.io/DeBros/network/pkg/logging"
|
"github.com/DeBrosOfficial/network/pkg/logging"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -11,10 +11,10 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/anyoneproxy"
|
"github.com/DeBrosOfficial/network/pkg/anyoneproxy"
|
||||||
"git.debros.io/DeBros/network/pkg/config"
|
"github.com/DeBrosOfficial/network/pkg/config"
|
||||||
"git.debros.io/DeBros/network/pkg/logging"
|
"github.com/DeBrosOfficial/network/pkg/logging"
|
||||||
"git.debros.io/DeBros/network/pkg/node"
|
"github.com/DeBrosOfficial/network/pkg/node"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/client"
|
"github.com/DeBrosOfficial/network/pkg/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getenv(k, def string) string {
|
func getenv(k, def string) string {
|
||||||
@ -42,7 +42,9 @@ func TestClient_Database_CreateQueryMigrate(t *testing.T) {
|
|||||||
var peers []string
|
var peers []string
|
||||||
for _, p := range parts {
|
for _, p := range parts {
|
||||||
p = strings.TrimSpace(p)
|
p = strings.TrimSpace(p)
|
||||||
if p != "" { peers = append(peers, p) }
|
if p != "" {
|
||||||
|
peers = append(peers, p)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cfg.BootstrapPeers = peers
|
cfg.BootstrapPeers = peers
|
||||||
}
|
}
|
||||||
@ -52,9 +54,13 @@ func TestClient_Database_CreateQueryMigrate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c, err := client.NewClient(cfg)
|
c, err := client.NewClient(cfg)
|
||||||
if err != nil { t.Fatalf("new client: %v", err) }
|
if err != nil {
|
||||||
if err := c.Connect(); err != nil { t.Fatalf("connect: %v", err) }
|
t.Fatalf("new client: %v", err)
|
||||||
t.Cleanup(func(){ _ = c.Disconnect() })
|
}
|
||||||
|
if err := c.Connect(); err != nil {
|
||||||
|
t.Fatalf("connect: %v", err)
|
||||||
|
}
|
||||||
|
t.Cleanup(func() { _ = c.Disconnect() })
|
||||||
|
|
||||||
// Unique table per run
|
// Unique table per run
|
||||||
table := fmt.Sprintf("e2e_items_client_%d", time.Now().UnixNano())
|
table := fmt.Sprintf("e2e_items_client_%d", time.Now().UnixNano())
|
||||||
@ -78,6 +84,10 @@ func TestClient_Database_CreateQueryMigrate(t *testing.T) {
|
|||||||
ctx3, cancel3 := context.WithTimeout(context.Background(), 10*time.Second)
|
ctx3, cancel3 := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
defer cancel3()
|
defer cancel3()
|
||||||
res, err := c.Database().Query(ctx3, fmt.Sprintf("SELECT name FROM %s ORDER BY id", table))
|
res, err := c.Database().Query(ctx3, fmt.Sprintf("SELECT name FROM %s ORDER BY id", table))
|
||||||
if err != nil { t.Fatalf("query: %v", err) }
|
if err != nil {
|
||||||
if res.Count < 2 { t.Fatalf("expected at least 2 rows, got %d", res.Count) }
|
t.Fatalf("query: %v", err)
|
||||||
|
}
|
||||||
|
if res.Count < 2 {
|
||||||
|
t.Fatalf("expected at least 2 rows, got %d", res.Count)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/client"
|
"github.com/DeBrosOfficial/network/pkg/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
2
go.mod
2
go.mod
@ -1,4 +1,4 @@
|
|||||||
module git.debros.io/DeBros/network
|
module github.com/DeBrosOfficial/network
|
||||||
|
|
||||||
go 1.23.8
|
go 1.23.8
|
||||||
|
|
||||||
|
@ -20,8 +20,8 @@ import (
|
|||||||
|
|
||||||
libp2ppubsub "github.com/libp2p/go-libp2p-pubsub"
|
libp2ppubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/anyoneproxy"
|
"github.com/DeBrosOfficial/network/pkg/anyoneproxy"
|
||||||
"git.debros.io/DeBros/network/pkg/pubsub"
|
"github.com/DeBrosOfficial/network/pkg/pubsub"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client implements the NetworkClient interface
|
// Client implements the NetworkClient interface
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/pubsub"
|
"github.com/DeBrosOfficial/network/pkg/pubsub"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MakeJWT creates a minimal JWT-like token with a json payload
|
// MakeJWT creates a minimal JWT-like token with a json payload
|
||||||
|
@ -3,7 +3,7 @@ package client
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/pubsub"
|
"github.com/DeBrosOfficial/network/pkg/pubsub"
|
||||||
)
|
)
|
||||||
|
|
||||||
// contextKey for internal operations
|
// contextKey for internal operations
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/config"
|
"github.com/DeBrosOfficial/network/pkg/config"
|
||||||
"github.com/multiformats/go-multiaddr"
|
"github.com/multiformats/go-multiaddr"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/anyoneproxy"
|
"github.com/DeBrosOfficial/network/pkg/anyoneproxy"
|
||||||
"github.com/libp2p/go-libp2p/core/peer"
|
"github.com/libp2p/go-libp2p/core/peer"
|
||||||
"github.com/multiformats/go-multiaddr"
|
"github.com/multiformats/go-multiaddr"
|
||||||
"github.com/rqlite/gorqlite"
|
"github.com/rqlite/gorqlite"
|
||||||
|
@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/pubsub"
|
"github.com/DeBrosOfficial/network/pkg/pubsub"
|
||||||
)
|
)
|
||||||
|
|
||||||
// pubSubBridge bridges between our PubSubClient interface and the pubsub package
|
// pubSubBridge bridges between our PubSubClient interface and the pubsub package
|
||||||
|
@ -15,7 +15,7 @@ import (
|
|||||||
"github.com/rqlite/gorqlite"
|
"github.com/rqlite/gorqlite"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/config"
|
"github.com/DeBrosOfficial/network/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RQLiteManager manages an RQLite node instance
|
// RQLiteManager manages an RQLite node instance
|
||||||
|
@ -7,16 +7,16 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/storage"
|
"github.com/DeBrosOfficial/network/pkg/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// appsHandler implements minimal CRUD for apps within a namespace.
|
// appsHandler implements minimal CRUD for apps within a namespace.
|
||||||
// Routes handled:
|
// Routes handled:
|
||||||
// - GET /v1/apps -> list
|
// - GET /v1/apps -> list
|
||||||
// - POST /v1/apps -> create
|
// - POST /v1/apps -> create
|
||||||
// - GET /v1/apps/{app_id} -> fetch
|
// - GET /v1/apps/{app_id} -> fetch
|
||||||
// - PUT /v1/apps/{app_id} -> update (name/public_key)
|
// - PUT /v1/apps/{app_id} -> update (name/public_key)
|
||||||
// - DELETE /v1/apps/{app_id} -> delete
|
// - DELETE /v1/apps/{app_id} -> delete
|
||||||
func (g *Gateway) appsHandler(w http.ResponseWriter, r *http.Request) {
|
func (g *Gateway) appsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if g.client == nil {
|
if g.client == nil {
|
||||||
writeError(w, http.StatusServiceUnavailable, "client not initialized")
|
writeError(w, http.StatusServiceUnavailable, "client not initialized")
|
||||||
@ -29,7 +29,9 @@ func (g *Gateway) appsHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
ns = s
|
ns = s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if strings.TrimSpace(ns) == "" { ns = "default" }
|
if strings.TrimSpace(ns) == "" {
|
||||||
|
ns = "default"
|
||||||
|
}
|
||||||
db := g.client.Database()
|
db := g.client.Database()
|
||||||
nsID, err := g.resolveNamespaceID(ctx, ns)
|
nsID, err := g.resolveNamespaceID(ctx, ns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -11,8 +11,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/client"
|
"github.com/DeBrosOfficial/network/pkg/client"
|
||||||
"git.debros.io/DeBros/network/pkg/storage"
|
"github.com/DeBrosOfficial/network/pkg/storage"
|
||||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ package gateway
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/client"
|
"github.com/DeBrosOfficial/network/pkg/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (g *Gateway) resolveNamespaceID(ctx context.Context, ns string) (interface{}, error) {
|
func (g *Gateway) resolveNamespaceID(ctx context.Context, ns string) (interface{}, error) {
|
||||||
|
@ -7,10 +7,9 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/client"
|
"github.com/DeBrosOfficial/network/pkg/client"
|
||||||
"git.debros.io/DeBros/network/pkg/logging"
|
"github.com/DeBrosOfficial/network/pkg/logging"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -59,7 +58,7 @@ func New(logger *logging.ColoredLogger, cfg *Config) (*Gateway, error) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
logger.ComponentInfo(logging.ComponentGeneral, "Creating gateway instance...")
|
logger.ComponentInfo(logging.ComponentGeneral, "Creating gateway instance...")
|
||||||
gw := &Gateway{
|
gw := &Gateway{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
client: c,
|
client: c,
|
||||||
|
@ -9,9 +9,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/client"
|
"github.com/DeBrosOfficial/network/pkg/client"
|
||||||
"git.debros.io/DeBros/network/pkg/logging"
|
"github.com/DeBrosOfficial/network/pkg/logging"
|
||||||
"git.debros.io/DeBros/network/pkg/storage"
|
"github.com/DeBrosOfficial/network/pkg/storage"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -96,13 +96,13 @@ func (g *Gateway) authMiddleware(next http.Handler) http.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look up API key in DB and derive namespace
|
// Look up API key in DB and derive namespace
|
||||||
db := g.client.Database()
|
db := g.client.Database()
|
||||||
// Use internal auth for DB validation (auth not established yet)
|
// Use internal auth for DB validation (auth not established yet)
|
||||||
internalCtx := client.WithInternalAuth(r.Context())
|
internalCtx := client.WithInternalAuth(r.Context())
|
||||||
// Join to namespaces to resolve name in one query
|
// Join to namespaces to resolve name in one query
|
||||||
q := "SELECT namespaces.name FROM api_keys JOIN namespaces ON api_keys.namespace_id = namespaces.id WHERE api_keys.key = ? LIMIT 1"
|
q := "SELECT namespaces.name FROM api_keys JOIN namespaces ON api_keys.namespace_id = namespaces.id WHERE api_keys.key = ? LIMIT 1"
|
||||||
res, err := db.Query(internalCtx, q, key)
|
res, err := db.Query(internalCtx, q, key)
|
||||||
if err != nil || res == nil || res.Count == 0 || len(res.Rows) == 0 || len(res.Rows[0]) == 0 {
|
if err != nil || res == nil || res.Count == 0 || len(res.Rows) == 0 || len(res.Rows[0]) == 0 {
|
||||||
w.Header().Set("WWW-Authenticate", "Bearer error=\"invalid_token\"")
|
w.Header().Set("WWW-Authenticate", "Bearer error=\"invalid_token\"")
|
||||||
writeError(w, http.StatusUnauthorized, "invalid API key")
|
writeError(w, http.StatusUnauthorized, "invalid API key")
|
||||||
@ -123,10 +123,10 @@ func (g *Gateway) authMiddleware(next http.Handler) http.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach auth metadata to context for downstream use
|
// Attach auth metadata to context for downstream use
|
||||||
reqCtx := context.WithValue(r.Context(), ctxKeyAPIKey, key)
|
reqCtx := context.WithValue(r.Context(), ctxKeyAPIKey, key)
|
||||||
reqCtx = storage.WithNamespace(reqCtx, ns)
|
reqCtx = storage.WithNamespace(reqCtx, ns)
|
||||||
next.ServeHTTP(w, r.WithContext(reqCtx))
|
next.ServeHTTP(w, r.WithContext(reqCtx))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,25 +203,25 @@ func (g *Gateway) authorizationMiddleware(next http.Handler) http.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identify actor from context
|
// Identify actor from context
|
||||||
ownerType := ""
|
ownerType := ""
|
||||||
ownerID := ""
|
ownerID := ""
|
||||||
if v := ctx.Value(ctxKeyJWT); v != nil {
|
if v := ctx.Value(ctxKeyJWT); v != nil {
|
||||||
if claims, ok := v.(*jwtClaims); ok && claims != nil && strings.TrimSpace(claims.Sub) != "" {
|
if claims, ok := v.(*jwtClaims); ok && claims != nil && strings.TrimSpace(claims.Sub) != "" {
|
||||||
// Determine subject type.
|
// Determine subject type.
|
||||||
// If subject looks like an API key (e.g., ak_<random>:<namespace>),
|
// If subject looks like an API key (e.g., ak_<random>:<namespace>),
|
||||||
// treat it as an API key owner; otherwise assume a wallet subject.
|
// treat it as an API key owner; otherwise assume a wallet subject.
|
||||||
subj := strings.TrimSpace(claims.Sub)
|
subj := strings.TrimSpace(claims.Sub)
|
||||||
lowerSubj := strings.ToLower(subj)
|
lowerSubj := strings.ToLower(subj)
|
||||||
if strings.HasPrefix(lowerSubj, "ak_") || strings.Contains(subj, ":") {
|
if strings.HasPrefix(lowerSubj, "ak_") || strings.Contains(subj, ":") {
|
||||||
ownerType = "api_key"
|
ownerType = "api_key"
|
||||||
ownerID = subj
|
ownerID = subj
|
||||||
} else {
|
} else {
|
||||||
ownerType = "wallet"
|
ownerType = "wallet"
|
||||||
ownerID = subj
|
ownerID = subj
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ownerType == "" && ownerID == "" {
|
if ownerType == "" && ownerID == "" {
|
||||||
if v := ctx.Value(ctxKeyAPIKey); v != nil {
|
if v := ctx.Value(ctxKeyAPIKey); v != nil {
|
||||||
if s, ok := v.(string); ok && strings.TrimSpace(s) != "" {
|
if s, ok := v.(string); ok && strings.TrimSpace(s) != "" {
|
||||||
@ -236,23 +236,23 @@ func (g *Gateway) authorizationMiddleware(next http.Handler) http.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check ownership in DB using internal auth context
|
// Check ownership in DB using internal auth context
|
||||||
db := g.client.Database()
|
db := g.client.Database()
|
||||||
internalCtx := client.WithInternalAuth(ctx)
|
internalCtx := client.WithInternalAuth(ctx)
|
||||||
// Ensure namespace exists and get id
|
// Ensure namespace exists and get id
|
||||||
if _, err := db.Query(internalCtx, "INSERT OR IGNORE INTO namespaces(name) VALUES (?)", ns); err != nil {
|
if _, err := db.Query(internalCtx, "INSERT OR IGNORE INTO namespaces(name) VALUES (?)", ns); err != nil {
|
||||||
writeError(w, http.StatusInternalServerError, err.Error())
|
writeError(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nres, err := db.Query(internalCtx, "SELECT id FROM namespaces WHERE name = ? LIMIT 1", ns)
|
nres, err := db.Query(internalCtx, "SELECT id FROM namespaces WHERE name = ? LIMIT 1", ns)
|
||||||
if err != nil || nres == nil || nres.Count == 0 || len(nres.Rows) == 0 || len(nres.Rows[0]) == 0 {
|
if err != nil || nres == nil || nres.Count == 0 || len(nres.Rows) == 0 || len(nres.Rows[0]) == 0 {
|
||||||
writeError(w, http.StatusForbidden, "namespace not found")
|
writeError(w, http.StatusForbidden, "namespace not found")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nsID := nres.Rows[0][0]
|
nsID := nres.Rows[0][0]
|
||||||
|
|
||||||
q := "SELECT 1 FROM namespace_ownership WHERE namespace_id = ? AND owner_type = ? AND owner_id = ? LIMIT 1"
|
q := "SELECT 1 FROM namespace_ownership WHERE namespace_id = ? AND owner_type = ? AND owner_id = ? LIMIT 1"
|
||||||
res, err := db.Query(internalCtx, q, nsID, ownerType, ownerID)
|
res, err := db.Query(internalCtx, q, nsID, ownerType, ownerID)
|
||||||
if err != nil || res == nil || res.Count == 0 {
|
if err != nil || res == nil || res.Count == 0 {
|
||||||
writeError(w, http.StatusForbidden, "forbidden: not an owner of namespace")
|
writeError(w, http.StatusForbidden, "forbidden: not an owner of namespace")
|
||||||
return
|
return
|
||||||
@ -274,9 +274,9 @@ func requiresNamespaceOwnership(p string) bool {
|
|||||||
if strings.HasPrefix(p, "/v1/pubsub") {
|
if strings.HasPrefix(p, "/v1/pubsub") {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(p, "/v1/db/") {
|
if strings.HasPrefix(p, "/v1/db/") {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,8 +9,8 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/client"
|
"github.com/DeBrosOfficial/network/pkg/client"
|
||||||
"git.debros.io/DeBros/network/pkg/logging"
|
"github.com/DeBrosOfficial/network/pkg/logging"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
package gateway
|
package gateway
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/client"
|
"github.com/DeBrosOfficial/network/pkg/client"
|
||||||
"git.debros.io/DeBros/network/pkg/storage"
|
"github.com/DeBrosOfficial/network/pkg/storage"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -25,51 +25,51 @@ var wsUpgrader = websocket.Upgrader{
|
|||||||
// are published to the same namespaced topic.
|
// are published to the same namespaced topic.
|
||||||
func (g *Gateway) pubsubWebsocketHandler(w http.ResponseWriter, r *http.Request) {
|
func (g *Gateway) pubsubWebsocketHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if g.client == nil {
|
if g.client == nil {
|
||||||
g.logger.ComponentWarn("gateway", "pubsub ws: client not initialized")
|
g.logger.ComponentWarn("gateway", "pubsub ws: client not initialized")
|
||||||
writeError(w, http.StatusServiceUnavailable, "client not initialized")
|
writeError(w, http.StatusServiceUnavailable, "client not initialized")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if r.Method != http.MethodGet {
|
if r.Method != http.MethodGet {
|
||||||
g.logger.ComponentWarn("gateway", "pubsub ws: method not allowed",)
|
g.logger.ComponentWarn("gateway", "pubsub ws: method not allowed")
|
||||||
writeError(w, http.StatusMethodNotAllowed, "method not allowed")
|
writeError(w, http.StatusMethodNotAllowed, "method not allowed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve namespace from auth context
|
// Resolve namespace from auth context
|
||||||
ns := resolveNamespaceFromRequest(r)
|
ns := resolveNamespaceFromRequest(r)
|
||||||
if ns == "" {
|
if ns == "" {
|
||||||
g.logger.ComponentWarn("gateway", "pubsub ws: namespace not resolved")
|
g.logger.ComponentWarn("gateway", "pubsub ws: namespace not resolved")
|
||||||
writeError(w, http.StatusForbidden, "namespace not resolved")
|
writeError(w, http.StatusForbidden, "namespace not resolved")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
topic := r.URL.Query().Get("topic")
|
topic := r.URL.Query().Get("topic")
|
||||||
if topic == "" {
|
if topic == "" {
|
||||||
g.logger.ComponentWarn("gateway", "pubsub ws: missing topic")
|
g.logger.ComponentWarn("gateway", "pubsub ws: missing topic")
|
||||||
writeError(w, http.StatusBadRequest, "missing 'topic'")
|
writeError(w, http.StatusBadRequest, "missing 'topic'")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
conn, err := wsUpgrader.Upgrade(w, r, nil)
|
conn, err := wsUpgrader.Upgrade(w, r, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
g.logger.ComponentWarn("gateway", "pubsub ws: upgrade failed",)
|
g.logger.ComponentWarn("gateway", "pubsub ws: upgrade failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
// Channel to deliver PubSub messages to WS writer
|
// Channel to deliver PubSub messages to WS writer
|
||||||
msgs := make(chan []byte, 128)
|
msgs := make(chan []byte, 128)
|
||||||
// Use internal auth context when interacting with client to avoid circular auth requirements
|
// Use internal auth context when interacting with client to avoid circular auth requirements
|
||||||
ctx := client.WithInternalAuth(r.Context())
|
ctx := client.WithInternalAuth(r.Context())
|
||||||
// Subscribe to the topic; push data into msgs with simple per-connection de-dup
|
// Subscribe to the topic; push data into msgs with simple per-connection de-dup
|
||||||
recent := make(map[string]time.Time)
|
recent := make(map[string]time.Time)
|
||||||
h := func(_ string, data []byte) error {
|
h := func(_ string, data []byte) error {
|
||||||
// Drop duplicates seen in the last 2 seconds
|
// Drop duplicates seen in the last 2 seconds
|
||||||
sum := sha256.Sum256(data)
|
sum := sha256.Sum256(data)
|
||||||
key := hex.EncodeToString(sum[:])
|
key := hex.EncodeToString(sum[:])
|
||||||
if t, ok := recent[key]; ok && time.Since(t) < 2*time.Second {
|
if t, ok := recent[key]; ok && time.Since(t) < 2*time.Second {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
recent[key] = time.Now()
|
recent[key] = time.Now()
|
||||||
select {
|
select {
|
||||||
case msgs <- data:
|
case msgs <- data:
|
||||||
return nil
|
return nil
|
||||||
@ -78,14 +78,14 @@ func (g *Gateway) pubsubWebsocketHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := g.client.PubSub().Subscribe(ctx, topic, h); err != nil {
|
if err := g.client.PubSub().Subscribe(ctx, topic, h); err != nil {
|
||||||
g.logger.ComponentWarn("gateway", "pubsub ws: subscribe failed",)
|
g.logger.ComponentWarn("gateway", "pubsub ws: subscribe failed")
|
||||||
writeError(w, http.StatusInternalServerError, err.Error())
|
writeError(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer func() { _ = g.client.PubSub().Unsubscribe(ctx, topic) }()
|
defer func() { _ = g.client.PubSub().Unsubscribe(ctx, topic) }()
|
||||||
|
|
||||||
// no extra fan-out; rely on libp2p subscription
|
// no extra fan-out; rely on libp2p subscription
|
||||||
|
|
||||||
// Writer loop
|
// Writer loop
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
@ -116,7 +116,7 @@ func (g *Gateway) pubsubWebsocketHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// Reader loop: treat any client message as publish to the same topic
|
// Reader loop: treat any client message as publish to the same topic
|
||||||
for {
|
for {
|
||||||
mt, data, err := conn.ReadMessage()
|
mt, data, err := conn.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
@ -124,7 +124,7 @@ func (g *Gateway) pubsubWebsocketHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
if mt != websocket.TextMessage && mt != websocket.BinaryMessage {
|
if mt != websocket.TextMessage && mt != websocket.BinaryMessage {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := g.client.PubSub().Publish(ctx, topic, data); err != nil {
|
if err := g.client.PubSub().Publish(ctx, topic, data); err != nil {
|
||||||
// Best-effort notify client
|
// Best-effort notify client
|
||||||
_ = conn.WriteMessage(websocket.TextMessage, []byte("publish_error"))
|
_ = conn.WriteMessage(websocket.TextMessage, []byte("publish_error"))
|
||||||
}
|
}
|
||||||
@ -142,14 +142,14 @@ func (g *Gateway) pubsubPublishHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
writeError(w, http.StatusMethodNotAllowed, "method not allowed")
|
writeError(w, http.StatusMethodNotAllowed, "method not allowed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ns := resolveNamespaceFromRequest(r)
|
ns := resolveNamespaceFromRequest(r)
|
||||||
if ns == "" {
|
if ns == "" {
|
||||||
writeError(w, http.StatusForbidden, "namespace not resolved")
|
writeError(w, http.StatusForbidden, "namespace not resolved")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var body struct {
|
var body struct {
|
||||||
Topic string `json:"topic"`
|
Topic string `json:"topic"`
|
||||||
DataB64 string `json:"data_base64"`
|
DataB64 string `json:"data_base64"`
|
||||||
}
|
}
|
||||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil || body.Topic == "" || body.DataB64 == "" {
|
if err := json.NewDecoder(r.Body).Decode(&body); err != nil || body.Topic == "" || body.DataB64 == "" {
|
||||||
writeError(w, http.StatusBadRequest, "invalid body: expected {topic,data_base64}")
|
writeError(w, http.StatusBadRequest, "invalid body: expected {topic,data_base64}")
|
||||||
@ -160,11 +160,11 @@ func (g *Gateway) pubsubPublishHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
writeError(w, http.StatusBadRequest, "invalid base64 data")
|
writeError(w, http.StatusBadRequest, "invalid base64 data")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := g.client.PubSub().Publish(client.WithInternalAuth(r.Context()), body.Topic, data); err != nil {
|
if err := g.client.PubSub().Publish(client.WithInternalAuth(r.Context()), body.Topic, data); err != nil {
|
||||||
writeError(w, http.StatusInternalServerError, err.Error())
|
writeError(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// rely on libp2p to deliver to WS subscribers
|
// rely on libp2p to deliver to WS subscribers
|
||||||
writeJSON(w, http.StatusOK, map[string]any{"status": "ok"})
|
writeJSON(w, http.StatusOK, map[string]any{"status": "ok"})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,13 +179,13 @@ func (g *Gateway) pubsubTopicsHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
writeError(w, http.StatusForbidden, "namespace not resolved")
|
writeError(w, http.StatusForbidden, "namespace not resolved")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
all, err := g.client.PubSub().ListTopics(client.WithInternalAuth(r.Context()))
|
all, err := g.client.PubSub().ListTopics(client.WithInternalAuth(r.Context()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeError(w, http.StatusInternalServerError, err.Error())
|
writeError(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Client returns topics already trimmed to its namespace; return as-is
|
// Client returns topics already trimmed to its namespace; return as-is
|
||||||
writeJSON(w, http.StatusOK, map[string]any{"topics": all})
|
writeJSON(w, http.StatusOK, map[string]any{"topics": all})
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolveNamespaceFromRequest gets namespace from context set by auth middleware
|
// resolveNamespaceFromRequest gets namespace from context set by auth middleware
|
||||||
|
@ -5,8 +5,8 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/client"
|
"github.com/DeBrosOfficial/network/pkg/client"
|
||||||
"git.debros.io/DeBros/network/pkg/logging"
|
"github.com/DeBrosOfficial/network/pkg/logging"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -4,116 +4,125 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/client"
|
"github.com/DeBrosOfficial/network/pkg/client"
|
||||||
"git.debros.io/DeBros/network/pkg/pubsub"
|
"github.com/DeBrosOfficial/network/pkg/pubsub"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Database HTTP handlers
|
// Database HTTP handlers
|
||||||
func (g *Gateway) dbQueryHandler(w http.ResponseWriter, r *http.Request) {
|
func (g *Gateway) dbQueryHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if g.client == nil {
|
if g.client == nil {
|
||||||
writeError(w, http.StatusServiceUnavailable, "client not initialized");
|
writeError(w, http.StatusServiceUnavailable, "client not initialized")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if r.Method != http.MethodPost {
|
if r.Method != http.MethodPost {
|
||||||
writeError(w, http.StatusMethodNotAllowed, "method not allowed");
|
writeError(w, http.StatusMethodNotAllowed, "method not allowed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var body struct{ SQL string `json:"sql"`; Args []any `json:"args"` }
|
var body struct {
|
||||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil || body.SQL == "" {
|
SQL string `json:"sql"`
|
||||||
writeError(w, http.StatusBadRequest, "invalid body: {sql, args?}");
|
Args []any `json:"args"`
|
||||||
return
|
}
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&body); err != nil || body.SQL == "" {
|
||||||
|
writeError(w, http.StatusBadRequest, "invalid body: {sql, args?}")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
ctx := client.WithInternalAuth(r.Context())
|
ctx := client.WithInternalAuth(r.Context())
|
||||||
res, err := g.client.Database().Query(ctx, body.SQL, body.Args...)
|
res, err := g.client.Database().Query(ctx, body.SQL, body.Args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeError(w, http.StatusInternalServerError, err.Error());
|
writeError(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
writeJSON(w, http.StatusOK, res)
|
writeJSON(w, http.StatusOK, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Gateway) dbTransactionHandler(w http.ResponseWriter, r *http.Request) {
|
func (g *Gateway) dbTransactionHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if g.client == nil {
|
if g.client == nil {
|
||||||
writeError(w, http.StatusServiceUnavailable, "client not initialized");
|
writeError(w, http.StatusServiceUnavailable, "client not initialized")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if r.Method != http.MethodPost {
|
if r.Method != http.MethodPost {
|
||||||
writeError(w, http.StatusMethodNotAllowed, "method not allowed");
|
writeError(w, http.StatusMethodNotAllowed, "method not allowed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var body struct{ Statements []string `json:"statements"` }
|
var body struct {
|
||||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil || len(body.Statements) == 0 {
|
Statements []string `json:"statements"`
|
||||||
writeError(w, http.StatusBadRequest, "invalid body: {statements:[...]}");
|
}
|
||||||
return
|
if err := json.NewDecoder(r.Body).Decode(&body); err != nil || len(body.Statements) == 0 {
|
||||||
|
writeError(w, http.StatusBadRequest, "invalid body: {statements:[...]}")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
ctx := client.WithInternalAuth(r.Context())
|
ctx := client.WithInternalAuth(r.Context())
|
||||||
if err := g.client.Database().Transaction(ctx, body.Statements); err != nil {
|
if err := g.client.Database().Transaction(ctx, body.Statements); err != nil {
|
||||||
writeError(w, http.StatusInternalServerError, err.Error());
|
writeError(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
writeJSON(w, http.StatusOK, map[string]any{"status":"ok"})
|
writeJSON(w, http.StatusOK, map[string]any{"status": "ok"})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Gateway) dbSchemaHandler(w http.ResponseWriter, r *http.Request) {
|
func (g *Gateway) dbSchemaHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if g.client == nil {
|
if g.client == nil {
|
||||||
writeError(w, http.StatusServiceUnavailable, "client not initialized");
|
writeError(w, http.StatusServiceUnavailable, "client not initialized")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if r.Method != http.MethodGet {
|
if r.Method != http.MethodGet {
|
||||||
writeError(w, http.StatusMethodNotAllowed, "method not allowed");
|
writeError(w, http.StatusMethodNotAllowed, "method not allowed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx := client.WithInternalAuth(r.Context())
|
ctx := client.WithInternalAuth(r.Context())
|
||||||
schema, err := g.client.Database().GetSchema(ctx)
|
schema, err := g.client.Database().GetSchema(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeError(w, http.StatusInternalServerError, err.Error());
|
writeError(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
writeJSON(w, http.StatusOK, schema)
|
writeJSON(w, http.StatusOK, schema)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Gateway) dbCreateTableHandler(w http.ResponseWriter, r *http.Request) {
|
func (g *Gateway) dbCreateTableHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if g.client == nil {
|
if g.client == nil {
|
||||||
writeError(w, http.StatusServiceUnavailable, "client not initialized");
|
writeError(w, http.StatusServiceUnavailable, "client not initialized")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if r.Method != http.MethodPost {
|
if r.Method != http.MethodPost {
|
||||||
writeError(w, http.StatusMethodNotAllowed, "method not allowed");
|
writeError(w, http.StatusMethodNotAllowed, "method not allowed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var body struct{ Schema string `json:"schema"` }
|
var body struct {
|
||||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil || body.Schema == "" {
|
Schema string `json:"schema"`
|
||||||
writeError(w, http.StatusBadRequest, "invalid body: {schema}");
|
}
|
||||||
return
|
if err := json.NewDecoder(r.Body).Decode(&body); err != nil || body.Schema == "" {
|
||||||
|
writeError(w, http.StatusBadRequest, "invalid body: {schema}")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
ctx := client.WithInternalAuth(r.Context())
|
ctx := client.WithInternalAuth(r.Context())
|
||||||
if err := g.client.Database().CreateTable(ctx, body.Schema); err != nil {
|
if err := g.client.Database().CreateTable(ctx, body.Schema); err != nil {
|
||||||
writeError(w, http.StatusInternalServerError, err.Error());
|
writeError(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
writeJSON(w, http.StatusCreated, map[string]any{"status":"ok"})
|
writeJSON(w, http.StatusCreated, map[string]any{"status": "ok"})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Gateway) dbDropTableHandler(w http.ResponseWriter, r *http.Request) {
|
func (g *Gateway) dbDropTableHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if g.client == nil {
|
if g.client == nil {
|
||||||
writeError(w, http.StatusServiceUnavailable, "client not initialized");
|
writeError(w, http.StatusServiceUnavailable, "client not initialized")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if r.Method != http.MethodPost {
|
if r.Method != http.MethodPost {
|
||||||
writeError(w, http.StatusMethodNotAllowed, "method not allowed");
|
writeError(w, http.StatusMethodNotAllowed, "method not allowed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var body struct{ Table string `json:"table"` }
|
var body struct {
|
||||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil || body.Table == "" {
|
Table string `json:"table"`
|
||||||
writeError(w, http.StatusBadRequest, "invalid body: {table}");
|
}
|
||||||
return
|
if err := json.NewDecoder(r.Body).Decode(&body); err != nil || body.Table == "" {
|
||||||
|
writeError(w, http.StatusBadRequest, "invalid body: {table}")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
ctx := client.WithInternalAuth(r.Context())
|
ctx := client.WithInternalAuth(r.Context())
|
||||||
if err := g.client.Database().DropTable(ctx, body.Table); err != nil {
|
if err := g.client.Database().DropTable(ctx, body.Table); err != nil {
|
||||||
writeError(w, http.StatusInternalServerError, err.Error());
|
writeError(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
writeJSON(w, http.StatusOK, map[string]any{"status":"ok"})
|
writeJSON(w, http.StatusOK, map[string]any{"status": "ok"})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Gateway) networkStatusHandler(w http.ResponseWriter, r *http.Request) {
|
func (g *Gateway) networkStatusHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -22,11 +22,11 @@ import (
|
|||||||
"github.com/multiformats/go-multiaddr"
|
"github.com/multiformats/go-multiaddr"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/anyoneproxy"
|
"github.com/DeBrosOfficial/network/pkg/anyoneproxy"
|
||||||
"git.debros.io/DeBros/network/pkg/config"
|
"github.com/DeBrosOfficial/network/pkg/config"
|
||||||
"git.debros.io/DeBros/network/pkg/database"
|
"github.com/DeBrosOfficial/network/pkg/database"
|
||||||
"git.debros.io/DeBros/network/pkg/logging"
|
"github.com/DeBrosOfficial/network/pkg/logging"
|
||||||
"git.debros.io/DeBros/network/pkg/pubsub"
|
"github.com/DeBrosOfficial/network/pkg/pubsub"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Node represents a network node with RQLite database
|
// Node represents a network node with RQLite database
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/config"
|
"github.com/DeBrosOfficial/network/pkg/config"
|
||||||
"github.com/libp2p/go-libp2p"
|
"github.com/libp2p/go-libp2p"
|
||||||
"github.com/libp2p/go-libp2p/core/crypto"
|
"github.com/libp2p/go-libp2p/core/crypto"
|
||||||
"github.com/libp2p/go-libp2p/core/network"
|
"github.com/libp2p/go-libp2p/core/network"
|
||||||
|
@ -17,7 +17,7 @@ NOCOLOR='\033[0m'
|
|||||||
|
|
||||||
# Defaults
|
# Defaults
|
||||||
INSTALL_DIR="/opt/debros"
|
INSTALL_DIR="/opt/debros"
|
||||||
REPO_URL="https://git.debros.io/DeBros/network.git"
|
REPO_URL="https://github.com/DeBrosOfficial/network.git"
|
||||||
MIN_GO_VERSION="1.21"
|
MIN_GO_VERSION="1.21"
|
||||||
NODE_PORT="4001"
|
NODE_PORT="4001"
|
||||||
RQLITE_PORT="5001"
|
RQLITE_PORT="5001"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user