chore: seed migration objects batch 5
This commit is contained in:
@@ -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 //
|
||||
}
|
||||
@@ -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,96 @@
|
||||
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 ImAbuseReasonListInp struct {
|
||||
form.PageReq
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
TargetType string `json:"targetType" dc:"对象类型"`
|
||||
ReasonCode string `json:"reasonCode" dc:"原因编码"`
|
||||
Enabled *int `json:"enabled" dc:"启用状态"`
|
||||
}
|
||||
|
||||
func (in *ImAbuseReasonListInp) Filter(ctx context.Context) (err error) {
|
||||
in.TargetType = strings.TrimSpace(in.TargetType)
|
||||
in.ReasonCode = strings.TrimSpace(in.ReasonCode)
|
||||
if in.TargetType != "" && !dict.HasOptionKey(consts.ImAbuseTargetTypeOptions, in.TargetType) {
|
||||
return gerror.New("举报对象类型不合法")
|
||||
}
|
||||
if in.Enabled != nil && !dict.HasOptionKey(consts.ImAbuseReasonEnabledOptions, *in.Enabled) {
|
||||
return gerror.New("启用状态不合法")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImAbuseReasonModel struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
TargetType string `json:"targetType" dc:"对象类型"`
|
||||
ReasonCode string `json:"reasonCode" dc:"原因编码"`
|
||||
Label string `json:"label" dc:"展示文案"`
|
||||
RequiresDescription int `json:"requiresDescription" dc:"要求描述"`
|
||||
AllowsEvidence int `json:"allowsEvidence" dc:"允许证据"`
|
||||
SortOrder int `json:"sortOrder" dc:"排序"`
|
||||
Enabled int `json:"enabled" dc:"启用状态"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
}
|
||||
|
||||
type ImAbuseReasonEditInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
TargetType string `json:"targetType" v:"required#对象类型不能为空" dc:"对象类型"`
|
||||
ReasonCode string `json:"reasonCode" v:"required#原因编码不能为空" dc:"原因编码"`
|
||||
Label string `json:"label" v:"required#展示文案不能为空" dc:"展示文案"`
|
||||
RequiresDescription int `json:"requiresDescription" dc:"要求描述"`
|
||||
AllowsEvidence int `json:"allowsEvidence" dc:"允许证据"`
|
||||
SortOrder int `json:"sortOrder" dc:"排序"`
|
||||
Enabled int `json:"enabled" dc:"启用状态"`
|
||||
}
|
||||
|
||||
func (in *ImAbuseReasonEditInp) Filter(ctx context.Context) (err error) {
|
||||
in.TargetType = strings.TrimSpace(in.TargetType)
|
||||
in.ReasonCode = strings.TrimSpace(in.ReasonCode)
|
||||
in.Label = strings.TrimSpace(in.Label)
|
||||
if !dict.HasOptionKey(consts.ImAbuseTargetTypeOptions, in.TargetType) {
|
||||
return gerror.New("举报对象类型不合法")
|
||||
}
|
||||
if in.ReasonCode == "" || strings.ContainsAny(in.ReasonCode, " \t\r\n/") || len([]rune(in.ReasonCode)) > 64 {
|
||||
return gerror.New("原因编码不能为空,且不能包含空格或斜杠")
|
||||
}
|
||||
if in.Label == "" || len([]rune(in.Label)) > 128 {
|
||||
return gerror.New("展示文案不能为空且不能超过128个字符")
|
||||
}
|
||||
if !dict.HasOptionKey(consts.ImAbuseReasonEnabledOptions, in.RequiresDescription) {
|
||||
return gerror.New("要求描述开关不合法")
|
||||
}
|
||||
if !dict.HasOptionKey(consts.ImAbuseReasonEnabledOptions, in.AllowsEvidence) {
|
||||
return gerror.New("允许证据开关不合法")
|
||||
}
|
||||
if !dict.HasOptionKey(consts.ImAbuseReasonEnabledOptions, in.Enabled) {
|
||||
return gerror.New("启用状态不合法")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImAbuseReasonDeleteInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Id int64 `json:"id" v:"required|min:1#请选择要禁用的举报原因|请选择要禁用的举报原因" dc:"ID"`
|
||||
}
|
||||
|
||||
func (in *ImAbuseReasonDeleteInp) Filter(ctx context.Context) (err error) {
|
||||
if in.Id <= 0 {
|
||||
return gerror.New("请选择要禁用的举报原因")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
package sysin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/library/dict"
|
||||
"hotgo/internal/model/input/form"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
type ImAppReleaseListInp struct {
|
||||
form.PageReq
|
||||
Platform string `json:"platform" dc:"平台"`
|
||||
Channel string `json:"channel" dc:"渠道"`
|
||||
}
|
||||
|
||||
func (in *ImAppReleaseListInp) Filter(ctx context.Context) (err error) {
|
||||
in.Platform = strings.TrimSpace(in.Platform)
|
||||
in.Channel = strings.TrimSpace(in.Channel)
|
||||
if in.Platform != "" && !dict.HasOptionKey(consts.ImAppPlatformOptions, in.Platform) {
|
||||
return gerror.New("客户端平台不合法")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImAppReleaseModel struct {
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
Platform string `json:"platform" dc:"平台"`
|
||||
Channel string `json:"channel" dc:"渠道"`
|
||||
LatestVersion string `json:"latestVersion" dc:"最新版本"`
|
||||
MinSupportedVersion string `json:"minSupportedVersion" dc:"最低支持版本"`
|
||||
UpdateType string `json:"updateType" dc:"更新类型"`
|
||||
ReleaseNotes string `json:"releaseNotes" dc:"更新说明"`
|
||||
StoreUrl string `json:"storeUrl" dc:"商店地址"`
|
||||
PackageUrl string `json:"packageUrl" dc:"安装包地址"`
|
||||
Checksum string `json:"checksum" dc:"校验值"`
|
||||
RemindAfterSeconds int `json:"remindAfterSeconds" dc:"再次提醒秒数"`
|
||||
PublishedAt *gtime.Time `json:"publishedAt" dc:"发布时间"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
}
|
||||
|
||||
type ImAppReleaseEditInp struct {
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
Platform string `json:"platform" v:"required#平台不能为空" dc:"平台"`
|
||||
Channel string `json:"channel" v:"required#渠道不能为空" dc:"渠道"`
|
||||
LatestVersion string `json:"latestVersion" v:"required#最新版本不能为空" dc:"最新版本"`
|
||||
MinSupportedVersion string `json:"minSupportedVersion" v:"required#最低支持版本不能为空" dc:"最低支持版本"`
|
||||
UpdateType string `json:"updateType" v:"required#更新类型不能为空" dc:"更新类型"`
|
||||
ReleaseNotes string `json:"releaseNotes" dc:"更新说明"`
|
||||
StoreUrl string `json:"storeUrl" dc:"商店地址"`
|
||||
PackageUrl string `json:"packageUrl" dc:"安装包地址"`
|
||||
Checksum string `json:"checksum" dc:"校验值"`
|
||||
RemindAfterSeconds int `json:"remindAfterSeconds" dc:"再次提醒秒数"`
|
||||
}
|
||||
|
||||
func (in *ImAppReleaseEditInp) Filter(ctx context.Context) (err error) {
|
||||
in.Platform = strings.TrimSpace(in.Platform)
|
||||
in.Channel = strings.TrimSpace(in.Channel)
|
||||
in.LatestVersion = strings.TrimSpace(in.LatestVersion)
|
||||
in.MinSupportedVersion = strings.TrimSpace(in.MinSupportedVersion)
|
||||
in.UpdateType = strings.TrimSpace(in.UpdateType)
|
||||
in.StoreUrl = strings.TrimSpace(in.StoreUrl)
|
||||
in.PackageUrl = strings.TrimSpace(in.PackageUrl)
|
||||
in.Checksum = strings.TrimSpace(in.Checksum)
|
||||
if !dict.HasOptionKey(consts.ImAppPlatformOptions, in.Platform) {
|
||||
return gerror.New("客户端平台不合法")
|
||||
}
|
||||
if in.Channel == "" || strings.ContainsAny(in.Channel, " \t\r\n/") || len([]rune(in.Channel)) > 32 {
|
||||
return gerror.New("渠道不能为空,且不能包含空格或斜杠")
|
||||
}
|
||||
if in.LatestVersion == "" || len([]rune(in.LatestVersion)) > 64 {
|
||||
return gerror.New("最新版本不能为空且不能超过64个字符")
|
||||
}
|
||||
if in.MinSupportedVersion == "" || len([]rune(in.MinSupportedVersion)) > 64 {
|
||||
return gerror.New("最低支持版本不能为空且不能超过64个字符")
|
||||
}
|
||||
latest, err := parseAppVersion(in.LatestVersion)
|
||||
if err != nil {
|
||||
return gerror.New("最新版本号格式不正确,请使用数字点分版本号")
|
||||
}
|
||||
minimum, err := parseAppVersion(in.MinSupportedVersion)
|
||||
if err != nil {
|
||||
return gerror.New("最低支持版本号格式不正确,请使用数字点分版本号")
|
||||
}
|
||||
if compareAppVersion(latest, minimum) < 0 {
|
||||
return gerror.New("最新版本不能低于最低支持版本")
|
||||
}
|
||||
if !dict.HasOptionKey(consts.ImAppUpdateTypeOptions, in.UpdateType) {
|
||||
return gerror.New("更新类型不合法")
|
||||
}
|
||||
if in.RemindAfterSeconds < 0 {
|
||||
return gerror.New("再次提醒时间不能小于0")
|
||||
}
|
||||
if in.Platform == consts.ImAppPlatformIos && in.UpdateType != consts.ImAppUpdateTypeNone {
|
||||
storeURL, parseErr := url.Parse(in.StoreUrl)
|
||||
if parseErr != nil || storeURL.Scheme != "https" || !strings.EqualFold(storeURL.Hostname(), "apps.apple.com") {
|
||||
return gerror.New("iOS更新策略需要配置 apps.apple.com 的 HTTPS 商店地址")
|
||||
}
|
||||
in.PackageUrl = ""
|
||||
in.Checksum = ""
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseAppVersion(raw string) ([]uint64, error) {
|
||||
raw = strings.TrimPrefix(strings.ToLower(strings.TrimSpace(raw)), "v")
|
||||
parts := strings.Split(raw, ".")
|
||||
if len(parts) == 0 || len(parts) > 8 {
|
||||
return nil, gerror.New("版本号格式不正确")
|
||||
}
|
||||
result := make([]uint64, len(parts))
|
||||
for i, part := range parts {
|
||||
if part == "" {
|
||||
return nil, gerror.New("版本号格式不正确")
|
||||
}
|
||||
value, err := strconv.ParseUint(part, 10, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[i] = value
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func compareAppVersion(left, right []uint64) int {
|
||||
length := len(left)
|
||||
if len(right) > length {
|
||||
length = len(right)
|
||||
}
|
||||
for i := 0; i < length; i++ {
|
||||
var l, r uint64
|
||||
if i < len(left) {
|
||||
l = left[i]
|
||||
}
|
||||
if i < len(right) {
|
||||
r = right[i]
|
||||
}
|
||||
if l < r {
|
||||
return -1
|
||||
}
|
||||
if l > r {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package sysin
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestImAppReleaseEditFilter(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input ImAppReleaseEditInp
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "valid ios release",
|
||||
input: ImAppReleaseEditInp{Platform: "ios", Channel: "stable", LatestVersion: "1.10.0", MinSupportedVersion: "1.9.9", UpdateType: "recommended", StoreUrl: "https://apps.apple.com/app/id123"},
|
||||
},
|
||||
{
|
||||
name: "minimum newer than latest",
|
||||
input: ImAppReleaseEditInp{Platform: "android", Channel: "stable", LatestVersion: "1.2.0", MinSupportedVersion: "2.0.0", UpdateType: "force"},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid version",
|
||||
input: ImAppReleaseEditInp{Platform: "android", Channel: "stable", LatestVersion: "1.2-beta", MinSupportedVersion: "1.0.0", UpdateType: "recommended"},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "ios store url required",
|
||||
input: ImAppReleaseEditInp{Platform: "ios", Channel: "stable", LatestVersion: "2.0.0", MinSupportedVersion: "1.0.0", UpdateType: "force", StoreUrl: "https://example.com/app"},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := tt.input.Filter(nil)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Fatalf("Filter() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -29,9 +29,6 @@ type ImAuditLogListInp struct {
|
||||
}
|
||||
|
||||
func (in *ImAuditLogListInp) Filter(ctx context.Context) (err error) {
|
||||
if in.TenantId <= 0 {
|
||||
return gerror.New("请选择租户")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -61,9 +58,6 @@ type ImAuditLogViewInp struct {
|
||||
}
|
||||
|
||||
func (in *ImAuditLogViewInp) Filter(ctx context.Context) (err error) {
|
||||
if in.TenantId <= 0 {
|
||||
return gerror.New("请选择租户")
|
||||
}
|
||||
if in.Id <= 0 {
|
||||
return gerror.New("ID不能为空")
|
||||
}
|
||||
@@ -73,3 +67,18 @@ func (in *ImAuditLogViewInp) Filter(ctx context.Context) (err error) {
|
||||
type ImAuditLogViewModel struct {
|
||||
ImAuditLogListModel
|
||||
}
|
||||
|
||||
type ImAuditLogExportModel struct {
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
ActorUid int64 `json:"actorUid" dc:"操作人UID"`
|
||||
ActorRole string `json:"actorRole" dc:"操作角色"`
|
||||
Action string `json:"action" dc:"操作类型"`
|
||||
TargetType string `json:"targetType" dc:"目标类型"`
|
||||
TargetId string `json:"targetId" dc:"目标ID"`
|
||||
Reason string `json:"reason" dc:"操作原因"`
|
||||
RequestId string `json:"requestId" dc:"请求ID"`
|
||||
Ip string `json:"ip" dc:"IP"`
|
||||
UserAgent string `json:"userAgent" dc:"客户端"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
}
|
||||
|
||||
@@ -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,85 @@
|
||||
package sysin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"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 ImExternalConfigListInp struct {
|
||||
form.PageReq
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Service string `json:"service" dc:"服务"`
|
||||
Provider string `json:"provider" dc:"服务商"`
|
||||
Enabled *int `json:"enabled" dc:"是否启用"`
|
||||
}
|
||||
|
||||
func (in *ImExternalConfigListInp) Filter(ctx context.Context) (err error) { return }
|
||||
|
||||
type ImExternalConfigListModel struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
Service string `json:"service" dc:"服务"`
|
||||
Provider string `json:"provider" dc:"服务商"`
|
||||
Endpoint string `json:"endpoint" dc:"端点"`
|
||||
Enabled int `json:"enabled" dc:"是否启用"`
|
||||
Status string `json:"status" dc:"配置状态"`
|
||||
ConfigJson string `json:"configJson" dc:"普通配置"`
|
||||
HasSecret bool `json:"hasSecret" dc:"是否有敏感配置"`
|
||||
CheckedAt *gtime.Time `json:"checkedAt" dc:"检查时间"`
|
||||
CheckResult string `json:"checkResult" dc:"检查结果"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
}
|
||||
|
||||
type ImExternalConfigViewInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Service string `json:"service" v:"required#服务不能为空" dc:"服务"`
|
||||
}
|
||||
|
||||
func (in *ImExternalConfigViewInp) Filter(ctx context.Context) (err error) {
|
||||
if in.Service == "" {
|
||||
return gerror.New("服务不能为空")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImExternalConfigViewModel struct {
|
||||
ImExternalConfigListModel
|
||||
}
|
||||
|
||||
type ImExternalConfigUpdateInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Service string `json:"service" v:"required#服务不能为空" dc:"服务"`
|
||||
Provider string `json:"provider" dc:"服务商"`
|
||||
Endpoint string `json:"endpoint" dc:"端点"`
|
||||
Enabled int `json:"enabled" dc:"是否启用"`
|
||||
ConfigJson *gjson.Json `json:"configJson" dc:"普通配置"`
|
||||
SecretJson *gjson.Json `json:"secretJson" dc:"敏感配置,空则保持原值"`
|
||||
}
|
||||
|
||||
func (in *ImExternalConfigUpdateInp) Filter(ctx context.Context) (err error) {
|
||||
if in.Service == "" {
|
||||
return gerror.New("服务不能为空")
|
||||
}
|
||||
if in.Enabled != 0 && in.Enabled != 1 {
|
||||
return gerror.New("启用状态不正确")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImExternalConfigCheckInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Service string `json:"service" v:"required#服务不能为空" dc:"服务"`
|
||||
}
|
||||
|
||||
func (in *ImExternalConfigCheckInp) Filter(ctx context.Context) (err error) {
|
||||
if in.Service == "" {
|
||||
return gerror.New("服务不能为空")
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package sysin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/library/dict"
|
||||
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
type ImFeedbackConfigGetInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
}
|
||||
|
||||
func (in *ImFeedbackConfigGetInp) Filter(ctx context.Context) (err error) { return }
|
||||
|
||||
type ImFeedbackConfigModel struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
Categories string `json:"categories" dc:"分类JSON"`
|
||||
MaxLength int `json:"maxLength" dc:"最大字数"`
|
||||
AttachmentPolicy string `json:"attachmentPolicy" dc:"附件策略JSON"`
|
||||
AllowContact int `json:"allowContact" dc:"允许联系方式"`
|
||||
DiagnosticsNotice string `json:"diagnosticsNotice" dc:"诊断信息提示"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
}
|
||||
|
||||
type ImFeedbackConfigUpdateInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Categories *gjson.Json `json:"categories" dc:"分类JSON"`
|
||||
MaxLength int `json:"maxLength" dc:"最大字数"`
|
||||
AttachmentPolicy *gjson.Json `json:"attachmentPolicy" dc:"附件策略JSON"`
|
||||
AllowContact int `json:"allowContact" dc:"允许联系方式"`
|
||||
DiagnosticsNotice string `json:"diagnosticsNotice" v:"required#诊断提示不能为空" dc:"诊断信息提示"`
|
||||
}
|
||||
|
||||
func (in *ImFeedbackConfigUpdateInp) Filter(ctx context.Context) (err error) {
|
||||
if in.MaxLength <= 0 {
|
||||
return gerror.New("最大字数必须大于0")
|
||||
}
|
||||
if !dict.HasOptionKey(consts.ImFilePolicySwitchOptions, in.AllowContact) {
|
||||
return gerror.New("联系方式开关不合法")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
// Package sysin
|
||||
// @Link https://github.com/bufanyun/hotgo
|
||||
// @Copyright Copyright (c) 2026 HotGo
|
||||
// @Author Ms <133814250@qq.com>
|
||||
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
|
||||
package sysin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"hotgo/internal/model/input/form"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
type ImFileListInp struct {
|
||||
form.PageReq
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
FileId int64 `json:"fileId" dc:"文件ID"`
|
||||
UserId int64 `json:"userId" dc:"上传用户ID"`
|
||||
Status *int `json:"status" dc:"状态"`
|
||||
Purpose string `json:"purpose" dc:"用途"`
|
||||
MimeType string `json:"mimeType" dc:"MIME类型"`
|
||||
Topic string `json:"topic" dc:"关联Topic"`
|
||||
CreatedAt []*gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt []*gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
}
|
||||
|
||||
func (in *ImFileListInp) Filter(ctx context.Context) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
type ImFileListModel struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
Id int64 `json:"id" dc:"文件ID"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
UserId int64 `json:"userId" dc:"上传用户ID"`
|
||||
Status int `json:"status" dc:"状态"`
|
||||
MimeType string `json:"mimeType" dc:"MIME类型"`
|
||||
Size int64 `json:"size" dc:"大小"`
|
||||
Etag string `json:"etag" dc:"ETag"`
|
||||
Location string `json:"location" dc:"文件位置"`
|
||||
Purpose string `json:"purpose" dc:"用途"`
|
||||
LinkCount int `json:"linkCount" dc:"引用数"`
|
||||
FirstTopic string `json:"firstTopic" dc:"首个关联Topic"`
|
||||
FirstMsgId int64 `json:"firstMsgId" dc:"首个关联消息ID"`
|
||||
FirstLinkAt *gtime.Time `json:"firstLinkAt" dc:"首个关联时间"`
|
||||
}
|
||||
|
||||
type ImFileViewInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Id int64 `json:"id" v:"required#文件ID不能为空" dc:"文件ID"`
|
||||
}
|
||||
|
||||
func (in *ImFileViewInp) Filter(ctx context.Context) (err error) {
|
||||
if in.Id <= 0 {
|
||||
return gerror.New("文件ID不能为空")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImFileViewModel struct {
|
||||
ImFileListModel
|
||||
Links []*ImFileLinkModel `json:"links" dc:"引用列表"`
|
||||
}
|
||||
|
||||
type ImFileLinkModel struct {
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
FileId int64 `json:"fileId" dc:"文件ID"`
|
||||
MsgId int64 `json:"msgId" dc:"消息ID"`
|
||||
Topic string `json:"topic" dc:"Topic"`
|
||||
UserId int64 `json:"userId" dc:"用户ID"`
|
||||
}
|
||||
|
||||
type ImFileActionInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Id int64 `json:"id" v:"required#文件ID不能为空" dc:"文件ID"`
|
||||
Reason string `json:"reason" dc:"原因"`
|
||||
}
|
||||
|
||||
func (in *ImFileActionInp) Filter(ctx context.Context) (err error) {
|
||||
if in.Id <= 0 {
|
||||
return gerror.New("文件ID不能为空")
|
||||
}
|
||||
if len([]rune(in.Reason)) > 200 {
|
||||
return gerror.New("原因不能超过200个字符")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImFileCleanupOrphanInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Days int `json:"days" dc:"保留天数"`
|
||||
Limit int `json:"limit" dc:"处理上限"`
|
||||
}
|
||||
|
||||
func (in *ImFileCleanupOrphanInp) Filter(ctx context.Context) (err error) {
|
||||
if in.Days <= 0 {
|
||||
in.Days = 7
|
||||
}
|
||||
if in.Limit <= 0 {
|
||||
in.Limit = 100
|
||||
}
|
||||
if in.Limit > 1000 {
|
||||
return gerror.New("单次清理上限不能超过1000")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImFileCleanupOrphanModel struct {
|
||||
Count int `json:"count" dc:"标记数量"`
|
||||
Locations []string `json:"locations" dc:"待物理清理位置"`
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package sysin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/library/dict"
|
||||
"hotgo/internal/model/input/form"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
type ImFilePolicyListInp struct {
|
||||
form.PageReq
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Purpose string `json:"purpose" dc:"用途"`
|
||||
AutoCleanup *int `json:"autoCleanup" dc:"自动清理"`
|
||||
ScanEnabled *int `json:"scanEnabled" dc:"病毒扫描"`
|
||||
}
|
||||
|
||||
func (in *ImFilePolicyListInp) Filter(ctx context.Context) (err error) { return }
|
||||
|
||||
type ImFilePolicyListModel struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
Purpose string `json:"purpose" dc:"用途"`
|
||||
MaxSize int64 `json:"maxSize" dc:"单文件大小上限"`
|
||||
RetentionDays int `json:"retentionDays" dc:"保留天数"`
|
||||
AllowedMimes string `json:"allowedMimes" dc:"允许MIME JSON"`
|
||||
AutoCleanup int `json:"autoCleanup" dc:"自动清理"`
|
||||
ScanEnabled int `json:"scanEnabled" dc:"病毒扫描"`
|
||||
Remark string `json:"remark" dc:"备注"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
}
|
||||
|
||||
type ImFilePolicyUpdateInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Purpose string `json:"purpose" v:"required#用途不能为空" dc:"用途"`
|
||||
MaxSize int64 `json:"maxSize" dc:"单文件大小上限"`
|
||||
RetentionDays int `json:"retentionDays" dc:"保留天数"`
|
||||
AllowedMimes *gjson.Json `json:"allowedMimes" dc:"允许MIME JSON"`
|
||||
AutoCleanup int `json:"autoCleanup" dc:"自动清理"`
|
||||
ScanEnabled int `json:"scanEnabled" dc:"病毒扫描"`
|
||||
Remark string `json:"remark" dc:"备注"`
|
||||
}
|
||||
|
||||
func (in *ImFilePolicyUpdateInp) Filter(ctx context.Context) (err error) {
|
||||
in.Purpose = strings.TrimSpace(in.Purpose)
|
||||
in.Remark = strings.TrimSpace(in.Remark)
|
||||
if !dict.HasOptionKey(consts.ImFilePurposeOptions, in.Purpose) {
|
||||
return gerror.New("文件用途不合法")
|
||||
}
|
||||
if in.Purpose == consts.ImFilePurposeUnknown || in.Purpose == consts.ImFilePurposeOrphan {
|
||||
return gerror.New("该文件用途不允许配置策略")
|
||||
}
|
||||
if in.MaxSize <= 0 {
|
||||
return gerror.New("单文件大小上限必须大于0")
|
||||
}
|
||||
if in.RetentionDays < 0 {
|
||||
return gerror.New("保留天数不能小于0")
|
||||
}
|
||||
if !dict.HasOptionKey(consts.ImFilePolicySwitchOptions, in.AutoCleanup) {
|
||||
return gerror.New("自动清理开关不合法")
|
||||
}
|
||||
if !dict.HasOptionKey(consts.ImFilePolicySwitchOptions, in.ScanEnabled) {
|
||||
return gerror.New("病毒扫描开关不合法")
|
||||
}
|
||||
if len([]rune(in.Remark)) > 200 {
|
||||
return gerror.New("备注不能超过200个字符")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -26,28 +26,27 @@ type ImGroupListInp struct {
|
||||
}
|
||||
|
||||
func (in *ImGroupListInp) Filter(ctx context.Context) (err error) {
|
||||
if in.TenantId <= 0 {
|
||||
return gerror.New("请选择租户")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImGroupListModel struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
Topic string `json:"topic" dc:"Topic"`
|
||||
State int `json:"state" dc:"状态"`
|
||||
OwnerId int64 `json:"ownerId" dc:"群主ID"`
|
||||
SeqId int `json:"seqId" dc:"最新消息序号"`
|
||||
DelId int `json:"delId" dc:"删除序号"`
|
||||
SubCnt int `json:"subCnt" dc:"成员数"`
|
||||
TouchedAt *gtime.Time `json:"touchedAt" dc:"活跃时间"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"修改时间"`
|
||||
PublicJson string `json:"publicJson" dc:"公开资料"`
|
||||
TrustedJson string `json:"trustedJson" dc:"可信资料"`
|
||||
TagsJson string `json:"tagsJson" dc:"标签"`
|
||||
AuxJson string `json:"auxJson" dc:"辅助资料"`
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
Topic string `json:"topic" dc:"Topic"`
|
||||
State int `json:"state" dc:"状态"`
|
||||
OwnerId int64 `json:"ownerId,string" dc:"群主ID"`
|
||||
OwnerNickname string `json:"ownerNickname" dc:"群主昵称"`
|
||||
OwnerUsername string `json:"ownerUsername" dc:"群主用户名"`
|
||||
SeqId int `json:"seqId" dc:"最新消息序号"`
|
||||
DelId int `json:"delId" dc:"删除序号"`
|
||||
SubCnt int `json:"subCnt" dc:"成员数"`
|
||||
TouchedAt *gtime.Time `json:"touchedAt" dc:"活跃时间"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"修改时间"`
|
||||
PublicJson string `json:"publicJson" dc:"公开资料"`
|
||||
TrustedJson string `json:"trustedJson" dc:"可信资料"`
|
||||
TagsJson string `json:"tagsJson" dc:"标签"`
|
||||
AuxJson string `json:"auxJson" dc:"辅助资料"`
|
||||
|
||||
GroupName string `json:"groupName" dc:"群名称"`
|
||||
AvatarFileId string `json:"avatarFileId" dc:"头像文件ID"`
|
||||
@@ -72,9 +71,6 @@ type ImGroupViewInp struct {
|
||||
}
|
||||
|
||||
func (in *ImGroupViewInp) Filter(ctx context.Context) (err error) {
|
||||
if in.TenantId <= 0 {
|
||||
return gerror.New("请选择租户")
|
||||
}
|
||||
if in.Topic == "" {
|
||||
return gerror.New("Topic不能为空")
|
||||
}
|
||||
@@ -98,9 +94,6 @@ type ImGroupMemberListInp struct {
|
||||
}
|
||||
|
||||
func (in *ImGroupMemberListInp) Filter(ctx context.Context) (err error) {
|
||||
if in.TenantId <= 0 {
|
||||
return gerror.New("请选择租户")
|
||||
}
|
||||
if in.Topic == "" {
|
||||
return gerror.New("Topic不能为空")
|
||||
}
|
||||
@@ -108,7 +101,7 @@ func (in *ImGroupMemberListInp) Filter(ctx context.Context) (err error) {
|
||||
}
|
||||
|
||||
type ImGroupMemberListModel struct {
|
||||
UserId int64 `json:"userId" dc:"用户ID"`
|
||||
UserId int64 `json:"userId,string" dc:"用户ID"`
|
||||
Nickname string `json:"nickname" dc:"昵称"`
|
||||
State int `json:"state" dc:"用户状态"`
|
||||
ModeWant string `json:"modeWant" dc:"期望权限"`
|
||||
@@ -126,10 +119,10 @@ type ImGroupMemberListModel struct {
|
||||
Pinned int `json:"pinned" dc:"置顶"`
|
||||
MuteNotifications int `json:"muteNotifications" dc:"免打扰"`
|
||||
JoinSource string `json:"joinSource" dc:"加入来源"`
|
||||
JoinedBy int64 `json:"joinedBy" dc:"邀请/处理人"`
|
||||
JoinedBy int64 `json:"joinedBy,string" dc:"邀请/处理人"`
|
||||
JoinedAt *gtime.Time `json:"joinedAt" dc:"业务加入时间"`
|
||||
LeftAt *gtime.Time `json:"leftAt" dc:"离开时间"`
|
||||
RemovedBy int64 `json:"removedBy" dc:"移除人"`
|
||||
RemovedBy int64 `json:"removedBy,string" dc:"移除人"`
|
||||
Version int `json:"version" dc:"版本"`
|
||||
}
|
||||
|
||||
@@ -140,9 +133,6 @@ type ImGroupTopicInp struct {
|
||||
}
|
||||
|
||||
func (in *ImGroupTopicInp) Filter(ctx context.Context) (err error) {
|
||||
if in.TenantId <= 0 {
|
||||
return gerror.New("请选择租户")
|
||||
}
|
||||
if in.Topic == "" {
|
||||
return gerror.New("Topic不能为空")
|
||||
}
|
||||
@@ -153,7 +143,7 @@ type ImGroupGovernanceModel struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
Topic string `json:"topic" dc:"Topic"`
|
||||
OwnerUserId int64 `json:"ownerUserId" dc:"群主ID"`
|
||||
OwnerUserId int64 `json:"ownerUserId,string" dc:"群主ID"`
|
||||
Name string `json:"name" dc:"群名称"`
|
||||
AvatarFileId string `json:"avatarFileId" dc:"头像文件ID"`
|
||||
Description string `json:"description" dc:"简介"`
|
||||
@@ -167,13 +157,176 @@ type ImGroupGovernanceModel struct {
|
||||
MaxAdminCount int `json:"maxAdminCount" dc:"最大管理员数"`
|
||||
MemberCount int `json:"memberCount" dc:"成员数"`
|
||||
Version int `json:"version" dc:"版本"`
|
||||
CreatedBy int64 `json:"createdBy" dc:"创建人"`
|
||||
DissolvedBy int64 `json:"dissolvedBy" dc:"解散人"`
|
||||
CreatedBy int64 `json:"createdBy,string" dc:"创建人"`
|
||||
DissolvedBy int64 `json:"dissolvedBy,string" dc:"解散人"`
|
||||
DissolvedAt *gtime.Time `json:"dissolvedAt" dc:"解散时间"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"修改时间"`
|
||||
}
|
||||
|
||||
type ImGroupGovernanceUpdateInp struct {
|
||||
ImGroupTopicInp
|
||||
JoinApproval int `json:"joinApproval" dc:"入群审批"`
|
||||
MuteAll int `json:"muteAll" dc:"全员禁言"`
|
||||
MemberUploadFiles int `json:"memberUploadFiles" dc:"成员上传文件"`
|
||||
MemberPrivateChat int `json:"memberPrivateChat" dc:"成员私聊"`
|
||||
MemberInvite int `json:"memberInvite" dc:"成员邀请"`
|
||||
MaxMemberCount int `json:"maxMemberCount" dc:"最大成员数"`
|
||||
MaxAdminCount int `json:"maxAdminCount" dc:"最大管理员数"`
|
||||
}
|
||||
|
||||
func (in *ImGroupGovernanceUpdateInp) Filter(ctx context.Context) (err error) {
|
||||
if err = in.ImGroupTopicInp.Filter(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if in.JoinApproval != 0 && in.JoinApproval != 1 {
|
||||
return gerror.New("入群审批值不正确")
|
||||
}
|
||||
if in.MuteAll != 0 && in.MuteAll != 1 {
|
||||
return gerror.New("全员禁言值不正确")
|
||||
}
|
||||
if in.MemberUploadFiles != 0 && in.MemberUploadFiles != 1 {
|
||||
return gerror.New("成员上传文件值不正确")
|
||||
}
|
||||
if in.MemberPrivateChat != 0 && in.MemberPrivateChat != 1 {
|
||||
return gerror.New("成员私聊值不正确")
|
||||
}
|
||||
if in.MemberInvite != 0 && in.MemberInvite != 1 {
|
||||
return gerror.New("成员邀请值不正确")
|
||||
}
|
||||
if in.MaxMemberCount < 0 || in.MaxAdminCount < 0 {
|
||||
return gerror.New("人数上限不能小于0")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImGroupProfileUpdateInp struct {
|
||||
ImGroupTopicInp
|
||||
Name string `json:"name" dc:"群名称"`
|
||||
AvatarFileId string `json:"avatarFileId" dc:"头像文件ID"`
|
||||
Description string `json:"description" dc:"简介"`
|
||||
Version int64 `json:"version" dc:"版本"`
|
||||
}
|
||||
|
||||
func (in *ImGroupProfileUpdateInp) Filter(ctx context.Context) (err error) {
|
||||
if err = in.ImGroupTopicInp.Filter(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if in.Name == "" && in.AvatarFileId == "" && in.Description == "" {
|
||||
return gerror.New("请填写需要修改的群资料")
|
||||
}
|
||||
if len([]rune(in.Name)) > 80 {
|
||||
return gerror.New("群名称不能超过80个字符")
|
||||
}
|
||||
if len([]rune(in.Description)) > 500 {
|
||||
return gerror.New("群简介不能超过500个字符")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImGroupDissolveInp struct {
|
||||
ImGroupTopicInp
|
||||
Reason string `json:"reason" dc:"解散原因"`
|
||||
}
|
||||
|
||||
func (in *ImGroupDissolveInp) Filter(ctx context.Context) (err error) {
|
||||
if err = in.ImGroupTopicInp.Filter(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if len([]rune(in.Reason)) > 200 {
|
||||
return gerror.New("解散原因不能超过200个字符")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImGroupMuteInp struct {
|
||||
ImGroupTopicInp
|
||||
UserId int64 `json:"userId" v:"required#用户ID不能为空" dc:"用户ID"`
|
||||
ExpiresAt *gtime.Time `json:"expiresAt" dc:"过期时间"`
|
||||
Reason string `json:"reason" dc:"禁言原因"`
|
||||
}
|
||||
|
||||
func (in *ImGroupMuteInp) Filter(ctx context.Context) (err error) {
|
||||
if err = in.ImGroupTopicInp.Filter(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if in.UserId <= 0 {
|
||||
return gerror.New("用户ID不能为空")
|
||||
}
|
||||
if len([]rune(in.Reason)) > 200 {
|
||||
return gerror.New("禁言原因不能超过200个字符")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImGroupUnmuteInp struct {
|
||||
ImGroupTopicInp
|
||||
UserId int64 `json:"userId" v:"required#用户ID不能为空" dc:"用户ID"`
|
||||
}
|
||||
|
||||
func (in *ImGroupUnmuteInp) Filter(ctx context.Context) (err error) {
|
||||
if err = in.ImGroupTopicInp.Filter(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if in.UserId <= 0 {
|
||||
return gerror.New("用户ID不能为空")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImGroupJoinRequestResolveInp struct {
|
||||
ImGroupTopicInp
|
||||
RequestId string `json:"requestId" v:"required#申请ID不能为空" dc:"申请ID"`
|
||||
RejectReason string `json:"rejectReason" dc:"拒绝原因"`
|
||||
}
|
||||
|
||||
func (in *ImGroupJoinRequestResolveInp) Filter(ctx context.Context) (err error) {
|
||||
if err = in.ImGroupTopicInp.Filter(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if in.RequestId == "" {
|
||||
return gerror.New("申请ID不能为空")
|
||||
}
|
||||
if len([]rune(in.RejectReason)) > 200 {
|
||||
return gerror.New("拒绝原因不能超过200个字符")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImGroupRoleUpdateInp struct {
|
||||
ImGroupTopicInp
|
||||
UserId int64 `json:"userId" v:"required#用户ID不能为空" dc:"用户ID"`
|
||||
Role string `json:"role" v:"required#角色不能为空" dc:"角色"`
|
||||
}
|
||||
|
||||
func (in *ImGroupRoleUpdateInp) Filter(ctx context.Context) (err error) {
|
||||
if err = in.ImGroupTopicInp.Filter(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if in.UserId <= 0 {
|
||||
return gerror.New("用户ID不能为空")
|
||||
}
|
||||
if in.Role == "" {
|
||||
return gerror.New("角色不能为空")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImGroupOwnerTransferInp struct {
|
||||
ImGroupTopicInp
|
||||
UserId int64 `json:"userId" v:"required#新群主ID不能为空" dc:"新群主ID"`
|
||||
}
|
||||
|
||||
func (in *ImGroupOwnerTransferInp) Filter(ctx context.Context) (err error) {
|
||||
if err = in.ImGroupTopicInp.Filter(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if in.UserId <= 0 {
|
||||
return gerror.New("新群主ID不能为空")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImGroupJoinRequestListInp struct {
|
||||
form.PageReq
|
||||
ImGroupTopicInp
|
||||
@@ -185,13 +338,13 @@ type ImGroupJoinRequestListModel struct {
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
RequestId string `json:"requestId" dc:"申请ID"`
|
||||
Topic string `json:"topic" dc:"Topic"`
|
||||
ApplicantUserId int64 `json:"applicantUserId" dc:"申请人ID"`
|
||||
InviterUserId int64 `json:"inviterUserId" dc:"邀请人ID"`
|
||||
ApplicantUserId int64 `json:"applicantUserId,string" dc:"申请人ID"`
|
||||
InviterUserId int64 `json:"inviterUserId,string" dc:"邀请人ID"`
|
||||
Source string `json:"source" dc:"来源"`
|
||||
Message string `json:"message" dc:"申请消息"`
|
||||
Status string `json:"status" dc:"状态"`
|
||||
RejectReason string `json:"rejectReason" dc:"拒绝原因"`
|
||||
HandledBy int64 `json:"handledBy" dc:"处理人"`
|
||||
HandledBy int64 `json:"handledBy,string" dc:"处理人"`
|
||||
HandledAt *gtime.Time `json:"handledAt" dc:"处理时间"`
|
||||
ExpiresAt *gtime.Time `json:"expiresAt" dc:"过期时间"`
|
||||
Version int `json:"version" dc:"版本"`
|
||||
@@ -199,6 +352,49 @@ type ImGroupJoinRequestListModel struct {
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"修改时间"`
|
||||
}
|
||||
|
||||
type ImGroupFileListInp struct {
|
||||
form.PageReq
|
||||
ImGroupTopicInp
|
||||
Status string `json:"status" dc:"状态"`
|
||||
FileType string `json:"fileType" dc:"文件类型"`
|
||||
FileName string `json:"fileName" dc:"文件名"`
|
||||
UploaderId int64 `json:"uploaderId" dc:"上传人ID"`
|
||||
}
|
||||
|
||||
type ImGroupFileListModel struct {
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
GroupFileId string `json:"groupFileId" dc:"群文件ID"`
|
||||
Topic string `json:"topic" dc:"Topic"`
|
||||
FileId string `json:"fileId" dc:"文件ID"`
|
||||
SourceTopic string `json:"sourceTopic" dc:"来源Topic"`
|
||||
SourceSeq int `json:"sourceSeq" dc:"来源消息序号"`
|
||||
UploaderId int64 `json:"uploaderId,string" dc:"上传人ID"`
|
||||
FileName string `json:"fileName" dc:"文件名"`
|
||||
MimeType string `json:"mimeType" dc:"MIME类型"`
|
||||
FileType string `json:"fileType" dc:"文件类型"`
|
||||
FileSize int64 `json:"fileSize" dc:"文件大小"`
|
||||
Status string `json:"status" dc:"状态"`
|
||||
DeletedBy int64 `json:"deletedBy,string" dc:"删除人"`
|
||||
DeletedAt *gtime.Time `json:"deletedAt" dc:"删除时间"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"修改时间"`
|
||||
}
|
||||
|
||||
type ImGroupFileDeleteInp struct {
|
||||
ImGroupTopicInp
|
||||
GroupFileId string `json:"groupFileId" v:"required#群文件ID不能为空" dc:"群文件ID"`
|
||||
}
|
||||
|
||||
func (in *ImGroupFileDeleteInp) Filter(ctx context.Context) (err error) {
|
||||
if err = in.ImGroupTopicInp.Filter(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if in.GroupFileId == "" {
|
||||
return gerror.New("群文件ID不能为空")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImGroupInvitationListInp struct {
|
||||
form.PageReq
|
||||
ImGroupTopicInp
|
||||
@@ -211,8 +407,8 @@ type ImGroupInvitationListModel struct {
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
InvitationId string `json:"invitationId" dc:"邀请ID"`
|
||||
Topic string `json:"topic" dc:"Topic"`
|
||||
InviterUserId int64 `json:"inviterUserId" dc:"邀请人ID"`
|
||||
TargetUserId int64 `json:"targetUserId" dc:"目标用户ID"`
|
||||
InviterUserId int64 `json:"inviterUserId,string" dc:"邀请人ID"`
|
||||
TargetUserId int64 `json:"targetUserId,string" dc:"目标用户ID"`
|
||||
Message string `json:"message" dc:"邀请消息"`
|
||||
Status string `json:"status" dc:"状态"`
|
||||
Result string `json:"result" dc:"结果"`
|
||||
@@ -233,12 +429,12 @@ type ImGroupAnnouncementListModel struct {
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
AnnouncementId string `json:"announcementId" dc:"公告ID"`
|
||||
Topic string `json:"topic" dc:"Topic"`
|
||||
AuthorUserId int64 `json:"authorUserId" dc:"发布人ID"`
|
||||
AuthorUserId int64 `json:"authorUserId,string" dc:"发布人ID"`
|
||||
Content string `json:"content" dc:"内容"`
|
||||
Status string `json:"status" dc:"状态"`
|
||||
Version int `json:"version" dc:"版本"`
|
||||
PublishedAt *gtime.Time `json:"publishedAt" dc:"发布时间"`
|
||||
DeletedBy int64 `json:"deletedBy" dc:"删除人"`
|
||||
DeletedBy int64 `json:"deletedBy,string" dc:"删除人"`
|
||||
DeletedAt *gtime.Time `json:"deletedAt" dc:"删除时间"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"修改时间"`
|
||||
@@ -253,13 +449,13 @@ type ImGroupMuteListInp struct {
|
||||
|
||||
type ImGroupMuteListModel struct {
|
||||
Topic string `json:"topic" dc:"Topic"`
|
||||
UserId int64 `json:"userId" dc:"用户ID"`
|
||||
MutedBy int64 `json:"mutedBy" dc:"禁言人"`
|
||||
UserId int64 `json:"userId,string" dc:"用户ID"`
|
||||
MutedBy int64 `json:"mutedBy,string" dc:"禁言人"`
|
||||
MutedAt *gtime.Time `json:"mutedAt" dc:"禁言时间"`
|
||||
ExpiresAt *gtime.Time `json:"expiresAt" dc:"过期时间"`
|
||||
Reason string `json:"reason" dc:"原因"`
|
||||
Status string `json:"status" dc:"状态"`
|
||||
RevokedBy int64 `json:"revokedBy" dc:"解除人"`
|
||||
RevokedBy int64 `json:"revokedBy,string" dc:"解除人"`
|
||||
RevokedAt *gtime.Time `json:"revokedAt" dc:"解除时间"`
|
||||
Version int `json:"version" dc:"版本"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
@@ -277,8 +473,8 @@ type ImGroupAdminLogListModel struct {
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
LogId string `json:"logId" dc:"日志ID"`
|
||||
Topic string `json:"topic" dc:"Topic"`
|
||||
OperatorId int64 `json:"operatorId" dc:"操作人"`
|
||||
TargetUserId int64 `json:"targetUserId" dc:"目标用户"`
|
||||
OperatorId int64 `json:"operatorId,string" dc:"操作人"`
|
||||
TargetUserId int64 `json:"targetUserId,string" dc:"目标用户"`
|
||||
Action string `json:"action" dc:"动作"`
|
||||
ObjectType string `json:"objectType" dc:"对象类型"`
|
||||
ObjectId string `json:"objectId" dc:"对象ID"`
|
||||
@@ -289,6 +485,25 @@ type ImGroupAdminLogListModel struct {
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
}
|
||||
|
||||
type ImGroupMemberRemoveInp struct {
|
||||
ImGroupTopicInp
|
||||
UserId int64 `json:"userId" v:"required#用户ID不能为空" dc:"用户ID"`
|
||||
Reason string `json:"reason" dc:"原因"`
|
||||
}
|
||||
|
||||
func (in *ImGroupMemberRemoveInp) Filter(ctx context.Context) (err error) {
|
||||
if err = in.ImGroupTopicInp.Filter(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if in.UserId <= 0 {
|
||||
return gerror.New("用户ID不能为空")
|
||||
}
|
||||
if len([]rune(in.Reason)) > 200 {
|
||||
return gerror.New("原因不能超过200个字符")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImGroupCommandModel struct {
|
||||
CommandID string `json:"commandId" dc:"命令ID"`
|
||||
EventID string `json:"eventId" dc:"Kafka事件ID"`
|
||||
@@ -298,62 +513,3 @@ type ImGroupCommandModel struct {
|
||||
EventType string `json:"eventType" dc:"事件类型"`
|
||||
IdempotencyKey string `json:"idempotencyKey" dc:"幂等键"`
|
||||
}
|
||||
|
||||
type ImGroupProfileUpdateInp struct {
|
||||
ImGroupTopicInp
|
||||
ActorUserId int64 `json:"actorUserId" v:"required#操作IM用户ID不能为空" dc:"操作IM用户ID"`
|
||||
Name string `json:"name" dc:"群名称"`
|
||||
AvatarFileId string `json:"avatarFileId" dc:"头像文件ID"`
|
||||
Description string `json:"description" dc:"简介"`
|
||||
Version int `json:"version" dc:"版本"`
|
||||
}
|
||||
|
||||
type ImGroupGovernanceUpdateInp struct {
|
||||
ImGroupTopicInp
|
||||
ActorUserId int64 `json:"actorUserId" v:"required#操作IM用户ID不能为空" dc:"操作IM用户ID"`
|
||||
JoinApproval *bool `json:"joinApproval" dc:"入群审批"`
|
||||
MuteAll *bool `json:"muteAll" dc:"全员禁言"`
|
||||
MemberUploadFiles *bool `json:"memberUploadFiles" dc:"成员上传文件"`
|
||||
MemberPrivateChat *bool `json:"memberPrivateChat" dc:"成员私聊"`
|
||||
MemberInvite *bool `json:"memberInvite" dc:"成员邀请"`
|
||||
Version int `json:"version" dc:"版本"`
|
||||
}
|
||||
|
||||
type ImGroupAdminSetInp struct {
|
||||
ImGroupTopicInp
|
||||
ActorUserId int64 `json:"actorUserId" v:"required#操作IM用户ID不能为空" dc:"操作IM用户ID"`
|
||||
UserIds []int64 `json:"userIds" v:"required#用户ID不能为空" dc:"用户ID列表"`
|
||||
}
|
||||
|
||||
type ImGroupAdminRemoveInp struct {
|
||||
ImGroupTopicInp
|
||||
ActorUserId int64 `json:"actorUserId" v:"required#操作IM用户ID不能为空" dc:"操作IM用户ID"`
|
||||
UserId int64 `json:"userId" v:"required#用户ID不能为空" dc:"用户ID"`
|
||||
}
|
||||
|
||||
type ImGroupMemberMuteInp struct {
|
||||
ImGroupTopicInp
|
||||
ActorUserId int64 `json:"actorUserId" v:"required#操作IM用户ID不能为空" dc:"操作IM用户ID"`
|
||||
UserId int64 `json:"userId" v:"required#用户ID不能为空" dc:"用户ID"`
|
||||
Reason string `json:"reason" dc:"原因"`
|
||||
ExpiresAt *gtime.Time `json:"expiresAt" dc:"过期时间"`
|
||||
}
|
||||
|
||||
type ImGroupMemberUnmuteInp struct {
|
||||
ImGroupTopicInp
|
||||
ActorUserId int64 `json:"actorUserId" v:"required#操作IM用户ID不能为空" dc:"操作IM用户ID"`
|
||||
UserId int64 `json:"userId" v:"required#用户ID不能为空" dc:"用户ID"`
|
||||
}
|
||||
|
||||
type ImGroupMemberRemoveInp struct {
|
||||
ImGroupTopicInp
|
||||
ActorUserId int64 `json:"actorUserId" v:"required#操作IM用户ID不能为空" dc:"操作IM用户ID"`
|
||||
UserId int64 `json:"userId" v:"required#用户ID不能为空" dc:"用户ID"`
|
||||
}
|
||||
|
||||
type ImGroupOwnerTransferInp struct {
|
||||
ImGroupTopicInp
|
||||
ActorUserId int64 `json:"actorUserId" v:"required#操作IM用户ID不能为空" dc:"操作IM用户ID"`
|
||||
TargetUserId int64 `json:"targetUserId" v:"required#新群主ID不能为空" dc:"新群主ID"`
|
||||
Version int `json:"version" dc:"版本"`
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"hotgo/internal/model/input/form"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
@@ -25,6 +26,9 @@ type ImInviteListInp struct {
|
||||
}
|
||||
|
||||
func (in *ImInviteListInp) Filter(ctx context.Context) (err error) {
|
||||
if in.Page <= 0 {
|
||||
in.Page = 1
|
||||
}
|
||||
if in.PerPage <= 0 {
|
||||
in.PerPage = 20
|
||||
}
|
||||
@@ -53,12 +57,16 @@ type ImInviteCreateInp struct {
|
||||
}
|
||||
|
||||
func (in *ImInviteCreateInp) Filter(ctx context.Context) (err error) {
|
||||
in.IdempotencyKey = strings.TrimSpace(in.IdempotencyKey)
|
||||
if in.ExpiresAt == nil || in.ExpiresAt.Before(gtime.Now()) {
|
||||
return gerror.New("到期时间必须晚于当前时间")
|
||||
}
|
||||
if len(in.Remark) > 255 {
|
||||
return gerror.New("备注不能超过255个字符")
|
||||
}
|
||||
if len(in.IdempotencyKey) > 128 {
|
||||
return gerror.New("幂等键不能超过128个字符")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -71,6 +79,7 @@ type ImInviteBatchCreateInp struct {
|
||||
}
|
||||
|
||||
func (in *ImInviteBatchCreateInp) Filter(ctx context.Context) (err error) {
|
||||
in.IdempotencyKey = strings.TrimSpace(in.IdempotencyKey)
|
||||
if in.Quantity < 1 || in.Quantity > 1000 {
|
||||
return gerror.New("批量生成数量必须在1到1000之间")
|
||||
}
|
||||
@@ -80,6 +89,9 @@ func (in *ImInviteBatchCreateInp) Filter(ctx context.Context) (err error) {
|
||||
if len(in.Remark) > 255 {
|
||||
return gerror.New("备注不能超过255个字符")
|
||||
}
|
||||
if len(in.IdempotencyKey) == 0 || len(in.IdempotencyKey) > 128 {
|
||||
return gerror.New("批量生成必须提供不超过128个字符的幂等键")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -93,30 +105,51 @@ type ImInviteRevokeInp struct {
|
||||
Id string `json:"id" v:"required#邀请码ID不能为空" dc:"邀请码ID"`
|
||||
}
|
||||
|
||||
type ImInviteBindUserInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"IM租户ID"`
|
||||
Id string `json:"id" v:"required#邀请码ID不能为空" dc:"邀请码ID"`
|
||||
UserId int64 `json:"userId" v:"required|min:1#绑定用户不能为空|绑定用户不合法" dc:"绑定C端用户ID"`
|
||||
}
|
||||
|
||||
func (in *ImInviteBindUserInp) Filter(ctx context.Context) (err error) {
|
||||
if _, err = ParseOptionalInt64(in.Id); err != nil {
|
||||
return gerror.New("邀请码ID不能为空")
|
||||
}
|
||||
if in.UserId <= 0 {
|
||||
return gerror.New("绑定用户不能为空")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImInviteBatchRevokeInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"IM租户ID"`
|
||||
BatchId string `json:"batchId" v:"required#批次ID不能为空" dc:"批次ID"`
|
||||
}
|
||||
|
||||
type ImInviteCodeModel struct {
|
||||
Id string `json:"id" dc:"ID"`
|
||||
BatchId string `json:"batchId" dc:"批次ID"`
|
||||
Code string `json:"code" dc:"邀请码"`
|
||||
Status string `json:"status" dc:"状态"`
|
||||
ExpiresAt *gtime.Time `json:"expiresAt" dc:"到期时间"`
|
||||
UsedBy string `json:"usedBy" dc:"使用用户"`
|
||||
UsedAt *gtime.Time `json:"usedAt" dc:"使用时间"`
|
||||
RequestId string `json:"requestId" dc:"请求ID"`
|
||||
CreatedBy string `json:"createdBy" dc:"创建人"`
|
||||
Remark string `json:"remark" dc:"备注"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
Id string `json:"id" dc:"ID"`
|
||||
TenantId string `json:"tenantId" dc:"IM租户ID"`
|
||||
TenantName string `json:"tenantName" dc:"IM租户名称"`
|
||||
BatchId string `json:"batchId" dc:"批次ID"`
|
||||
Code string `json:"code" dc:"邀请码"`
|
||||
Status string `json:"status" dc:"状态"`
|
||||
ExpiresAt *gtime.Time `json:"expiresAt" dc:"到期时间"`
|
||||
MaxUses int `json:"maxUses" dc:"最大可用次数,0表示不限制"`
|
||||
UsageCount int `json:"usageCount" dc:"累计使用次数"`
|
||||
BoundUserId string `json:"boundUserId" dc:"绑定用户ID"`
|
||||
BoundUserLabel string `json:"boundUserLabel" dc:"绑定用户展示名"`
|
||||
LastUsedAt *gtime.Time `json:"lastUsedAt" dc:"最后使用时间"`
|
||||
CreatedBy string `json:"createdBy" dc:"创建人"`
|
||||
Remark string `json:"remark" dc:"备注"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
}
|
||||
|
||||
type ImInviteBatchModel struct {
|
||||
BatchId string `json:"batchId" dc:"批次ID"`
|
||||
TenantId string `json:"tenantId" dc:"IM租户ID"`
|
||||
Quantity int `json:"quantity" dc:"数量"`
|
||||
ActiveCount int `json:"activeCount" dc:"有效数量"`
|
||||
UsedCount int `json:"usedCount" dc:"已使用数量"`
|
||||
UsageCount int `json:"usageCount" dc:"累计使用次数"`
|
||||
RevokedCount int `json:"revokedCount" dc:"已撤销数量"`
|
||||
ExpiredCount int `json:"expiredCount" dc:"已过期数量"`
|
||||
ExpiresAt *gtime.Time `json:"expiresAt" 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,59 @@
|
||||
package sysin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/library/dict"
|
||||
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
type ImMailboxConfigGetInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
}
|
||||
|
||||
func (in *ImMailboxConfigGetInp) Filter(ctx context.Context) (err error) { return }
|
||||
|
||||
type ImMailboxConfigModel struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
Enabled int `json:"enabled" dc:"启用状态"`
|
||||
AllowAnonymous int `json:"allowAnonymous" dc:"允许匿名"`
|
||||
RequiredFields string `json:"requiredFields" dc:"必填字段JSON"`
|
||||
MaxLength int `json:"maxLength" dc:"最大字数"`
|
||||
AttachmentPolicy string `json:"attachmentPolicy" dc:"附件策略JSON"`
|
||||
NoticeTitle string `json:"noticeTitle" dc:"告知标题"`
|
||||
NoticeContent string `json:"noticeContent" dc:"告知内容"`
|
||||
NoticeUpdatedAt *gtime.Time `json:"noticeUpdatedAt" dc:"告知更新时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
}
|
||||
|
||||
type ImMailboxConfigUpdateInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Enabled int `json:"enabled" dc:"启用状态"`
|
||||
AllowAnonymous int `json:"allowAnonymous" dc:"允许匿名"`
|
||||
RequiredFields *gjson.Json `json:"requiredFields" dc:"必填字段JSON"`
|
||||
MaxLength int `json:"maxLength" dc:"最大字数"`
|
||||
AttachmentPolicy *gjson.Json `json:"attachmentPolicy" dc:"附件策略JSON"`
|
||||
NoticeTitle string `json:"noticeTitle" v:"required#告知标题不能为空" dc:"告知标题"`
|
||||
NoticeContent string `json:"noticeContent" v:"required#告知内容不能为空" dc:"告知内容"`
|
||||
}
|
||||
|
||||
func (in *ImMailboxConfigUpdateInp) Filter(ctx context.Context) (err error) {
|
||||
if !dict.HasOptionKey(consts.ImFilePolicySwitchOptions, in.Enabled) {
|
||||
return gerror.New("启用状态不合法")
|
||||
}
|
||||
if !dict.HasOptionKey(consts.ImFilePolicySwitchOptions, in.AllowAnonymous) {
|
||||
return gerror.New("匿名开关不合法")
|
||||
}
|
||||
if in.MaxLength <= 0 {
|
||||
return gerror.New("最大字数必须大于0")
|
||||
}
|
||||
if len([]rune(in.NoticeTitle)) > 128 {
|
||||
return gerror.New("告知标题不能超过128个字符")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
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"`
|
||||
SeqId int64 `json:"seqId" dc:"消息序号"`
|
||||
SenderUserId string `json:"senderUserId" dc:"发送用户ID"`
|
||||
SenderUsername string `json:"senderUsername" dc:"发送人用户名"`
|
||||
SenderNickname string `json:"senderNickname" dc:"发送人昵称"`
|
||||
GroupName string `json:"groupName" dc:"群名称"`
|
||||
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 {
|
||||
in.SenderUsername = strings.TrimSpace(in.SenderUsername)
|
||||
in.SenderNickname = strings.TrimSpace(in.SenderNickname)
|
||||
in.GroupName = strings.TrimSpace(in.GroupName)
|
||||
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,22 @@
|
||||
package sysin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestImGroupMessageListFilterTrimsTextFilters(t *testing.T) {
|
||||
in := &ImGroupMessageListInp{
|
||||
SenderUsername: " alice ",
|
||||
SenderNickname: " 小明 ",
|
||||
GroupName: " 测试群 ",
|
||||
Keyword: " 关键字 ",
|
||||
Topic: " grpTest ",
|
||||
}
|
||||
if err := in.Filter(context.Background()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if in.SenderUsername != "alice" || in.SenderNickname != "小明" || in.GroupName != "测试群" || in.Keyword != "关键字" || in.Topic != "grpTest" {
|
||||
t.Fatalf("message filters were not normalized: %#v", in)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package sysin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/library/dict"
|
||||
"hotgo/internal/model/input/form"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
type ImNotificationTemplateListInp struct {
|
||||
form.PageReq
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Scene string `json:"scene" dc:"通知场景"`
|
||||
Status *int `json:"status" dc:"状态"`
|
||||
}
|
||||
|
||||
func (in *ImNotificationTemplateListInp) Filter(ctx context.Context) (err error) { return }
|
||||
|
||||
type ImNotificationTemplateListModel struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
Scene string `json:"scene" dc:"通知场景"`
|
||||
Name string `json:"name" dc:"场景名称"`
|
||||
InAppEnabled int `json:"inAppEnabled" dc:"站内通知"`
|
||||
PushEnabled int `json:"pushEnabled" dc:"Push通知"`
|
||||
SmsEnabled int `json:"smsEnabled" dc:"短信通知"`
|
||||
Status int `json:"status" dc:"状态"`
|
||||
TitleTemplate string `json:"titleTemplate" dc:"标题模板"`
|
||||
ContentTemplate string `json:"contentTemplate" dc:"内容模板"`
|
||||
PayloadJson string `json:"payloadJson" dc:"扩展JSON"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
}
|
||||
|
||||
type ImNotificationTemplateUpdateInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Scene string `json:"scene" v:"required#通知场景不能为空" dc:"通知场景"`
|
||||
InAppEnabled int `json:"inAppEnabled" dc:"站内通知"`
|
||||
PushEnabled int `json:"pushEnabled" dc:"Push通知"`
|
||||
SmsEnabled int `json:"smsEnabled" dc:"短信通知"`
|
||||
Status int `json:"status" dc:"状态"`
|
||||
TitleTemplate string `json:"titleTemplate" dc:"标题模板"`
|
||||
ContentTemplate string `json:"contentTemplate" dc:"内容模板"`
|
||||
PayloadJson *gjson.Json `json:"payloadJson" dc:"扩展JSON"`
|
||||
}
|
||||
|
||||
func (in *ImNotificationTemplateUpdateInp) Filter(ctx context.Context) (err error) {
|
||||
in.Scene = strings.TrimSpace(in.Scene)
|
||||
in.TitleTemplate = strings.TrimSpace(in.TitleTemplate)
|
||||
in.ContentTemplate = strings.TrimSpace(in.ContentTemplate)
|
||||
if !dict.HasOptionKey(consts.ImNotificationSceneOptions, in.Scene) {
|
||||
return gerror.New("通知场景不合法")
|
||||
}
|
||||
if !dict.HasOptionKey(consts.ImNotificationTemplateStatusOptions, in.Status) {
|
||||
return gerror.New("通知模板状态不合法")
|
||||
}
|
||||
if in.TitleTemplate == "" {
|
||||
return gerror.New("标题模板不能为空")
|
||||
}
|
||||
if in.ContentTemplate == "" {
|
||||
return gerror.New("内容模板不能为空")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
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 ImOrgDepartmentListInp struct {
|
||||
form.PageReq
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
DepartmentId string `json:"departmentId" dc:"部门ID"`
|
||||
ParentId string `json:"parentId" dc:"上级部门ID"`
|
||||
Name string `json:"name" dc:"部门名称"`
|
||||
State string `json:"state" dc:"状态"`
|
||||
}
|
||||
|
||||
func (in *ImOrgDepartmentListInp) Filter(ctx context.Context) (err error) { return }
|
||||
|
||||
type ImOrgDepartmentModel struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
DepartmentId string `json:"departmentId" dc:"部门ID"`
|
||||
Name string `json:"name" dc:"部门名称"`
|
||||
ParentId string `json:"parentId" dc:"上级部门ID"`
|
||||
SortOrder int `json:"sortOrder" dc:"排序"`
|
||||
Version int `json:"version" dc:"版本"`
|
||||
State string `json:"state" dc:"状态"`
|
||||
ChildCount int `json:"childCount" dc:"子部门数"`
|
||||
MemberCount int `json:"memberCount" dc:"成员数"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
}
|
||||
|
||||
type ImOrgDepartmentExportModel struct {
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
DepartmentId string `json:"departmentId" dc:"部门ID"`
|
||||
Name string `json:"name" dc:"部门名称"`
|
||||
ParentId string `json:"parentId" dc:"上级部门ID"`
|
||||
SortOrder int `json:"sortOrder" dc:"排序"`
|
||||
Version int `json:"version" dc:"版本"`
|
||||
State string `json:"state" dc:"状态"`
|
||||
ChildCount int `json:"childCount" dc:"子部门数"`
|
||||
MemberCount int `json:"memberCount" dc:"成员数"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
}
|
||||
|
||||
type ImOrgDepartmentEditInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
DepartmentId string `json:"departmentId" dc:"部门ID"`
|
||||
Name string `json:"name" dc:"部门名称"`
|
||||
ParentId string `json:"parentId" dc:"上级部门ID"`
|
||||
SortOrder int `json:"sortOrder" dc:"排序"`
|
||||
State string `json:"state" dc:"状态"`
|
||||
}
|
||||
|
||||
func (in *ImOrgDepartmentEditInp) Filter(ctx context.Context) (err error) {
|
||||
in.Name = strings.TrimSpace(in.Name)
|
||||
in.DepartmentId = strings.TrimSpace(in.DepartmentId)
|
||||
in.ParentId = strings.TrimSpace(in.ParentId)
|
||||
in.State = strings.TrimSpace(in.State)
|
||||
if in.Name == "" {
|
||||
return gerror.New("部门名称不能为空")
|
||||
}
|
||||
if in.ParentId == "" {
|
||||
in.ParentId = "root"
|
||||
}
|
||||
if in.State == "" {
|
||||
in.State = consts.ImOrgDepartmentStateActive
|
||||
}
|
||||
if !dict.HasOptionKey(consts.ImOrgDepartmentStateOptions, in.State) {
|
||||
return gerror.New("部门状态不合法")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImOrgDepartmentDeleteInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
DepartmentId string `json:"departmentId" v:"required#部门ID不能为空" dc:"部门ID"`
|
||||
}
|
||||
|
||||
func (in *ImOrgDepartmentDeleteInp) Filter(ctx context.Context) (err error) {
|
||||
in.DepartmentId = strings.TrimSpace(in.DepartmentId)
|
||||
if in.DepartmentId == "" {
|
||||
return gerror.New("部门ID不能为空")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImOrgMemberListInp struct {
|
||||
form.PageReq
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
DepartmentId string `json:"departmentId" dc:"部门ID"`
|
||||
UserId int64 `json:"userId" dc:"用户ID"`
|
||||
Query string `json:"query" dc:"关键词"`
|
||||
EmploymentState string `json:"employmentState" dc:"在职状态"`
|
||||
}
|
||||
|
||||
func (in *ImOrgMemberListInp) Filter(ctx context.Context) (err error) { return }
|
||||
|
||||
type ImOrgMemberModel struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
DepartmentId string `json:"departmentId" dc:"部门ID"`
|
||||
DepartmentName string `json:"departmentName" dc:"部门名称"`
|
||||
UserId int64 `json:"userId" dc:"用户ID"`
|
||||
DisplayName string `json:"displayName" dc:"展示名称"`
|
||||
Position string `json:"position" dc:"岗位"`
|
||||
AvatarFileId string `json:"avatarFileId" dc:"头像文件ID"`
|
||||
Mobile string `json:"mobile" dc:"手机号"`
|
||||
Email string `json:"email" dc:"邮箱"`
|
||||
EmploymentState string `json:"employmentState" dc:"在职状态"`
|
||||
Contactable int `json:"contactable" dc:"是否可联系"`
|
||||
SortOrder int `json:"sortOrder" dc:"排序"`
|
||||
Version int `json:"version" dc:"版本"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
}
|
||||
|
||||
type ImOrgMemberExportModel struct {
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
DepartmentId string `json:"departmentId" dc:"部门ID"`
|
||||
DepartmentName string `json:"departmentName" dc:"部门名称"`
|
||||
UserId int64 `json:"userId" dc:"用户ID"`
|
||||
DisplayName string `json:"displayName" dc:"展示名称"`
|
||||
Position string `json:"position" dc:"岗位"`
|
||||
Mobile string `json:"mobile" dc:"手机号"`
|
||||
Email string `json:"email" dc:"邮箱"`
|
||||
EmploymentState string `json:"employmentState" dc:"在职状态"`
|
||||
Contactable int `json:"contactable" dc:"是否可联系"`
|
||||
SortOrder int `json:"sortOrder" dc:"排序"`
|
||||
Version int `json:"version" dc:"版本"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
}
|
||||
|
||||
type ImOrgMemberEditInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
DepartmentId string `json:"departmentId" dc:"部门ID"`
|
||||
UserId int64 `json:"userId" dc:"用户ID"`
|
||||
DisplayName string `json:"displayName" dc:"展示名称"`
|
||||
Position string `json:"position" dc:"岗位"`
|
||||
AvatarFileId string `json:"avatarFileId" dc:"头像文件ID"`
|
||||
Mobile string `json:"mobile" dc:"手机号"`
|
||||
Email string `json:"email" dc:"邮箱"`
|
||||
EmploymentState string `json:"employmentState" dc:"在职状态"`
|
||||
Contactable int `json:"contactable" dc:"是否可联系"`
|
||||
SortOrder int `json:"sortOrder" dc:"排序"`
|
||||
}
|
||||
|
||||
func (in *ImOrgMemberEditInp) Filter(ctx context.Context) (err error) {
|
||||
in.DepartmentId = strings.TrimSpace(in.DepartmentId)
|
||||
in.DisplayName = strings.TrimSpace(in.DisplayName)
|
||||
in.Position = strings.TrimSpace(in.Position)
|
||||
in.AvatarFileId = strings.TrimSpace(in.AvatarFileId)
|
||||
in.Mobile = strings.TrimSpace(in.Mobile)
|
||||
in.Email = strings.TrimSpace(in.Email)
|
||||
in.EmploymentState = strings.TrimSpace(in.EmploymentState)
|
||||
if in.DepartmentId == "" {
|
||||
return gerror.New("部门ID不能为空")
|
||||
}
|
||||
if in.UserId <= 0 {
|
||||
return gerror.New("用户ID不能为空")
|
||||
}
|
||||
if in.EmploymentState == "" {
|
||||
in.EmploymentState = consts.ImOrgEmploymentStateActive
|
||||
}
|
||||
if !dict.HasOptionKey(consts.ImOrgEmploymentStateOptions, in.EmploymentState) {
|
||||
return gerror.New("在职状态不合法")
|
||||
}
|
||||
if !dict.HasOptionKey(consts.ImOrgContactableOptions, in.Contactable) {
|
||||
return gerror.New("可联系状态不合法")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImOrgMemberDeleteInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Id int64 `json:"id" v:"required#成员关系ID不能为空" dc:"ID"`
|
||||
}
|
||||
|
||||
func (in *ImOrgMemberDeleteInp) Filter(ctx context.Context) (err error) {
|
||||
if in.Id <= 0 {
|
||||
return gerror.New("成员关系ID不能为空")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImOrgSearchInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Query string `json:"query" v:"required#关键词不能为空" dc:"关键词"`
|
||||
}
|
||||
|
||||
func (in *ImOrgSearchInp) Filter(ctx context.Context) (err error) {
|
||||
in.Query = strings.TrimSpace(in.Query)
|
||||
if in.Query == "" {
|
||||
return gerror.New("关键词不能为空")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImOrgSearchModel struct {
|
||||
Departments []*ImOrgDepartmentModel `json:"departments" dc:"部门"`
|
||||
Members []*ImOrgMemberModel `json:"members" dc:"成员"`
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
// Package sysin
|
||||
// @Link https://github.com/bufanyun/hotgo
|
||||
// @Copyright Copyright (c) 2026 HotGo
|
||||
// @Author Ms <133814250@qq.com>
|
||||
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
|
||||
package sysin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"hotgo/internal/model/input/form"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
const (
|
||||
ImOutboxSourceBusiness = "business"
|
||||
ImOutboxSourceGroup = "group"
|
||||
|
||||
ImOutboxStatusPending = "pending"
|
||||
ImOutboxStatusDelivered = "delivered"
|
||||
ImOutboxStatusFailed = "failed"
|
||||
ImOutboxStatusDead = "dead"
|
||||
)
|
||||
|
||||
type ImOutboxListInp struct {
|
||||
form.PageReq
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Source string `json:"source" dc:"事件来源"`
|
||||
EventId string `json:"eventId" dc:"事件ID"`
|
||||
EventType string `json:"eventType" dc:"事件类型"`
|
||||
TargetType string `json:"targetType" dc:"目标类型"`
|
||||
Target string `json:"target" dc:"目标"`
|
||||
Status string `json:"status" dc:"状态"`
|
||||
CreatedAt []*gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
}
|
||||
|
||||
func (in *ImOutboxListInp) Filter(ctx context.Context) (err error) {
|
||||
if in.Source == "" {
|
||||
in.Source = ImOutboxSourceBusiness
|
||||
}
|
||||
if in.Source != ImOutboxSourceBusiness && in.Source != ImOutboxSourceGroup {
|
||||
return gerror.New("Outbox来源不正确")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImOutboxListModel struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
Source string `json:"source" dc:"事件来源"`
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
EventId string `json:"eventId" dc:"事件ID"`
|
||||
TargetType string `json:"targetType" dc:"目标类型"`
|
||||
Target string `json:"target" dc:"目标"`
|
||||
ActorUserId int64 `json:"actorUserId" dc:"操作用户ID"`
|
||||
EventType string `json:"eventType" dc:"事件类型"`
|
||||
Payload string `json:"payload" dc:"事件负载"`
|
||||
Status string `json:"status" dc:"状态"`
|
||||
Attempts int `json:"attempts" dc:"尝试次数"`
|
||||
NextRetryAt *gtime.Time `json:"nextRetryAt" dc:"下次重试时间"`
|
||||
DeliveredAt *gtime.Time `json:"deliveredAt" dc:"投递时间"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
}
|
||||
|
||||
type ImOutboxViewInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Source string `json:"source" v:"required#事件来源不能为空" dc:"事件来源"`
|
||||
Id int64 `json:"id" v:"required#ID不能为空" dc:"ID"`
|
||||
}
|
||||
|
||||
func (in *ImOutboxViewInp) Filter(ctx context.Context) (err error) {
|
||||
if in.Source != ImOutboxSourceBusiness && in.Source != ImOutboxSourceGroup {
|
||||
return gerror.New("Outbox来源不正确")
|
||||
}
|
||||
if in.Id <= 0 {
|
||||
return gerror.New("ID不能为空")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImOutboxViewModel struct {
|
||||
ImOutboxListModel
|
||||
}
|
||||
|
||||
type ImOutboxActionInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Source string `json:"source" v:"required#事件来源不能为空" dc:"事件来源"`
|
||||
Id int64 `json:"id" v:"required#ID不能为空" dc:"ID"`
|
||||
}
|
||||
|
||||
func (in *ImOutboxActionInp) Filter(ctx context.Context) (err error) {
|
||||
if in.Source != ImOutboxSourceBusiness && in.Source != ImOutboxSourceGroup {
|
||||
return gerror.New("Outbox来源不正确")
|
||||
}
|
||||
if in.Id <= 0 {
|
||||
return gerror.New("ID不能为空")
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
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应被拒绝")
|
||||
}
|
||||
}
|
||||
|
||||
func TestImTenantLoginIPWhitelistSaveFilter(t *testing.T) {
|
||||
in := &ImTenantLoginIPWhitelistSaveInp{
|
||||
TenantId: 1,
|
||||
AppList: []string{" 203.0.113.10 ", "2001:db8::/32", "203.0.113.10"},
|
||||
WebList: []string{"198.51.100.7/24"},
|
||||
}
|
||||
if err := in.Filter(context.Background()); err != nil {
|
||||
t.Fatalf("合法租户登录白名单不应报错: %v", err)
|
||||
}
|
||||
if len(in.AppList) != 2 || in.AppList[0] != "203.0.113.10" || in.WebList[0] != "198.51.100.0/24" {
|
||||
t.Fatalf("IP白名单未正确规范化: app=%v web=%v", in.AppList, in.WebList)
|
||||
}
|
||||
in.AppList = []string{"not-an-ip"}
|
||||
if err := in.Filter(context.Background()); err == nil {
|
||||
t.Fatal("非法IP地址应被拒绝")
|
||||
}
|
||||
}
|
||||
@@ -26,9 +26,6 @@ type ImRealnameListInp struct {
|
||||
}
|
||||
|
||||
func (in *ImRealnameListInp) Filter(ctx context.Context) (err error) {
|
||||
if in.TenantId <= 0 {
|
||||
return gerror.New("请选择租户")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -55,9 +52,6 @@ type ImRealnameViewInp struct {
|
||||
}
|
||||
|
||||
func (in *ImRealnameViewInp) Filter(ctx context.Context) (err error) {
|
||||
if in.TenantId <= 0 {
|
||||
return gerror.New("请选择租户")
|
||||
}
|
||||
if in.Id <= 0 {
|
||||
return gerror.New("ID不能为空")
|
||||
}
|
||||
@@ -78,9 +72,6 @@ type ImRealnameReviewInp struct {
|
||||
}
|
||||
|
||||
func (in *ImRealnameReviewInp) Filter(ctx context.Context) (err error) {
|
||||
if in.TenantId <= 0 {
|
||||
return gerror.New("请选择租户")
|
||||
}
|
||||
if in.Id <= 0 {
|
||||
return gerror.New("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,35 @@
|
||||
package sysin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"hotgo/internal/model/input/form"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
type ImTaskDashboardListInp struct {
|
||||
form.PageReq
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Status string `json:"status" dc:"状态"`
|
||||
}
|
||||
|
||||
func (in *ImTaskDashboardListInp) Filter(ctx context.Context) (err error) { return }
|
||||
|
||||
type ImTaskDashboardListModel struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
TenantCode string `json:"tenantCode" dc:"租户编码"`
|
||||
TenantState int `json:"tenantState" dc:"租户状态"`
|
||||
DbStatus string `json:"dbStatus" dc:"数据库状态"`
|
||||
Status string `json:"status" dc:"看板状态"`
|
||||
OutboxPendingCount int `json:"outboxPendingCount" dc:"业务Outbox待处理"`
|
||||
OutboxFailedCount int `json:"outboxFailedCount" dc:"业务Outbox失败"`
|
||||
GroupOutboxPending int `json:"groupOutboxPending" dc:"群Outbox待处理"`
|
||||
GroupOutboxFailed int `json:"groupOutboxFailed" dc:"群Outbox失败"`
|
||||
OrphanFileCount int `json:"orphanFileCount" dc:"孤儿文件数"`
|
||||
DeletedFileCount int `json:"deletedFileCount" dc:"待物理清理文件数"`
|
||||
LastOutboxCreatedAt *gtime.Time `json:"lastOutboxCreatedAt" dc:"最新Outbox时间"`
|
||||
LastGroupEventAt *gtime.Time `json:"lastGroupEventAt" dc:"最新群事件时间"`
|
||||
LastFileUpdatedAt *gtime.Time `json:"lastFileUpdatedAt" dc:"最新文件更新时间"`
|
||||
RecommendedNextAction string `json:"recommendedNextAction" dc:"建议动作"`
|
||||
}
|
||||
@@ -155,3 +155,67 @@ func (in *ImTenantStatusInp) Filter(ctx context.Context) (err error) {
|
||||
}
|
||||
|
||||
type ImTenantStatusModel struct{}
|
||||
|
||||
type ImTenantUsageInp struct {
|
||||
Id int64 `json:"id" v:"required#ID不能为空" dc:"ID"`
|
||||
}
|
||||
|
||||
func (in *ImTenantUsageInp) Filter(ctx context.Context) (err error) {
|
||||
if in.Id <= 0 {
|
||||
return gerror.New("ID不能为空")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImTenantUsageModel struct {
|
||||
Id int64 `json:"id" dc:"租户ID"`
|
||||
Code string `json:"code" dc:"租户编码"`
|
||||
Name string `json:"name" dc:"租户名称"`
|
||||
DbName string `json:"dbName" dc:"业务库名"`
|
||||
DbDsnConfigured bool `json:"dbDsnConfigured" dc:"是否配置独立连接串"`
|
||||
DbReachable bool `json:"dbReachable" dc:"业务库是否可达"`
|
||||
DbCheckError string `json:"dbCheckError" dc:"业务库检查错误"`
|
||||
SchemaVersion string `json:"schemaVersion" dc:"Schema版本"`
|
||||
UserCount int64 `json:"userCount" dc:"用户数"`
|
||||
ActiveUserCount int64 `json:"activeUserCount" dc:"正常用户数"`
|
||||
GroupCount int64 `json:"groupCount" dc:"群数"`
|
||||
DeviceCount int64 `json:"deviceCount" dc:"设备数"`
|
||||
PushTokenCount int64 `json:"pushTokenCount" dc:"Push Token数"`
|
||||
InviteUseCount int64 `json:"inviteUseCount" dc:"邀请码使用次数"`
|
||||
OutboxPendingCount int64 `json:"outboxPendingCount" dc:"待处理Outbox数"`
|
||||
Warnings []string `json:"warnings" dc:"警告信息"`
|
||||
}
|
||||
|
||||
type ImTenantDeletionCheckInp struct {
|
||||
Id int64 `json:"id" v:"required#ID不能为空" dc:"ID"`
|
||||
}
|
||||
|
||||
func (in *ImTenantDeletionCheckInp) Filter(ctx context.Context) (err error) {
|
||||
if in.Id <= 0 {
|
||||
return gerror.New("ID不能为空")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImTenantDeletionCheckModel struct {
|
||||
Id int64 `json:"id" dc:"租户ID"`
|
||||
Code string `json:"code" dc:"租户编码"`
|
||||
Name string `json:"name" dc:"租户名称"`
|
||||
CanEnterDeleting bool `json:"canEnterDeleting" dc:"是否可进入删除流程"`
|
||||
Blockers []string `json:"blockers" dc:"阻断原因"`
|
||||
Warnings []string `json:"warnings" dc:"警告信息"`
|
||||
UserCount int64 `json:"userCount" dc:"用户数"`
|
||||
GroupCount int64 `json:"groupCount" dc:"群数"`
|
||||
PendingOutbox int64 `json:"pendingOutbox" dc:"待处理Outbox"`
|
||||
}
|
||||
|
||||
type ImTenantLifecycleInp struct {
|
||||
Id int64 `json:"id" v:"required#ID不能为空" dc:"ID"`
|
||||
}
|
||||
|
||||
func (in *ImTenantLifecycleInp) Filter(ctx context.Context) (err error) {
|
||||
if in.Id <= 0 {
|
||||
return gerror.New("ID不能为空")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ package sysin
|
||||
import (
|
||||
"context"
|
||||
"hotgo/internal/model/input/form"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
@@ -17,7 +18,9 @@ import (
|
||||
type ImUserListInp struct {
|
||||
form.PageReq
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
UserId int64 `json:"userId" dc:"用户ID"`
|
||||
UserId string `json:"userId" dc:"后台展示编号"`
|
||||
GroupId int64 `json:"groupId" dc:"用户策略分组ID"`
|
||||
Keyword string `json:"keyword" dc:"用户名、昵称、手机号或编号"`
|
||||
Nickname string `json:"nickname" dc:"昵称"`
|
||||
AuthName string `json:"authName" dc:"登录标识"`
|
||||
State *int `json:"state" dc:"账号状态"`
|
||||
@@ -26,8 +29,11 @@ type ImUserListInp struct {
|
||||
}
|
||||
|
||||
func (in *ImUserListInp) Filter(ctx context.Context) (err error) {
|
||||
if in.TenantId <= 0 {
|
||||
return gerror.New("请选择租户")
|
||||
in.Keyword = strings.TrimSpace(in.Keyword)
|
||||
if in.UserId != "" {
|
||||
if _, err = ParseOptionalInt64(in.UserId); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -35,7 +41,10 @@ func (in *ImUserListInp) Filter(ctx context.Context) (err error) {
|
||||
type ImUserListModel struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
UserId int64 `json:"userId" dc:"用户ID"`
|
||||
DisplayNo int `json:"displayNo" dc:"后台展示编号"`
|
||||
UserId string `json:"userId" dc:"用户ID"`
|
||||
Username string `json:"username" dc:"登录账号"`
|
||||
Phone string `json:"phone" dc:"手机号"`
|
||||
Nickname string `json:"nickname" dc:"昵称"`
|
||||
PublicAccount string `json:"publicAccount" dc:"公开账号"`
|
||||
Gender string `json:"gender" dc:"性别"`
|
||||
@@ -49,24 +58,140 @@ type ImUserListModel struct {
|
||||
UserAgent string `json:"userAgent" dc:"客户端"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"修改时间"`
|
||||
AvatarFileId string `json:"avatarFileId" dc:"头像文件ID"`
|
||||
Avatar string `json:"avatar" dc:"头像地址"`
|
||||
PolicyGroupId int64 `json:"policyGroupId" dc:"用户策略分组ID"`
|
||||
PolicyGroupName string `json:"policyGroupName" dc:"用户策略分组名称"`
|
||||
RegisterType string `json:"registerType" dc:"注册方式"`
|
||||
}
|
||||
|
||||
type ImUserCreateInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Username string `json:"username" dc:"用户名"`
|
||||
Nickname string `json:"nickname" v:"required#昵称不能为空" dc:"昵称"`
|
||||
Phone string `json:"phone" dc:"手机号"`
|
||||
Password string `json:"password" v:"required#密码不能为空" dc:"密码"`
|
||||
GroupId int64 `json:"groupId" dc:"用户策略分组ID"`
|
||||
}
|
||||
|
||||
func (in *ImUserCreateInp) Filter(ctx context.Context) error {
|
||||
in.Username = strings.ToLower(strings.TrimSpace(in.Username))
|
||||
in.Nickname = strings.TrimSpace(in.Nickname)
|
||||
in.Phone = strings.TrimSpace(in.Phone)
|
||||
if in.Nickname == "" {
|
||||
return gerror.New("昵称不能为空")
|
||||
}
|
||||
if len([]rune(in.Password)) < 3 || len([]byte(in.Password)) > 72 {
|
||||
return gerror.New("密码长度需为3至72字节")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImUserCreateModel struct {
|
||||
DisplayNo int `json:"displayNo" dc:"后台展示编号"`
|
||||
UserId int64 `json:"userId" dc:"用户ID"`
|
||||
Username string `json:"username" dc:"用户名"`
|
||||
Nickname string `json:"nickname" dc:"昵称"`
|
||||
Phone string `json:"phone" dc:"手机号"`
|
||||
}
|
||||
|
||||
type ImUserBatchCreateInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Count int `json:"count" v:"required|min:1|max:100#创建数量不能为空|创建数量最少为1|单次最多创建100个用户" dc:"创建数量"`
|
||||
Password string `json:"password" v:"required#默认密码不能为空" dc:"默认密码"`
|
||||
NicknamePrefix string `json:"nicknamePrefix" dc:"昵称前缀"`
|
||||
GroupId int64 `json:"groupId" dc:"用户策略分组ID"`
|
||||
}
|
||||
|
||||
func (in *ImUserBatchCreateInp) Filter(ctx context.Context) error {
|
||||
in.NicknamePrefix = strings.TrimSpace(in.NicknamePrefix)
|
||||
if in.Count < 1 || in.Count > 100 {
|
||||
return gerror.New("单次创建数量需为1至100")
|
||||
}
|
||||
if len([]rune(in.Password)) < 3 || len([]byte(in.Password)) > 72 {
|
||||
return gerror.New("密码长度需为3至72字节")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImUserBatchItemModel struct {
|
||||
Row int `json:"row" dc:"行号"`
|
||||
DisplayNo int `json:"displayNo" dc:"后台展示编号"`
|
||||
Username string `json:"username" dc:"用户名"`
|
||||
UserId int64 `json:"userId" dc:"用户ID"`
|
||||
Success bool `json:"success" dc:"是否成功"`
|
||||
Reason string `json:"reason" dc:"失败原因"`
|
||||
}
|
||||
|
||||
type ImUserBatchCreateModel struct {
|
||||
SuccessCount int `json:"successCount" dc:"成功数量"`
|
||||
FailedCount int `json:"failedCount" dc:"失败数量"`
|
||||
Items []*ImUserBatchItemModel `json:"items" dc:"处理明细"`
|
||||
}
|
||||
|
||||
type ImUserImportInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
GroupId int64 `json:"groupId" dc:"默认用户策略分组ID"`
|
||||
Rows []*ImUserCreateInp `json:"rows" dc:"导入用户"`
|
||||
}
|
||||
|
||||
// ImUserViewInp 获取指定IM用户信息
|
||||
type ImUserViewInp struct {
|
||||
TenantId int64 `json:"tenantId" v:"required#租户ID不能为空" dc:"租户ID"`
|
||||
UserId int64 `json:"userId" v:"required#用户ID不能为空" dc:"用户ID"`
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
UserId string `json:"userId" v:"required#用户ID不能为空" dc:"用户ID"`
|
||||
}
|
||||
|
||||
func (in *ImUserViewInp) Filter(ctx context.Context) (err error) {
|
||||
if in.TenantId <= 0 {
|
||||
return gerror.New("请选择租户")
|
||||
}
|
||||
if in.UserId <= 0 {
|
||||
if _, err = ParseOptionalInt64(in.UserId); err != nil {
|
||||
return gerror.New("用户ID不能为空")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImUserPasswordResetInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
UserId string `json:"userId" v:"required#用户ID不能为空" dc:"用户ID"`
|
||||
NewPassword string `json:"newPassword" v:"required#新密码不能为空" dc:"新密码"`
|
||||
}
|
||||
|
||||
func (in *ImUserPasswordResetInp) Filter(ctx context.Context) error {
|
||||
if _, err := ParseOptionalInt64(in.UserId); err != nil {
|
||||
return err
|
||||
}
|
||||
if len([]rune(in.NewPassword)) < 3 {
|
||||
return gerror.New("新密码长度不能少于3位")
|
||||
}
|
||||
if len([]byte(in.NewPassword)) > 72 {
|
||||
return gerror.New("新密码长度不能超过72字节")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImUserRevokeSessionsInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
UserId string `json:"userId" v:"required#用户ID不能为空" dc:"用户ID"`
|
||||
}
|
||||
|
||||
func (in *ImUserRevokeSessionsInp) Filter(ctx context.Context) error {
|
||||
if _, err := ParseOptionalInt64(in.UserId); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImUserStatusInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
UserId string `json:"userId" v:"required#用户ID不能为空" dc:"用户ID"`
|
||||
State int `json:"state" dc:"账号状态"`
|
||||
}
|
||||
|
||||
func (in *ImUserStatusInp) Filter(ctx context.Context) error {
|
||||
if _, err := ParseOptionalInt64(in.UserId); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImUserViewModel struct {
|
||||
ImUserListModel
|
||||
Signature string `json:"signature" dc:"个性签名"`
|
||||
@@ -74,19 +199,36 @@ type ImUserViewModel struct {
|
||||
BirthDate string `json:"birthDate" dc:"出生日期"`
|
||||
ProfileJson string `json:"profileJson" dc:"Tinode Public资料"`
|
||||
TrustedJson string `json:"trustedJson" dc:"Tinode Trusted资料"`
|
||||
TagsJson string `json:"tagsJson" dc:"Tinode标签"`
|
||||
AccessJson string `json:"accessJson" dc:"访问权限"`
|
||||
ProfileVersion int `json:"profileVersion" dc:"资料版本"`
|
||||
}
|
||||
|
||||
type ImUserCommandModel struct {
|
||||
CommandID string `json:"commandId" dc:"命令ID"`
|
||||
EventID string `json:"eventId" dc:"事件ID"`
|
||||
Status string `json:"status" dc:"状态"`
|
||||
TenantID int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantCode string `json:"tenantCode" dc:"租户编码"`
|
||||
EventType string `json:"eventType" dc:"事件类型"`
|
||||
IdempotencyKey string `json:"idempotencyKey" dc:"幂等键"`
|
||||
type ImUserDeviceListInp struct {
|
||||
form.PageReq
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
UserId string `json:"userId" v:"required#用户ID不能为空" dc:"用户ID"`
|
||||
}
|
||||
|
||||
func (in *ImUserDeviceListInp) Filter(ctx context.Context) (err error) {
|
||||
if _, err = ParseOptionalInt64(in.UserId); err != nil {
|
||||
return gerror.New("用户ID不能为空")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ImUserDeviceListModel struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
UserId int64 `json:"userId" dc:"用户ID"`
|
||||
DeviceId string `json:"deviceId" dc:"设备ID"`
|
||||
Platform string `json:"platform" dc:"平台"`
|
||||
Lang string `json:"lang" dc:"语言"`
|
||||
LastSeen *gtime.Time `json:"lastSeen" dc:"最后活跃时间"`
|
||||
PushProvider string `json:"pushProvider" dc:"Push服务商"`
|
||||
PushPlatform string `json:"pushPlatform" dc:"Push平台"`
|
||||
PushAppVersion string `json:"pushAppVersion" dc:"App版本"`
|
||||
PushTokenConfigured bool `json:"pushTokenConfigured" dc:"是否配置Push Token"`
|
||||
PushUpdatedAt *gtime.Time `json:"pushUpdatedAt" dc:"Push更新时间"`
|
||||
}
|
||||
|
||||
type ImUserGovernanceInp struct {
|
||||
@@ -105,12 +247,39 @@ func (in *ImUserGovernanceInp) Filter(ctx context.Context) (err error) {
|
||||
if in.UserId <= 0 {
|
||||
return gerror.New("用户ID不能为空")
|
||||
}
|
||||
if in.ActorUserId <= 0 {
|
||||
return gerror.New("操作IM用户ID不能为空")
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImUserAdjustGroupInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
UserId int64 `json:"userId" v:"required|min:1#用户ID不能为空|用户ID不合法" dc:"用户ID"`
|
||||
GroupId int64 `json:"groupId" v:"required|min:1#用户分组不能为空|用户分组不合法" dc:"用户策略分组ID"`
|
||||
}
|
||||
|
||||
func (in *ImUserAdjustGroupInp) Filter(ctx context.Context) error {
|
||||
if in.UserId <= 0 || in.GroupId <= 0 {
|
||||
return gerror.New("用户和用户分组不能为空")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImUserIPWhitelistInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
UserId int64 `json:"userId" v:"required|min:1#用户ID不能为空|用户ID不合法" dc:"用户ID"`
|
||||
IPList []string `json:"ipList" dc:"IP或CIDR列表"`
|
||||
}
|
||||
|
||||
func (in *ImUserIPWhitelistInp) Filter(ctx context.Context) error {
|
||||
if in.UserId <= 0 {
|
||||
return gerror.New("用户ID不能为空")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImUserIPWhitelistModel struct {
|
||||
IPList []string `json:"ipList" dc:"IP或CIDR列表"`
|
||||
}
|
||||
|
||||
func (in *ImUserGovernanceInp) FilterDevice(ctx context.Context) (err error) {
|
||||
if err = in.Filter(ctx); err != nil {
|
||||
return err
|
||||
@@ -120,3 +289,13 @@ func (in *ImUserGovernanceInp) FilterDevice(ctx context.Context) (err error) {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImUserCommandModel struct {
|
||||
CommandID string `json:"commandId" dc:"命令ID"`
|
||||
EventID string `json:"eventId" dc:"Kafka事件ID"`
|
||||
Status string `json:"status" dc:"状态"`
|
||||
TenantID int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantCode string `json:"tenantCode" dc:"租户编码"`
|
||||
EventType string `json:"eventType" dc:"事件类型"`
|
||||
IdempotencyKey string `json:"idempotencyKey" dc:"幂等键"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
package sysin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/netip"
|
||||
"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 }
|
||||
|
||||
type ImTenantLoginIPWhitelistInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
}
|
||||
|
||||
func (in *ImTenantLoginIPWhitelistInp) Filter(ctx context.Context) error {
|
||||
if in.TenantId < 0 {
|
||||
return gerror.New("租户ID不合法")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImTenantLoginIPWhitelistSaveInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
AppList []string `json:"appList" dc:"APP登录IP白名单"`
|
||||
WebList []string `json:"webList" dc:"Web登录IP白名单"`
|
||||
}
|
||||
|
||||
func (in *ImTenantLoginIPWhitelistSaveInp) Filter(ctx context.Context) (err error) {
|
||||
if in.TenantId < 0 {
|
||||
return gerror.New("租户ID不合法")
|
||||
}
|
||||
if in.AppList, err = normalizeTenantLoginIPList(in.AppList); err != nil {
|
||||
return gerror.Wrap(err, "APP登录白名单不合法")
|
||||
}
|
||||
if in.WebList, err = normalizeTenantLoginIPList(in.WebList); err != nil {
|
||||
return gerror.Wrap(err, "Web登录白名单不合法")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImTenantLoginIPWhitelistModel struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
AppList []string `json:"appList" dc:"APP登录IP白名单"`
|
||||
WebList []string `json:"webList" dc:"Web登录IP白名单"`
|
||||
}
|
||||
|
||||
func normalizeTenantLoginIPList(values []string) ([]string, error) {
|
||||
if len(values) > 500 {
|
||||
return nil, gerror.New("单个渠道最多配置500条IP或CIDR")
|
||||
}
|
||||
result := make([]string, 0, len(values))
|
||||
seen := make(map[string]struct{}, len(values))
|
||||
for _, value := range values {
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" {
|
||||
continue
|
||||
}
|
||||
if prefix, err := netip.ParsePrefix(value); err == nil {
|
||||
value = prefix.Masked().String()
|
||||
} else if address, addressErr := netip.ParseAddr(value); addressErr == nil {
|
||||
value = address.String()
|
||||
} else {
|
||||
return nil, gerror.Newf("%s 不是有效的IPv4、IPv6或CIDR", value)
|
||||
}
|
||||
if _, ok := seen[value]; ok {
|
||||
continue
|
||||
}
|
||||
seen[value] = struct{}{}
|
||||
result = append(result, value)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package sysin
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
)
|
||||
|
||||
func TestImUserGovernanceAllowsAdminActor(t *testing.T) {
|
||||
in := &ImUserGovernanceInp{TenantId: 1, UserId: 2}
|
||||
if err := in.Filter(gctx.New()); err != nil {
|
||||
t.Fatalf("admin governance should not require an IM actor: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestImUserActionInputs(t *testing.T) {
|
||||
ctx := gctx.New()
|
||||
if err := (&ImUserAdjustGroupInp{UserId: 2, GroupId: 3}).Filter(ctx); err != nil {
|
||||
t.Fatalf("valid group adjustment rejected: %v", err)
|
||||
}
|
||||
if err := (&ImUserAdjustGroupInp{UserId: 2}).Filter(ctx); err == nil {
|
||||
t.Fatal("missing group must be rejected")
|
||||
}
|
||||
if err := (&ImUserIPWhitelistInp{UserId: 2}).Filter(ctx); err != nil {
|
||||
t.Fatalf("valid whitelist input rejected: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -32,9 +32,6 @@ type ImWorkOrderListInp struct {
|
||||
}
|
||||
|
||||
func (in *ImWorkOrderListInp) Filter(ctx context.Context) (err error) {
|
||||
if in.TenantId <= 0 {
|
||||
return gerror.New("请选择租户")
|
||||
}
|
||||
if in.Type == "" {
|
||||
return gerror.New("请选择工单类型")
|
||||
}
|
||||
@@ -68,9 +65,6 @@ type ImWorkOrderViewInp struct {
|
||||
}
|
||||
|
||||
func (in *ImWorkOrderViewInp) Filter(ctx context.Context) (err error) {
|
||||
if in.TenantId <= 0 {
|
||||
return gerror.New("请选择租户")
|
||||
}
|
||||
if in.Type != ImWorkOrderTypeAbuse && in.Type != ImWorkOrderTypeFeedback {
|
||||
return gerror.New("工单类型不正确")
|
||||
}
|
||||
@@ -100,9 +94,6 @@ type ImWorkOrderStatusInp struct {
|
||||
}
|
||||
|
||||
func (in *ImWorkOrderStatusInp) Filter(ctx context.Context) (err error) {
|
||||
if in.TenantId <= 0 {
|
||||
return gerror.New("请选择租户")
|
||||
}
|
||||
if in.Type != ImWorkOrderTypeAbuse && in.Type != ImWorkOrderTypeFeedback {
|
||||
return gerror.New("工单类型不正确")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
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 ImWorkbenchAppListInp struct {
|
||||
form.PageReq
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Code string `json:"code" dc:"模块编码"`
|
||||
Name string `json:"name" dc:"模块名称"`
|
||||
Enabled *int `json:"enabled" dc:"启用状态"`
|
||||
}
|
||||
|
||||
func (in *ImWorkbenchAppListInp) Filter(ctx context.Context) (err error) {
|
||||
in.Code = strings.TrimSpace(in.Code)
|
||||
in.Name = strings.TrimSpace(in.Name)
|
||||
if in.Enabled != nil && !dict.HasOptionKey(consts.ImWorkbenchAppEnabledOptions, *in.Enabled) {
|
||||
return gerror.New("启用状态不合法")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImWorkbenchAppModel struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
TenantName string `json:"tenantName" dc:"租户名称"`
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
Code string `json:"code" dc:"模块编码"`
|
||||
Name string `json:"name" dc:"模块名称"`
|
||||
IconFileId string `json:"iconFileId" dc:"图标文件ID"`
|
||||
Route string `json:"route" dc:"客户端路由"`
|
||||
SortOrder int `json:"sortOrder" dc:"排序"`
|
||||
UnreadKey string `json:"unreadKey" dc:"未读角标Key"`
|
||||
Enabled int `json:"enabled" dc:"启用状态"`
|
||||
Permission string `json:"permission" dc:"权限策略"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
}
|
||||
|
||||
type ImWorkbenchAppEditInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
Code string `json:"code" v:"required#模块编码不能为空" dc:"模块编码"`
|
||||
Name string `json:"name" v:"required#模块名称不能为空" dc:"模块名称"`
|
||||
IconFileId string `json:"iconFileId" dc:"图标文件ID"`
|
||||
Route string `json:"route" v:"required#客户端路由不能为空" dc:"客户端路由"`
|
||||
SortOrder int `json:"sortOrder" dc:"排序"`
|
||||
UnreadKey string `json:"unreadKey" dc:"未读角标Key"`
|
||||
Enabled int `json:"enabled" dc:"启用状态"`
|
||||
Permission string `json:"permission" dc:"权限策略"`
|
||||
}
|
||||
|
||||
func (in *ImWorkbenchAppEditInp) Filter(ctx context.Context) (err error) {
|
||||
in.Code = strings.TrimSpace(in.Code)
|
||||
in.Name = strings.TrimSpace(in.Name)
|
||||
in.IconFileId = strings.TrimSpace(in.IconFileId)
|
||||
in.Route = strings.TrimSpace(in.Route)
|
||||
in.UnreadKey = strings.TrimSpace(in.UnreadKey)
|
||||
in.Permission = strings.TrimSpace(in.Permission)
|
||||
if in.Code == "" {
|
||||
return gerror.New("模块编码不能为空")
|
||||
}
|
||||
if strings.ContainsAny(in.Code, " \t\r\n/") {
|
||||
return gerror.New("模块编码不能包含空格或斜杠")
|
||||
}
|
||||
if len([]rune(in.Code)) > 64 {
|
||||
return gerror.New("模块编码不能超过64个字符")
|
||||
}
|
||||
if in.Name == "" {
|
||||
return gerror.New("模块名称不能为空")
|
||||
}
|
||||
if len([]rune(in.Name)) > 128 {
|
||||
return gerror.New("模块名称不能超过128个字符")
|
||||
}
|
||||
if !dict.HasOptionKey(consts.ImWorkbenchRouteOptions, in.Route) {
|
||||
return gerror.New("客户端路由不在当前IM服务端白名单内")
|
||||
}
|
||||
if !dict.HasOptionKey(consts.ImWorkbenchAppEnabledOptions, in.Enabled) {
|
||||
return gerror.New("启用状态不合法")
|
||||
}
|
||||
if in.Permission == "" {
|
||||
in.Permission = consts.ImWorkbenchPermissionEnabled
|
||||
}
|
||||
if !dict.HasOptionKey(consts.ImWorkbenchPermissionOptions, in.Permission) {
|
||||
return gerror.New("权限策略不合法")
|
||||
}
|
||||
if len([]rune(in.IconFileId)) > 64 {
|
||||
return gerror.New("图标文件ID不能超过64个字符")
|
||||
}
|
||||
if len([]rune(in.UnreadKey)) > 64 {
|
||||
return gerror.New("未读角标Key不能超过64个字符")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImWorkbenchAppDeleteInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
Code string `json:"code" dc:"模块编码"`
|
||||
}
|
||||
|
||||
func (in *ImWorkbenchAppDeleteInp) Filter(ctx context.Context) (err error) {
|
||||
in.Code = strings.TrimSpace(in.Code)
|
||||
if in.Id <= 0 && in.Code == "" {
|
||||
return gerror.New("请选择要禁用的工作台模块")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImWorkbenchAppReorderItem struct {
|
||||
Code string `json:"code" dc:"模块编码"`
|
||||
SortOrder int `json:"sortOrder" dc:"排序"`
|
||||
}
|
||||
|
||||
type ImWorkbenchAppReorderInp struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Items []*ImWorkbenchAppReorderItem `json:"items" dc:"排序列表"`
|
||||
}
|
||||
|
||||
func (in *ImWorkbenchAppReorderInp) Filter(ctx context.Context) (err error) {
|
||||
if len(in.Items) == 0 {
|
||||
return gerror.New("排序列表不能为空")
|
||||
}
|
||||
for _, item := range in.Items {
|
||||
if item == nil {
|
||||
return gerror.New("排序项不能为空")
|
||||
}
|
||||
item.Code = strings.TrimSpace(item.Code)
|
||||
if item.Code == "" {
|
||||
return gerror.New("模块编码不能为空")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user