feat: 接入消息加密与实名认证能力

This commit is contained in:
richjohnrambo
2026-09-21 09:53:39 +08:00
parent 841c0c77cd
commit e3b93113f1
33 changed files with 1747 additions and 99 deletions
+89 -1
View File
@@ -1,6 +1,7 @@
package main
import (
"encoding/json"
"fmt"
"net/http"
"strconv"
@@ -127,11 +128,23 @@ func serveInternalAdminResourceList(wrt http.ResponseWriter, req *http.Request,
writeIMError(wrt, req, http.StatusBadRequest, 30000, imReasonMalformedRequest, "malformed request", nil)
return
}
result, err := store.InternalAdminQueries.Query(tenantID, query, countQuery, args, page, perPage)
var result *types.InternalAdminQueryResult
keyword := strings.TrimSpace(req.URL.Query().Get("keyword"))
if (resource == "private-messages" || resource == "group-messages") && keyword != "" {
result, err = queryEncryptedAdminMessages(req, tenantID, spec, scope, keyword, page, perPage)
} else {
result, err = store.InternalAdminQueries.Query(tenantID, query, countQuery, args, page, perPage)
}
if err != nil {
writeInternalQueryError(wrt, req, err)
return
}
if resource == "private-messages" || resource == "group-messages" {
if err = decryptInternalAdminMessageRows(tenantID, result.Items); err != nil {
writeInternalQueryError(wrt, req, err)
return
}
}
writeIMSuccess(wrt, req, map[string]any{
"items": normalizeInternalAdminRowsForAPI(result.Items),
"total": result.Total,
@@ -140,6 +153,81 @@ func serveInternalAdminResourceList(wrt http.ResponseWriter, req *http.Request,
})
}
func queryEncryptedAdminMessages(req *http.Request, tenantID types.TenantID, spec *internalQuerySpec, scope, keyword string, page, perPage int) (*types.InternalAdminQueryResult, error) {
requestCopy := req.Clone(req.Context())
urlCopy := *req.URL
queryValues := req.URL.Query()
queryValues.Del("keyword")
urlCopy.RawQuery = queryValues.Encode()
requestCopy.URL = &urlCopy
query, countQuery, args, _, _, err := buildInternalAdminListQuery(requestCopy, spec, scope)
if err != nil {
return nil, err
}
const batchSize = 200
start := (page - 1) * perPage
end := start + perPage
items := make([]map[string]any, 0, perPage)
matched := 0
for batchPage := 1; ; batchPage++ {
batch, queryErr := store.InternalAdminQueries.Query(tenantID, query, countQuery, args, batchPage, batchSize)
if queryErr != nil {
return nil, queryErr
}
if err = decryptInternalAdminMessageRows(tenantID, batch.Items); err != nil {
return nil, err
}
for _, row := range batch.Items {
if !strings.Contains(strings.ToLower(fmt.Sprint(row["content_excerpt"])), strings.ToLower(keyword)) {
continue
}
if matched >= start && matched < end {
items = append(items, row)
}
matched++
}
if len(batch.Items) < batchSize || int64(batchPage*batchSize) >= batch.Total {
break
}
}
return &types.InternalAdminQueryResult{Items: items, Total: int64(matched), Page: page, PerPage: perPage}, nil
}
func decryptInternalAdminMessageRows(tenantID types.TenantID, rows []map[string]any) error {
for _, row := range rows {
seq, ok := numericID(row["seq_id"])
if !ok || seq <= 0 {
continue
}
msg, err := store.Messages.GetOne(tenantID, fmt.Sprint(row["topic"]), seq)
if err != nil {
return err
}
row["content_excerpt"] = internalMessageExcerpt(msg.Content)
}
return nil
}
func internalMessageExcerpt(content any) string {
if value, ok := content.(map[string]any); ok {
for _, key := range []string{"txt", "text", "content", "title"} {
if text := strings.TrimSpace(fmt.Sprint(value[key])); text != "" && text != "<nil>" {
if len([]rune(text)) > 500 {
return string([]rune(text)[:500])
}
return text
}
}
}
raw, _ := json.Marshal(content)
text := string(raw)
if len([]rune(text)) > 500 {
text = string([]rune(text)[:500])
}
return text
}
func serveInternalAdminResourceDetail(wrt http.ResponseWriter, req *http.Request, tenantID types.TenantID, resource, id string) {
spec, ok := internalAdminQuerySpec(resource)
if !ok || spec.DetailKey == "" {