1
0

setting_test.go 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. package controller
  2. import (
  3. "net/http"
  4. "net/http/httptest"
  5. "path/filepath"
  6. "strconv"
  7. "strings"
  8. "testing"
  9. "github.com/gin-gonic/gin"
  10. "github.com/mhsanaei/3x-ui/v3/internal/database"
  11. "github.com/mhsanaei/3x-ui/v3/internal/database/model"
  12. "github.com/mhsanaei/3x-ui/v3/internal/util/crypto"
  13. )
  14. func TestValidateRegex(t *testing.T) {
  15. gin.SetMode(gin.TestMode)
  16. router := gin.New()
  17. NewSettingController(router.Group("/panel/api"))
  18. tests := []struct {
  19. name string
  20. body string
  21. success bool
  22. }{
  23. {name: "Go RE2 inline flag", body: `{"regex":"(?m)^general-purpose$"}`, success: true},
  24. {name: "invalid expression", body: `{"regex":"["}`, success: false},
  25. }
  26. for _, tt := range tests {
  27. t.Run(tt.name, func(t *testing.T) {
  28. req := httptest.NewRequest(http.MethodPost, "/panel/api/setting/validateRegex", strings.NewReader(tt.body))
  29. req.Header.Set("Content-Type", "application/json")
  30. resp := httptest.NewRecorder()
  31. router.ServeHTTP(resp, req)
  32. if resp.Code != http.StatusOK {
  33. t.Fatalf("status = %d, want 200; body=%s", resp.Code, resp.Body.String())
  34. }
  35. needle := `"success":true`
  36. if !tt.success {
  37. needle = `"success":false`
  38. }
  39. if !strings.Contains(resp.Body.String(), needle) {
  40. t.Fatalf("body = %s, want %s", resp.Body.String(), needle)
  41. }
  42. })
  43. }
  44. }
  45. func TestAPITokenMutationRoutesEnforceExpectedScope(t *testing.T) {
  46. t.Setenv("XUI_DB_FOLDER", t.TempDir())
  47. if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
  48. t.Fatalf("InitDB: %v", err)
  49. }
  50. t.Cleanup(func() { _ = database.CloseDB() })
  51. row := &model.ApiToken{Name: "route-scope", Token: crypto.HashTokenSHA256("token"), Enabled: true, Scope: model.ApiScopeNodeSync}
  52. if err := database.GetDB().Create(row).Error; err != nil {
  53. t.Fatalf("seed token: %v", err)
  54. }
  55. gin.SetMode(gin.TestMode)
  56. router := gin.New()
  57. NewSettingController(router.Group("/panel/api"))
  58. for _, path := range []string{
  59. "/panel/api/setting/apiTokens/delete/" + strconv.Itoa(row.Id),
  60. "/panel/api/setting/apiTokens/setEnabled/" + strconv.Itoa(row.Id),
  61. } {
  62. body := `{"expectedScope":"admin","enabled":false}`
  63. req := httptest.NewRequest(http.MethodPost, path, strings.NewReader(body))
  64. req.Header.Set("Content-Type", "application/json")
  65. resp := httptest.NewRecorder()
  66. router.ServeHTTP(resp, req)
  67. if !strings.Contains(resp.Body.String(), `"success":false`) {
  68. t.Fatalf("%s accepted wrong expected scope: %s", path, resp.Body.String())
  69. }
  70. }
  71. var stored model.ApiToken
  72. if err := database.GetDB().First(&stored, row.Id).Error; err != nil {
  73. t.Fatalf("token was deleted by wrong scope: %v", err)
  74. }
  75. if !stored.Enabled {
  76. t.Fatal("token was disabled by wrong scope")
  77. }
  78. }