fix: return not found for missing internal user

This commit is contained in:
richjohnrambo
2026-08-28 13:05:26 +08:00
parent 08a4f138e3
commit 5987f2d87a
2 changed files with 69 additions and 0 deletions
+14
View File
@@ -12,6 +12,7 @@ import (
"io"
"net/http"
"net/url"
"runtime/debug"
"strconv"
"strings"
"sync"
@@ -72,6 +73,12 @@ func initInternalAPI(raw json.RawMessage) error {
}
func serveInternalAdminQuery(wrt http.ResponseWriter, req *http.Request, prefix string) {
defer func() {
if recovered := recover(); recovered != nil {
logs.Err.Printf("internal admin query panic path:%s err:%v stack:%s", req.URL.RequestURI(), recovered, debug.Stack())
writeIMError(wrt, req, http.StatusInternalServerError, 90000, imReasonInternal, "internal error", nil)
}
}()
if req.Method != http.MethodGet {
writeIMError(wrt, req, http.StatusMethodNotAllowed, 30002, imReasonMethodNotAllowed, "method not allowed", nil)
return
@@ -246,14 +253,21 @@ func serveInternalUserQuery(wrt http.ResponseWriter, req *http.Request, tenantID
if row, err := store.InternalAdminQueries.QueryOne(tenantID, query, []any{userDBID}); err == nil {
writeIMSuccess(wrt, req, normalizeInternalAdminRowForAPI(row))
return
} else {
logs.Warn.Printf("internal user query sql failed tenant:%d user:%d err:%v", tenantID, userDBID, err)
}
}
uid := store.EncodeUid(userDBID)
user, err := store.Users.Get(tenantID, uid)
if err != nil {
logs.Warn.Printf("internal user query fallback failed tenant:%d user:%d err:%v", tenantID, userDBID, err)
writeInternalQueryError(wrt, req, err)
return
}
if user == nil {
writeInternalQueryError(wrt, req, types.ErrUserNotFound)
return
}
writeIMSuccess(wrt, req, map[string]any{
"user_id": userDBID,
"state": user.State,
+55
View File
@@ -0,0 +1,55 @@
package main
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/golang/mock/gomock"
"github.com/tinode/chat/server/store"
"github.com/tinode/chat/server/store/mock_store"
"github.com/tinode/chat/server/store/types"
)
type internalAdminQueryNotFound struct{}
func (internalAdminQueryNotFound) Query(types.TenantID, string, string, []any, int, int) (*types.InternalAdminQueryResult, error) {
return nil, types.ErrNotFound
}
func (internalAdminQueryNotFound) QueryOne(types.TenantID, string, []any) (map[string]any, error) {
return nil, types.ErrNotFound
}
func TestServeInternalUserQueryMissingUserReturnsNotFound(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
oldQueries := store.InternalAdminQueries
oldUsers := store.Users
defer func() {
store.InternalAdminQueries = oldQueries
store.Users = oldUsers
}()
store.InternalAdminQueries = internalAdminQueryNotFound{}
users := mock_store.NewMockUsersPersistenceInterface(ctrl)
users.EXPECT().Get(types.TenantID(1), gomock.Any()).Return(nil, nil)
store.Users = users
req := httptest.NewRequest(http.MethodGet, "/internal/admin-query/tenants/default/users/1566402774239809500", nil)
wrt := httptest.NewRecorder()
serveInternalUserQuery(wrt, req, types.TenantID(1), "1566402774239809500")
if wrt.Code != http.StatusNotFound {
t.Fatalf("unexpected status: got %d, want %d; body=%s", wrt.Code, http.StatusNotFound, wrt.Body.String())
}
var resp imHTTPResponse
if err := json.Unmarshal(wrt.Body.Bytes(), &resp); err != nil {
t.Fatalf("failed to decode response: %v", err)
}
if resp.Code != 30004 {
t.Fatalf("unexpected response code: got %d, want 30004", resp.Code)
}
}