Files
full/module/base/mgt/internal/logic/user/fetch_pmn.go

229 lines
6.4 KiB
Go

package user
import (
"bsm/full/module/base/mgt/internal/impl"
"bsm/full/module/base/mgt/internal/libs"
mgtmw "bsm/full/module/base/mgt/internal/middleware"
"bsm/full/module/base/mgt/internal/models"
"bsm/full/module/base/mgt/internal/types"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/infra"
"git.apinb.com/bsm-sdk/core/middleware"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
const permissionPreloadSelect = "id,identity,title,title_en,sort_key,parent_id,menu_path,menu_icon,code,component,is_web_page,is_new_tab,is_full,hide_menu,web_url,app_id"
func permissionOrder(db *gorm.DB) *gorm.DB { return db.Order("sort_key asc") }
func pmnPreloadWithWorkspace(workspace string) func(*gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB {
db = db.Select(permissionPreloadSelect)
if workspace != "" {
db = db.Where("app_id = (SELECT id FROM mgt_application WHERE workspace = ?)", workspace)
}
return permissionOrder(db)
}
}
func mergeEffectivePermissions(u *models.MgtUser) []models.MgtPermission {
seen := make(map[uint]struct{})
out := make([]models.MgtPermission, 0)
add := func(list []models.MgtPermission) {
for _, p := range list {
if p.ID == 0 {
continue
}
if _, ok := seen[p.ID]; ok {
continue
}
seen[p.ID] = struct{}{}
out = append(out, p)
}
}
add(u.Permissions)
for i := range u.Roles {
add(u.Roles[i].Permissions)
}
for i := range u.Departments {
add(u.Departments[i].Permissions)
for j := range u.Departments[i].Roles {
add(u.Departments[i].Roles[j].Permissions)
}
}
return out
}
func PermissionsFetch(c *gin.Context) {
var (
request = types.FetchBase{}
data = make([]models.MgtUser, 0)
db = impl.DBService.Model(&models.MgtUser{})
)
if err := c.ShouldBindJSON(&request); err != nil {
infra.Response.Error(c, errcode.ErrJsonUnmarshal)
return
}
if err := libs.ValidateStruct(&request); err != nil {
infra.Response.Error(c, errcode.ErrInvalidArgument)
return
}
auth, err := middleware.ParseAuth(c)
if err != nil {
infra.Response.Error(c, errcode.ErrTokenAuthParseFail)
return
}
if request.ID == 0 {
request.ID = auth.ID
}
if !mgtmw.EnsureSelfOrAdmin(c, request.ID) {
return
}
ws := request.Workspace
db = db.Where("id = ?", request.ID).Select("id", "identity", "name").
Preload("Permissions", pmnPreloadWithWorkspace(ws)).
Preload("Roles", func(db *gorm.DB) *gorm.DB {
return db.Select("id", "identity", "name").Preload("Permissions", pmnPreloadWithWorkspace(ws))
}).
Preload("Departments", func(db *gorm.DB) *gorm.DB {
return db.Select("id", "identity", "name").
Preload("Permissions", pmnPreloadWithWorkspace(ws)).
Preload("Roles", func(db *gorm.DB) *gorm.DB {
return db.Select("id", "identity", "name").Preload("Permissions", pmnPreloadWithWorkspace(ws))
})
})
if err := db.Find(&data).Error; err != nil {
infra.Response.Error(c, errcode.ErrDB)
return
}
if len(data) == 0 {
infra.Response.Success(c, data)
return
}
merged := mergeEffectivePermissions(&data[0])
data[0].Permissions = merged
infra.Response.Success(c, data)
}
func PermissionsFetchTree(c *gin.Context) {
var (
request = types.FetchBase{}
data = make([]models.MgtUser, 0)
)
if err := c.ShouldBindJSON(&request); err != nil {
infra.Response.Error(c, errcode.ErrJsonUnmarshal)
return
}
if err := libs.ValidateStruct(&request); err != nil {
infra.Response.Error(c, errcode.ErrInvalidArgument)
return
}
auth, err := middleware.ParseAuth(c)
if err != nil {
infra.Response.Error(c, errcode.ErrTokenAuthParseFail)
return
}
if request.ID == 0 {
request.ID = auth.ID
}
if !mgtmw.EnsureSelfOrAdmin(c, request.ID) {
return
}
db := impl.DBService.Model(&models.MgtUser{}).Where("id = ?", request.ID).
Select("id", "identity", "name").
Preload("Permissions", func(db *gorm.DB) *gorm.DB {
return db.Select(permissionPreloadSelect).Order("sort_key asc")
}).
Preload("Roles", func(db *gorm.DB) *gorm.DB {
return db.Select("id", "identity", "name").Preload("Permissions", func(db *gorm.DB) *gorm.DB {
return db.Select(permissionPreloadSelect).Order("sort_key asc")
})
}).
Preload("Departments", func(db *gorm.DB) *gorm.DB {
return db.Select("id", "identity", "name").
Preload("Permissions", func(db *gorm.DB) *gorm.DB {
return db.Select(permissionPreloadSelect).Order("sort_key asc")
}).
Preload("Roles", func(db *gorm.DB) *gorm.DB {
return db.Select("id", "identity", "name").Preload("Permissions", func(db *gorm.DB) *gorm.DB {
return db.Select(permissionPreloadSelect).Order("sort_key asc")
})
})
})
if err := db.Find(&data).Error; err != nil {
infra.Response.Error(c, errcode.ErrDB)
return
}
if len(data) == 0 {
infra.Response.Success(c, data)
return
}
merged := mergeEffectivePermissions(&data[0])
pmnIdsByApp := make(map[uint][]uint)
for _, p := range merged {
if p.Appid == 0 {
continue
}
pmnIdsByApp[p.Appid] = append(pmnIdsByApp[p.Appid], p.ID)
}
appDb := impl.DBService.Model(&models.MgtUser{}).Where("id = ?", request.ID).
Select("id", "identity", "name")
appDb = appDb.Preload("Application", func(db *gorm.DB) *gorm.DB {
db = db.Select("id", "identity", "title", "workspace")
if request.Workspace != "" {
db = db.Where("workspace = ?", request.Workspace)
}
return db
})
var userWithApp []models.MgtUser
if err := appDb.Find(&userWithApp).Error; err != nil || len(userWithApp) == 0 {
infra.Response.Success(c, data)
return
}
apps := userWithApp[0].Application
if len(apps) == 0 {
data[0].Application = nil
infra.Response.Success(c, data)
return
}
treeSelect := "id,identity,title,title_en,sort_key,parent_id,menu_path,menu_icon,code,component,is_web_page,is_new_tab,web_url,app_id"
for i := range apps {
ids := pmnIdsByApp[apps[i].ID]
if len(ids) == 0 {
apps[i].UsersPmn = nil
apps[i].RolesPmn = nil
continue
}
var tree []models.MgtPermission
err := impl.DBService.Model(&models.MgtPermission{}).
Select(treeSelect).
Where("app_id = ? AND parent_id = 0 AND id IN ?", apps[i].ID, ids).
Order("sort_key asc").
Preload("Children", func(db *gorm.DB) *gorm.DB {
return db.Select(treeSelect).Where("id IN ?", ids).Order("sort_key asc")
}).
Find(&tree).Error
if err != nil {
apps[i].UsersPmn = nil
apps[i].RolesPmn = nil
continue
}
apps[i].UsersPmn = tree
}
data[0].Application = apps
infra.Response.Success(c, data)
}