fix: 独立审计日志并补齐令牌身份与失败记录

This commit is contained in:
Nixevol
2026-09-30 16:22:49 +08:00
parent eb4e2db918
commit b7c8b6ffd6
12 changed files with 641 additions and 124 deletions
+33 -26
View File
@@ -100,23 +100,23 @@ func (h *Handler) handleGroupCreate(w http.ResponseWriter, r *http.Request) {
MemberIDs []string `json:"member_ids"`
}
if err := httpx.DecodeJSON(r, &req); err != nil {
h.audit(actorString(p), "group_create", "", "bad_request", ip)
h.auditP(p, "group_create", "", "bad_request", ip)
httpx.WriteError(w, http.StatusBadRequest, "bad_request", "请求体无效")
return
}
if strings.TrimSpace(req.ID) != "" {
// AdminCreate 不接受自定义 id;与契约「留空则生成」一致时忽略非空会误导,故拒绝。
h.audit(actorString(p), "group_create", req.ID, "bad_request", ip)
h.auditP(p, "group_create", req.ID, "bad_request", ip)
httpx.WriteError(w, http.StatusBadRequest, "bad_request", "后台创建群请留空 id,由服务器生成")
return
}
if !protocol.ValidName(req.Name) || req.Name == "" {
h.audit(actorString(p), "group_create", "", "bad_request", ip)
h.auditP(p, "group_create", "", "bad_request", ip)
httpx.WriteError(w, http.StatusBadRequest, "bad_request", "名称不合法")
return
}
if req.OwnerID == "" {
h.audit(actorString(p), "group_create", "", "bad_request", ip)
h.auditP(p, "group_create", "", "bad_request", ip)
httpx.WriteError(w, http.StatusBadRequest, "bad_request", "缺少 owner_id")
return
}
@@ -126,7 +126,7 @@ func (h *Handler) handleGroupCreate(w http.ResponseWriter, r *http.Request) {
h.writeGroupErr(w, p, "group_create", req.OwnerID, ip, err)
return
}
h.audit(actorString(p), "group_create", res.ID, "ok", ip)
h.auditP(p, "group_create", res.ID, "ok", ip)
failed := res.Failed
if failed == nil {
failed = []group.MemberFail{}
@@ -227,18 +227,18 @@ func (h *Handler) handleGroupRename(w http.ResponseWriter, r *http.Request) {
Name string `json:"name"`
}
if err := httpx.DecodeJSON(r, &req); err != nil {
h.audit(actorString(p), "group_rename", id, "bad_request", ip)
h.auditP(p, "group_rename", id, "bad_request", ip)
httpx.WriteError(w, http.StatusBadRequest, "bad_request", "请求体无效")
return
}
owner, err := h.groupOwner(r.Context(), id)
if isNoRows(err) {
h.audit(actorString(p), "group_rename", id, "not_found", ip)
h.auditP(p, "group_rename", id, "not_found", ip)
httpx.WriteError(w, http.StatusNotFound, "not_found", "群不存在")
return
}
if err != nil {
h.audit(actorString(p), "group_rename", id, "error", ip)
h.auditP(p, "group_rename", id, "error", ip)
httpx.WriteError(w, http.StatusInternalServerError, "internal", "内部错误")
return
}
@@ -252,11 +252,11 @@ func (h *Handler) handleGroupRename(w http.ResponseWriter, r *http.Request) {
}
summary, err := h.groupSummary(r.Context(), id)
if err != nil {
h.audit(actorString(p), "group_rename", id, "error", ip)
h.auditP(p, "group_rename", id, "error", ip)
httpx.WriteError(w, http.StatusInternalServerError, "internal", "内部错误")
return
}
h.audit(actorString(p), "group_rename", id, "ok", ip)
h.auditP(p, "group_rename", id, "ok", ip)
httpx.WriteOK(w, summary)
}
@@ -270,12 +270,12 @@ func (h *Handler) handleGroupDissolve(w http.ResponseWriter, r *http.Request) {
owner, err := h.groupOwner(r.Context(), id)
if isNoRows(err) {
h.audit(actorString(p), "group_dissolve", id, "not_found", ip)
h.auditP(p, "group_dissolve", id, "not_found", ip)
httpx.WriteError(w, http.StatusNotFound, "not_found", "群不存在")
return
}
if err != nil {
h.audit(actorString(p), "group_dissolve", id, "error", ip)
h.auditP(p, "group_dissolve", id, "error", ip)
httpx.WriteError(w, http.StatusInternalServerError, "internal", "内部错误")
return
}
@@ -286,7 +286,7 @@ func (h *Handler) handleGroupDissolve(w http.ResponseWriter, r *http.Request) {
h.writeGroupErr(w, p, "group_dissolve", id, ip, err)
return
}
h.audit(actorString(p), "group_dissolve", id, "ok", ip)
h.auditP(p, "group_dissolve", id, "ok", ip)
httpx.WriteOK(w, map[string]any{})
}
@@ -302,16 +302,16 @@ func (h *Handler) handleGroupAddMembers(w http.ResponseWriter, r *http.Request)
MemberIDs []string `json:"member_ids"`
}
if err := httpx.DecodeJSON(r, &req); err != nil {
h.audit(actorString(p), "group_add_members", id, "bad_request", ip)
h.auditP(p, "group_add_members", id, "bad_request", ip)
httpx.WriteError(w, http.StatusBadRequest, "bad_request", "请求体无效")
return
}
if _, err := h.groupOwner(r.Context(), id); isNoRows(err) {
h.audit(actorString(p), "group_add_members", id, "not_found", ip)
h.auditP(p, "group_add_members", id, "not_found", ip)
httpx.WriteError(w, http.StatusNotFound, "not_found", "群不存在")
return
} else if err != nil {
h.audit(actorString(p), "group_add_members", id, "error", ip)
h.auditP(p, "group_add_members", id, "error", ip)
httpx.WriteError(w, http.StatusInternalServerError, "internal", "内部错误")
return
}
@@ -325,7 +325,14 @@ func (h *Handler) handleGroupAddMembers(w http.ResponseWriter, r *http.Request)
if failed == nil {
failed = []group.MemberFail{}
}
h.audit(actorString(p), "group_add_members", id, "ok", ip)
okN := len(req.MemberIDs) - len(failed)
if okN < 0 {
okN = 0
}
h.auditPD(p, "group_add_members", id, batchAuditResult(okN, len(failed)), ip, map[string]any{
"members": req.MemberIDs,
"failed": failed,
})
httpx.WriteOK(w, map[string]any{"failed": failed})
}
@@ -340,12 +347,12 @@ func (h *Handler) handleGroupRemoveMember(w http.ResponseWriter, r *http.Request
owner, err := h.groupOwner(r.Context(), id)
if isNoRows(err) {
h.audit(actorString(p), "group_remove_member", id, "not_found", ip)
h.auditP(p, "group_remove_member", id, "not_found", ip)
httpx.WriteError(w, http.StatusNotFound, "not_found", "群不存在")
return
}
if err != nil {
h.audit(actorString(p), "group_remove_member", id, "error", ip)
h.auditP(p, "group_remove_member", id, "error", ip)
httpx.WriteError(w, http.StatusInternalServerError, "internal", "内部错误")
return
}
@@ -357,7 +364,7 @@ func (h *Handler) handleGroupRemoveMember(w http.ResponseWriter, r *http.Request
h.writeGroupErr(w, p, "group_remove_member", id, ip, err)
return
}
h.audit(actorString(p), "group_remove_member", id+"/"+endpointID, "ok", ip)
h.auditP(p, "group_remove_member", id+"/"+endpointID, "ok", ip)
httpx.WriteOK(w, map[string]any{})
}
@@ -373,18 +380,18 @@ func (h *Handler) handleGroupTransfer(w http.ResponseWriter, r *http.Request) {
EndpointID string `json:"endpoint_id"`
}
if err := httpx.DecodeJSON(r, &req); err != nil {
h.audit(actorString(p), "group_transfer", id, "bad_request", ip)
h.auditP(p, "group_transfer", id, "bad_request", ip)
httpx.WriteError(w, http.StatusBadRequest, "bad_request", "请求体无效")
return
}
owner, err := h.groupOwner(r.Context(), id)
if isNoRows(err) {
h.audit(actorString(p), "group_transfer", id, "not_found", ip)
h.auditP(p, "group_transfer", id, "not_found", ip)
httpx.WriteError(w, http.StatusNotFound, "not_found", "群不存在")
return
}
if err != nil {
h.audit(actorString(p), "group_transfer", id, "error", ip)
h.auditP(p, "group_transfer", id, "error", ip)
httpx.WriteError(w, http.StatusInternalServerError, "internal", "内部错误")
return
}
@@ -396,7 +403,7 @@ func (h *Handler) handleGroupTransfer(w http.ResponseWriter, r *http.Request) {
h.writeGroupErr(w, p, "group_transfer", id, ip, err)
return
}
h.audit(actorString(p), "group_transfer", id, "ok", ip)
h.auditPD(p, "group_transfer", id, "ok", ip, map[string]any{"new_owner": req.EndpointID})
httpx.WriteOK(w, map[string]any{"owner_id": req.EndpointID})
}
@@ -440,11 +447,11 @@ func (h *Handler) writeGroupErr(w http.ResponseWriter, p principal, action, obje
case protocol.CodeBusy:
status = http.StatusServiceUnavailable
}
h.audit(actorString(p), action, object, pe.Code, ip)
h.auditP(p, action, object, pe.Code, ip)
httpx.WriteError(w, status, pe.Code, pe.Message)
return
}
h.audit(actorString(p), action, object, "error", ip)
h.auditP(p, action, object, "error", ip)
httpx.WriteError(w, http.StatusInternalServerError, "internal", "内部错误")
}