HH-548: allow Super Admin sessions to load platform lists (#125)

* fix(HH-548): authorize super admin platform lists

* fix(HH-548): limit dual auth to platform lists

---------

Co-authored-by: Rogee <rogee@ipao.vip>
This commit is contained in:
Rogee
2026-08-23 20:21:05 +08:00
committed by GitHub
co-authored by rogee
parent eb83d241fe
commit 8d5d019bb5
8 changed files with 279 additions and 6 deletions
@@ -41,9 +41,18 @@ func NewPlatformAccountHandler(
// GET /platform/api/v1/accounts
// Reference: Chatwoot Platform::Api::V1::AccountsController#index
func (h *PlatformAccountHandler) List(c *gin.Context) {
platformAppID := getPlatformAppID(c)
page := pagination.Parse(c)
if c.GetBool("is_super_admin") {
accounts, total, err := h.accountRepo.FindAll(c.Request.Context(), page.Offset, page.PerPage)
if err != nil {
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, err.Error())
return
}
response.OKWithMeta(c, accounts, page.Page, page.PerPage, total)
return
}
platformAppID := getPlatformAppID(c)
permissibles, err := h.permissibleRepo.FindByPlatformAppID(c.Request.Context(), platformAppID)
if err != nil {
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, err.Error())
@@ -294,6 +294,35 @@ func TestPlatformUserE2E_List(t *testing.T) {
assert.Equal(t, http.StatusOK, w.Code)
}
func TestPlatformSuperAdminListsAllAccountsAndUsers(t *testing.T) {
db := testutil.NewTestDBWithModels(t, &model.Account{}, &model.User{}, &model.Permissible{})
accountRepo := repository.NewAccountRepo(db)
userRepo := repository.NewUserRepo(db)
permissibleRepo := repository.NewPermissibleRepo(db)
accountHandler := v1.NewPlatformAccountHandler(accountRepo, permissibleRepo, service.NewAccountService(accountRepo))
userHandler := v1.NewPlatformUserHandler(service.NewPlatformUserService(userRepo, permissibleRepo))
require.NoError(t, accountRepo.Create(t.Context(), &model.Account{Name: "Global Account"}))
require.NoError(t, userRepo.Create(t.Context(), &model.User{Name: "Global User", Email: "global@example.com"}))
engine := gin.New()
engine.Use(func(c *gin.Context) { c.Set("is_super_admin", true); c.Next() })
engine.GET("/platform/api/v1/accounts", accountHandler.List)
engine.GET("/platform/api/v1/users", userHandler.List)
for _, path := range []string{"/platform/api/v1/accounts", "/platform/api/v1/users"} {
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, path, nil)
engine.ServeHTTP(w, req)
require.Equal(t, http.StatusOK, w.Code, w.Body.String())
var envelope struct {
Data []json.RawMessage `json:"data"`
}
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &envelope))
require.Len(t, envelope.Data, 1)
}
}
// --- Platform Account E2E Tests ---
func TestPlatformAccountE2E_Create(t *testing.T) {
@@ -275,9 +275,18 @@ func handlePlatformError(c *gin.Context, err error) {
// GET /platform/api/v1/users
// Reference: Chatwoot Platform::Api::V1::UsersController#index (lists permissibles)
func (h *PlatformUserHandler) List(c *gin.Context) {
platformAppID := getPlatformAppID(c)
page := pagination.Parse(c)
if c.GetBool("is_super_admin") {
users, total, err := h.svc.ListUsers(c.Request.Context(), page.Offset, page.PerPage)
if err != nil {
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, err.Error())
return
}
response.OKWithMeta(c, users, page.Page, page.PerPage, total)
return
}
platformAppID := getPlatformAppID(c)
users, err := h.svc.ListPermissibleUsers(c.Request.Context(), platformAppID)
if err != nil {
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, err.Error())