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