管理员免登录直接评论:后台会话映射站主身份(免审核、不可被禁言)+ 评论作者字段对齐后端 user
- 公开 API 解析顺序:读者 cookie → 管理员 cookie(provider=admin 站主读者,名字取站点作者名) - 站主发评论跳过禁言与审核;后台禁言接口拒绝站主身份 - CommentItem 读 c.author 改为 c.user(后端实际字段),站主徽章按 provider 判断
This commit is contained in:
@@ -30,17 +30,50 @@ const (
|
||||
editWindow = 10 * time.Minute
|
||||
)
|
||||
|
||||
// readerID 从会话 cookie 解出读者 ID;匿名返回 false
|
||||
// readerID 从会话 cookie 解出读者 ID;匿名返回 false。
|
||||
// 后台管理员已登录(one_session)时直接映射为站主读者身份——
|
||||
// 站主发评论不必再走一遍 GitHub 登录。
|
||||
func (a *API) readerID(r *http.Request) (int64, bool) {
|
||||
ck, err := r.Cookie(auth.ReaderCookie)
|
||||
if err != nil {
|
||||
rd, ok, err := a.resolveReader(r)
|
||||
if err != nil || !ok {
|
||||
return 0, false
|
||||
}
|
||||
id, err := a.ReaderSessions.Verify(ck.Value)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
return rd.ID, true
|
||||
}
|
||||
|
||||
// resolveReader 解出当前访客的读者身份:读者会话优先,
|
||||
// 其次是后台管理员会话(自动 upsert 一个 provider=admin 的站主读者)。
|
||||
func (a *API) resolveReader(r *http.Request) (model.Reader, bool, error) {
|
||||
if ck, err := r.Cookie(auth.ReaderCookie); err == nil && ck.Value != "" {
|
||||
if id, verr := a.ReaderSessions.Verify(ck.Value); verr == nil {
|
||||
rd, gerr := a.Store.GetReader(id)
|
||||
if gerr == nil {
|
||||
return rd, true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return id, true
|
||||
if a.AdminSessions != nil {
|
||||
if ck, err := r.Cookie("one_session"); err == nil && ck.Value != "" {
|
||||
if _, verr := a.AdminSessions.Verify(ck.Value); verr == nil {
|
||||
rd, oerr := a.ownerReader()
|
||||
if oerr == nil {
|
||||
return rd, true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return model.Reader{}, false, nil
|
||||
}
|
||||
|
||||
// ownerReader 取(或创建)站主评论身份:provider=admin,名字用站点作者名。
|
||||
func (a *API) ownerReader() (model.Reader, error) {
|
||||
name := "站主"
|
||||
if st, err := a.Store.GetSettings(); err == nil && st.AuthorName != "" {
|
||||
name = st.AuthorName
|
||||
}
|
||||
return a.Store.UpsertReader(model.Reader{
|
||||
Provider: "admin", Handle: a.Cfg.AdminUser, Name: name,
|
||||
})
|
||||
}
|
||||
|
||||
func (a *API) authProviders(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -55,13 +88,11 @@ func (a *API) authProviders(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (a *API) authMe(w http.ResponseWriter, r *http.Request) {
|
||||
var user any // 匿名时 {user: null},前端判空即「未登录」
|
||||
if id, ok := a.readerID(r); ok {
|
||||
if reader, err := a.Store.GetReader(id); err == nil {
|
||||
user = map[string]any{
|
||||
"id": reader.ID, "name": reader.Name, "handle": reader.Handle,
|
||||
"avatar_url": reader.AvatarURL, "url": reader.URL,
|
||||
"provider": reader.Provider, "is_owner": false, "banned": reader.Banned,
|
||||
}
|
||||
if reader, ok, err := a.resolveReader(r); err == nil && ok {
|
||||
user = map[string]any{
|
||||
"id": reader.ID, "name": reader.Name, "handle": reader.Handle,
|
||||
"avatar_url": reader.AvatarURL, "url": reader.URL,
|
||||
"provider": reader.Provider, "is_owner": reader.Provider == "admin", "banned": reader.Banned,
|
||||
}
|
||||
}
|
||||
httpx.OK(w, map[string]any{"user": user})
|
||||
@@ -180,19 +211,19 @@ func (a *API) listComments(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// createComment 发表评论(含回复)。登录 + 未禁言 + 评论开关开着;
|
||||
// 审核开关开着时新评论进「待审」。
|
||||
// 审核开关开着时新评论进「待审」。站主身份(管理员会话)不受禁言与审核约束。
|
||||
func (a *API) createComment(w http.ResponseWriter, r *http.Request) {
|
||||
readerID, ok := a.readerID(r)
|
||||
if !ok {
|
||||
httpx.Error(w, http.StatusUnauthorized, "登录后才能评论")
|
||||
return
|
||||
}
|
||||
reader, err := a.Store.GetReader(readerID)
|
||||
reader, ok, err := a.resolveReader(r)
|
||||
if err != nil {
|
||||
httpx.Error(w, http.StatusUnauthorized, "登录已过期,刷新页面重新登录")
|
||||
return
|
||||
}
|
||||
if reader.Banned {
|
||||
if !ok {
|
||||
httpx.Error(w, http.StatusUnauthorized, "登录后才能评论")
|
||||
return
|
||||
}
|
||||
isOwner := reader.Provider == "admin"
|
||||
if reader.Banned && !isOwner {
|
||||
httpx.Error(w, http.StatusForbidden, "你已被禁言,暂时无法评论")
|
||||
return
|
||||
}
|
||||
@@ -246,11 +277,11 @@ func (a *API) createComment(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
status := "visible"
|
||||
if st.CommentsReview {
|
||||
if st.CommentsReview && !isOwner {
|
||||
status = "pending"
|
||||
}
|
||||
c, err := a.Store.CreateComment(model.Comment{
|
||||
PostID: in.PostID, UserID: readerID, ParentID: in.ParentID, RootID: root,
|
||||
PostID: in.PostID, UserID: reader.ID, ParentID: in.ParentID, RootID: root,
|
||||
BodyMd: body, BodyHTML: render.Markdown(body), Status: status,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user