user_handler_role_stepup_test.go 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package admin
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "net/http"
  6. "net/http/httptest"
  7. "testing"
  8. "github.com/Wei-Shaw/sub2api/internal/service"
  9. "github.com/gin-gonic/gin"
  10. "github.com/stretchr/testify/require"
  11. )
  12. // 角色提升为管理员的 step-up 门控条件测试。
  13. // 测试环境不注入认证上下文,因此门控一旦触发会以 401 中止;
  14. // 借此区分「触发了 step-up 校验」与「直接放行到业务层(200)」。
  15. func setupRoleStepUpRouter(t *testing.T) (*gin.Engine, *stubAdminService) {
  16. t.Helper()
  17. gin.SetMode(gin.TestMode)
  18. router := gin.New()
  19. adminSvc := newStubAdminService()
  20. // 追加一个已是管理员的目标用户,验证「目标已是 admin 不触发门控」。
  21. adminSvc.users = append(adminSvc.users, service.User{
  22. ID: 2,
  23. Email: "admin@example.com",
  24. Role: service.RoleAdmin,
  25. Status: service.StatusActive,
  26. })
  27. h := NewUserHandler(adminSvc, nil, nil, nil, nil, nil, nil)
  28. router.POST("/api/v1/admin/users", h.Create)
  29. router.PUT("/api/v1/admin/users/:id", h.Update)
  30. return router, adminSvc
  31. }
  32. func doJSON(t *testing.T, router *gin.Engine, method, path string, payload map[string]any) *httptest.ResponseRecorder {
  33. t.Helper()
  34. body, err := json.Marshal(payload)
  35. require.NoError(t, err)
  36. rec := httptest.NewRecorder()
  37. req := httptest.NewRequest(method, path, bytes.NewReader(body))
  38. req.Header.Set("Content-Type", "application/json")
  39. router.ServeHTTP(rec, req)
  40. return rec
  41. }
  42. func TestUpdateUserPromoteToAdminRequiresStepUp(t *testing.T) {
  43. router, _ := setupRoleStepUpRouter(t)
  44. rec := doJSON(t, router, http.MethodPut, "/api/v1/admin/users/1", map[string]any{"role": "admin"})
  45. require.Equal(t, http.StatusUnauthorized, rec.Code)
  46. }
  47. func TestUpdateUserKeepAdminRoleSkipsStepUp(t *testing.T) {
  48. router, _ := setupRoleStepUpRouter(t)
  49. rec := doJSON(t, router, http.MethodPut, "/api/v1/admin/users/2", map[string]any{"role": "admin"})
  50. require.Equal(t, http.StatusOK, rec.Code)
  51. }
  52. func TestUpdateUserRegularRoleSkipsStepUp(t *testing.T) {
  53. router, _ := setupRoleStepUpRouter(t)
  54. rec := doJSON(t, router, http.MethodPut, "/api/v1/admin/users/1", map[string]any{"role": "user", "email": "u@example.com"})
  55. require.Equal(t, http.StatusOK, rec.Code)
  56. }
  57. func TestCreateAdminUserRequiresStepUp(t *testing.T) {
  58. router, _ := setupRoleStepUpRouter(t)
  59. rec := doJSON(t, router, http.MethodPost, "/api/v1/admin/users", map[string]any{
  60. "email": "new-admin@example.com", "password": "pass123", "role": "admin",
  61. })
  62. require.Equal(t, http.StatusUnauthorized, rec.Code)
  63. }
  64. func TestCreateRegularUserSkipsStepUp(t *testing.T) {
  65. router, _ := setupRoleStepUpRouter(t)
  66. rec := doJSON(t, router, http.MethodPost, "/api/v1/admin/users", map[string]any{
  67. "email": "new-user@example.com", "password": "pass123", "role": "user",
  68. })
  69. require.Equal(t, http.StatusOK, rec.Code)
  70. }