- renderArticleDetail 计算 CanEdit/EditURL:管理员(/admin/articles/:id/edit) 或登录用户且为文章作者(/my/articles/:id/edit)可见 - templates/pages/article.html 改用 .CanEdit/.EditURL 渲染 - my 编辑页/接口本身有 author_id 所有权约束,暴露链接无越权风险 - 新增 TestArticleDetailEditButton:作者/管理员可见、他人/匿名不可见
69 lines
2.2 KiB
Go
69 lines
2.2 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
|
|
"go_blog/models"
|
|
)
|
|
|
|
// TestArticleDetailEditButton 验证文章页编辑按钮的可见性:
|
|
// - 文章作者(普通用户)可见,链接指向 /my/articles/:id/edit
|
|
// - 管理员对所有文章可见,链接指向 /admin/articles/:id/edit
|
|
// - 其他登录用户与未登录访客不可见
|
|
func TestArticleDetailEditButton(t *testing.T) {
|
|
e := newSecurityTestEnv(t)
|
|
|
|
var aliceArt models.Article
|
|
if err := e.db.Where("slug = ?", "alice-post").First(&aliceArt).Error; err != nil {
|
|
t.Fatalf("alice article not found: %v", err)
|
|
}
|
|
id := strconv.FormatUint(uint64(aliceArt.ID), 10)
|
|
myEdit := "/my/articles/" + id + "/edit"
|
|
adminEdit := "/admin/articles/" + id + "/edit"
|
|
|
|
// 未登录访客:两种链接都不得出现。
|
|
w := e.do(http.MethodGet, "/article/alice-post", "", nil, "")
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("anonymous GET article: status = %d", w.Code)
|
|
}
|
|
if strings.Contains(w.Body.String(), myEdit) || strings.Contains(w.Body.String(), adminEdit) {
|
|
t.Fatal("anonymous viewer must not see any edit button")
|
|
}
|
|
|
|
// 文章作者:看到 /my/articles/:id/edit。
|
|
alice := e.login(t, "alice")
|
|
w = e.do(http.MethodGet, "/article/alice-post", alice, nil, "")
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("author GET article: status = %d", w.Code)
|
|
}
|
|
if !strings.Contains(w.Body.String(), myEdit) {
|
|
t.Fatal("author should see their own edit button")
|
|
}
|
|
if strings.Contains(w.Body.String(), adminEdit) {
|
|
t.Fatal("author must not see the admin edit button")
|
|
}
|
|
|
|
// 其他作者:不可见。
|
|
bob := e.login(t, "bob")
|
|
w = e.do(http.MethodGet, "/article/alice-post", bob, nil, "")
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("other author GET article: status = %d", w.Code)
|
|
}
|
|
if strings.Contains(w.Body.String(), myEdit) || strings.Contains(w.Body.String(), adminEdit) {
|
|
t.Fatal("other author must not see the edit button")
|
|
}
|
|
|
|
// 管理员:看到 /admin/articles/:id/edit。
|
|
admin := e.login(t, "admin")
|
|
w = e.do(http.MethodGet, "/article/alice-post", admin, nil, "")
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("admin GET article: status = %d", w.Code)
|
|
}
|
|
if !strings.Contains(w.Body.String(), adminEdit) {
|
|
t.Fatal("admin should see the admin edit button")
|
|
}
|
|
}
|