feat: 完成鸽达达后台安全与审计改造

This commit is contained in:
richjohnrambo
2026-09-07 11:50:29 +08:00
parent ab2b84c9fa
commit bb87d01644
196 changed files with 19970 additions and 280 deletions
@@ -0,0 +1,39 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package do
import (
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
)
// ImMessageCurfewRules is the golang structure of table im_message_curfew_rules for DAO operations like Where/Data.
type ImMessageCurfewRules struct {
g.Meta `orm:"table:im_message_curfew_rules, do:true"`
Id any //
TenantId any //
PolicyId any //
RuleCode any //
RuleName any //
DateType any // daily, weekday, weekend, custom
CustomDates *gjson.Json // YYYY-MM-DD values for custom date type
Weekdays *gjson.Json // ISO weekdays 1 through 7
Timezone any //
StartTime *gtime.Time //
EndTime *gtime.Time // Less than start_time means crossing midnight
Scope any // private_message or group_message
WhitelistUserIds *gjson.Json //
WhitelistGroupIds *gjson.Json //
Message any //
Status any // 1 enabled, 2 disabled
Sort any //
CreatedAt *gtime.Time //
CreatedBy any //
UpdatedAt *gtime.Time //
UpdatedBy any //
DeletedAt *gtime.Time //
DeletedBy any //
}
@@ -0,0 +1,32 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package do
import (
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
)
// ImSecurityIpRules is the golang structure of table im_security_ip_rules for DAO operations like Where/Data.
type ImSecurityIpRules struct {
g.Meta `orm:"table:im_security_ip_rules, do:true"`
Id any //
TenantId any //
RuleType any // whitelist or blacklist
IpCidr any // IPv4, IPv6 or CIDR
Action any // allow, challenge, block, audit_only
SceneJson *gjson.Json // login, register, message, upload and other scenes
RiskLevel any //
Status any // 1 enabled, 2 disabled
ExpiresAt *gtime.Time //
Remark any //
CreatedAt *gtime.Time //
CreatedBy any //
UpdatedAt *gtime.Time //
UpdatedBy any //
DeletedAt *gtime.Time //
DeletedBy any //
}
@@ -0,0 +1,39 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package do
import (
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
)
// ImSecurityPolicy is the golang structure of table im_security_policy for DAO operations like Where/Data.
type ImSecurityPolicy struct {
g.Meta `orm:"table:im_security_policy, do:true"`
Id any //
TenantId any // 0 means global fallback policy
PolicyVersion any //
PolicyName any //
PublishStatus any //
PasswordPolicy *gjson.Json //
LoginRateLimit *gjson.Json //
SensitiveWordPolicy *gjson.Json //
FileReviewPolicy *gjson.Json //
RealnamePolicy *gjson.Json //
RiskChallengePolicy *gjson.Json //
GlobalFriendEnabled any // Backend master switch for every add-friend entry
FriendDisabledPolicy *gjson.Json // Profile masking, QR and group-member restrictions
MessageCurfewEnabled any // Backend master switch for message curfew
Remark any //
PublishedAt *gtime.Time //
PublishedBy any //
CreatedAt *gtime.Time //
CreatedBy any //
UpdatedAt *gtime.Time //
UpdatedBy any //
DeletedAt *gtime.Time //
DeletedBy any //
}
@@ -0,0 +1,28 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package do
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
)
// ImSensitiveWordGroups is the golang structure of table im_sensitive_word_groups for DAO operations like Where/Data.
type ImSensitiveWordGroups struct {
g.Meta `orm:"table:im_sensitive_word_groups, do:true"`
Id any //
TenantId any // 0 means global dictionary
GroupCode any //
GroupName any //
Priority any //
Status any // 1 enabled, 2 disabled
Remark any //
CreatedAt *gtime.Time //
CreatedBy any //
UpdatedAt *gtime.Time //
UpdatedBy any //
DeletedAt *gtime.Time //
DeletedBy any //
}
@@ -0,0 +1,35 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package do
import (
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
)
// ImSensitiveWords is the golang structure of table im_sensitive_words for DAO operations like Where/Data.
type ImSensitiveWords struct {
g.Meta `orm:"table:im_sensitive_words, do:true"`
Id any //
TenantId any // 0 means global dictionary
GroupId any //
Word any //
WordHash any // SHA-256 of normalized word
MatchType any //
SceneJson *gjson.Json // Enabled scenes
Action any //
Replacement any //
RiskLevel any //
Priority any //
Status any // 1 enabled, 2 disabled
Remark any //
CreatedAt *gtime.Time //
CreatedBy any //
UpdatedAt *gtime.Time //
UpdatedBy any //
DeletedAt *gtime.Time //
DeletedBy any //
}
+14 -10
View File
@@ -11,14 +11,18 @@ import (
// ImTenantConfig is the golang structure of table im_tenant_config for DAO operations like Where/Data.
type ImTenantConfig struct {
g.Meta `orm:"table:im_tenant_config, do:true"`
Id any //
TenantId any //
MaxUsers any // 0 means unlimited
MaxGroups any // 0 means unlimited
MaxGroupMembers any // 0 means unlimited
CreatedAt *gtime.Time //
CreatedBy any //
UpdatedAt *gtime.Time //
UpdatedBy any //
g.Meta `orm:"table:im_tenant_config, do:true"`
Id any //
TenantId any //
MaxUsers any // 0 means unlimited
MaxGroups any // 0 means unlimited
MaxGroupMembers any // 0 means unlimited
DefaultPolicyGroupId any // Default user policy group
SecurityPolicyVersion any // Published security policy version
GlobalFriendEnabled any // Published global friend switch
MessageCurfewEnabled any // Published message curfew switch
CreatedAt *gtime.Time //
CreatedBy any //
UpdatedAt *gtime.Time //
UpdatedBy any //
}
@@ -0,0 +1,29 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package do
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
)
// ImUserPolicyGroupMembers is the golang structure of table im_user_policy_group_members for DAO operations like Where/Data.
type ImUserPolicyGroupMembers struct {
g.Meta `orm:"table:im_user_policy_group_members, do:true"`
Id any //
TenantId any //
GroupId any //
UserId any // User ID in the tenant database
Status any // 1 enabled, 2 disabled
ValidFrom *gtime.Time //
ValidUntil *gtime.Time //
Remark any //
CreatedAt *gtime.Time //
CreatedBy any //
UpdatedAt *gtime.Time //
UpdatedBy any //
DeletedAt *gtime.Time //
DeletedBy any //
}
@@ -0,0 +1,33 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package do
import (
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
)
// ImUserPolicyGroups is the golang structure of table im_user_policy_groups for DAO operations like Where/Data.
type ImUserPolicyGroups struct {
g.Meta `orm:"table:im_user_policy_groups, do:true"`
Id any //
TenantId any // 0 means global default
GroupCode any // Stable policy group code
GroupName any // Policy group name
Priority any // Higher value has higher priority
Status any // 1 enabled, 2 disabled
PolicyJson *gjson.Json // Login, friend, message, group and file policies
IpWhitelist *gjson.Json // IPv4/IPv6 or CIDR list
IpBlacklist *gjson.Json // IPv4/IPv6 or CIDR list
Version any // Optimistic-lock/config version
Remark any //
CreatedAt *gtime.Time //
CreatedBy any //
UpdatedAt *gtime.Time //
UpdatedBy any //
DeletedAt *gtime.Time //
DeletedBy any //
}
@@ -0,0 +1,37 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package entity
import (
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/os/gtime"
)
// ImMessageCurfewRules is the golang structure for table im_message_curfew_rules.
type ImMessageCurfewRules struct {
Id int64 `json:"id" orm:"id" description:""`
TenantId int64 `json:"tenantId" orm:"tenant_id" description:""`
PolicyId int64 `json:"policyId" orm:"policy_id" description:""`
RuleCode string `json:"ruleCode" orm:"rule_code" description:""`
RuleName string `json:"ruleName" orm:"rule_name" description:""`
DateType string `json:"dateType" orm:"date_type" description:"daily, weekday, weekend, custom"`
CustomDates *gjson.Json `json:"customDates" orm:"custom_dates" description:"YYYY-MM-DD values for custom date type"`
Weekdays *gjson.Json `json:"weekdays" orm:"weekdays" description:"ISO weekdays 1 through 7"`
Timezone string `json:"timezone" orm:"timezone" description:""`
StartTime *gtime.Time `json:"startTime" orm:"start_time" description:""`
EndTime *gtime.Time `json:"endTime" orm:"end_time" description:"Less than start_time means crossing midnight"`
Scope string `json:"scope" orm:"scope" description:"private_message or group_message"`
WhitelistUserIds *gjson.Json `json:"whitelistUserIds" orm:"whitelist_user_ids" description:""`
WhitelistGroupIds *gjson.Json `json:"whitelistGroupIds" orm:"whitelist_group_ids" description:""`
Message string `json:"message" orm:"message" description:""`
Status int `json:"status" orm:"status" description:"1 enabled, 2 disabled"`
Sort int `json:"sort" orm:"sort" description:""`
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:""`
CreatedBy int64 `json:"createdBy" orm:"created_by" description:""`
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:""`
UpdatedBy int64 `json:"updatedBy" orm:"updated_by" description:""`
DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:""`
DeletedBy int64 `json:"deletedBy" orm:"deleted_by" description:""`
}
@@ -0,0 +1,30 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package entity
import (
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/os/gtime"
)
// ImSecurityIpRules is the golang structure for table im_security_ip_rules.
type ImSecurityIpRules struct {
Id int64 `json:"id" orm:"id" description:""`
TenantId int64 `json:"tenantId" orm:"tenant_id" description:""`
RuleType string `json:"ruleType" orm:"rule_type" description:"whitelist or blacklist"`
IpCidr string `json:"ipCidr" orm:"ip_cidr" description:"IPv4, IPv6 or CIDR"`
Action string `json:"action" orm:"action" description:"allow, challenge, block, audit_only"`
SceneJson *gjson.Json `json:"sceneJson" orm:"scene_json" description:"login, register, message, upload and other scenes"`
RiskLevel string `json:"riskLevel" orm:"risk_level" description:""`
Status int `json:"status" orm:"status" description:"1 enabled, 2 disabled"`
ExpiresAt *gtime.Time `json:"expiresAt" orm:"expires_at" description:""`
Remark string `json:"remark" orm:"remark" description:""`
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:""`
CreatedBy int64 `json:"createdBy" orm:"created_by" description:""`
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:""`
UpdatedBy int64 `json:"updatedBy" orm:"updated_by" description:""`
DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:""`
DeletedBy int64 `json:"deletedBy" orm:"deleted_by" description:""`
}
@@ -0,0 +1,37 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package entity
import (
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/os/gtime"
)
// ImSecurityPolicy is the golang structure for table im_security_policy.
type ImSecurityPolicy struct {
Id int64 `json:"id" orm:"id" description:""`
TenantId int64 `json:"tenantId" orm:"tenant_id" description:"0 means global fallback policy"`
PolicyVersion uint `json:"policyVersion" orm:"policy_version" description:""`
PolicyName string `json:"policyName" orm:"policy_name" description:""`
PublishStatus string `json:"publishStatus" orm:"publish_status" description:""`
PasswordPolicy *gjson.Json `json:"passwordPolicy" orm:"password_policy" description:""`
LoginRateLimit *gjson.Json `json:"loginRateLimit" orm:"login_rate_limit" description:""`
SensitiveWordPolicy *gjson.Json `json:"sensitiveWordPolicy" orm:"sensitive_word_policy" description:""`
FileReviewPolicy *gjson.Json `json:"fileReviewPolicy" orm:"file_review_policy" description:""`
RealnamePolicy *gjson.Json `json:"realnamePolicy" orm:"realname_policy" description:""`
RiskChallengePolicy *gjson.Json `json:"riskChallengePolicy" orm:"risk_challenge_policy" description:""`
GlobalFriendEnabled int `json:"globalFriendEnabled" orm:"global_friend_enabled" description:"Backend master switch for every add-friend entry"`
FriendDisabledPolicy *gjson.Json `json:"friendDisabledPolicy" orm:"friend_disabled_policy" description:"Profile masking, QR and group-member restrictions"`
MessageCurfewEnabled int `json:"messageCurfewEnabled" orm:"message_curfew_enabled" description:"Backend master switch for message curfew"`
Remark string `json:"remark" orm:"remark" description:""`
PublishedAt *gtime.Time `json:"publishedAt" orm:"published_at" description:""`
PublishedBy int64 `json:"publishedBy" orm:"published_by" description:""`
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:""`
CreatedBy int64 `json:"createdBy" orm:"created_by" description:""`
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:""`
UpdatedBy int64 `json:"updatedBy" orm:"updated_by" description:""`
DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:""`
DeletedBy int64 `json:"deletedBy" orm:"deleted_by" description:""`
}
@@ -0,0 +1,26 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package entity
import (
"github.com/gogf/gf/v2/os/gtime"
)
// ImSensitiveWordGroups is the golang structure for table im_sensitive_word_groups.
type ImSensitiveWordGroups struct {
Id int64 `json:"id" orm:"id" description:""`
TenantId int64 `json:"tenantId" orm:"tenant_id" description:"0 means global dictionary"`
GroupCode string `json:"groupCode" orm:"group_code" description:""`
GroupName string `json:"groupName" orm:"group_name" description:""`
Priority int `json:"priority" orm:"priority" description:""`
Status int `json:"status" orm:"status" description:"1 enabled, 2 disabled"`
Remark string `json:"remark" orm:"remark" description:""`
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:""`
CreatedBy int64 `json:"createdBy" orm:"created_by" description:""`
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:""`
UpdatedBy int64 `json:"updatedBy" orm:"updated_by" description:""`
DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:""`
DeletedBy int64 `json:"deletedBy" orm:"deleted_by" description:""`
}
@@ -0,0 +1,33 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package entity
import (
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/os/gtime"
)
// ImSensitiveWords is the golang structure for table im_sensitive_words.
type ImSensitiveWords struct {
Id int64 `json:"id" orm:"id" description:""`
TenantId int64 `json:"tenantId" orm:"tenant_id" description:"0 means global dictionary"`
GroupId int64 `json:"groupId" orm:"group_id" description:""`
Word string `json:"word" orm:"word" description:""`
WordHash string `json:"wordHash" orm:"word_hash" description:"SHA-256 of normalized word"`
MatchType string `json:"matchType" orm:"match_type" description:""`
SceneJson *gjson.Json `json:"sceneJson" orm:"scene_json" description:"Enabled scenes"`
Action string `json:"action" orm:"action" description:""`
Replacement string `json:"replacement" orm:"replacement" description:""`
RiskLevel string `json:"riskLevel" orm:"risk_level" description:""`
Priority int `json:"priority" orm:"priority" description:""`
Status int `json:"status" orm:"status" description:"1 enabled, 2 disabled"`
Remark string `json:"remark" orm:"remark" description:""`
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:""`
CreatedBy int64 `json:"createdBy" orm:"created_by" description:""`
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:""`
UpdatedBy int64 `json:"updatedBy" orm:"updated_by" description:""`
DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:""`
DeletedBy int64 `json:"deletedBy" orm:"deleted_by" description:""`
}
@@ -10,13 +10,17 @@ import (
// ImTenantConfig is the golang structure for table im_tenant_config.
type ImTenantConfig struct {
Id int64 `json:"id" orm:"id" description:""`
TenantId int64 `json:"tenantId" orm:"tenant_id" description:""`
MaxUsers uint64 `json:"maxUsers" orm:"max_users" description:"0 means unlimited"`
MaxGroups uint64 `json:"maxGroups" orm:"max_groups" description:"0 means unlimited"`
MaxGroupMembers uint `json:"maxGroupMembers" orm:"max_group_members" description:"0 means unlimited"`
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:""`
CreatedBy int64 `json:"createdBy" orm:"created_by" description:""`
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:""`
UpdatedBy int64 `json:"updatedBy" orm:"updated_by" description:""`
Id int64 `json:"id" orm:"id" description:""`
TenantId int64 `json:"tenantId" orm:"tenant_id" description:""`
MaxUsers uint64 `json:"maxUsers" orm:"max_users" description:"0 means unlimited"`
MaxGroups uint64 `json:"maxGroups" orm:"max_groups" description:"0 means unlimited"`
MaxGroupMembers uint `json:"maxGroupMembers" orm:"max_group_members" description:"0 means unlimited"`
DefaultPolicyGroupId int64 `json:"defaultPolicyGroupId" orm:"default_policy_group_id" description:"Default user policy group"`
SecurityPolicyVersion uint `json:"securityPolicyVersion" orm:"security_policy_version" description:"Published security policy version"`
GlobalFriendEnabled int `json:"globalFriendEnabled" orm:"global_friend_enabled" description:"Published global friend switch"`
MessageCurfewEnabled int `json:"messageCurfewEnabled" orm:"message_curfew_enabled" description:"Published message curfew switch"`
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:""`
CreatedBy int64 `json:"createdBy" orm:"created_by" description:""`
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:""`
UpdatedBy int64 `json:"updatedBy" orm:"updated_by" description:""`
}
@@ -0,0 +1,27 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package entity
import (
"github.com/gogf/gf/v2/os/gtime"
)
// ImUserPolicyGroupMembers is the golang structure for table im_user_policy_group_members.
type ImUserPolicyGroupMembers struct {
Id int64 `json:"id" orm:"id" description:""`
TenantId int64 `json:"tenantId" orm:"tenant_id" description:""`
GroupId int64 `json:"groupId" orm:"group_id" description:""`
UserId int64 `json:"userId" orm:"user_id" description:"User ID in the tenant database"`
Status int `json:"status" orm:"status" description:"1 enabled, 2 disabled"`
ValidFrom *gtime.Time `json:"validFrom" orm:"valid_from" description:""`
ValidUntil *gtime.Time `json:"validUntil" orm:"valid_until" description:""`
Remark string `json:"remark" orm:"remark" description:""`
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:""`
CreatedBy int64 `json:"createdBy" orm:"created_by" description:""`
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:""`
UpdatedBy int64 `json:"updatedBy" orm:"updated_by" description:""`
DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:""`
DeletedBy int64 `json:"deletedBy" orm:"deleted_by" description:""`
}
@@ -0,0 +1,31 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package entity
import (
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/os/gtime"
)
// ImUserPolicyGroups is the golang structure for table im_user_policy_groups.
type ImUserPolicyGroups struct {
Id int64 `json:"id" orm:"id" description:""`
TenantId int64 `json:"tenantId" orm:"tenant_id" description:"0 means global default"`
GroupCode string `json:"groupCode" orm:"group_code" description:"Stable policy group code"`
GroupName string `json:"groupName" orm:"group_name" description:"Policy group name"`
Priority int `json:"priority" orm:"priority" description:"Higher value has higher priority"`
Status int `json:"status" orm:"status" description:"1 enabled, 2 disabled"`
PolicyJson *gjson.Json `json:"policyJson" orm:"policy_json" description:"Login, friend, message, group and file policies"`
IpWhitelist *gjson.Json `json:"ipWhitelist" orm:"ip_whitelist" description:"IPv4/IPv6 or CIDR list"`
IpBlacklist *gjson.Json `json:"ipBlacklist" orm:"ip_blacklist" description:"IPv4/IPv6 or CIDR list"`
Version uint `json:"version" orm:"version" description:"Optimistic-lock/config version"`
Remark string `json:"remark" orm:"remark" description:""`
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:""`
CreatedBy int64 `json:"createdBy" orm:"created_by" description:""`
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:""`
UpdatedBy int64 `json:"updatedBy" orm:"updated_by" description:""`
DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:""`
DeletedBy int64 `json:"deletedBy" orm:"deleted_by" description:""`
}
@@ -0,0 +1,44 @@
package sysin
import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/os/gtime"
)
type ImDashboardOverviewInp struct {
TenantId int64 `json:"tenantId" dc:"租户ID"`
}
type ImDashboardOverviewModel struct {
TenantId int64 `json:"tenantId" dc:"租户ID"`
TenantName string `json:"tenantName" dc:"租户名称"`
TotalUsers int64 `json:"totalUsers" dc:"总用户数"`
ActiveUsers int64 `json:"activeUsers" dc:"活跃用户数"`
TotalGroups int64 `json:"totalGroups" dc:"总群组数"`
TotalConversations int64 `json:"totalConversations" dc:"总会话数"`
TotalMessages int64 `json:"totalMessages" dc:"总消息数"`
TodayMessages int64 `json:"todayMessages" dc:"今日消息数"`
}
type ImDashboardTrendsInp struct {
TenantId int64 `json:"tenantId" dc:"租户ID"`
Days int `json:"days" dc:"统计天数"`
}
func (in *ImDashboardTrendsInp) Filter(ctx context.Context) error {
if in.Days == 0 {
in.Days = 7
}
if in.Days < 1 || in.Days > 31 {
return gerror.New("统计天数必须在1到31天之间")
}
return nil
}
type ImDashboardTrendModel struct {
Date *gtime.Time `json:"date" dc:"日期"`
UserCount int64 `json:"userCount" dc:"新增用户数"`
MessageCount int64 `json:"messageCount" dc:"新增消息数"`
}
@@ -0,0 +1,161 @@
package sysin
import (
"context"
"hotgo/internal/model/input/form"
"strings"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/os/gtime"
)
type ImUserLoginHistoryListInp struct {
form.PageReq
TenantId int64 `json:"tenantId" dc:"租户ID"`
UserId string `json:"userId" dc:"用户ID"`
Account string `json:"account" dc:"脱敏账号"`
LoginType string `json:"loginType" dc:"登录方式"`
EventType string `json:"eventType" dc:"事件类型"`
Platform string `json:"platform" dc:"客户端平台"`
Ip string `json:"ip" dc:"IP地址"`
LoginAt []*gtime.Time `json:"loginAt" dc:"登录时间"`
}
func (in *ImUserLoginHistoryListInp) Filter(ctx context.Context) error {
in.Account = strings.TrimSpace(in.Account)
in.Ip = strings.TrimSpace(in.Ip)
return filterImAuditPage(&in.PageReq)
}
type ImUserLoginHistoryModel struct {
TenantId int64 `json:"tenantId" dc:"租户ID"`
TenantName string `json:"tenantName" dc:"租户名称"`
Id int64 `json:"id" dc:"ID"`
UserId string `json:"userId" dc:"用户ID"`
Username string `json:"username" dc:"用户名"`
AccountType string `json:"accountType" dc:"账号类型"`
AccountMask string `json:"accountMask" dc:"脱敏账号"`
LoginType string `json:"loginType" dc:"登录方式"`
EventType string `json:"eventType" dc:"事件类型"`
SessionId string `json:"sessionId" dc:"会话ID"`
DeviceId string `json:"deviceId" dc:"设备ID"`
Platform string `json:"platform" dc:"客户端平台"`
AppVersion string `json:"appVersion" dc:"客户端版本"`
Ip string `json:"ip" dc:"IP地址"`
Region string `json:"region" dc:"地区"`
UserAgent string `json:"userAgent" dc:"客户端标识"`
RiskLevel string `json:"riskLevel" dc:"风险等级"`
RequestId string `json:"requestId" dc:"请求ID"`
LoginAt *gtime.Time `json:"loginAt" dc:"登录时间"`
LogoutAt *gtime.Time `json:"logoutAt" dc:"登出时间"`
Metadata string `json:"metadata" dc:"元数据"`
}
type ImLoginFailureLogListInp struct {
form.PageReq
TenantId int64 `json:"tenantId" dc:"租户ID"`
UserId string `json:"userId" dc:"用户ID"`
Account string `json:"account" dc:"脱敏账号"`
FailureType string `json:"failureType" dc:"失败类型"`
Platform string `json:"platform" dc:"客户端平台"`
Ip string `json:"ip" dc:"IP地址"`
AttemptAt []*gtime.Time `json:"attemptAt" dc:"尝试时间"`
}
func (in *ImLoginFailureLogListInp) Filter(ctx context.Context) error {
in.Account = strings.TrimSpace(in.Account)
in.Ip = strings.TrimSpace(in.Ip)
return filterImAuditPage(&in.PageReq)
}
func filterImAuditPage(page *form.PageReq) error {
if page.Page <= 0 {
page.Page = 1
}
if page.PerPage <= 0 {
page.PerPage = 20
}
if page.PerPage > 200 {
return gerror.New("每页数量不能超过200")
}
return nil
}
type ImLoginFailureLogModel struct {
TenantId int64 `json:"tenantId" dc:"租户ID"`
TenantName string `json:"tenantName" dc:"租户名称"`
Id int64 `json:"id" dc:"ID"`
UserId string `json:"userId" dc:"用户ID"`
AccountType string `json:"accountType" dc:"账号类型"`
AccountMask string `json:"accountMask" dc:"脱敏账号"`
FailureType string `json:"failureType" dc:"失败类型"`
Reason string `json:"reason" dc:"原因码"`
Detail string `json:"detail" dc:"失败详情"`
Ip string `json:"ip" dc:"IP地址"`
Region string `json:"region" dc:"地区"`
DeviceId string `json:"deviceId" dc:"设备ID"`
Platform string `json:"platform" dc:"客户端平台"`
AppVersion string `json:"appVersion" dc:"客户端版本"`
UserAgent string `json:"userAgent" dc:"客户端标识"`
RiskLevel string `json:"riskLevel" dc:"风险等级"`
RiskAction string `json:"riskAction" dc:"风控动作"`
RequestId string `json:"requestId" dc:"请求ID"`
AttemptAt *gtime.Time `json:"attemptAt" dc:"尝试时间"`
Metadata string `json:"metadata" dc:"元数据"`
}
type ImLoginFailureViewInp struct {
TenantId int64 `json:"tenantId" dc:"租户ID"`
Id int64 `json:"id" dc:"日志ID"`
}
func (in *ImLoginFailureViewInp) Filter(ctx context.Context) error {
if in.Id <= 0 {
return gerror.New("日志ID不能为空")
}
return nil
}
type ImLoginFailureAddBlacklistInp struct {
TenantId int64 `json:"tenantId" dc:"租户ID"`
Ip string `json:"ip" dc:"IP地址"`
Remark string `json:"remark" dc:"备注"`
}
func (in *ImLoginFailureAddBlacklistInp) Filter(ctx context.Context) error {
in.Ip = strings.TrimSpace(in.Ip)
if in.Ip == "" {
return gerror.New("IP地址不能为空")
}
return nil
}
type ImLoginFailureBanUserInp struct {
TenantId int64 `json:"tenantId" dc:"租户ID"`
UserId int64 `json:"userId" dc:"用户ID"`
Reason string `json:"reason" dc:"封禁原因"`
}
func (in *ImLoginFailureBanUserInp) Filter(ctx context.Context) error {
in.Reason = strings.TrimSpace(in.Reason)
if in.UserId <= 0 {
return gerror.New("用户ID不能为空")
}
if in.Reason == "" {
return gerror.New("封禁原因不能为空")
}
return nil
}
type ImLoginAuditExportModel struct {
Id int64 `json:"id" dc:"ID"`
UserId string `json:"userId" dc:"用户ID"`
AccountMask string `json:"accountMask" dc:"脱敏账号"`
EventType string `json:"eventType" dc:"事件/失败类型"`
Platform string `json:"platform" dc:"客户端平台"`
Ip string `json:"ip" dc:"IP地址"`
Region string `json:"region" dc:"地区"`
RiskLevel string `json:"riskLevel" dc:"风险等级"`
Reason string `json:"reason" dc:"原因"`
OccurredAt *gtime.Time `json:"occurredAt" dc:"发生时间"`
}
@@ -0,0 +1,147 @@
package sysin
import (
"context"
"hotgo/internal/consts"
"hotgo/internal/library/dict"
"hotgo/internal/model/input/form"
"strings"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/os/gtime"
)
type ImPrivateMessageListInp struct {
form.PageReq
TenantId int64 `json:"tenantId" dc:"租户ID"`
Topic string `json:"topic" dc:"会话Topic"`
FromUserId string `json:"fromUserId" dc:"发送用户ID"`
ToUserId string `json:"toUserId" dc:"接收用户ID"`
ContentType string `json:"contentType" dc:"内容类型"`
Status string `json:"status" dc:"状态"`
Keyword string `json:"keyword" dc:"内容关键词"`
CreatedAt []*gtime.Time `json:"createdAt" dc:"发送时间"`
}
func (in *ImPrivateMessageListInp) Filter(ctx context.Context) error {
return filterImMessageList(&in.PageReq, &in.Topic, &in.Keyword, in.ContentType, in.Status)
}
type ImGroupMessageListInp struct {
form.PageReq
TenantId int64 `json:"tenantId" dc:"租户ID"`
Topic string `json:"topic" dc:"群Topic"`
SenderUserId string `json:"senderUserId" dc:"发送用户ID"`
ContentType string `json:"contentType" dc:"内容类型"`
Status string `json:"status" dc:"状态"`
Keyword string `json:"keyword" dc:"内容关键词"`
CreatedAt []*gtime.Time `json:"createdAt" dc:"发送时间"`
}
func (in *ImGroupMessageListInp) Filter(ctx context.Context) error {
return filterImMessageList(&in.PageReq, &in.Topic, &in.Keyword, in.ContentType, in.Status)
}
func filterImMessageList(page *form.PageReq, topic *string, keyword *string, contentType string, status string) error {
*topic = strings.TrimSpace(*topic)
*keyword = strings.TrimSpace(*keyword)
if page.Page <= 0 {
page.Page = 1
}
if page.PerPage <= 0 {
page.PerPage = 20
}
if page.PerPage > 200 {
return gerror.New("每页数量不能超过200")
}
if contentType != "" && !dict.HasOptionKey(consts.ImMessageContentTypeOptions, contentType) {
return gerror.New("消息类型不合法")
}
if status != "" && !dict.HasOptionKey(consts.ImMessageStatusOptions, status) {
return gerror.New("消息状态不合法")
}
return nil
}
type ImMessageListModel struct {
TenantId int64 `json:"tenantId" dc:"租户ID"`
TenantName string `json:"tenantName" dc:"租户名称"`
Topic string `json:"topic" dc:"会话Topic"`
SeqId int64 `json:"seqId" dc:"消息序号"`
FromUserId string `json:"fromUserId" dc:"发送用户ID"`
SenderUsername string `json:"senderUsername" dc:"发送人用户名"`
SenderNickname string `json:"senderNickname" dc:"发送人昵称"`
ToUserId string `json:"toUserId" dc:"接收用户ID"`
ReceiverUsername string `json:"receiverUsername" dc:"接收人用户名"`
ReceiverNickname string `json:"receiverNickname" dc:"接收人昵称"`
GroupName string `json:"groupName" dc:"群名称"`
GroupNo string `json:"groupNo" dc:"群号"`
ContentType string `json:"contentType" dc:"消息类型"`
ContentExcerpt string `json:"contentExcerpt" dc:"内容摘要"`
Status string `json:"status" dc:"状态"`
ReplyToSeq int64 `json:"replyToSeq" dc:"回复消息序号"`
AtUsers string `json:"atUsers" dc:"@用户"`
CreatedAt *gtime.Time `json:"createdAt" dc:"发送时间"`
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
}
type ImMessageViewInp struct {
TenantId int64 `json:"tenantId" dc:"租户ID"`
Topic string `json:"topic" dc:"会话Topic"`
SeqId int64 `json:"seqId" dc:"消息序号"`
}
func (in *ImMessageViewInp) Filter(ctx context.Context) error {
in.Topic = strings.TrimSpace(in.Topic)
if in.Topic == "" || in.SeqId <= 0 {
return gerror.New("消息Topic和序号不能为空")
}
return nil
}
type ImMessageViewModel struct {
ImMessageListModel
Head string `json:"head" dc:"消息头"`
Content string `json:"content" dc:"完整消息内容"`
Metadata string `json:"metadata" dc:"扩展数据"`
}
type ImMessageActionInp struct {
TenantId int64 `json:"tenantId" dc:"租户ID"`
Topic string `json:"topic" dc:"会话Topic"`
SeqId int64 `json:"seqId" dc:"消息序号"`
Reason string `json:"reason" dc:"处置原因"`
}
func (in *ImMessageActionInp) Filter(ctx context.Context) error {
in.Topic = strings.TrimSpace(in.Topic)
in.Reason = strings.TrimSpace(in.Reason)
if in.Topic == "" || in.SeqId <= 0 {
return gerror.New("消息Topic和序号不能为空")
}
if in.Reason == "" {
return gerror.New("处置原因不能为空")
}
if len([]rune(in.Reason)) > 500 {
return gerror.New("处置原因不能超过500个字符")
}
return nil
}
type ImMessageCommandModel struct {
CommandId string `json:"commandId" dc:"命令ID"`
EventId string `json:"eventId" dc:"事件ID"`
Status string `json:"status" dc:"命令状态"`
}
type ImMessageExportModel struct {
Topic string `json:"topic" dc:"Topic"`
SeqId int64 `json:"seqId" dc:"消息序号"`
FromUserId string `json:"fromUserId" dc:"发送用户ID"`
ToUserId string `json:"toUserId" dc:"接收用户ID"`
GroupName string `json:"groupName" dc:"群名称"`
ContentType string `json:"contentType" dc:"消息类型"`
ContentExcerpt string `json:"contentExcerpt" dc:"内容摘要"`
Status string `json:"status" dc:"状态"`
CreatedAt *gtime.Time `json:"createdAt" dc:"发送时间"`
}
@@ -0,0 +1,145 @@
package sysin
import (
"context"
"testing"
"hotgo/internal/consts"
"github.com/gogf/gf/v2/encoding/gjson"
)
func TestImMessageCurfewRuleFilter(t *testing.T) {
ctx := context.Background()
valid := &ImMessageCurfewRuleInp{
RuleCode: "after_work",
RuleName: "下班时段",
DateType: consts.ImCurfewDateWeekday,
StartTime: "18:00",
EndTime: "09:00",
Scope: consts.ImCurfewScopePrivate,
}
if err := valid.Filter(ctx); err != nil {
t.Fatalf("跨午夜宵禁规则应合法: %v", err)
}
if valid.Timezone != "Asia/Shanghai" || valid.Status != consts.StatusEnabled {
t.Fatalf("默认值未补齐: timezone=%s status=%d", valid.Timezone, valid.Status)
}
invalidTime := *valid
invalidTime.StartTime = "25:00"
if err := invalidTime.Filter(ctx); err == nil {
t.Fatal("非法宵禁时间应被拒绝")
}
}
func TestImSecurityPolicySaveFilterRequiresCurfewRule(t *testing.T) {
in := &ImSecurityPolicySaveInp{
PolicyName: "默认策略",
GlobalFriendEnabled: 1,
MessageCurfewEnabled: 1,
}
if err := in.Filter(context.Background()); err == nil {
t.Fatal("启用宵禁但未配置规则应被拒绝")
}
in.CurfewRules = []*ImMessageCurfewRuleInp{{
RuleCode: "group_only",
RuleName: "仅群聊",
DateType: consts.ImCurfewDateDaily,
StartTime: "18:00",
EndTime: "09:00",
Scope: consts.ImCurfewScopeGroup,
}}
if err := in.Filter(context.Background()); err == nil {
t.Fatal("宵禁仅配置群聊规则时应被拒绝")
}
}
func TestImSecurityPolicySaveFilterForcesEveryFriendEntryOff(t *testing.T) {
in := &ImSecurityPolicySaveInp{
PolicyName: "下班策略",
GlobalFriendEnabled: 0,
MessageCurfewEnabled: 0,
FriendDisabledPolicy: gjson.New(map[string]interface{}{
"hide_profile": false,
"blocked_entries": []string{"search"},
}),
}
if err := in.Filter(context.Background()); err != nil {
t.Fatalf("关闭全局好友功能的策略应合法: %v", err)
}
policy := in.FriendDisabledPolicy.Map()
if hide, ok := policy["hide_profile"].(bool); !ok || !hide {
t.Fatal("关闭全局好友功能时必须强制隐藏个人资料")
}
entries := in.FriendDisabledPolicy.Get("blocked_entries").Array()
if len(entries) != 6 {
t.Fatalf("关闭全局好友功能时必须禁用全部6个入口: %#v", policy["blocked_entries"])
}
}
func TestImSecurityPolicyPublishFilter(t *testing.T) {
ctx := context.Background()
if err := (&ImSecurityPolicyPublishInp{Id: 1, Reason: " "}).Filter(ctx); err == nil {
t.Fatal("空发布原因应被拒绝")
}
if err := (&ImSecurityPolicyPublishInp{Id: 1, Reason: "管理员发布"}).Filter(ctx); err != nil {
t.Fatalf("合法发布参数不应报错: %v", err)
}
}
func TestImSecurityIPRuleEditFilter(t *testing.T) {
ctx := context.Background()
valid := &ImSecurityIPRuleEditInp{
RuleType: "blacklist",
IpCidr: "192.0.2.0/24",
Action: consts.ImSecurityActionBlock,
SceneJson: gjson.New([]string{"login"}),
RiskLevel: consts.ImRiskLevelHigh,
}
if err := valid.Filter(ctx); err != nil {
t.Fatalf("合法IP阻断规则不应报错: %v", err)
}
invalidAction := *valid
invalidAction.Action = consts.ImPolicyActionDeny
if err := invalidAction.Filter(ctx); err == nil {
t.Fatal("数据库枚举不支持的deny动作应被拒绝")
}
}
func TestImSensitiveWordEditFilter(t *testing.T) {
in := &ImSensitiveWordEditInp{
GroupId: 1,
Word: "测试词",
MatchType: consts.ImSensitiveMatchContains,
SceneJson: gjson.New([]string{"private_message"}),
Action: consts.ImSensitiveActionReplace,
RiskLevel: consts.ImRiskLevelMedium,
}
if err := in.Filter(context.Background()); err == nil {
t.Fatal("替换动作未填写替换文本应被拒绝")
}
}
func TestImSensitiveWordGroupEditFilter(t *testing.T) {
in := &ImSensitiveWordGroupEditInp{GroupCode: "default", GroupName: " "}
if err := in.Filter(context.Background()); err == nil {
t.Fatal("空分组名称应被拒绝")
}
}
func TestImUserPolicyGroupInputFilter(t *testing.T) {
ctx := context.Background()
group := &ImUserPolicyGroupEditInp{
GroupCode: "staff",
GroupName: " ",
PolicyJson: gjson.New(map[string]interface{}{}),
}
if err := group.Filter(ctx); err == nil {
t.Fatal("空用户策略分组名称应被拒绝")
}
if err := (&ImUserPolicyGroupMemberAddInp{GroupId: 1, UserId: 0}).Filter(ctx); err == nil {
t.Fatal("无效用户ID应被拒绝")
}
}
@@ -0,0 +1,324 @@
package sysin
import (
"context"
"strings"
"time"
"hotgo/internal/consts"
"hotgo/internal/library/dict"
"hotgo/internal/model/input/form"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/os/gtime"
)
type ImSecurityPolicyListInp struct {
form.PageReq
TenantId int64 `json:"tenantId"`
PublishStatus string `json:"publishStatus"`
}
func (in *ImSecurityPolicyListInp) Filter(ctx context.Context) error {
if in.PublishStatus != "" && !dict.HasOptionKey(consts.ImSecurityPublishStatusOptions, in.PublishStatus) {
return gerror.New("发布状态不合法")
}
return nil
}
type ImMessageCurfewRuleModel struct {
Id int64 `json:"id"`
RuleCode string `json:"ruleCode"`
RuleName string `json:"ruleName"`
DateType string `json:"dateType"`
CustomDates string `json:"customDates"`
Weekdays string `json:"weekdays"`
Timezone string `json:"timezone"`
StartTime string `json:"startTime"`
EndTime string `json:"endTime"`
Scope string `json:"scope"`
WhitelistUserIds string `json:"whitelistUserIds"`
WhitelistGroupIds string `json:"whitelistGroupIds"`
Message string `json:"message"`
Status int `json:"status"`
Sort int `json:"sort"`
}
type ImSecurityPolicyModel struct {
Id int64 `json:"id"`
TenantId int64 `json:"tenantId"`
PolicyVersion uint `json:"policyVersion"`
PolicyName string `json:"policyName"`
PublishStatus string `json:"publishStatus"`
PasswordPolicy string `json:"passwordPolicy"`
LoginRateLimit string `json:"loginRateLimit"`
SensitiveWordPolicy string `json:"sensitiveWordPolicy"`
FileReviewPolicy string `json:"fileReviewPolicy"`
RealnamePolicy string `json:"realnamePolicy"`
RiskChallengePolicy string `json:"riskChallengePolicy"`
GlobalFriendEnabled int `json:"globalFriendEnabled"`
FriendDisabledPolicy string `json:"friendDisabledPolicy"`
MessageCurfewEnabled int `json:"messageCurfewEnabled"`
Remark string `json:"remark"`
PublishedAt *gtime.Time `json:"publishedAt"`
PublishedBy int64 `json:"publishedBy"`
CreatedAt *gtime.Time `json:"createdAt"`
UpdatedAt *gtime.Time `json:"updatedAt"`
CurfewRules []*ImMessageCurfewRuleModel `json:"curfewRules"`
}
type ImSecurityPolicyViewInp struct {
Id int64 `json:"id"`
TenantId int64 `json:"tenantId"`
}
func (in *ImSecurityPolicyViewInp) Filter(ctx context.Context) error {
if in.Id <= 0 && in.TenantId < 0 {
return gerror.New("策略ID或租户ID不合法")
}
return nil
}
type ImMessageCurfewRuleInp struct {
RuleCode string `json:"ruleCode"`
RuleName string `json:"ruleName"`
DateType string `json:"dateType"`
CustomDates *gjson.Json `json:"customDates"`
Weekdays *gjson.Json `json:"weekdays"`
Timezone string `json:"timezone"`
StartTime string `json:"startTime"`
EndTime string `json:"endTime"`
Scope string `json:"scope"`
WhitelistUserIds *gjson.Json `json:"whitelistUserIds"`
WhitelistGroupIds *gjson.Json `json:"whitelistGroupIds"`
Message string `json:"message"`
Status int `json:"status"`
Sort int `json:"sort"`
}
func (in *ImMessageCurfewRuleInp) Filter(ctx context.Context) error {
in.RuleCode = strings.TrimSpace(in.RuleCode)
in.RuleName = strings.TrimSpace(in.RuleName)
in.Timezone = strings.TrimSpace(in.Timezone)
in.Message = strings.TrimSpace(in.Message)
if !imPolicyGroupCodePattern.MatchString(in.RuleCode) {
return gerror.New("宵禁规则编码格式不合法")
}
if in.RuleName == "" {
return gerror.New("宵禁规则名称不能为空")
}
if !dict.HasOptionKey(consts.ImCurfewDateTypeOptions, in.DateType) {
return gerror.New("宵禁日期类型不合法")
}
if !dict.HasOptionKey(consts.ImCurfewScopeOptions, in.Scope) {
return gerror.New("宵禁范围不合法")
}
if len(in.StartTime) != 5 || len(in.EndTime) != 5 {
return gerror.New("宵禁时间必须使用HH:mm格式")
}
if _, err := time.Parse("15:04", in.StartTime); err != nil {
return gerror.New("宵禁开始时间不合法")
}
if _, err := time.Parse("15:04", in.EndTime); err != nil {
return gerror.New("宵禁结束时间不合法")
}
if in.Timezone == "" {
in.Timezone = "Asia/Shanghai"
}
if in.Message == "" {
in.Message = "当前时段暂不能发送消息"
}
if in.Status == 0 {
in.Status = consts.StatusEnabled
}
if in.Status != consts.StatusEnabled && in.Status != consts.StatusDisable {
return gerror.New("宵禁规则状态不合法")
}
return nil
}
type ImSecurityPolicySaveInp struct {
Id int64 `json:"id"`
TenantId int64 `json:"tenantId"`
PolicyName string `json:"policyName" v:"required#策略名称不能为空"`
PasswordPolicy *gjson.Json `json:"passwordPolicy"`
LoginRateLimit *gjson.Json `json:"loginRateLimit"`
SensitiveWordPolicy *gjson.Json `json:"sensitiveWordPolicy"`
FileReviewPolicy *gjson.Json `json:"fileReviewPolicy"`
RealnamePolicy *gjson.Json `json:"realnamePolicy"`
RiskChallengePolicy *gjson.Json `json:"riskChallengePolicy"`
GlobalFriendEnabled int `json:"globalFriendEnabled"`
FriendDisabledPolicy *gjson.Json `json:"friendDisabledPolicy"`
MessageCurfewEnabled int `json:"messageCurfewEnabled"`
Remark string `json:"remark"`
CurfewRules []*ImMessageCurfewRuleInp `json:"curfewRules"`
}
func (in *ImSecurityPolicySaveInp) Filter(ctx context.Context) error {
in.PolicyName = strings.TrimSpace(in.PolicyName)
in.Remark = strings.TrimSpace(in.Remark)
if in.PolicyName == "" || len([]rune(in.PolicyName)) > 128 {
return gerror.New("策略名称长度必须为1至128个字符")
}
if in.GlobalFriendEnabled != 0 && in.GlobalFriendEnabled != 1 {
return gerror.New("全局好友开关不合法")
}
if in.MessageCurfewEnabled != 0 && in.MessageCurfewEnabled != 1 {
return gerror.New("宵禁开关不合法")
}
if in.GlobalFriendEnabled == 0 {
policy := make(map[string]interface{})
if in.FriendDisabledPolicy != nil {
policy = in.FriendDisabledPolicy.Map()
}
policy["hide_profile"] = true
policy["block_qrcode"] = true
policy["block_group_member_entry"] = true
policy["blocked_entries"] = []string{
"search", "profile_card", "group_member", "qrcode", "invite_auto_add", "recommendation",
}
message, ok := policy["message"].(string)
if !ok || strings.TrimSpace(message) == "" {
policy["message"] = "当前时段暂不允许添加好友"
}
in.FriendDisabledPolicy = gjson.New(policy)
}
if in.MessageCurfewEnabled == 1 && len(in.CurfewRules) == 0 {
return gerror.New("启用宵禁时至少配置一条宵禁规则")
}
seen := make(map[string]struct{}, len(in.CurfewRules))
hasPrivateMessageRule := false
for _, rule := range in.CurfewRules {
if rule == nil {
return gerror.New("宵禁规则不能为空")
}
if err := rule.Filter(ctx); err != nil {
return err
}
if _, ok := seen[rule.RuleCode]; ok {
return gerror.New("宵禁规则编码不能重复")
}
seen[rule.RuleCode] = struct{}{}
if rule.Scope == consts.ImCurfewScopePrivate && rule.Status == consts.StatusEnabled {
hasPrivateMessageRule = true
}
}
if in.MessageCurfewEnabled == 1 && !hasPrivateMessageRule {
return gerror.New("启用宵禁时至少配置一条启用的单聊/私聊规则")
}
return nil
}
type ImSecurityPolicyPublishInp struct {
Id int64 `json:"id" v:"required|min:1#策略ID不能为空|策略ID不合法"`
Reason string `json:"reason" v:"required#发布原因不能为空"`
}
func (in *ImSecurityPolicyPublishInp) Filter(ctx context.Context) error {
in.Reason = strings.TrimSpace(in.Reason)
if in.Id <= 0 {
return gerror.New("策略ID不合法")
}
if in.Reason == "" {
return gerror.New("发布原因不能为空")
}
if len([]rune(in.Reason)) > 500 {
return gerror.New("发布原因不能超过500个字符")
}
return nil
}
type ImSecurityPolicyRestoreInp struct {
TenantId int64 `json:"tenantId"`
Reason string `json:"reason" v:"required#恢复原因不能为空"`
}
func (in *ImSecurityPolicyRestoreInp) Filter(ctx context.Context) error {
in.Reason = strings.TrimSpace(in.Reason)
if in.TenantId < 0 {
return gerror.New("租户ID不合法")
}
if in.Reason == "" {
return gerror.New("恢复原因不能为空")
}
if len([]rune(in.Reason)) > 500 {
return gerror.New("恢复原因不能超过500个字符")
}
return nil
}
type ImSecurityIPRuleListInp struct {
form.PageReq
TenantId int64 `json:"tenantId"`
RuleType string `json:"ruleType"`
IpCidr string `json:"ipCidr"`
Status int `json:"status"`
}
func (in *ImSecurityIPRuleListInp) Filter(ctx context.Context) error {
in.IpCidr = strings.TrimSpace(in.IpCidr)
if in.RuleType != "" && in.RuleType != "whitelist" && in.RuleType != "blacklist" {
return gerror.New("IP规则类型不合法")
}
return nil
}
type ImSecurityIPRuleModel struct {
Id int64 `json:"id"`
TenantId int64 `json:"tenantId"`
RuleType string `json:"ruleType"`
IpCidr string `json:"ipCidr"`
Action string `json:"action"`
SceneJson string `json:"sceneJson"`
RiskLevel string `json:"riskLevel"`
Status int `json:"status"`
ExpiresAt *gtime.Time `json:"expiresAt"`
Remark string `json:"remark"`
CreatedAt *gtime.Time `json:"createdAt"`
UpdatedAt *gtime.Time `json:"updatedAt"`
}
type ImSecurityIPRuleEditInp struct {
Id int64 `json:"id"`
TenantId int64 `json:"tenantId"`
RuleType string `json:"ruleType"`
IpCidr string `json:"ipCidr"`
Action string `json:"action"`
SceneJson *gjson.Json `json:"sceneJson"`
RiskLevel string `json:"riskLevel"`
Status int `json:"status"`
ExpiresAt *gtime.Time `json:"expiresAt"`
Remark string `json:"remark"`
}
func (in *ImSecurityIPRuleEditInp) Filter(ctx context.Context) error {
in.IpCidr = strings.TrimSpace(in.IpCidr)
if in.RuleType != "whitelist" && in.RuleType != "blacklist" {
return gerror.New("IP规则类型不合法")
}
if in.IpCidr == "" {
return gerror.New("IP或CIDR不能为空")
}
if !dict.HasOptionKey(consts.ImSecurityActionOptions, in.Action) {
return gerror.New("规则动作不合法")
}
if !dict.HasOptionKey(consts.ImRiskLevelOptions, in.RiskLevel) {
return gerror.New("风险等级不合法")
}
if in.Status == 0 {
in.Status = consts.StatusEnabled
}
if in.Status != consts.StatusEnabled && in.Status != consts.StatusDisable {
return gerror.New("状态不合法")
}
if in.SceneJson == nil || in.SceneJson.String() == "" || in.SceneJson.String() == "null" {
return gerror.New("生效场景不能为空")
}
return nil
}
type ImSecurityIPRuleDeleteInp struct {
Id int64 `json:"id" v:"required|min:1#IP规则ID不能为空|IP规则ID不合法"`
}
func (in *ImSecurityIPRuleDeleteInp) Filter(ctx context.Context) error { return nil }
@@ -0,0 +1,190 @@
package sysin
import (
"context"
"strings"
"hotgo/internal/consts"
"hotgo/internal/library/dict"
"hotgo/internal/model/input/form"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/os/gtime"
)
type ImSensitiveWordListInp struct {
form.PageReq
TenantId int64 `json:"tenantId"`
GroupId int64 `json:"groupId"`
Word string `json:"word"`
MatchType string `json:"matchType"`
Action string `json:"action"`
RiskLevel string `json:"riskLevel"`
Status int `json:"status"`
}
func (in *ImSensitiveWordListInp) Filter(ctx context.Context) error {
in.Word = strings.TrimSpace(in.Word)
if in.MatchType != "" && !dict.HasOptionKey(consts.ImSensitiveMatchTypeOptions, in.MatchType) {
return gerror.New("匹配类型不合法")
}
if in.Action != "" && !dict.HasOptionKey(consts.ImSensitiveActionOptions, in.Action) {
return gerror.New("命中动作不合法")
}
if in.RiskLevel != "" && !dict.HasOptionKey(consts.ImRiskLevelOptions, in.RiskLevel) {
return gerror.New("风险等级不合法")
}
return nil
}
type ImSensitiveWordListModel struct {
Id int64 `json:"id"`
TenantId int64 `json:"tenantId"`
GroupId int64 `json:"groupId"`
GroupName string `json:"groupName"`
Word string `json:"word"`
MatchType string `json:"matchType"`
SceneJson string `json:"sceneJson"`
Action string `json:"action"`
Replacement string `json:"replacement"`
RiskLevel string `json:"riskLevel"`
Priority int `json:"priority"`
Status int `json:"status"`
Remark string `json:"remark"`
CreatedAt *gtime.Time `json:"createdAt"`
UpdatedAt *gtime.Time `json:"updatedAt"`
}
type ImSensitiveWordEditInp struct {
Id int64 `json:"id"`
TenantId int64 `json:"tenantId"`
GroupId int64 `json:"groupId" v:"required|min:1#敏感词分组不能为空|敏感词分组不合法"`
Word string `json:"word" v:"required#敏感词不能为空"`
MatchType string `json:"matchType"`
SceneJson *gjson.Json `json:"sceneJson" v:"required#生效场景不能为空"`
Action string `json:"action"`
Replacement string `json:"replacement"`
RiskLevel string `json:"riskLevel"`
Priority int `json:"priority"`
Status int `json:"status"`
Remark string `json:"remark"`
}
func (in *ImSensitiveWordEditInp) Filter(ctx context.Context) error {
in.Word = strings.TrimSpace(in.Word)
in.Replacement = strings.TrimSpace(in.Replacement)
in.Remark = strings.TrimSpace(in.Remark)
if in.Word == "" || len([]rune(in.Word)) > 255 {
return gerror.New("敏感词长度必须为1至255个字符")
}
if !dict.HasOptionKey(consts.ImSensitiveMatchTypeOptions, in.MatchType) {
return gerror.New("匹配类型不合法")
}
if !dict.HasOptionKey(consts.ImSensitiveActionOptions, in.Action) {
return gerror.New("命中动作不合法")
}
if !dict.HasOptionKey(consts.ImRiskLevelOptions, in.RiskLevel) {
return gerror.New("风险等级不合法")
}
if in.Status == 0 {
in.Status = consts.StatusEnabled
}
if in.Status != consts.StatusEnabled && in.Status != consts.StatusDisable {
return gerror.New("状态不合法")
}
if in.SceneJson == nil || in.SceneJson.String() == "" || in.SceneJson.String() == "null" {
return gerror.New("生效场景不能为空")
}
if in.Action == consts.ImSensitiveActionReplace && in.Replacement == "" {
return gerror.New("替换动作必须填写替换文本")
}
return nil
}
type ImSensitiveWordDeleteInp struct {
Id int64 `json:"id" v:"required|min:1#敏感词ID不能为空|敏感词ID不合法"`
}
func (in *ImSensitiveWordDeleteInp) Filter(ctx context.Context) error { return nil }
type ImSensitiveWordStatusInp struct {
Id int64 `json:"id" v:"required|min:1#敏感词ID不能为空|敏感词ID不合法"`
Status int `json:"status" v:"required#状态不能为空"`
}
func (in *ImSensitiveWordStatusInp) Filter(ctx context.Context) error {
if in.Status != consts.StatusEnabled && in.Status != consts.StatusDisable {
return gerror.New("状态不合法")
}
return nil
}
type ImSensitiveWordBatchImportInp struct {
TenantId int64 `json:"tenantId"`
GroupId int64 `json:"groupId" v:"required|min:1#敏感词分组不能为空|敏感词分组不合法"`
Words []string `json:"words" v:"required#敏感词列表不能为空"`
MatchType string `json:"matchType"`
SceneJson *gjson.Json `json:"sceneJson"`
Action string `json:"action"`
Replacement string `json:"replacement"`
RiskLevel string `json:"riskLevel"`
}
func (in *ImSensitiveWordBatchImportInp) Filter(ctx context.Context) error {
if len(in.Words) == 0 || len(in.Words) > 5000 {
return gerror.New("每次导入1至5000个敏感词")
}
base := ImSensitiveWordEditInp{GroupId: in.GroupId, Word: "validate", MatchType: in.MatchType, SceneJson: in.SceneJson, Action: in.Action, Replacement: in.Replacement, RiskLevel: in.RiskLevel, Status: consts.StatusEnabled}
return base.Filter(ctx)
}
type ImSensitiveWordBatchImportModel struct {
Inserted int `json:"inserted"`
Skipped int `json:"skipped"`
}
type ImSensitiveWordGroupListInp struct {
TenantId int64 `json:"tenantId"`
}
func (in *ImSensitiveWordGroupListInp) Filter(ctx context.Context) error { return nil }
type ImSensitiveWordGroupModel struct {
Id int64 `json:"id"`
TenantId int64 `json:"tenantId"`
GroupCode string `json:"groupCode"`
GroupName string `json:"groupName"`
Priority int `json:"priority"`
Status int `json:"status"`
Remark string `json:"remark"`
CreatedAt *gtime.Time `json:"createdAt"`
}
type ImSensitiveWordGroupEditInp struct {
Id int64 `json:"id"`
TenantId int64 `json:"tenantId"`
GroupCode string `json:"groupCode" v:"required#分组编码不能为空"`
GroupName string `json:"groupName" v:"required#分组名称不能为空"`
Priority int `json:"priority"`
Status int `json:"status"`
Remark string `json:"remark"`
}
func (in *ImSensitiveWordGroupEditInp) Filter(ctx context.Context) error {
in.GroupCode = strings.TrimSpace(in.GroupCode)
in.GroupName = strings.TrimSpace(in.GroupName)
in.Remark = strings.TrimSpace(in.Remark)
if !imPolicyGroupCodePattern.MatchString(in.GroupCode) {
return gerror.New("分组编码格式不合法")
}
if in.GroupName == "" || len([]rune(in.GroupName)) > 128 {
return gerror.New("分组名称长度必须为1至128个字符")
}
if in.Status == 0 {
in.Status = consts.StatusEnabled
}
if in.Status != consts.StatusEnabled && in.Status != consts.StatusDisable {
return gerror.New("状态不合法")
}
return nil
}
@@ -0,0 +1,157 @@
package sysin
import (
"context"
"regexp"
"strings"
"hotgo/internal/consts"
"hotgo/internal/model/input/form"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/os/gtime"
)
var imPolicyGroupCodePattern = regexp.MustCompile(`^[A-Za-z][A-Za-z0-9_-]{1,63}$`)
type ImUserPolicyGroupListInp struct {
form.PageReq
TenantId int64 `json:"tenantId" dc:"租户ID,0为全局默认"`
Keyword string `json:"keyword" dc:"编码或名称"`
Status int `json:"status" dc:"状态"`
}
func (in *ImUserPolicyGroupListInp) Filter(ctx context.Context) error {
in.Keyword = strings.TrimSpace(in.Keyword)
if in.Status != 0 && in.Status != consts.StatusEnabled && in.Status != consts.StatusDisable {
return gerror.New("状态不合法")
}
return nil
}
type ImUserPolicyGroupListModel struct {
Id int64 `json:"id"`
TenantId int64 `json:"tenantId"`
GroupCode string `json:"groupCode"`
GroupName string `json:"groupName"`
Priority int `json:"priority"`
Status int `json:"status"`
PolicyJson string `json:"policyJson"`
IpWhitelist string `json:"ipWhitelist"`
IpBlacklist string `json:"ipBlacklist"`
Version uint `json:"version"`
Remark string `json:"remark"`
MemberCount int `json:"memberCount"`
CreatedAt *gtime.Time `json:"createdAt"`
UpdatedAt *gtime.Time `json:"updatedAt"`
}
type ImUserPolicyGroupViewInp struct {
Id int64 `json:"id" v:"required|min:1#策略分组ID不能为空|策略分组ID不合法"`
}
func (in *ImUserPolicyGroupViewInp) Filter(ctx context.Context) error { return nil }
type ImUserPolicyGroupViewModel struct{ ImUserPolicyGroupListModel }
type ImUserPolicyGroupEditInp struct {
Id int64 `json:"id"`
TenantId int64 `json:"tenantId" dc:"租户ID,0为全局默认"`
GroupCode string `json:"groupCode" v:"required#分组编码不能为空"`
GroupName string `json:"groupName" v:"required#分组名称不能为空"`
Priority int `json:"priority"`
Status int `json:"status"`
PolicyJson *gjson.Json `json:"policyJson" v:"required#策略配置不能为空"`
IpWhitelist *gjson.Json `json:"ipWhitelist"`
IpBlacklist *gjson.Json `json:"ipBlacklist"`
Remark string `json:"remark"`
}
func (in *ImUserPolicyGroupEditInp) Filter(ctx context.Context) error {
in.GroupCode = strings.TrimSpace(in.GroupCode)
in.GroupName = strings.TrimSpace(in.GroupName)
in.Remark = strings.TrimSpace(in.Remark)
if !imPolicyGroupCodePattern.MatchString(in.GroupCode) {
return gerror.New("分组编码必须以字母开头,只能包含字母、数字、下划线和中划线")
}
if in.GroupName == "" || len([]rune(in.GroupName)) > 128 {
return gerror.New("分组名称长度必须为1至128个字符")
}
if in.Status == 0 {
in.Status = consts.StatusEnabled
}
if in.Status != consts.StatusEnabled && in.Status != consts.StatusDisable {
return gerror.New("状态不合法")
}
if in.PolicyJson == nil || in.PolicyJson.String() == "null" {
return gerror.New("策略配置不能为空")
}
return nil
}
type ImUserPolicyGroupDeleteInp struct {
Id int64 `json:"id" v:"required|min:1#策略分组ID不能为空|策略分组ID不合法"`
}
func (in *ImUserPolicyGroupDeleteInp) Filter(ctx context.Context) error { return nil }
type ImUserPolicyGroupStatusInp struct {
Id int64 `json:"id" v:"required|min:1#策略分组ID不能为空|策略分组ID不合法"`
Status int `json:"status" v:"required#状态不能为空"`
}
func (in *ImUserPolicyGroupStatusInp) Filter(ctx context.Context) error {
if in.Status != consts.StatusEnabled && in.Status != consts.StatusDisable {
return gerror.New("状态不合法")
}
return nil
}
type ImUserPolicyGroupMemberListInp struct {
form.PageReq
GroupId int64 `json:"groupId" v:"required|min:1#策略分组ID不能为空|策略分组ID不合法"`
UserId int64 `json:"userId"`
}
func (in *ImUserPolicyGroupMemberListInp) Filter(ctx context.Context) error { return nil }
type ImUserPolicyGroupMemberModel struct {
Id int64 `json:"id"`
GroupId int64 `json:"groupId"`
TenantId int64 `json:"tenantId"`
UserId int64 `json:"userId"`
Status int `json:"status"`
ValidFrom *gtime.Time `json:"validFrom"`
ValidUntil *gtime.Time `json:"validUntil"`
Remark string `json:"remark"`
CreatedAt *gtime.Time `json:"createdAt"`
}
type ImUserPolicyGroupMemberAddInp struct {
GroupId int64 `json:"groupId" v:"required|min:1#策略分组ID不能为空|策略分组ID不合法"`
UserId int64 `json:"userId" v:"required|min:1#用户ID不能为空|用户ID不合法"`
ValidFrom *gtime.Time `json:"validFrom"`
ValidUntil *gtime.Time `json:"validUntil"`
Remark string `json:"remark"`
}
func (in *ImUserPolicyGroupMemberAddInp) Filter(ctx context.Context) error {
in.Remark = strings.TrimSpace(in.Remark)
if in.GroupId <= 0 {
return gerror.New("策略分组ID不合法")
}
if in.UserId <= 0 {
return gerror.New("用户ID不合法")
}
if in.ValidFrom != nil && in.ValidUntil != nil && in.ValidUntil.Before(in.ValidFrom) {
return gerror.New("有效结束时间不能早于开始时间")
}
return nil
}
type ImUserPolicyGroupMemberRemoveInp struct {
Id int64 `json:"id" v:"required|min:1#成员关系ID不能为空|成员关系ID不合法"`
}
func (in *ImUserPolicyGroupMemberRemoveInp) Filter(ctx context.Context) error { return nil }