feat: add admin panel with multi-chain support and notification system
- Add full admin REST API: auth, API keys, chains, chain tokens, wallets, orders, RPC nodes, settings, dashboard stats, notifications - Add JWT-based admin authentication and API key auth middleware - Add multi-chain listeners: BSC, ETH, Polygon, Plasma, EVM WebSocket - Add RPC node health check job with automatic failover - Add Telegram notification channel for order events - Add installer for first-run database initialization - Add new DB models: admin_user, api_key, chain, chain_token, rpc_node, settings, notification_channel - Add order statistics aggregation (daily/monthly/by-chain) - Serve built admin SPA from embedded www/ assets - Add comprehensive test coverage for all new features
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestResolveSPAFilePath(t *testing.T) {
|
||||
root := filepath.Join("tmp", "www")
|
||||
indexPath := filepath.Join(root, "index.html")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
wildcard string
|
||||
wantPath string
|
||||
wantTryStat bool
|
||||
}{
|
||||
{
|
||||
name: "relative asset path",
|
||||
wildcard: "assets/app.js",
|
||||
wantPath: filepath.Join(root, "assets", "app.js"),
|
||||
wantTryStat: true,
|
||||
},
|
||||
{
|
||||
name: "absolute style asset path",
|
||||
wildcard: "/assets/app.js",
|
||||
wantPath: filepath.Join(root, "assets", "app.js"),
|
||||
wantTryStat: true,
|
||||
},
|
||||
{
|
||||
name: "empty wildcard",
|
||||
wildcard: "",
|
||||
wantPath: indexPath,
|
||||
wantTryStat: false,
|
||||
},
|
||||
{
|
||||
name: "dot wildcard",
|
||||
wildcard: ".",
|
||||
wantPath: indexPath,
|
||||
wantTryStat: false,
|
||||
},
|
||||
{
|
||||
name: "directory traversal fallback",
|
||||
wildcard: "../../etc/passwd",
|
||||
wantPath: indexPath,
|
||||
wantTryStat: false,
|
||||
},
|
||||
{
|
||||
name: "absolute directory traversal fallback",
|
||||
wildcard: "/../../etc/passwd",
|
||||
wantPath: filepath.Join(root, "etc", "passwd"),
|
||||
wantTryStat: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotPath, gotTryStat := ResolveSPAFilePath(root, tt.wildcard)
|
||||
|
||||
if gotTryStat != tt.wantTryStat {
|
||||
t.Fatalf("tryStat = %v, want %v", gotTryStat, tt.wantTryStat)
|
||||
}
|
||||
if gotPath != tt.wantPath {
|
||||
t.Fatalf("path = %q, want %q", gotPath, tt.wantPath)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user