refactor: merge tenant configuration into tenant registry
This commit is contained in:
@@ -35,8 +35,6 @@ type TenantModel struct {
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
TenantDesc *string `json:"tenant_desc,omitempty"`
|
||||
DBName string `json:"db_name"`
|
||||
DBDSN string `json:"db_dsn"`
|
||||
State int `json:"state"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
CreatedBy int64 `json:"created_by"`
|
||||
|
||||
@@ -178,17 +178,8 @@ func (c *cConfig) ModerationPolicy(ctx context.Context, req *api.ModerationPolic
|
||||
return nil, err
|
||||
}
|
||||
res = defaultModerationPolicy(tenant)
|
||||
var tenantConfig struct {
|
||||
AliyunModerationEnabled int `json:"aliyun_moderation_enabled"`
|
||||
LocalModerationEnabled int `json:"local_moderation_enabled"`
|
||||
}
|
||||
if err = imtenant.RegistryDB().Model(dao.ImTenantConfig.Table()).Safe().Ctx(ctx).
|
||||
Fields("aliyun_moderation_enabled", "local_moderation_enabled").
|
||||
Where(dao.ImTenantConfig.Columns().TenantId, tenant.Id).Scan(&tenantConfig); err != nil {
|
||||
return nil, gerror.Wrap(err, "获取商户内容审核开关失败")
|
||||
}
|
||||
res.AliyunEnabled = tenantConfig.AliyunModerationEnabled == 1
|
||||
res.LocalWordsEnabled = tenantConfig.LocalModerationEnabled == 1
|
||||
res.AliyunEnabled = tenant.AliyunModerationEnabled == 1
|
||||
res.LocalWordsEnabled = tenant.LocalModerationEnabled == 1
|
||||
res.Enabled = res.AliyunEnabled || res.LocalWordsEnabled
|
||||
columns := dao.ImSecurityPolicy.Columns()
|
||||
var row struct {
|
||||
@@ -333,18 +324,7 @@ func (c *cConfig) RealnamePolicy(ctx context.Context, req *api.RealnamePolicyReq
|
||||
return nil, err
|
||||
}
|
||||
res = defaultRealnamePolicy(tenant.Id)
|
||||
var row *struct {
|
||||
RealnameReviewPolicy int `json:"realname_review_policy"`
|
||||
}
|
||||
if err = imtenant.RegistryDB().Model(dao.ImTenantConfig.Table()).Safe().Ctx(ctx).
|
||||
Fields("realname_review_policy").
|
||||
Where(dao.ImTenantConfig.Columns().TenantId, tenant.Id).Scan(&row); err != nil {
|
||||
return nil, gerror.Wrap(err, "获取租户实名认证策略失败")
|
||||
}
|
||||
if row == nil {
|
||||
return res, nil
|
||||
}
|
||||
if row.RealnameReviewPolicy == 1 {
|
||||
if tenant.RealnameReviewPolicy == 1 {
|
||||
res.RealnameReviewPolicy = 1
|
||||
}
|
||||
return res, nil
|
||||
@@ -553,8 +533,6 @@ func tenantToModel(tenant *entity.ImTenant) *api.TenantModel {
|
||||
Code: tenant.Code,
|
||||
Name: tenant.Name,
|
||||
TenantDesc: &desc,
|
||||
DBName: tenant.DbName,
|
||||
DBDSN: tenant.DbDsn,
|
||||
State: tenant.State,
|
||||
CreatedAt: gtimeToRFC3339(tenant.CreatedAt),
|
||||
CreatedBy: tenant.CreatedBy,
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
// =================================================================================
|
||||
// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed.
|
||||
// =================================================================================
|
||||
|
||||
package dao
|
||||
|
||||
import (
|
||||
"hotgo/internal/dao/internal"
|
||||
)
|
||||
|
||||
// imTenantConfigDao is the data access object for the table im_tenant_config.
|
||||
// You can define custom methods on it to extend its functionality as needed.
|
||||
type imTenantConfigDao struct {
|
||||
*internal.ImTenantConfigDao
|
||||
}
|
||||
|
||||
var (
|
||||
// ImTenantConfig is a globally accessible object for table im_tenant_config operations.
|
||||
ImTenantConfig = imTenantConfigDao{internal.NewImTenantConfigDao()}
|
||||
)
|
||||
|
||||
// Add your custom methods and functionality below.
|
||||
@@ -21,32 +21,58 @@ type ImTenantDao struct {
|
||||
|
||||
// ImTenantColumns defines and stores column names for the table im_tenant.
|
||||
type ImTenantColumns struct {
|
||||
Id string //
|
||||
Code string //
|
||||
Name string //
|
||||
TenantDesc string //
|
||||
DbName string //
|
||||
DbDsn string //
|
||||
State string //
|
||||
CreatedAt string //
|
||||
CreatedBy string //
|
||||
UpdatedAt string //
|
||||
UpdatedBy string //
|
||||
Id string //
|
||||
Code string //
|
||||
Name string //
|
||||
TenantDesc string //
|
||||
MaxUsers string // 0表示ä¸é™åˆ¶
|
||||
MaxGroups string // 0表示ä¸é™åˆ¶
|
||||
MaxGroupMembers string // 0表示ä¸é™åˆ¶
|
||||
RealnameReviewPolicy string // 实åå®¡æ ¸ç–略:0自动通过,1è½¬äººå·¥å®¡æ ¸
|
||||
RealnameProviderMode string // 实åè®¤è¯æ¨¡å¼
|
||||
RealnameRequired string // 是å¦å¼ºåˆ¶å®žå
|
||||
RealnameAllowSkip string // 是å¦å…许跳过实å
|
||||
RealnameRemindAfter string // 实åæé†’延迟
|
||||
AliyunModerationEnabled string // 是å¦å¯ç”¨é˜¿é‡Œäº‘å†…å®¹å®¡æ ¸
|
||||
LocalModerationEnabled string // 是å¦å¯ç”¨æœ¬åœ°å†…å®¹å®¡æ ¸
|
||||
MessageEncryptionEnabled string // 是å¦å¯ç”¨æ¶ˆæ¯åР坆
|
||||
DefaultPolicyGroupId string // 默认用户ç–略组
|
||||
SecurityPolicyVersion string // å·²å‘布安全ç–略版本
|
||||
GlobalFriendEnabled string // å…¨å±€åŠ å¥½å‹å¼€å…³
|
||||
MessageCurfewEnabled string // 消æ¯å®µç¦å¼€å…³
|
||||
State string //
|
||||
CreatedAt string //
|
||||
CreatedBy string //
|
||||
UpdatedAt string //
|
||||
UpdatedBy string //
|
||||
}
|
||||
|
||||
// imTenantColumns holds the columns for the table im_tenant.
|
||||
var imTenantColumns = ImTenantColumns{
|
||||
Id: "id",
|
||||
Code: "code",
|
||||
Name: "name",
|
||||
TenantDesc: "tenant_desc",
|
||||
DbName: "db_name",
|
||||
DbDsn: "db_dsn",
|
||||
State: "state",
|
||||
CreatedAt: "created_at",
|
||||
CreatedBy: "created_by",
|
||||
UpdatedAt: "updated_at",
|
||||
UpdatedBy: "updated_by",
|
||||
Id: "id",
|
||||
Code: "code",
|
||||
Name: "name",
|
||||
TenantDesc: "tenant_desc",
|
||||
MaxUsers: "max_users",
|
||||
MaxGroups: "max_groups",
|
||||
MaxGroupMembers: "max_group_members",
|
||||
RealnameReviewPolicy: "realname_review_policy",
|
||||
RealnameProviderMode: "realname_provider_mode",
|
||||
RealnameRequired: "realname_required",
|
||||
RealnameAllowSkip: "realname_allow_skip",
|
||||
RealnameRemindAfter: "realname_remind_after",
|
||||
AliyunModerationEnabled: "aliyun_moderation_enabled",
|
||||
LocalModerationEnabled: "local_moderation_enabled",
|
||||
MessageEncryptionEnabled: "message_encryption_enabled",
|
||||
DefaultPolicyGroupId: "default_policy_group_id",
|
||||
SecurityPolicyVersion: "security_policy_version",
|
||||
GlobalFriendEnabled: "global_friend_enabled",
|
||||
MessageCurfewEnabled: "message_curfew_enabled",
|
||||
State: "state",
|
||||
CreatedAt: "created_at",
|
||||
CreatedBy: "created_by",
|
||||
UpdatedAt: "updated_at",
|
||||
UpdatedBy: "updated_by",
|
||||
}
|
||||
|
||||
// NewImTenantDao creates and returns a new DAO object for table data access.
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
// ==========================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// ==========================================================================
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// ImTenantConfigDao is the data access object for the table im_tenant_config.
|
||||
type ImTenantConfigDao struct {
|
||||
table string // table is the underlying table name of the DAO.
|
||||
group string // group is the database configuration group name of the current DAO.
|
||||
columns ImTenantConfigColumns // columns contains all the column names of Table for convenient usage.
|
||||
handlers []gdb.ModelHandler // handlers for customized model modification.
|
||||
}
|
||||
|
||||
// ImTenantConfigColumns defines and stores column names for the table im_tenant_config.
|
||||
type ImTenantConfigColumns struct {
|
||||
Id string //
|
||||
TenantId string //
|
||||
MaxUsers string // 0 means unlimited
|
||||
MaxGroups string // 0 means unlimited
|
||||
MaxGroupMembers string // 0 means unlimited
|
||||
DefaultPolicyGroupId string // Default user policy group
|
||||
SecurityPolicyVersion string // Published security policy version
|
||||
GlobalFriendEnabled string // Published global friend switch
|
||||
MessageCurfewEnabled string // Published message curfew switch
|
||||
CreatedAt string //
|
||||
CreatedBy string //
|
||||
UpdatedAt string //
|
||||
UpdatedBy string //
|
||||
}
|
||||
|
||||
// imTenantConfigColumns holds the columns for the table im_tenant_config.
|
||||
var imTenantConfigColumns = ImTenantConfigColumns{
|
||||
Id: "id",
|
||||
TenantId: "tenant_id",
|
||||
MaxUsers: "max_users",
|
||||
MaxGroups: "max_groups",
|
||||
MaxGroupMembers: "max_group_members",
|
||||
DefaultPolicyGroupId: "default_policy_group_id",
|
||||
SecurityPolicyVersion: "security_policy_version",
|
||||
GlobalFriendEnabled: "global_friend_enabled",
|
||||
MessageCurfewEnabled: "message_curfew_enabled",
|
||||
CreatedAt: "created_at",
|
||||
CreatedBy: "created_by",
|
||||
UpdatedAt: "updated_at",
|
||||
UpdatedBy: "updated_by",
|
||||
}
|
||||
|
||||
// NewImTenantConfigDao creates and returns a new DAO object for table data access.
|
||||
func NewImTenantConfigDao(handlers ...gdb.ModelHandler) *ImTenantConfigDao {
|
||||
return &ImTenantConfigDao{
|
||||
group: "default",
|
||||
table: "im_tenant_config",
|
||||
columns: imTenantConfigColumns,
|
||||
handlers: handlers,
|
||||
}
|
||||
}
|
||||
|
||||
// DB retrieves and returns the underlying raw database management object of the current DAO.
|
||||
func (dao *ImTenantConfigDao) DB() gdb.DB {
|
||||
return g.DB(dao.group)
|
||||
}
|
||||
|
||||
// Table returns the table name of the current DAO.
|
||||
func (dao *ImTenantConfigDao) Table() string {
|
||||
return dao.table
|
||||
}
|
||||
|
||||
// Columns returns all column names of the current DAO.
|
||||
func (dao *ImTenantConfigDao) Columns() ImTenantConfigColumns {
|
||||
return dao.columns
|
||||
}
|
||||
|
||||
// Group returns the database configuration group name of the current DAO.
|
||||
func (dao *ImTenantConfigDao) Group() string {
|
||||
return dao.group
|
||||
}
|
||||
|
||||
// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation.
|
||||
func (dao *ImTenantConfigDao) Ctx(ctx context.Context) *gdb.Model {
|
||||
model := dao.DB().Model(dao.table)
|
||||
for _, handler := range dao.handlers {
|
||||
model = handler(model)
|
||||
}
|
||||
return model.Safe().Ctx(ctx)
|
||||
}
|
||||
|
||||
// Transaction wraps the transaction logic using function f.
|
||||
// It rolls back the transaction and returns the error if function f returns a non-nil error.
|
||||
// It commits the transaction and returns nil if function f returns nil.
|
||||
//
|
||||
// Note: Do not commit or roll back the transaction in function f,
|
||||
// as it is automatically handled by this function.
|
||||
func (dao *ImTenantConfigDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
|
||||
return dao.Ctx(ctx).Transaction(ctx, f)
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
var tenantDbGroups sync.Map
|
||||
|
||||
const registryDbGroup = "imRegistry"
|
||||
const sharedBusinessDatabase = "meeting_im"
|
||||
|
||||
var registryDbGroupOnce sync.Once
|
||||
|
||||
@@ -47,19 +48,15 @@ func DB(ctx context.Context, tenantId int64) (db gdb.DB, tenant *entity.ImTenant
|
||||
// Tenant isolation inside this database is implemented by tenant_id predicates
|
||||
// and the three tenant-partitioned high-volume table families.
|
||||
func SharedDB(ctx context.Context) (gdb.DB, error) {
|
||||
var sharedTenant *entity.ImTenant
|
||||
if err := RegistryDB().Model(dao.ImTenant.Table()).Safe().Ctx(ctx).
|
||||
Where(dao.ImTenant.Columns().Code, "default").Scan(&sharedTenant); err != nil {
|
||||
return nil, gerror.Wrap(err, "获取共享业务库配置失败")
|
||||
defaultLink := defaultDbLink(ctx)
|
||||
if defaultLink == "" {
|
||||
return nil, gerror.New("默认数据库连接未配置,无法连接共享业务库")
|
||||
}
|
||||
if sharedTenant == nil || sharedTenant.Id <= 0 {
|
||||
return nil, gerror.New("默认商户不存在,无法确定共享业务库")
|
||||
}
|
||||
link, err := tenantLink(ctx, sharedTenant)
|
||||
link, err := replaceMySQLDatabase(defaultLink, sharedBusinessDatabase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dbForLink(link, sharedTenant.Id)
|
||||
return dbForLink(link, 0)
|
||||
}
|
||||
|
||||
func dbForLink(link string, ownerID int64) (gdb.DB, error) {
|
||||
@@ -111,31 +108,6 @@ func ensureRegistryDBGroup() {
|
||||
_ = gdb.SetConfigGroup(registryDbGroup, cloned)
|
||||
}
|
||||
|
||||
func tenantLink(ctx context.Context, tenant *entity.ImTenant) (string, error) {
|
||||
if tenant.DbDsn != "" {
|
||||
return normalizeMySQLTimeOptions(tenant.DbDsn)
|
||||
}
|
||||
if tenant.DbName == "" {
|
||||
// 未配置独立业务库的商户回落共享默认库
|
||||
defaultLink := defaultDbLink(ctx)
|
||||
if defaultLink == "" {
|
||||
return "", gerror.New("默认数据库连接未配置,无法回落共享业务库")
|
||||
}
|
||||
return normalizeMySQLTimeOptions(defaultLink)
|
||||
}
|
||||
|
||||
defaultLink := defaultDbLink(ctx)
|
||||
if defaultLink == "" {
|
||||
return "", gerror.New("默认数据库连接未配置,无法推导租户业务库连接")
|
||||
}
|
||||
|
||||
link, err := replaceMySQLDatabase(defaultLink, tenant.DbName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return link, nil
|
||||
}
|
||||
|
||||
func defaultDbLink(ctx context.Context) string {
|
||||
if configs, err := gdb.GetConfigGroup("default"); err == nil && len(configs) > 0 {
|
||||
if configs[0].Link != "" {
|
||||
|
||||
@@ -40,10 +40,9 @@ func (s *sSysImMessageEncryption) List(ctx context.Context, in *sysin.ImMessageE
|
||||
}
|
||||
db := imtenant.RegistryDB()
|
||||
mod := db.Model(dao.ImTenant.Table()+" t").Safe().Ctx(ctx).
|
||||
LeftJoin(dao.ImTenantConfig.Table()+" c", "c.tenant_id=t.id").
|
||||
Fields(
|
||||
"t.id tenant_id", "t.code tenant_code", "t.name tenant_name",
|
||||
"COALESCE(c."+imTenantMessageEncryptionColumn+",0) message_encryption_enabled",
|
||||
"t."+imTenantMessageEncryptionColumn+" message_encryption_enabled",
|
||||
"COALESCE((SELECT MAX(k.key_version) FROM "+imMessageEncryptionKeyTable+" k WHERE k.tenant_id=t.id AND k.status='active'),0) active_version",
|
||||
"COALESCE((SELECT MAX(k.key_version) FROM "+imMessageEncryptionKeyTable+" k WHERE k.tenant_id=t.id AND k.status='pending'),0) pending_version",
|
||||
"(SELECT COUNT(1) FROM "+imMessageEncryptionKeyTable+" k WHERE k.tenant_id=t.id) key_count",
|
||||
@@ -56,7 +55,7 @@ func (s *sSysImMessageEncryption) List(ctx context.Context, in *sysin.ImMessageE
|
||||
mod = mod.Where("t.code LIKE ? OR t.name LIKE ?", "%"+keyword+"%", "%"+keyword+"%")
|
||||
}
|
||||
if in.Enabled != nil {
|
||||
mod = mod.Where("COALESCE(c."+imTenantMessageEncryptionColumn+",0)=?", *in.Enabled)
|
||||
mod = mod.Where("t."+imTenantMessageEncryptionColumn, *in.Enabled)
|
||||
}
|
||||
if err = mod.Page(in.Page, in.PerPage).OrderAsc("t.id").ScanAndCount(&list, &total, false); err != nil {
|
||||
return nil, 0, gerror.Wrap(err, "获取商户消息加密配置失败")
|
||||
@@ -185,16 +184,16 @@ func (s *sSysImMessageEncryption) Switch(ctx context.Context, in *sysin.ImMessag
|
||||
return gerror.New("启用消息加密前必须先初始化有效密钥")
|
||||
}
|
||||
}
|
||||
result, err := imtenant.RegistryDB().Model(dao.ImTenantConfig.Table()).Safe().Ctx(ctx).
|
||||
Where(dao.ImTenantConfig.Columns().TenantId, tenant.Id).
|
||||
Data(g.Map{imTenantMessageEncryptionColumn: in.Enabled, dao.ImTenantConfig.Columns().UpdatedBy: contexts.GetUserId(ctx)}).Update()
|
||||
result, err := imtenant.RegistryDB().Model(dao.ImTenant.Table()).Safe().Ctx(ctx).
|
||||
Where(dao.ImTenant.Columns().Id, tenant.Id).
|
||||
Data(g.Map{dao.ImTenant.Columns().MessageEncryptionEnabled: in.Enabled, dao.ImTenant.Columns().UpdatedBy: contexts.GetUserId(ctx)}).Update()
|
||||
if err != nil {
|
||||
return gerror.Wrap(err, "更新商户消息加密开关失败")
|
||||
}
|
||||
if affected, _ := result.RowsAffected(); affected == 0 {
|
||||
return gerror.New("商户配置不存在")
|
||||
}
|
||||
_ = writeImAdminAudit(ctx, tenant.Id, "message_encryption_switch", "im_tenant_config", tenant.Id, "success", g.Map{"enabled": in.Enabled})
|
||||
_ = writeImAdminAudit(ctx, tenant.Id, "message_encryption_switch", dao.ImTenant.Table(), tenant.Id, "success", g.Map{"enabled": in.Enabled})
|
||||
return publishImPolicyEvent(ctx, tenant.Id, tenant.Code, "tenant.features.updated", "message_encryption", 0)
|
||||
}
|
||||
|
||||
@@ -203,8 +202,8 @@ func (s *sSysImMessageEncryption) GetKey(ctx context.Context, in *sysin.ImMessag
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
enabledValue, err := imtenant.RegistryDB().Model(dao.ImTenantConfig.Table()).Safe().Ctx(ctx).
|
||||
Fields(imTenantMessageEncryptionColumn).Where(dao.ImTenantConfig.Columns().TenantId, tenant.Id).Value()
|
||||
enabledValue, err := imtenant.RegistryDB().Model(dao.ImTenant.Table()).Safe().Ctx(ctx).
|
||||
Fields(dao.ImTenant.Columns().MessageEncryptionEnabled).Where(dao.ImTenant.Columns().Id, tenant.Id).Value()
|
||||
if err != nil {
|
||||
return nil, gerror.Wrap(err, "获取商户消息加密开关失败")
|
||||
}
|
||||
|
||||
@@ -207,8 +207,8 @@ func (s *sSysImSecurityPolicy) Publish(ctx context.Context, in *sysin.ImSecurity
|
||||
return updateErr
|
||||
}
|
||||
if tenantID > 0 {
|
||||
tc := dao.ImTenantConfig.Columns()
|
||||
if _, updateErr := tx.Model(dao.ImTenantConfig.Table()).Safe().Ctx(ctx).Where(tc.TenantId, tenantID).Data(g.Map{tc.SecurityPolicyVersion: row[c.PolicyVersion].Uint(), tc.GlobalFriendEnabled: row[c.GlobalFriendEnabled].Int(), tc.MessageCurfewEnabled: row[c.MessageCurfewEnabled].Int(), tc.UpdatedAt: now, tc.UpdatedBy: operator}).Update(); updateErr != nil {
|
||||
tc := dao.ImTenant.Columns()
|
||||
if _, updateErr := tx.Model(dao.ImTenant.Table()).Safe().Ctx(ctx).Where(tc.Id, tenantID).Data(g.Map{tc.SecurityPolicyVersion: row[c.PolicyVersion].Uint(), tc.GlobalFriendEnabled: row[c.GlobalFriendEnabled].Int(), tc.MessageCurfewEnabled: row[c.MessageCurfewEnabled].Int(), tc.UpdatedAt: now, tc.UpdatedBy: operator}).Update(); updateErr != nil {
|
||||
return updateErr
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,28 +27,9 @@ import (
|
||||
|
||||
type sSysImTenant struct{}
|
||||
|
||||
const (
|
||||
tenantConfigAliyunModerationEnabled = "aliyun_moderation_enabled"
|
||||
tenantConfigLocalModerationEnabled = "local_moderation_enabled"
|
||||
tenantConfigMessageEncryptionEnabled = "message_encryption_enabled"
|
||||
tenantConfigRealnameReviewPolicy = "realname_review_policy"
|
||||
)
|
||||
|
||||
// imManageRoleKey 商户级IM管理员角色标识
|
||||
const imManageRoleKey = "imManage"
|
||||
|
||||
type imTenantConfigModeration struct {
|
||||
Id int64 `json:"id" orm:"id"`
|
||||
TenantId int64 `json:"tenant_id" orm:"tenant_id"`
|
||||
MaxUsers uint64 `json:"max_users" orm:"max_users"`
|
||||
MaxGroups uint64 `json:"max_groups" orm:"max_groups"`
|
||||
MaxGroupMembers uint `json:"max_group_members" orm:"max_group_members"`
|
||||
AliyunModerationEnabled int `json:"aliyun_moderation_enabled" orm:"aliyun_moderation_enabled"`
|
||||
LocalModerationEnabled int `json:"local_moderation_enabled" orm:"local_moderation_enabled"`
|
||||
MessageEncryptionEnabled int `json:"message_encryption_enabled" orm:"message_encryption_enabled"`
|
||||
RealnameReviewPolicy int `json:"realname_review_policy" orm:"realname_review_policy"`
|
||||
}
|
||||
|
||||
func NewSysImTenant() *sSysImTenant {
|
||||
return &sSysImTenant{}
|
||||
}
|
||||
@@ -62,10 +43,6 @@ func (s *sSysImTenant) Model(ctx context.Context, option ...*handler.Option) *gd
|
||||
return handler.Model(imtenant.RegistryDB().Model(dao.ImTenant.Table()).Safe().Ctx(ctx), option...)
|
||||
}
|
||||
|
||||
func (s *sSysImTenant) configModel(ctx context.Context) *gdb.Model {
|
||||
return imtenant.RegistryDB().Model(dao.ImTenantConfig.Table()).Safe().Ctx(ctx)
|
||||
}
|
||||
|
||||
// List 获取IM租户列表
|
||||
func (s *sSysImTenant) List(ctx context.Context, in *sysin.ImTenantListInp) (list []*sysin.ImTenantListModel, totalCount int, err error) {
|
||||
if err = in.Filter(ctx); err != nil {
|
||||
@@ -77,7 +54,13 @@ func (s *sSysImTenant) List(ctx context.Context, in *sysin.ImTenantListInp) (lis
|
||||
dao.ImTenant.Columns().Code,
|
||||
dao.ImTenant.Columns().Name,
|
||||
dao.ImTenant.Columns().TenantDesc,
|
||||
dao.ImTenant.Columns().DbName,
|
||||
dao.ImTenant.Columns().MaxUsers,
|
||||
dao.ImTenant.Columns().MaxGroups,
|
||||
dao.ImTenant.Columns().MaxGroupMembers,
|
||||
dao.ImTenant.Columns().AliyunModerationEnabled,
|
||||
dao.ImTenant.Columns().LocalModerationEnabled,
|
||||
dao.ImTenant.Columns().MessageEncryptionEnabled,
|
||||
dao.ImTenant.Columns().RealnameReviewPolicy,
|
||||
dao.ImTenant.Columns().State,
|
||||
dao.ImTenant.Columns().CreatedBy,
|
||||
dao.ImTenant.Columns().UpdatedBy,
|
||||
@@ -102,9 +85,6 @@ func (s *sSysImTenant) List(ctx context.Context, in *sysin.ImTenantListInp) (lis
|
||||
if in.Name != "" {
|
||||
mod = mod.WhereLike(dao.ImTenant.Columns().Name, "%"+in.Name+"%")
|
||||
}
|
||||
if in.DbName != "" && isSuperTenantAdmin(ctx) {
|
||||
mod = mod.WhereLike(dao.ImTenant.Columns().DbName, "%"+in.DbName+"%")
|
||||
}
|
||||
if in.State != nil {
|
||||
mod = mod.Where(dao.ImTenant.Columns().State, *in.State)
|
||||
}
|
||||
@@ -120,64 +100,6 @@ func (s *sSysImTenant) List(ctx context.Context, in *sysin.ImTenantListInp) (lis
|
||||
err = gerror.Wrap(err, "获取IM租户列表失败,请稍后重试!")
|
||||
return
|
||||
}
|
||||
if len(list) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if err = s.fillListConfig(ctx, list); err != nil {
|
||||
return
|
||||
}
|
||||
// 业务库名仅超管可见,非超管脱敏返回
|
||||
if !isSuperTenantAdmin(ctx) {
|
||||
for _, item := range list {
|
||||
item.DbName = ""
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *sSysImTenant) fillListConfig(ctx context.Context, list []*sysin.ImTenantListModel) (err error) {
|
||||
ids := make([]int64, 0, len(list))
|
||||
for _, item := range list {
|
||||
ids = append(ids, item.Id)
|
||||
}
|
||||
|
||||
var configs []*imTenantConfigModeration
|
||||
if err = s.configModel(ctx).
|
||||
WhereIn(dao.ImTenantConfig.Columns().TenantId, ids).
|
||||
Scan(&configs); err != nil {
|
||||
return gerror.Wrap(err, "获取IM租户配置失败,请稍后重试!")
|
||||
}
|
||||
configMap := make(map[int64]*imTenantConfigModeration, len(configs))
|
||||
for _, item := range configs {
|
||||
configMap[item.TenantId] = item
|
||||
}
|
||||
|
||||
var tenants []*entity.ImTenant
|
||||
if err = s.Model(ctx).
|
||||
Fields(dao.ImTenant.Columns().Id, dao.ImTenant.Columns().DbDsn).
|
||||
WhereIn(dao.ImTenant.Columns().Id, ids).
|
||||
Scan(&tenants); err != nil {
|
||||
return gerror.Wrap(err, "获取IM租户连接配置失败,请稍后重试!")
|
||||
}
|
||||
dsnMap := make(map[int64]string, len(tenants))
|
||||
for _, item := range tenants {
|
||||
dsnMap[item.Id] = item.DbDsn
|
||||
}
|
||||
|
||||
super := isSuperTenantAdmin(ctx)
|
||||
for _, item := range list {
|
||||
if conf, ok := configMap[item.Id]; ok {
|
||||
item.MaxUsers = conf.MaxUsers
|
||||
item.MaxGroups = conf.MaxGroups
|
||||
item.MaxGroupMembers = conf.MaxGroupMembers
|
||||
item.AliyunModerationEnabled = conf.AliyunModerationEnabled
|
||||
item.LocalModerationEnabled = conf.LocalModerationEnabled
|
||||
item.MessageEncryptionEnabled = conf.MessageEncryptionEnabled
|
||||
item.RealnameReviewPolicy = conf.RealnameReviewPolicy
|
||||
}
|
||||
item.DbDsnConfigured = super && dsnMap[item.Id] != ""
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -230,14 +152,10 @@ func (s *sSysImTenant) saveTenant(ctx context.Context, in *sysin.ImTenantEditInp
|
||||
if err = ensureTenantIDSequence(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.DbName, in.DbDsn, err = sharedDatabaseConfig(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
in.State = consts.ImTenantStateProvisioning
|
||||
} else if !super {
|
||||
// 业务库名与独立连接串仅超管可维护,非超管提交一律强制忽略。
|
||||
in.DbName = ""
|
||||
in.DbDsn = ""
|
||||
}
|
||||
if err = validateTenantMessageEncryption(ctx, in.Id, in.MessageEncryptionEnabled); err != nil {
|
||||
return err
|
||||
}
|
||||
err = imtenant.RegistryDB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
|
||||
if err = s.checkCodeUnique(ctx, in.Id, in.Code); err != nil {
|
||||
@@ -248,21 +166,24 @@ func (s *sSysImTenant) saveTenant(ctx context.Context, in *sysin.ImTenantEditInp
|
||||
if in.Id > 0 {
|
||||
in.UpdatedBy = userId
|
||||
data := g.Map{
|
||||
dao.ImTenant.Columns().Code: in.Code,
|
||||
dao.ImTenant.Columns().Name: in.Name,
|
||||
dao.ImTenant.Columns().TenantDesc: in.TenantDesc,
|
||||
dao.ImTenant.Columns().State: in.State,
|
||||
dao.ImTenant.Columns().UpdatedBy: userId,
|
||||
}
|
||||
if super {
|
||||
data[dao.ImTenant.Columns().DbName] = in.DbName
|
||||
data[dao.ImTenant.Columns().DbDsn] = in.DbDsn
|
||||
dao.ImTenant.Columns().Code: in.Code,
|
||||
dao.ImTenant.Columns().Name: in.Name,
|
||||
dao.ImTenant.Columns().TenantDesc: in.TenantDesc,
|
||||
dao.ImTenant.Columns().MaxUsers: in.MaxUsers,
|
||||
dao.ImTenant.Columns().MaxGroups: in.MaxGroups,
|
||||
dao.ImTenant.Columns().MaxGroupMembers: in.MaxGroupMembers,
|
||||
dao.ImTenant.Columns().AliyunModerationEnabled: in.AliyunModerationEnabled,
|
||||
dao.ImTenant.Columns().LocalModerationEnabled: in.LocalModerationEnabled,
|
||||
dao.ImTenant.Columns().MessageEncryptionEnabled: in.MessageEncryptionEnabled,
|
||||
dao.ImTenant.Columns().RealnameReviewPolicy: in.RealnameReviewPolicy,
|
||||
dao.ImTenant.Columns().State: in.State,
|
||||
dao.ImTenant.Columns().UpdatedBy: userId,
|
||||
}
|
||||
if _, err = s.Model(ctx).
|
||||
WherePri(in.Id).Data(data).Update(); err != nil {
|
||||
return gerror.Wrap(err, "修改IM租户失败,请稍后重试!")
|
||||
}
|
||||
return s.saveConfig(ctx, in, userId)
|
||||
return nil
|
||||
}
|
||||
|
||||
in.Id, err = nextTenantID(tx)
|
||||
@@ -278,7 +199,7 @@ func (s *sSysImTenant) saveTenant(ctx context.Context, in *sysin.ImTenantEditInp
|
||||
return gerror.Wrap(err, "新增IM租户失败,请稍后重试!")
|
||||
}
|
||||
tenantID = in.Id
|
||||
return s.saveConfig(ctx, in, userId)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -413,15 +334,7 @@ func (s *sSysImTenant) resetTenantAdminPassword(ctx context.Context, tenantId in
|
||||
|
||||
// rollbackTenantCreation 商户创建补偿:删除已写入的商户及配置记录
|
||||
func (s *sSysImTenant) rollbackTenantCreation(ctx context.Context, tenantId int64) {
|
||||
_ = imtenant.RegistryDB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
|
||||
if _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).
|
||||
WherePri(tenantId).Delete(); err != nil {
|
||||
return
|
||||
}
|
||||
_, err = s.configModel(ctx).
|
||||
Where(dao.ImTenantConfig.Columns().TenantId, tenantId).Delete()
|
||||
return
|
||||
})
|
||||
_, _ = s.Model(ctx, &handler.Option{FilterAuth: false}).WherePri(tenantId).Delete()
|
||||
}
|
||||
|
||||
func (s *sSysImTenant) checkCodeUnique(ctx context.Context, id int64, code string) (err error) {
|
||||
@@ -439,10 +352,10 @@ func (s *sSysImTenant) checkCodeUnique(ctx context.Context, id int64, code strin
|
||||
return
|
||||
}
|
||||
|
||||
func (s *sSysImTenant) saveConfig(ctx context.Context, in *sysin.ImTenantEditInp, userId int64) (err error) {
|
||||
if in.MessageEncryptionEnabled == 1 {
|
||||
func validateTenantMessageEncryption(ctx context.Context, tenantId int64, enabled int) error {
|
||||
if enabled == 1 {
|
||||
count, queryErr := imtenant.RegistryDB().Model(imMessageEncryptionKeyTable).Safe().Ctx(ctx).
|
||||
Where("tenant_id", in.Id).
|
||||
Where("tenant_id", tenantId).
|
||||
Where("status", consts.ImMessageKeyStatusActive).
|
||||
Count()
|
||||
if queryErr != nil {
|
||||
@@ -452,61 +365,7 @@ func (s *sSysImTenant) saveConfig(ctx context.Context, in *sysin.ImTenantEditInp
|
||||
return gerror.New("启用消息加密前必须先在消息密钥管理中初始化有效密钥")
|
||||
}
|
||||
}
|
||||
var conf *entity.ImTenantConfig
|
||||
if err = s.configModel(ctx).
|
||||
Where(dao.ImTenantConfig.Columns().TenantId, in.Id).
|
||||
Scan(&conf); err != nil {
|
||||
return gerror.Wrap(err, "获取IM租户配置失败,请稍后重试!")
|
||||
}
|
||||
|
||||
data := g.Map{
|
||||
dao.ImTenantConfig.Columns().MaxUsers: in.MaxUsers,
|
||||
dao.ImTenantConfig.Columns().MaxGroups: in.MaxGroups,
|
||||
dao.ImTenantConfig.Columns().MaxGroupMembers: in.MaxGroupMembers,
|
||||
tenantConfigAliyunModerationEnabled: in.AliyunModerationEnabled,
|
||||
tenantConfigLocalModerationEnabled: in.LocalModerationEnabled,
|
||||
tenantConfigMessageEncryptionEnabled: in.MessageEncryptionEnabled,
|
||||
tenantConfigRealnameReviewPolicy: in.RealnameReviewPolicy,
|
||||
}
|
||||
if conf != nil && conf.Id > 0 {
|
||||
data[dao.ImTenantConfig.Columns().UpdatedBy] = userId
|
||||
if _, err = s.configModel(ctx).
|
||||
Fields(
|
||||
dao.ImTenantConfig.Columns().MaxUsers,
|
||||
dao.ImTenantConfig.Columns().MaxGroups,
|
||||
dao.ImTenantConfig.Columns().MaxGroupMembers,
|
||||
tenantConfigAliyunModerationEnabled,
|
||||
tenantConfigLocalModerationEnabled,
|
||||
tenantConfigMessageEncryptionEnabled,
|
||||
tenantConfigRealnameReviewPolicy,
|
||||
dao.ImTenantConfig.Columns().UpdatedBy,
|
||||
).
|
||||
WherePri(conf.Id).Data(data).Update(); err != nil {
|
||||
return gerror.Wrap(err, "修改IM租户配置失败,请稍后重试!")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
data[dao.ImTenantConfig.Columns().TenantId] = in.Id
|
||||
data[dao.ImTenantConfig.Columns().CreatedBy] = userId
|
||||
data[dao.ImTenantConfig.Columns().UpdatedBy] = userId
|
||||
if _, err = s.configModel(ctx).
|
||||
Fields(
|
||||
dao.ImTenantConfig.Columns().TenantId,
|
||||
dao.ImTenantConfig.Columns().MaxUsers,
|
||||
dao.ImTenantConfig.Columns().MaxGroups,
|
||||
dao.ImTenantConfig.Columns().MaxGroupMembers,
|
||||
tenantConfigAliyunModerationEnabled,
|
||||
tenantConfigLocalModerationEnabled,
|
||||
tenantConfigMessageEncryptionEnabled,
|
||||
tenantConfigRealnameReviewPolicy,
|
||||
dao.ImTenantConfig.Columns().CreatedBy,
|
||||
dao.ImTenantConfig.Columns().UpdatedBy,
|
||||
).
|
||||
Data(data).Insert(); err != nil {
|
||||
return gerror.Wrap(err, "新增IM租户配置失败,请稍后重试!")
|
||||
}
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
// View 获取IM租户指定信息
|
||||
@@ -522,23 +381,6 @@ func (s *sSysImTenant) View(ctx context.Context, in *sysin.ImTenantViewInp) (res
|
||||
return
|
||||
}
|
||||
|
||||
var conf *imTenantConfigModeration
|
||||
if err = s.configModel(ctx).
|
||||
Where(dao.ImTenantConfig.Columns().TenantId, in.Id).
|
||||
Scan(&conf); err != nil {
|
||||
err = gerror.Wrap(err, "获取IM租户配置失败,请稍后重试!")
|
||||
return
|
||||
}
|
||||
if conf != nil {
|
||||
res.MaxUsers = conf.MaxUsers
|
||||
res.MaxGroups = conf.MaxGroups
|
||||
res.MaxGroupMembers = conf.MaxGroupMembers
|
||||
res.AliyunModerationEnabled = conf.AliyunModerationEnabled
|
||||
res.LocalModerationEnabled = conf.LocalModerationEnabled
|
||||
res.MessageEncryptionEnabled = conf.MessageEncryptionEnabled
|
||||
res.RealnameReviewPolicy = conf.RealnameReviewPolicy
|
||||
}
|
||||
res.DbDsnConfigured = res.DbDsn != ""
|
||||
// 查询商户自动创建的管理员账号(编辑弹窗展示)
|
||||
roleVal, roleErr := dao.AdminRole.Ctx(ctx).
|
||||
Fields(dao.AdminRole.Columns().Id).
|
||||
@@ -558,12 +400,6 @@ func (s *sSysImTenant) View(ctx context.Context, in *sysin.ImTenantViewInp) (res
|
||||
res.AdminUsername = userVal.String()
|
||||
}
|
||||
}
|
||||
// 业务库名与独立连接串仅超管可见,非超管全部脱敏
|
||||
if !isSuperTenantAdmin(ctx) {
|
||||
res.DbName = ""
|
||||
res.DbDsn = ""
|
||||
res.DbDsnConfigured = false
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -601,17 +437,10 @@ func (s *sSysImTenant) Usage(ctx context.Context, in *sysin.ImTenantUsageInp) (r
|
||||
}
|
||||
|
||||
res = &sysin.ImTenantUsageModel{
|
||||
Id: tenant.Id,
|
||||
Code: tenant.Code,
|
||||
Name: tenant.Name,
|
||||
DbName: tenant.DbName,
|
||||
DbDsnConfigured: tenant.DbDsn != "",
|
||||
Warnings: []string{},
|
||||
}
|
||||
// 业务库名与连接串信息仅超管可见,非超管全部脱敏
|
||||
if !isSuperTenantAdmin(ctx) {
|
||||
res.DbName = ""
|
||||
res.DbDsnConfigured = false
|
||||
Id: tenant.Id,
|
||||
Code: tenant.Code,
|
||||
Name: tenant.Name,
|
||||
Warnings: []string{},
|
||||
}
|
||||
|
||||
db, _, dbErr := imtenant.DB(ctx, tenant.Id)
|
||||
|
||||
@@ -12,17 +12,6 @@ import (
|
||||
|
||||
const imTenantIDSequenceTable = "im_tenant_id_sequence"
|
||||
|
||||
func sharedDatabaseConfig(ctx context.Context) (dbName, dbDSN string, err error) {
|
||||
row, err := imtenant.RegistryDB().GetOne(ctx, "SELECT db_name,db_dsn FROM im_tenant WHERE code='default' LIMIT 1")
|
||||
if err != nil {
|
||||
return "", "", gerror.Wrap(err, "获取共享业务库配置失败")
|
||||
}
|
||||
if row.IsEmpty() {
|
||||
return "", "", gerror.New("默认商户不存在,无法确定共享业务库")
|
||||
}
|
||||
return row["db_name"].String(), row["db_dsn"].String(), nil
|
||||
}
|
||||
|
||||
func ensureTenantIDSequence(ctx context.Context) error {
|
||||
db := imtenant.RegistryDB()
|
||||
if _, err := db.Exec(ctx, `CREATE TABLE IF NOT EXISTS im_tenant_id_sequence (
|
||||
|
||||
@@ -11,16 +11,29 @@ import (
|
||||
|
||||
// ImTenant is the golang structure of table im_tenant for DAO operations like Where/Data.
|
||||
type ImTenant struct {
|
||||
g.Meta `orm:"table:im_tenant, do:true"`
|
||||
Id any //
|
||||
Code any //
|
||||
Name any //
|
||||
TenantDesc any //
|
||||
DbName any //
|
||||
DbDsn any //
|
||||
State any //
|
||||
CreatedAt *gtime.Time //
|
||||
CreatedBy any //
|
||||
UpdatedAt *gtime.Time //
|
||||
UpdatedBy any //
|
||||
g.Meta `orm:"table:im_tenant, do:true"`
|
||||
Id any //
|
||||
Code any //
|
||||
Name any //
|
||||
TenantDesc any //
|
||||
MaxUsers any // 0表示ä¸é™åˆ¶
|
||||
MaxGroups any // 0表示ä¸é™åˆ¶
|
||||
MaxGroupMembers any // 0表示ä¸é™åˆ¶
|
||||
RealnameReviewPolicy any // 实åå®¡æ ¸ç–略:0自动通过,1è½¬äººå·¥å®¡æ ¸
|
||||
RealnameProviderMode any // 实åè®¤è¯æ¨¡å¼
|
||||
RealnameRequired any // 是å¦å¼ºåˆ¶å®žå
|
||||
RealnameAllowSkip any // 是å¦å…许跳过实å
|
||||
RealnameRemindAfter any // 实åæé†’延迟
|
||||
AliyunModerationEnabled any // 是å¦å¯ç”¨é˜¿é‡Œäº‘å†…å®¹å®¡æ ¸
|
||||
LocalModerationEnabled any // 是å¦å¯ç”¨æœ¬åœ°å†…å®¹å®¡æ ¸
|
||||
MessageEncryptionEnabled any // 是å¦å¯ç”¨æ¶ˆæ¯åР坆
|
||||
DefaultPolicyGroupId any // 默认用户ç–略组
|
||||
SecurityPolicyVersion any // å·²å‘布安全ç–略版本
|
||||
GlobalFriendEnabled any // å…¨å±€åŠ å¥½å‹å¼€å…³
|
||||
MessageCurfewEnabled any // 消æ¯å®µç¦å¼€å…³
|
||||
State any //
|
||||
CreatedAt *gtime.Time //
|
||||
CreatedBy any //
|
||||
UpdatedAt *gtime.Time //
|
||||
UpdatedBy any //
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
// =================================================================================
|
||||
// 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"
|
||||
)
|
||||
|
||||
// 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
|
||||
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 //
|
||||
}
|
||||
@@ -10,15 +10,28 @@ import (
|
||||
|
||||
// ImTenant is the golang structure for table im_tenant.
|
||||
type ImTenant struct {
|
||||
Id int64 `json:"id" orm:"id" description:""`
|
||||
Code string `json:"code" orm:"code" description:""`
|
||||
Name string `json:"name" orm:"name" description:""`
|
||||
TenantDesc string `json:"tenantDesc" orm:"tenant_desc" description:""`
|
||||
DbName string `json:"dbName" orm:"db_name" description:""`
|
||||
DbDsn string `json:"dbDsn" orm:"db_dsn" description:""`
|
||||
State int `json:"state" orm:"state" 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:""`
|
||||
Id int64 `json:"id" orm:"id" description:""`
|
||||
Code string `json:"code" orm:"code" description:""`
|
||||
Name string `json:"name" orm:"name" description:""`
|
||||
TenantDesc string `json:"tenantDesc" orm:"tenant_desc" description:""`
|
||||
MaxUsers uint64 `json:"maxUsers" orm:"max_users" description:"0表示ä¸é™åˆ¶"`
|
||||
MaxGroups uint64 `json:"maxGroups" orm:"max_groups" description:"0表示ä¸é™åˆ¶"`
|
||||
MaxGroupMembers uint `json:"maxGroupMembers" orm:"max_group_members" description:"0表示ä¸é™åˆ¶"`
|
||||
RealnameReviewPolicy int `json:"realnameReviewPolicy" orm:"realname_review_policy" description:"实åå®¡æ ¸ç–略:0自动通过,1è½¬äººå·¥å®¡æ ¸"`
|
||||
RealnameProviderMode string `json:"realnameProviderMode" orm:"realname_provider_mode" description:"实åè®¤è¯æ¨¡å¼"`
|
||||
RealnameRequired int `json:"realnameRequired" orm:"realname_required" description:"是å¦å¼ºåˆ¶å®žå"`
|
||||
RealnameAllowSkip int `json:"realnameAllowSkip" orm:"realname_allow_skip" description:"是å¦å…许跳过实å"`
|
||||
RealnameRemindAfter string `json:"realnameRemindAfter" orm:"realname_remind_after" description:"实åæé†’延迟"`
|
||||
AliyunModerationEnabled int `json:"aliyunModerationEnabled" orm:"aliyun_moderation_enabled" description:"是å¦å¯ç”¨é˜¿é‡Œäº‘å†…å®¹å®¡æ ¸"`
|
||||
LocalModerationEnabled int `json:"localModerationEnabled" orm:"local_moderation_enabled" description:"是å¦å¯ç”¨æœ¬åœ°å†…å®¹å®¡æ ¸"`
|
||||
MessageEncryptionEnabled int `json:"messageEncryptionEnabled" orm:"message_encryption_enabled" description:"是å¦å¯ç”¨æ¶ˆæ¯åР坆"`
|
||||
DefaultPolicyGroupId int64 `json:"defaultPolicyGroupId" orm:"default_policy_group_id" description:"默认用户ç–略组"`
|
||||
SecurityPolicyVersion uint `json:"securityPolicyVersion" orm:"security_policy_version" description:"å·²å‘布安全ç–略版本"`
|
||||
GlobalFriendEnabled int `json:"globalFriendEnabled" orm:"global_friend_enabled" description:"å…¨å±€åŠ å¥½å‹å¼€å…³"`
|
||||
MessageCurfewEnabled int `json:"messageCurfewEnabled" orm:"message_curfew_enabled" description:"消æ¯å®µç¦å¼€å…³"`
|
||||
State int `json:"state" orm:"state" 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:""`
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package entity
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// 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"`
|
||||
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:""`
|
||||
}
|
||||
@@ -20,32 +20,10 @@ import (
|
||||
|
||||
// ImTenantInsertFields 新增IM租户字段过滤
|
||||
type ImTenantInsertFields struct {
|
||||
Id int64 `json:"id" dc:"商户ID"`
|
||||
Code string `json:"code" dc:"租户编码"`
|
||||
Name string `json:"name" dc:"租户名称"`
|
||||
TenantDesc string `json:"tenantDesc" dc:"租户描述"`
|
||||
DbName string `json:"dbName" dc:"业务库名"`
|
||||
DbDsn string `json:"dbDsn" dc:"独立连接串"`
|
||||
State int `json:"state" dc:"状态"`
|
||||
CreatedBy int64 `json:"createdBy" dc:"创建者"`
|
||||
UpdatedBy int64 `json:"updatedBy" dc:"更新者"`
|
||||
}
|
||||
|
||||
// ImTenantConfigUpdateFields 修改IM租户配置字段过滤
|
||||
type ImTenantConfigUpdateFields struct {
|
||||
MaxUsers uint64 `json:"maxUsers" dc:"最大用户数"`
|
||||
MaxGroups uint64 `json:"maxGroups" dc:"最大群组数"`
|
||||
MaxGroupMembers uint `json:"maxGroupMembers" dc:"最大群成员数"`
|
||||
AliyunModerationEnabled int `json:"aliyunModerationEnabled" dc:"是否启用阿里云内容审核"`
|
||||
LocalModerationEnabled int `json:"localModerationEnabled" dc:"是否启用本地内容审核"`
|
||||
MessageEncryptionEnabled int `json:"messageEncryptionEnabled" dc:"是否启用消息加密"`
|
||||
RealnameReviewPolicy int `json:"realnameReviewPolicy" dc:"实名审核策略"`
|
||||
UpdatedBy int64 `json:"updatedBy" dc:"更新者"`
|
||||
}
|
||||
|
||||
// ImTenantConfigInsertFields 新增IM租户配置字段过滤
|
||||
type ImTenantConfigInsertFields struct {
|
||||
TenantId int64 `json:"tenantId" dc:"租户ID"`
|
||||
Id int64 `json:"id" dc:"商户ID"`
|
||||
Code string `json:"code" dc:"商户编码"`
|
||||
Name string `json:"name" dc:"商户名称"`
|
||||
TenantDesc string `json:"tenantDesc" dc:"商户描述"`
|
||||
MaxUsers uint64 `json:"maxUsers" dc:"最大用户数"`
|
||||
MaxGroups uint64 `json:"maxGroups" dc:"最大群组数"`
|
||||
MaxGroupMembers uint `json:"maxGroupMembers" dc:"最大群成员数"`
|
||||
@@ -53,21 +31,16 @@ type ImTenantConfigInsertFields struct {
|
||||
LocalModerationEnabled int `json:"localModerationEnabled" dc:"是否启用本地内容审核"`
|
||||
MessageEncryptionEnabled int `json:"messageEncryptionEnabled" dc:"是否启用消息加密"`
|
||||
RealnameReviewPolicy int `json:"realnameReviewPolicy" dc:"实名审核策略"`
|
||||
State int `json:"state" dc:"状态"`
|
||||
CreatedBy int64 `json:"createdBy" dc:"创建者"`
|
||||
UpdatedBy int64 `json:"updatedBy" dc:"更新者"`
|
||||
}
|
||||
|
||||
// ImTenantEditInp 修改/新增IM租户
|
||||
type ImTenantEditInp struct {
|
||||
entity.ImTenant
|
||||
MaxUsers uint64 `json:"maxUsers" dc:"最大用户数"`
|
||||
MaxGroups uint64 `json:"maxGroups" dc:"最大群组数"`
|
||||
MaxGroupMembers uint `json:"maxGroupMembers" dc:"最大群成员数"`
|
||||
AliyunModerationEnabled int `json:"aliyunModerationEnabled" dc:"是否启用阿里云内容审核"`
|
||||
LocalModerationEnabled int `json:"localModerationEnabled" dc:"是否启用本地内容审核"`
|
||||
MessageEncryptionEnabled int `json:"messageEncryptionEnabled" dc:"是否启用消息加密"`
|
||||
RealnameReviewPolicy int `json:"realnameReviewPolicy" dc:"实名审核策略"`
|
||||
AdminUsername string `json:"adminUsername" dc:"新增商户时自动创建的后台管理员账号名"`
|
||||
AdminPassword string `json:"adminPassword" dc:"新增商户时自动创建的后台管理员初始密码"`
|
||||
AdminUsername string `json:"adminUsername" dc:"新增商户时自动创建的后台管理员账号名"`
|
||||
AdminPassword string `json:"adminPassword" dc:"新增商户时自动创建的后台管理员初始密码"`
|
||||
}
|
||||
|
||||
func (in *ImTenantEditInp) Filter(ctx context.Context) (err error) {
|
||||
@@ -119,19 +92,9 @@ func (in *ImTenantViewInp) Filter(ctx context.Context) (err error) {
|
||||
|
||||
type ImTenantViewModel struct {
|
||||
entity.ImTenant
|
||||
AdminUsername string `json:"adminUsername" dc:"商户管理员账号"`
|
||||
MaxUsers uint64 `json:"maxUsers" dc:"最大用户数"`
|
||||
MaxGroups uint64 `json:"maxGroups" dc:"最大群组数"`
|
||||
MaxGroupMembers uint `json:"maxGroupMembers" dc:"最大群成员数"`
|
||||
AliyunModerationEnabled int `json:"aliyunModerationEnabled" dc:"是否启用阿里云内容审核"`
|
||||
LocalModerationEnabled int `json:"localModerationEnabled" dc:"是否启用本地内容审核"`
|
||||
MessageEncryptionEnabled int `json:"messageEncryptionEnabled" dc:"是否启用消息加密"`
|
||||
RealnameReviewPolicy int `json:"realnameReviewPolicy" dc:"实名审核策略"`
|
||||
CreatedBySumma *hook.MemberSumma `json:"createdBySumma" dc:"创建者摘要信息"`
|
||||
UpdatedBySumma *hook.MemberSumma `json:"updatedBySumma" dc:"更新者摘要信息"`
|
||||
DbDsnConfigured bool `json:"dbDsnConfigured" dc:"是否配置独立连接串"`
|
||||
TenantDbReachable bool `json:"tenantDbReachable" dc:"业务库是否可达"`
|
||||
TenantDbCheckError string `json:"tenantDbCheckError" dc:"业务库检查错误"`
|
||||
AdminUsername string `json:"adminUsername" dc:"商户管理员账号"`
|
||||
CreatedBySumma *hook.MemberSumma `json:"createdBySumma" dc:"创建者摘要信息"`
|
||||
UpdatedBySumma *hook.MemberSumma `json:"updatedBySumma" dc:"更新者摘要信息"`
|
||||
}
|
||||
|
||||
// ImTenantListInp 获取IM租户列表
|
||||
@@ -140,7 +103,6 @@ type ImTenantListInp struct {
|
||||
Id int64 `json:"id" dc:"ID"`
|
||||
Code string `json:"code" dc:"租户编码"`
|
||||
Name string `json:"name" dc:"租户名称"`
|
||||
DbName string `json:"dbName" dc:"业务库名"`
|
||||
State *int `json:"state" dc:"状态"`
|
||||
CreatedAt []*gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
}
|
||||
@@ -154,7 +116,6 @@ type ImTenantListModel struct {
|
||||
Code string `json:"code" dc:"租户编码"`
|
||||
Name string `json:"name" dc:"租户名称"`
|
||||
TenantDesc string `json:"tenantDesc" dc:"租户描述"`
|
||||
DbName string `json:"dbName" dc:"业务库名"`
|
||||
State int `json:"state" dc:"状态"`
|
||||
MaxUsers uint64 `json:"maxUsers" dc:"最大用户数"`
|
||||
MaxGroups uint64 `json:"maxGroups" dc:"最大群组数"`
|
||||
@@ -163,7 +124,6 @@ type ImTenantListModel struct {
|
||||
LocalModerationEnabled int `json:"localModerationEnabled" dc:"是否启用本地内容审核"`
|
||||
MessageEncryptionEnabled int `json:"messageEncryptionEnabled" dc:"是否启用消息加密"`
|
||||
RealnameReviewPolicy int `json:"realnameReviewPolicy" dc:"实名审核策略"`
|
||||
DbDsnConfigured bool `json:"dbDsnConfigured" dc:"是否配置独立连接串"`
|
||||
CreatedBy int64 `json:"createdBy" dc:"创建者"`
|
||||
CreatedBySumma *hook.MemberSumma `json:"createdBySumma" dc:"创建者摘要信息"`
|
||||
UpdatedBy int64 `json:"updatedBy" dc:"更新者"`
|
||||
@@ -205,8 +165,6 @@ 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版本"`
|
||||
|
||||
@@ -6,9 +6,9 @@ SET @now := NOW();
|
||||
|
||||
SET @im_sql = IF(
|
||||
(SELECT COUNT(*) FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'im_tenant_config'
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'im_tenant'
|
||||
AND COLUMN_NAME = 'message_encryption_enabled') = 0,
|
||||
'ALTER TABLE `im_tenant_config` ADD COLUMN `message_encryption_enabled` TINYINT(1) NOT NULL DEFAULT 0 COMMENT ''是否启用消息加密'' AFTER `local_moderation_enabled`',
|
||||
'ALTER TABLE `im_tenant` ADD COLUMN `message_encryption_enabled` TINYINT(1) NOT NULL DEFAULT 0 COMMENT ''是否启用消息加密'' AFTER `local_moderation_enabled`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE im_stmt FROM @im_sql;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
-- 第一阶段:将商户配置扩展并回填到 im_tenant。
|
||||
-- 必须先执行本文件,再发布新版 manager 与 IM Server。
|
||||
-- 本阶段保留 im_tenant_config、db_name、db_dsn,确保旧实例在滚动发布期间仍可运行。
|
||||
|
||||
ALTER TABLE `im_tenant`
|
||||
ADD COLUMN `max_users` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '0表示不限制' AFTER `tenant_desc`,
|
||||
ADD COLUMN `max_groups` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '0表示不限制' AFTER `max_users`,
|
||||
ADD COLUMN `max_group_members` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '0表示不限制' AFTER `max_groups`,
|
||||
ADD COLUMN `realname_review_policy` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '实名审核策略:0自动通过,1转人工审核' AFTER `max_group_members`,
|
||||
ADD COLUMN `realname_provider_mode` VARCHAR(32) NOT NULL DEFAULT 'id_card_2factor' COMMENT '实名认证模式' AFTER `realname_review_policy`,
|
||||
ADD COLUMN `realname_required` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否强制实名' AFTER `realname_provider_mode`,
|
||||
ADD COLUMN `realname_allow_skip` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许跳过实名' AFTER `realname_required`,
|
||||
ADD COLUMN `realname_remind_after` VARCHAR(32) NOT NULL DEFAULT '24h' COMMENT '实名提醒延迟' AFTER `realname_allow_skip`,
|
||||
ADD COLUMN `aliyun_moderation_enabled` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否启用阿里云内容审核' AFTER `realname_remind_after`,
|
||||
ADD COLUMN `local_moderation_enabled` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否启用本地内容审核' AFTER `aliyun_moderation_enabled`,
|
||||
ADD COLUMN `message_encryption_enabled` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否启用消息加密' AFTER `local_moderation_enabled`,
|
||||
ADD COLUMN `default_policy_group_id` BIGINT DEFAULT NULL COMMENT '默认用户策略组' AFTER `message_encryption_enabled`,
|
||||
ADD COLUMN `security_policy_version` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '已发布安全策略版本' AFTER `default_policy_group_id`,
|
||||
ADD COLUMN `global_friend_enabled` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '全局加好友开关' AFTER `security_policy_version`,
|
||||
ADD COLUMN `message_curfew_enabled` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '消息宵禁开关' AFTER `global_friend_enabled`;
|
||||
|
||||
UPDATE `im_tenant` t
|
||||
INNER JOIN `im_tenant_config` c ON c.`tenant_id`=t.`id`
|
||||
SET t.`max_users`=c.`max_users`,
|
||||
t.`max_groups`=c.`max_groups`,
|
||||
t.`max_group_members`=c.`max_group_members`,
|
||||
t.`realname_review_policy`=c.`realname_review_policy`,
|
||||
t.`realname_provider_mode`=c.`realname_provider_mode`,
|
||||
t.`realname_required`=c.`realname_required`,
|
||||
t.`realname_allow_skip`=c.`realname_allow_skip`,
|
||||
t.`realname_remind_after`=c.`realname_remind_after`,
|
||||
t.`aliyun_moderation_enabled`=c.`aliyun_moderation_enabled`,
|
||||
t.`local_moderation_enabled`=c.`local_moderation_enabled`,
|
||||
t.`message_encryption_enabled`=c.`message_encryption_enabled`,
|
||||
t.`default_policy_group_id`=c.`default_policy_group_id`,
|
||||
t.`security_policy_version`=c.`security_policy_version`,
|
||||
t.`global_friend_enabled`=c.`global_friend_enabled`,
|
||||
t.`message_curfew_enabled`=c.`message_curfew_enabled`;
|
||||
@@ -0,0 +1,9 @@
|
||||
-- 第二阶段:新版 manager 与 IM Server 全部发布并验证后执行。
|
||||
-- 清理已废弃的商户配置表和按商户选库字段。
|
||||
|
||||
DROP TABLE `im_tenant_config`;
|
||||
|
||||
ALTER TABLE `im_tenant`
|
||||
DROP INDEX `idx_im_tenant_db_name`,
|
||||
DROP COLUMN `db_name`,
|
||||
DROP COLUMN `db_dsn`;
|
||||
Reference in New Issue
Block a user