Files
iotlcm/app/server/internal/logic/system/sys_tenant.go
T

640 lines
20 KiB
Go

// package system
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package system
import (
"context"
"database/sql"
"errors"
"fmt"
"slices"
"strings"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/consts"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/dao"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/contexts"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/event"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/xgorm/handler"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model/do"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model/entity"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/service"
"git.5iot.com/iotlcm-public/iotlcm-app/utility"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv"
)
type sSysTenant struct {
}
func NewSysTenant() *sSysTenant {
return &sSysTenant{}
}
func init() {
s := NewSysTenant()
service.RegisterSysTenant(s)
}
func (l *sSysTenant) ModelQuery(ctx context.Context, option ...*handler.Option) *gdb.Model {
if len(option) == 0 {
option = append(option, &handler.Option{
FilterTenant: false,
})
}
return handler.Model(service.MemoryDB().DB(ctx).Ctx(ctx).Model(dao.SysTenant.Table()), option...)
}
// 获取租户信息
func (l *sSysTenant) View(ctx context.Context, param *model.SysTenantViewParam) (data *model.SysTenantViewModel, err error) {
db := l.ModelQuery(ctx)
if param.Id != 0 {
db = db.Where(dao.SysTenant.Columns().Id, param.Id)
} else if param.TenantId != "" {
db = db.Where(dao.SysTenant.Columns().TenantId, param.TenantId)
} else {
return nil, errors.New("参数错误")
}
err = db.Scan(&data)
return
}
// 获取租户列表
func (l *sSysTenant) List(ctx context.Context, param *model.SysTenantListParam) (data []*model.SysTenantListModel, total int, err error) {
// db := dao.SysTenant.Ctx(ctx)
// 内存数据库优化
db := l.ModelQuery(ctx)
if param.TenantId != "" {
db = db.Where(dao.SysTenant.Columns().TenantId, param.TenantId)
}
if param.ContactUserName != "" {
db = db.WhereLike(dao.SysTenant.Columns().ContactUserName, "%"+param.ContactUserName+"%")
}
if param.ContactPhone != "" {
db = db.WhereLike(dao.SysTenant.Columns().ContactPhone, "%"+param.ContactPhone+"%")
}
if param.CompanyName != "" {
db = db.WhereLike(dao.SysTenant.Columns().CompanyName, "%"+param.CompanyName+"%")
}
if param.LicenseNumber != "" {
db = db.WhereLike(dao.SysTenant.Columns().LicenseNumber, "%"+param.LicenseNumber+"%")
}
if param.Status != "" {
db = db.Where(dao.SysTenant.Columns().Status, param.Status)
}
total, err = db.Count()
if err != nil {
return nil, 0, err
}
err = db.Page(param.Page, param.PageSize).OrderAsc(dao.SysTenant.Columns().PackageId).Scan(&data)
if err != nil {
return nil, 0, err
}
return data, total, nil
}
func (l *sSysTenant) Add(ctx context.Context, param *model.SysTenantAddParam) (output *model.SysTenantAddModel, err error) {
data := &do.SysTenant{}
gconv.Struct(param, &data)
data.CreatedAt = gtime.Now()
data.CreatedBy = contexts.GetUserId(ctx)
data.CreatedDept = contexts.GetDeptId(ctx)
// 查询租户套餐
tenantPackage, err := service.SysTenantPackage().View(ctx, &model.SysTenantPackageViewParam{
PackageId: param.PackageId,
})
if err != nil || tenantPackage == nil {
g.Log().Errorf(ctx, "sSysTenant.Add SysTenantPackage().View err: %v, packageId: %d, param: %+v",
err, param.PackageId, param)
err = errors.New("租户套餐不存在")
return nil, err
}
if tenantPackage.MenuIds == "" {
err = errors.New("租户套餐菜单为空")
return nil, err
}
menuIds := strings.Split(tenantPackage.MenuIds, ",")
tenantId := ""
deptId := int64(0)
roleId := int64(0)
userId := int64(0)
sysConfigIds := make([]int64, 0)
err = g.DB().Transaction(context.TODO(), func(ctx context.Context, tx gdb.TX) error {
data.TenantId = "100000"
id, err := dao.SysTenant.Ctx(ctx).TX(tx).Data(data).OmitNil().InsertAndGetId()
if err != nil {
g.Log().Errorf(ctx, "sSysTenant.Add SysTenant.Table().InsertAndGetId err: %v, data: %+v", err, data)
return err
}
tenantId = fmt.Sprintf("%06d", 100000+id)
// 创建部门
dataDeptInsert := do.SysDept{}
dataDeptInsert.TenantId = tenantId
dataDeptInsert.DeptName = param.CompanyName
dataDeptInsert.ParentId = 0
dataDeptInsert.OrderNum = 0
dataDeptInsert.DeptType = 1 // 0:部门 1是公司
dataDeptInsert.Status = consts.SysDeptStatusNormal
dataDeptInsert.CreatedBy = contexts.GetUserId(ctx)
dataDeptInsert.CreatedAt = gtime.Now()
dataDeptInsert.UpdatedBy = contexts.GetUserId(ctx)
dataDeptInsert.UpdatedAt = gtime.Now()
deptId, err = dao.SysDept.Ctx(ctx).TX(tx).Data(dataDeptInsert).OmitNil().InsertAndGetId()
if err != nil {
g.Log().Errorf(ctx, "sSysTenant.Add SysDept.Table().InsertAndGetId err: %v, data: %+v", err, dataDeptInsert)
return err
}
// 创建角色
dataRoleInsert := do.SysRole{}
dataRoleInsert.TenantId = tenantId
dataRoleInsert.RoleName = "租户管理员"
dataRoleInsert.RoleKey = "tenantAdmin"
dataRoleInsert.RoleSort = 1
dataRoleInsert.Status = "0"
dataRoleInsert.DataScope = consts.SysRoleDataScopeAll
dataRoleInsert.MenuCheckStrictly = 0
dataRoleInsert.DeptCheckStrictly = 0
dataRoleInsert.CreatedBy = contexts.GetUserId(ctx)
dataRoleInsert.CreatedAt = gtime.Now()
dataRoleInsert.UpdatedBy = contexts.GetUserId(ctx)
dataRoleInsert.UpdatedAt = gtime.Now()
roleId, err = dao.SysRole.Ctx(ctx).TX(tx).Data(dataRoleInsert).OmitNil().InsertAndGetId()
if err != nil {
g.Log().Errorf(ctx, "sSysTenant.Add SysRole.Table().InsertAndGetId err: %v, data: %+v", err, dataRoleInsert)
return err
}
// 角色关联菜单
dataRoleMenuInserts := []*do.SysRoleMenu{}
for _, menuId := range menuIds {
dataRoleMenuInserts = append(dataRoleMenuInserts, &do.SysRoleMenu{
RoleId: roleId,
MenuId: menuId,
})
}
_, err = dao.SysRoleMenu.Ctx(ctx).TX(tx).Data(dataRoleMenuInserts).OmitNil().Insert()
if err != nil {
g.Log().Errorf(ctx, "sSysTenant.Add SysRoleMenu.Table().Insert err: %v, data: %+v", err, dataRoleMenuInserts)
return err
}
// 创建系统管理员
salt := utility.RandomString(5)
password := utility.PasswordEncrypt(param.Password, salt)
dataUserInsert := do.SysUser{}
dataUserInsert.TenantId = tenantId
dataUserInsert.DeptId = deptId
dataUserInsert.NickName = param.ContactUserName
dataUserInsert.UserName = param.Username
dataUserInsert.Password = password
dataUserInsert.UserType = consts.SysUserTypeSys
dataUserInsert.Salt = salt
dataUserInsert.Phonenumber = param.ContactPhone
dataUserInsert.Email = ""
dataUserInsert.Sex = consts.SysUserSexUnknown
dataUserInsert.Status = consts.SysUserStatusNormal
dataUserInsert.CreatedDept = contexts.GetDeptId(ctx)
dataUserInsert.CreatedBy = contexts.GetUserId(ctx)
dataUserInsert.CreatedAt = gtime.Now()
dataUserInsert.UpdatedBy = contexts.GetUserId(ctx)
dataUserInsert.UpdatedAt = gtime.Now()
userId, err = dao.SysUser.Ctx(ctx).TX(tx).Data(dataUserInsert).OmitNil().InsertAndGetId()
if err != nil {
g.Log().Errorf(ctx, "sSysTenant.Add SysUser.Table().InsertAndGetId err: %v, data: %+v", err, dataUserInsert)
return err
}
// 修改租户信息
tenantUpdate := do.SysTenant{
TenantId: tenantId,
AdminRoleId: roleId,
AdminDeptId: deptId,
AdminUserId: userId,
}
_, err = dao.SysTenant.Ctx(ctx).TX(tx).Data(tenantUpdate).
Where(dao.SysTenant.Columns().Id, id).Update()
if err != nil {
g.Log().Errorf(ctx, "sSysTenant.Add SysTenant.Table().Update err: %v, data: %+v", err, data)
return err
}
// 修改部门负责人
dataDeptUpdate := do.SysDept{}
dataDeptUpdate.DeptId = deptId
dataDeptUpdate.Leader = userId
dataDeptUpdate.UpdatedBy = contexts.GetUserId(ctx)
dataDeptUpdate.UpdatedAt = gtime.Now()
_, err = dao.SysDept.Ctx(ctx).TX(tx).Data(dataDeptUpdate).OmitNil().Where(dao.SysDept.Columns().DeptId, deptId).Update()
if err != nil {
g.Log().Errorf(ctx, "sSysTenant.Add SysDept.Table().Update err: %v, data: %+v", err, dataDeptUpdate)
return err
}
output = &model.SysTenantAddModel{
Id: id,
}
// 角色关联用户
dataUserRoleInserts := []*do.SysUserRole{}
dataUserRoleInserts = append(dataUserRoleInserts, &do.SysUserRole{
UserId: userId,
RoleId: roleId,
})
_, err = dao.SysUserRole.Ctx(ctx).TX(tx).Data(dataUserRoleInserts).OmitNil().Insert()
if err != nil {
g.Log().Errorf(ctx, "sSysTenant.Add SysUserRole.Table().Insert err: %v, data: %+v", err, dataUserRoleInserts)
return err
}
// 插入系统参数
sysConfigIds, err = l.BatchInsertSysParam(ctx, tx, tenantId, userId, deptId)
if err != nil {
g.Log().Errorf(ctx, "sSysTenant.Add batchInsertSysParam err: %v, tenantId: %s, createdBy: %d, createdDept: %d", err, tenantId, contexts.GetUserId(ctx), contexts.GetDeptId(ctx))
return err
}
return nil
})
if err != nil {
g.Log().Errorf(ctx, "sSysTenant.Add err: %v", err)
return nil, err
}
// 更新缓存
event.EventsInstance().Emit(ctx, consts.EventKeyDBSysDeptCreate, deptId)
event.EventsInstance().Emit(ctx, consts.EventKeyDBSysRoleCreate, roleId)
event.EventsInstance().Emit(ctx, consts.EventKeyDBSysTenantCreate, output.Id)
event.EventsInstance().Emit(ctx, consts.EventKeyUserCreate, userId)
for _, sysConfigId := range sysConfigIds {
event.EventsInstance().Emit(ctx, consts.EventKeyDBSysConfigCreate, sysConfigId)
}
return
}
func (l *sSysTenant) Edit(ctx context.Context, param *model.SysTenantEditParam) (output *model.SysTenantEditModel, err error) {
if param.Id == 0 {
return nil, errors.New("参数错误")
}
data := &do.SysTenant{}
gconv.Struct(param, &data)
data.UpdatedAt = gtime.Now()
data.UpdatedBy = contexts.GetUserId(ctx)
db := dao.SysTenant.Ctx(ctx)
db = db.Where(dao.SysTenant.Columns().Id, param.Id)
_, err = db.Data(data).OmitNil().Update()
if err != nil {
return nil, err
}
output = &model.SysTenantEditModel{
Id: param.Id,
}
event.EventsInstance().Emit(ctx, consts.EventKeyDBSysTenantUpdate, param.Id)
return
}
func (l *sSysTenant) Delete(ctx context.Context, param *model.SysTenantDeleteParam) (output *model.SysTenantDeleteModel, err error) {
if len(param.Ids) == 0 {
return nil, errors.New("参数错误")
}
if slices.Contains(param.Ids, 1) {
return nil, errors.New("不能删除默认租户")
}
data := &do.SysTenant{}
gconv.Struct(param, &data)
data.DeletedAt = gtime.Now()
data.DeletedBy = contexts.GetUserId(ctx)
db := dao.SysTenant.Ctx(ctx)
db = db.WhereIn(dao.SysTenant.Columns().Id, param.Ids)
_, err = db.Data(data).OmitNil().Update()
if err != nil {
return nil, err
}
output = &model.SysTenantDeleteModel{
Ids: param.Ids,
}
event.EventsInstance().Emit(ctx, consts.EventKeyDBSysTenantDelete, param.Ids)
return
}
func (l *sSysTenant) Status(ctx context.Context, param *model.SysTenantStatusParam) (output *model.SysTenantStatusModel, err error) {
if param.Id == 0 {
return nil, errors.New("参数错误")
}
data := &do.SysTenant{}
gconv.Struct(param, &data)
data.UpdatedAt = gtime.Now()
data.UpdatedBy = contexts.GetUserId(ctx)
db := dao.SysTenant.Ctx(ctx)
db = db.Where(dao.SysTenant.Columns().Id, param.Id)
_, err = db.Data(data).OmitNil().Update()
if err != nil {
return nil, err
}
output = &model.SysTenantStatusModel{
Id: param.Id,
}
event.EventsInstance().Emit(ctx, consts.EventKeyDBSysTenantUpdate, param.Id)
return
}
// 新建租户插入系统参数表数据
func (l *sSysTenant) BatchInsertSysParam(ctx context.Context, tx gdb.TX, tenantId string, createdBy int64, createdDept int64) (ids []int64, err error) {
now := gtime.Now()
configs := []do.SysConfig{
{
TenantId: tenantId,
ConfigName: "主框架页-默认皮肤样式名称",
ConfigKey: "sys.index.skinName",
ConfigValue: "skin-blue",
ConfigType: "Y",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
Remark: "蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow",
},
{
TenantId: tenantId,
ConfigName: "用户管理-账号初始密码",
ConfigKey: "sys.user.initPassword",
ConfigValue: "123456",
ConfigType: "Y",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
Remark: "初始化密码 123456",
},
{
TenantId: tenantId,
ConfigName: "主框架页-侧边栏主题",
ConfigKey: "sys.index.sideTheme",
ConfigValue: "theme-dark",
ConfigType: "Y",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
Remark: "深色主题theme-dark,浅色主题theme-light",
},
{
TenantId: tenantId,
ConfigName: "账号自助-是否开启用户注册功能",
ConfigKey: "sys.account.registerUser",
ConfigValue: "false",
ConfigType: "Y",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
Remark: "是否开启注册用户功能(true开启,false关闭)",
},
{
TenantId: tenantId,
ConfigName: "OSS预览列表资源开关",
ConfigKey: "sys.oss.previewListResource",
ConfigValue: "true",
ConfigType: "Y",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
Remark: "true:开启, false:关闭",
},
{
TenantId: tenantId,
ConfigName: "上传文件类型",
ConfigKey: "sys.oss.fileType",
ConfigValue: "txt,md,doc,docx,pdf,xls,xlsx,ppt,pptx,txt,jpg,jpeg,png,gif,mp4,avi,mov,mp3,wav,m4a,csv,json,application/json,bin,hex,fw,zip",
ConfigType: "Y",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
},
{
TenantId: tenantId,
ConfigName: "上传图片类型",
ConfigKey: "sys.oss.imgType",
ConfigValue: "jpg,jpeg,png,gif,webp",
ConfigType: "Y",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
},
{
TenantId: tenantId,
ConfigName: "上传文件大小",
ConfigKey: "sys.oss.fileSize",
ConfigValue: "20M",
ConfigType: "Y",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
},
{
TenantId: tenantId,
ConfigName: "上传图片大小",
ConfigKey: "sys.oss.imgSize",
ConfigValue: "5M",
ConfigType: "Y",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
},
{
TenantId: tenantId,
ConfigName: "上传文件Url路径",
ConfigKey: "sys.oss.urlPath",
ConfigValue: "/data/app/iotlcmadmin-web-svc/upload|http://example.com:8008/upload",
ConfigType: "Y",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
Remark: "\"http://ab.com/\" 或 \"/\" 或 \"resource/upload|http://ab.com/upload\"",
},
{
TenantId: tenantId,
ConfigName: "是否启动在线用户强制退出",
ConfigKey: "sys.online.forceLogout",
ConfigValue: "true",
ConfigType: "Y",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
Remark: "true开启,false关闭",
},
{
TenantId: tenantId,
ConfigName: "系统启用的监控通道",
ConfigKey: "iot.default.channel.gb28181",
ConfigValue: "0",
ConfigType: "Y",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
},
{
TenantId: tenantId,
ConfigName: "报警资源匹配时间",
ConfigKey: "iot.alarm.image.timesec",
ConfigValue: "10",
ConfigType: "N",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
},
{
TenantId: tenantId,
ConfigName: "自主注册组织ID",
ConfigKey: "iot.register.dept",
ConfigValue: "0",
ConfigType: "N",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
},
{
TenantId: tenantId,
ConfigName: "自主注册角色ID",
ConfigKey: "iot.register.role",
ConfigValue: "0",
ConfigType: "N",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
},
{
TenantId: tenantId,
ConfigName: "系统默认MQTT渠道",
ConfigKey: "iot.default.channel.mqtt",
ConfigValue: "0",
ConfigType: "N",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
},
{
TenantId: tenantId,
ConfigName: "系统默认TCP渠道",
ConfigKey: "iot.default.channel.tcp",
ConfigValue: "0",
ConfigType: "N",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
},
{
TenantId: tenantId,
ConfigName: "系统默认UDP渠道",
ConfigKey: "iot.default.channel.udp",
ConfigValue: "0",
ConfigType: "N",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
},
{
TenantId: tenantId,
ConfigName: "项目API默认地址",
ConfigKey: "iot.project.api.default.addr",
ConfigValue: "http://127.0.0.1:8510",
ConfigType: "Y",
CreatedDept: createdDept,
CreatedBy: createdBy,
CreatedAt: now,
},
}
ids = make([]int64, 0, len(configs))
configDao := dao.SysConfig.Ctx(ctx).TX(tx)
for _, config := range configs {
id, insertErr := configDao.Data(config).InsertAndGetId()
if insertErr != nil {
return nil, insertErr
}
ids = append(ids, id)
}
return ids, nil
}
// 同步租户菜单
func (l *sSysTenant) SyncTenantMenu(ctx context.Context, tenantId string) (err error) {
tenantInfo, err := l.View(ctx, &model.SysTenantViewParam{
TenantId: tenantId,
})
if err != nil {
g.Log().Errorf(ctx, "sSysTenant.SyncTenantMenu SysTenant().View err: %v, tenantId: %s", err, tenantId)
return err
}
tenantPackage, err := service.SysTenantPackage().View(ctx, &model.SysTenantPackageViewParam{
PackageId: tenantInfo.PackageId,
})
if err != nil {
g.Log().Errorf(ctx, "sSysTenant.SyncTenantMenu SysTenantPackage().View err: %v, tenantId: %s, packageId: %d", err, tenantId, tenantInfo.PackageId)
return err
}
if tenantPackage == nil {
return errors.New("租户套餐不存在")
}
menuIds := strings.Split(tenantPackage.MenuIds, ",")
// 获取角色对应菜单
roleMenuList, err := service.SysRole().GetRoleMenu(ctx, tenantInfo.AdminRoleId)
if err != nil {
g.Log().Errorf(ctx, "sSysTenant.SyncTenantMenu SysRole().GetRoleMenu err: %v, tenantId: %s, roleId: %d", err, tenantId, tenantInfo.AdminRoleId)
return err
}
insertMenuIds := make([]do.SysRoleMenu, 0)
for _, menuId := range menuIds {
found := false
for _, roleMenu := range roleMenuList {
if roleMenu.MenuId == gconv.Int64(menuId) {
found = true
break
}
}
if !found {
insertMenuIds = append(insertMenuIds, do.SysRoleMenu{
RoleId: tenantInfo.AdminRoleId,
MenuId: gconv.Int64(menuId),
})
}
}
delMenuIds := make([]int64, 0)
for _, roleMenu := range roleMenuList {
if !slices.Contains(menuIds, gconv.String(roleMenu.MenuId)) {
delMenuIds = append(delMenuIds, roleMenu.MenuId)
continue
}
}
if len(delMenuIds) > 0 {
_, err = dao.SysRoleMenu.Ctx(ctx).WhereIn(dao.SysRoleMenu.Columns().RoleId, tenantInfo.AdminRoleId).
WhereIn(dao.SysRoleMenu.Columns().MenuId, delMenuIds).Delete()
if err != nil {
g.Log().Errorf(ctx, "sSysTenant.SyncTenantMenu SysRoleMenu.Ctx(ctx).Delete err: %v, tenantId: %s, roleId: %d, delMenuIds: %v", err, tenantId, tenantInfo.AdminRoleId, delMenuIds)
return err
}
}
if len(insertMenuIds) > 0 {
_, err = dao.SysRoleMenu.Ctx(ctx).Data(insertMenuIds).Insert()
if err != nil {
g.Log().Errorf(ctx, "sSysTenant.SyncTenantMenu SysRoleMenu.Ctx(ctx).Insert err: %v, tenantId: %s, roleId: %d, insertMenuIds: %v", err, tenantId, tenantInfo.AdminRoleId, insertMenuIds)
return err
}
}
return nil
}
// 查询用户ID是否是租户管理员
func (l *sSysTenant) IsTenantAdmin(ctx context.Context, userIds []int64) (isAdminUserIds []int64, err error) {
entityList := make([]*entity.SysTenant, 0)
err = dao.SysTenant.Ctx(ctx).WhereIn(dao.SysTenant.Columns().AdminUserId, userIds).Scan(&entityList)
if err != nil && err != sql.ErrNoRows {
return nil, err
}
isAdminUserIds = make([]int64, 0)
for _, entity := range entityList {
isAdminUserIds = append(isAdminUserIds, entity.AdminUserId)
}
return isAdminUserIds, nil
}