mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-07 21:54:10 +00:00
155 lines
3.9 KiB
Go
155 lines
3.9 KiB
Go
package controller
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/gin-contrib/sessions"
|
|
"github.com/gin-contrib/sessions/cookie"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/mhsanaei/3x-ui/v2/database"
|
|
"github.com/mhsanaei/3x-ui/v2/database/model"
|
|
"github.com/mhsanaei/3x-ui/v2/web/global"
|
|
"github.com/mhsanaei/3x-ui/v2/web/session"
|
|
"github.com/mhsanaei/3x-ui/v2/xray"
|
|
"github.com/robfig/cron/v3"
|
|
)
|
|
|
|
type testWebServer struct {
|
|
cron *cron.Cron
|
|
}
|
|
|
|
func (s *testWebServer) GetCron() *cron.Cron { return s.cron }
|
|
func (s *testWebServer) GetCtx() context.Context { return context.Background() }
|
|
func (s *testWebServer) GetWSHub() any { return nil }
|
|
|
|
func setupControllerTestDB(t *testing.T) {
|
|
t.Helper()
|
|
tmpDir := t.TempDir()
|
|
t.Setenv("XUI_DEBUG", "")
|
|
t.Setenv("XUI_DB_FOLDER", tmpDir)
|
|
dbPath := filepath.Join(tmpDir, "controller-test.db")
|
|
if err := database.InitDBWithPath(dbPath); err != nil {
|
|
t.Fatalf("InitDB failed: %v", err)
|
|
}
|
|
t.Cleanup(func() {
|
|
database.CloseDB()
|
|
})
|
|
}
|
|
|
|
func newTestRouter(t *testing.T) *gin.Engine {
|
|
t.Helper()
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
r := gin.New()
|
|
store := cookie.NewStore([]byte("test-secret"))
|
|
r.Use(sessions.Sessions("3x-ui", store))
|
|
r.Use(func(c *gin.Context) {
|
|
c.Set("base_path", "/")
|
|
role := c.GetHeader("X-Test-Role")
|
|
if role == "" {
|
|
return
|
|
}
|
|
user := &model.User{
|
|
Id: 1,
|
|
Username: c.GetHeader("X-Test-Username"),
|
|
Role: role,
|
|
}
|
|
if user.Username == "" {
|
|
user.Username = "tester@example.com"
|
|
}
|
|
session.SetLoginUser(c, user)
|
|
})
|
|
return r
|
|
}
|
|
|
|
func TestXUIController_SettingsPageRequiresAdmin(t *testing.T) {
|
|
r := newTestRouter(t)
|
|
NewXUIController(r.Group("/"))
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/panel/settings", nil)
|
|
req.Header.Set("X-Test-Role", "user")
|
|
w := httptest.NewRecorder()
|
|
|
|
r.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusTemporaryRedirect {
|
|
t.Fatalf("expected %d, got %d", http.StatusTemporaryRedirect, w.Code)
|
|
}
|
|
if got := w.Header().Get("Location"); got != "/panel/user" {
|
|
t.Fatalf("expected redirect to /panel/user, got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestAPIController_AdminEndpointsRequireAdmin(t *testing.T) {
|
|
global.SetWebServer(&testWebServer{cron: cron.New()})
|
|
|
|
r := newTestRouter(t)
|
|
NewAPIController(r.Group("/"))
|
|
|
|
for _, path := range []string{
|
|
"/panel/api/inbounds/list",
|
|
"/panel/api/server/status",
|
|
} {
|
|
req := httptest.NewRequest(http.MethodGet, path, nil)
|
|
req.Header.Set("X-Test-Role", "user")
|
|
req.Header.Set("X-Requested-With", "XMLHttpRequest")
|
|
w := httptest.NewRecorder()
|
|
|
|
r.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusForbidden {
|
|
t.Fatalf("%s: expected %d, got %d", path, http.StatusForbidden, w.Code)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAPIController_UserInfoRemainsAvailableToLoggedInUser(t *testing.T) {
|
|
setupControllerTestDB(t)
|
|
global.SetWebServer(&testWebServer{cron: cron.New()})
|
|
|
|
inboundSettings, err := json.Marshal(map[string]any{
|
|
"clients": []map[string]any{
|
|
{"id": "client-1", "email": "tester@example.com", "enable": true, "subId": "sub-1"},
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("marshal inbound settings failed: %v", err)
|
|
}
|
|
|
|
inbound := &model.Inbound{
|
|
UserId: 1,
|
|
Port: 12001,
|
|
Protocol: model.VLESS,
|
|
Tag: "controller-user-info",
|
|
Settings: string(inboundSettings),
|
|
}
|
|
if err := database.GetDB().Create(inbound).Error; err != nil {
|
|
t.Fatalf("create inbound failed: %v", err)
|
|
}
|
|
if err := database.GetDB().Create(&xray.ClientTraffic{
|
|
InboundId: inbound.Id,
|
|
Email: "tester@example.com",
|
|
Enable: true,
|
|
}).Error; err != nil {
|
|
t.Fatalf("create client traffic failed: %v", err)
|
|
}
|
|
|
|
r := newTestRouter(t)
|
|
NewAPIController(r.Group("/"))
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/panel/api/inbounds/userInfo", nil)
|
|
req.Header.Set("X-Test-Role", "user")
|
|
req.Header.Set("X-Test-Username", "tester@example.com")
|
|
w := httptest.NewRecorder()
|
|
|
|
r.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("expected %d, got %d", http.StatusOK, w.Code)
|
|
}
|
|
}
|