68 lines
3.5 KiB
Go
68 lines
3.5 KiB
Go
package moderation
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/tinode/chat/server/store"
|
|
"github.com/tinode/chat/server/store/types"
|
|
)
|
|
|
|
type testConfig struct {
|
|
policy *types.ModerationPolicy
|
|
words *types.SensitiveWordSet
|
|
}
|
|
|
|
func (c testConfig) Provider() (*types.ModerationProviderConfig, error) {
|
|
return &types.ModerationProviderConfig{}, nil
|
|
}
|
|
func (c testConfig) Policy(string) (*types.ModerationPolicy, error) { return c.policy, nil }
|
|
func (c testConfig) Words(string) (*types.SensitiveWordSet, error) { return c.words, nil }
|
|
|
|
type testAudit struct{}
|
|
|
|
func (testAudit) RecordLogin(types.TenantID, *types.LoginAuditEvent) error { return nil }
|
|
func (testAudit) RecordLoginFailure(types.TenantID, *types.LoginFailureEvent) error { return nil }
|
|
func (testAudit) CloseLogin(types.TenantID, string, time.Time) error { return nil }
|
|
func (testAudit) ApplyMessageAction(types.TenantID, *types.MessageAdminAction) error { return nil }
|
|
func (testAudit) RecordContentModeration(types.TenantID, *types.ContentModerationLog) error {
|
|
return nil
|
|
}
|
|
|
|
func TestExtractText(t *testing.T) {
|
|
content := map[string]any{"txt": "正文", "ent": []any{map[string]any{"data": map[string]any{"title": "查看详情", "url": "https://example.com"}}}, "meta": "ignore"}
|
|
if got := ExtractText(content); got != "正文\n查看详情" && got != "查看详情\n正文" {
|
|
t.Fatalf("ExtractText()=%q", got)
|
|
}
|
|
}
|
|
|
|
func TestReviewLocalBlock(t *testing.T) {
|
|
oldConfig, oldAudit := store.ModerationConfig, store.SecurityAudit
|
|
defer func() { store.ModerationConfig, store.SecurityAudit = oldConfig, oldAudit }()
|
|
store.ModerationConfig = testConfig{policy: &types.ModerationPolicy{Enabled: true, LocalWordsEnabled: true, Scenes: map[string]bool{ScenePrivateMessage: true}, RiskActions: map[string]string{"high": ActionBlock}}, words: &types.SensitiveWordSet{Items: []*types.SensitiveWordRule{{Word: "违规词", MatchType: "contains", Scenes: []string{ScenePrivateMessage}, Action: ActionBlock, RiskLevel: "high"}}}}
|
|
store.SecurityAudit = testAudit{}
|
|
result, err := Review(context.Background(), Request{TenantID: 1, TenantCode: "default", Scene: ScenePrivateMessage, Text: "包含违规词的消息"})
|
|
if err != ErrRejected || result.Action != ActionBlock || result.Provider != "local" {
|
|
t.Fatalf("result=%+v err=%v", result, err)
|
|
}
|
|
}
|
|
|
|
func TestReviewOtherTenantUsesOwnPolicy(t *testing.T) {
|
|
oldConfig, oldAudit := store.ModerationConfig, store.SecurityAudit
|
|
defer func() { store.ModerationConfig, store.SecurityAudit = oldConfig, oldAudit }()
|
|
store.ModerationConfig = testConfig{policy: &types.ModerationPolicy{Enabled: true, LocalWordsEnabled: true, Scenes: map[string]bool{ScenePrivateMessage: true}, RiskActions: map[string]string{"high": ActionBlock}}, words: &types.SensitiveWordSet{Items: []*types.SensitiveWordRule{{Word: "违规词", MatchType: "contains", Scenes: []string{ScenePrivateMessage}, Action: ActionBlock, RiskLevel: "high"}}}}
|
|
store.SecurityAudit = testAudit{}
|
|
result, err := Review(context.Background(), Request{TenantID: 2, TenantCode: "team", Scene: ScenePrivateMessage, Text: "违规词"})
|
|
if err != ErrRejected || result.Action != ActionBlock {
|
|
t.Fatalf("result=%+v err=%v", result, err)
|
|
}
|
|
}
|
|
|
|
func TestMatchLocalWordsPinyin(t *testing.T) {
|
|
result := matchLocalWords("这里包含敏感内容", SceneGroupMessage, &types.SensitiveWordSet{Items: []*types.SensitiveWordRule{{Word: "mingan", MatchType: "pinyin", Scenes: []string{SceneGroupMessage}, RiskLevel: "medium"}}})
|
|
if result == nil || result.RiskLevel != "medium" {
|
|
t.Fatalf("result=%+v", result)
|
|
}
|
|
}
|