|
|
|
@@ -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)
|
|
|
|
|