fix: return not found for missing internal user
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"runtime/debug"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -72,6 +73,12 @@ func initInternalAPI(raw json.RawMessage) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func serveInternalAdminQuery(wrt http.ResponseWriter, req *http.Request, prefix string) {
|
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 {
|
if req.Method != http.MethodGet {
|
||||||
writeIMError(wrt, req, http.StatusMethodNotAllowed, 30002, imReasonMethodNotAllowed, "method not allowed", nil)
|
writeIMError(wrt, req, http.StatusMethodNotAllowed, 30002, imReasonMethodNotAllowed, "method not allowed", nil)
|
||||||
return
|
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 {
|
if row, err := store.InternalAdminQueries.QueryOne(tenantID, query, []any{userDBID}); err == nil {
|
||||||
writeIMSuccess(wrt, req, normalizeInternalAdminRowForAPI(row))
|
writeIMSuccess(wrt, req, normalizeInternalAdminRowForAPI(row))
|
||||||
return
|
return
|
||||||
|
} else {
|
||||||
|
logs.Warn.Printf("internal user query sql failed tenant:%d user:%d err:%v", tenantID, userDBID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uid := store.EncodeUid(userDBID)
|
uid := store.EncodeUid(userDBID)
|
||||||
user, err := store.Users.Get(tenantID, uid)
|
user, err := store.Users.Get(tenantID, uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
logs.Warn.Printf("internal user query fallback failed tenant:%d user:%d err:%v", tenantID, userDBID, err)
|
||||||
writeInternalQueryError(wrt, req, err)
|
writeInternalQueryError(wrt, req, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if user == nil {
|
||||||
|
writeInternalQueryError(wrt, req, types.ErrUserNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
writeIMSuccess(wrt, req, map[string]any{
|
writeIMSuccess(wrt, req, map[string]any{
|
||||||
"user_id": userDBID,
|
"user_id": userDBID,
|
||||||
"state": user.State,
|
"state": user.State,
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user