All checks were successful
Server Check Build (NixCN CMS) TeamCity build finished
Signed-off-by: Asai Neko <sugar@sne.moe>
228 lines
6.5 KiB
Go
228 lines
6.5 KiB
Go
package user
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
"github.com/spf13/viper"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"nixcn-cms/data"
|
|
"nixcn-cms/internal/authtoken"
|
|
"nixcn-cms/testutil"
|
|
)
|
|
|
|
func init() { gin.SetMode(gin.TestMode) }
|
|
|
|
func issueToken(t *testing.T, userId uuid.UUID) string {
|
|
t.Helper()
|
|
tok := &authtoken.Token{Application: viper.GetString("server.application")}
|
|
access, _, err := tok.IssueTokens(context.Background(), testutil.TestClientID, userId)
|
|
require.NoError(t, err)
|
|
return access
|
|
}
|
|
|
|
func newUserRouter(t *testing.T) *gin.Engine {
|
|
t.Helper()
|
|
r := gin.New()
|
|
ApiHandler(r.Group("/user"))
|
|
return r
|
|
}
|
|
|
|
func getWithBearer(t *testing.T, r *gin.Engine, path, token string) *httptest.ResponseRecorder {
|
|
t.Helper()
|
|
req := httptest.NewRequest(http.MethodGet, path, nil)
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
return w
|
|
}
|
|
|
|
func patchWithBearer(t *testing.T, r *gin.Engine, path, token string, body any) *httptest.ResponseRecorder {
|
|
t.Helper()
|
|
b, _ := json.Marshal(body)
|
|
req := httptest.NewRequest(http.MethodPatch, path, bytes.NewBuffer(b))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
return w
|
|
}
|
|
|
|
func patchJSON(t *testing.T, r *gin.Engine, path string, body any) *httptest.ResponseRecorder {
|
|
t.Helper()
|
|
b, _ := json.Marshal(body)
|
|
req := httptest.NewRequest(http.MethodPatch, path, bytes.NewBuffer(b))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
return w
|
|
}
|
|
|
|
func getRequest(t *testing.T, r *gin.Engine, path string) *httptest.ResponseRecorder {
|
|
t.Helper()
|
|
req := httptest.NewRequest(http.MethodGet, path, nil)
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
return w
|
|
}
|
|
|
|
// ---- Info ----
|
|
|
|
func TestUserInfoHandlerSelf(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
user := testutil.SeedUser(t, "selfinfo@example.com", 10)
|
|
token := issueToken(t, user.UserId)
|
|
r := newUserRouter(t)
|
|
|
|
w := getWithBearer(t, r, "/user/info", token)
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
var resp map[string]any
|
|
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp))
|
|
data, ok := resp["data"].(map[string]any)
|
|
require.True(t, ok)
|
|
assert.Equal(t, "selfinfo@example.com", data["email"])
|
|
}
|
|
|
|
func TestUserInfoHandlerOtherNotFound(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
user := testutil.SeedUser(t, "caller@example.com", 10)
|
|
token := issueToken(t, user.UserId)
|
|
r := newUserRouter(t)
|
|
|
|
w := getWithBearer(t, r, "/user/info/00000000-0000-0000-0000-000000000099", token)
|
|
assert.Equal(t, http.StatusNotFound, w.Code)
|
|
}
|
|
|
|
// ---- Update ----
|
|
|
|
func TestUserUpdateHandlerEmptyNickname(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
user := testutil.SeedUser(t, "update@example.com", 10)
|
|
token := issueToken(t, user.UserId)
|
|
r := newUserRouter(t)
|
|
|
|
w := patchWithBearer(t, r, "/user/update", token, map[string]any{
|
|
"nickname": "",
|
|
})
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
func TestUserUpdateHandlerSuccess(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
user := testutil.SeedUser(t, "update2@example.com", 10)
|
|
token := issueToken(t, user.UserId)
|
|
r := newUserRouter(t)
|
|
|
|
w := patchWithBearer(t, r, "/user/update", token, map[string]any{
|
|
"nickname": "New Nickname",
|
|
})
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
// ---- List (admin) ----
|
|
|
|
func TestUserListHandlerRequiresOffset(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
admin := testutil.SeedUser(t, "admin@example.com", 40)
|
|
token := issueToken(t, admin.UserId)
|
|
r := newUserRouter(t)
|
|
|
|
w := getWithBearer(t, r, "/user/list", token)
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
func TestUserListHandlerSuccess(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
admin := testutil.SeedUser(t, testutil.RandomEmail(), 40)
|
|
for i := 0; i < 3; i++ {
|
|
testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
}
|
|
token := issueToken(t, admin.UserId)
|
|
r := newUserRouter(t)
|
|
|
|
w := getWithBearer(t, r, "/user/list?offset=0&limit=10", token)
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
var resp map[string]any
|
|
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp))
|
|
assert.NotNil(t, resp["data"])
|
|
}
|
|
|
|
func TestUserListHandlerLowPermission(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
user := testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
token := issueToken(t, user.UserId)
|
|
r := newUserRouter(t)
|
|
|
|
w := getWithBearer(t, r, "/user/list?offset=0", token)
|
|
assert.Equal(t, http.StatusForbidden, w.Code)
|
|
}
|
|
|
|
// ---- Other (info by user_id) ----
|
|
|
|
func TestUserInfoHandlerOtherSuccess(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
caller := testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
target := testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
require.NoError(t, new(data.User).PatchByUserId(context.Background(), target.UserId, data.WithAllowPublic(true)))
|
|
|
|
token := issueToken(t, caller.UserId)
|
|
r := newUserRouter(t)
|
|
|
|
w := getWithBearer(t, r, "/user/info/"+target.UserId.String(), token)
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
var resp map[string]any
|
|
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp))
|
|
d, ok := resp["data"].(map[string]any)
|
|
require.True(t, ok)
|
|
assert.Equal(t, target.Email, d["email"])
|
|
}
|
|
|
|
// ---- AdminUpdate ----
|
|
|
|
func TestUserAdminUpdateHandlerSuccess(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
admin := testutil.SeedUser(t, testutil.RandomEmail(), 40)
|
|
target := testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
token := issueToken(t, admin.UserId)
|
|
r := newUserRouter(t)
|
|
|
|
w := patchWithBearer(t, r, "/user/update/"+target.UserId.String(), token, map[string]any{
|
|
"nickname": "Admin Set Nickname",
|
|
})
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
func TestUserAdminUpdateHandlerInvalidUserId(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
admin := testutil.SeedUser(t, testutil.RandomEmail(), 40)
|
|
token := issueToken(t, admin.UserId)
|
|
r := newUserRouter(t)
|
|
|
|
w := patchWithBearer(t, r, "/user/update/not-a-uuid", token, map[string]any{
|
|
"nickname": "Test",
|
|
})
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
func TestUserAdminUpdateHandlerLowPermission(t *testing.T) {
|
|
testutil.SetupWithAuth(t)
|
|
user := testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
target := testutil.SeedUser(t, testutil.RandomEmail(), 10)
|
|
token := issueToken(t, user.UserId)
|
|
r := newUserRouter(t)
|
|
|
|
w := patchWithBearer(t, r, "/user/update/"+target.UserId.String(), token, map[string]any{
|
|
"nickname": "Hacked",
|
|
})
|
|
assert.Equal(t, http.StatusForbidden, w.Code)
|
|
}
|
|
|