Files
cmautobuy/admin/client_assignment_integration_test.go
T

96 lines
3.9 KiB
Go
Raw Normal View History

package main
import (
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"time"
"cmautobuy/admin/model"
"cmautobuy/admin/repository"
"cmautobuy/admin/service"
)
func Test客户端归属页面与管理员写权限(t *testing.T) {
db := newMySQLTestDB(t)
now := time.Now()
if err := service.SetupInitialAdmin(db, "admin", "admin-password", "admin-password", now); err != nil {
t.Fatal(err)
}
admin, _ := repository.FindUserByUsername(db, "admin")
for _, name := range []string{"buyer-a", "buyer-b"} {
if err := service.CreatePurchaser(db, admin, name, "buyer-password", "buyer-password", now); err != nil {
t.Fatal(err)
}
}
buyerA, _ := repository.FindUserByUsername(db, "buyer-a")
for _, client := range []model.Client{
{ClientID: "client-a", Name: "采购一号机"},
{ClientID: "client-free", Name: "未绑定机器"},
} {
if err := service.RegisterClient(db, client, true); err != nil {
t.Fatal(err)
}
}
router, err := newRouter(db)
if err != nil {
t.Fatal(err)
}
adminToken, _, _, _ := service.Login(db, "admin", "admin-password", now)
adminPageRequest := httptest.NewRequest(http.MethodGet, "/clients", nil)
adminPageRequest.AddCookie(&http.Cookie{Name: "cmautobuy_session", Value: adminToken})
adminPage := httptest.NewRecorder()
router.ServeHTTP(adminPage, adminPageRequest)
if adminPage.Code != http.StatusOK {
t.Fatalf("管理员客户端页 = %d: %s", adminPage.Code, adminPage.Body.String())
}
for _, want := range []string{"当前负责人", "绑定", "buyer-a", "buyer-b", "/clients/delete"} {
if !strings.Contains(adminPage.Body.String(), want) {
t.Errorf("管理员客户端页缺少 %q", want)
}
}
csrf := findResponseCookie(t, adminPage, "cmautobuy_csrf")
assign := postFormRequest("/clients/assign", url.Values{
"csrf_token": {csrf.Value}, "client_id": {"client-a"}, "user_id": {buyerA.UserID},
}, csrf)
assign.AddCookie(&http.Cookie{Name: "cmautobuy_session", Value: adminToken})
assignResponse := httptest.NewRecorder()
router.ServeHTTP(assignResponse, assign)
if assignResponse.Code != http.StatusSeeOther || !strings.HasPrefix(assignResponse.Header().Get("Location"), "/clients?") {
t.Fatalf("管理员绑定响应 = %d %s", assignResponse.Code, assignResponse.Header().Get("Location"))
}
buyerToken, _, _, _ := service.Login(db, "buyer-a", "buyer-password", now)
buyerPageRequest := httptest.NewRequest(http.MethodGet, "/clients", nil)
buyerPageRequest.AddCookie(&http.Cookie{Name: "cmautobuy_session", Value: buyerToken})
buyerPage := httptest.NewRecorder()
router.ServeHTTP(buyerPage, buyerPageRequest)
body := buyerPage.Body.String()
if buyerPage.Code != http.StatusOK || !strings.Contains(body, "采购一号机") ||
strings.Contains(body, "未绑定机器") {
t.Fatalf("采购员客户端可见范围不正确: %d %s", buyerPage.Code, body)
}
for _, forbidden := range []string{"/clients/assign", "/clients/unassign", "/clients/delete", "转交"} {
if strings.Contains(body, forbidden) {
t.Errorf("采购员只读页面不应包含 %q", forbidden)
}
}
buyerCSRF := findResponseCookie(t, buyerPage, "cmautobuy_csrf")
forbiddenAssign := postFormRequest("/clients/assign", url.Values{
"csrf_token": {buyerCSRF.Value}, "client_id": {"client-free"}, "user_id": {buyerA.UserID},
}, buyerCSRF)
forbiddenAssign.AddCookie(&http.Cookie{Name: "cmautobuy_session", Value: buyerToken})
forbiddenResponse := httptest.NewRecorder()
router.ServeHTTP(forbiddenResponse, forbiddenAssign)
if forbiddenResponse.Code != http.StatusForbidden || !strings.Contains(forbiddenResponse.Body.String(), "只有管理员") {
t.Fatalf("采购员绑定应返回 403,实际 %d %s", forbiddenResponse.Code, forbiddenResponse.Body.String())
}
rows, err := service.ListClientViewsForUser(db, buyerA, "", time.Minute)
if err != nil || len(rows) != 1 || rows[0].ClientID != "client-a" {
t.Fatalf("越权请求后归属不应变化,rows=%+v err=%v", rows, err)
}
}