feat: import services and standardize Go 1.26.5

This commit is contained in:
2026-08-09 10:43:45 +08:00
parent 689c74b28f
commit 86024fa81d
1456 changed files with 220765 additions and 2 deletions

View File

@@ -0,0 +1,124 @@
package user
import (
"errors"
"git.apinb.com/bsm-apps/mgt/internal/libs"
"git.apinb.com/bsm-apps/mgt/internal/models"
"git.apinb.com/bsm-apps/mgt/internal/types"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/infra"
"git.apinb.com/bsm-sdk/core/middleware"
"git.apinb.com/bsm-sdk/core/printer"
coreTypes "git.apinb.com/bsm-sdk/core/types"
coreutils "git.apinb.com/bsm-sdk/core/utils"
"github.com/gin-gonic/gin"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
func Create(c *gin.Context) {
var (
request = types.UserRequest{}
data = models.MgtUser{}
linkData = models.MgtApplication{}
)
_, err := middleware.ParseAuth(c)
if err != nil {
infra.Response.Error(c, errcode.ErrTokenAuthNotFound)
return
}
err = c.ShouldBindJSON(&request)
if err != nil {
infra.Response.Error(c, errcode.ErrJsonUnmarshal)
return
}
if err := libs.ValidateStruct(&request); err != nil {
infra.Response.Error(c, errcode.ErrInvalidArgument)
return
}
if request.Account == "" || request.Phone == "" || request.PassWord == "" {
printer.Error("account, phone and password are required: account=%s, phone=%s", request.Account, request.Phone)
infra.Response.Error(c, errcode.ErrInvalidArgument)
return
}
db := models.DBService.Model(&models.MgtUser{})
if err = db.Where("phone = ? or account = ?", request.Phone, request.Account).First(&data).Error; err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
infra.Response.Error(c, errcode.ErrDB)
return
}
var deletedData models.MgtUser
if err = models.DBService.Unscoped().Where("phone = ?", request.Phone).First(&deletedData).Error; err == nil {
if err = models.DBService.Unscoped().Delete(&deletedData).Error; err != nil {
infra.Response.Error(c, errcode.ErrDB)
return
}
printer.Info("user deleted: id=%d, phone=%s", deletedData.ID, deletedData.Phone)
}
if request.Phone != request.Account {
if err = models.DBService.Unscoped().Where("account = ?", request.Account).First(&deletedData).Error; err == nil {
if err = models.DBService.Unscoped().Delete(&deletedData).Error; err != nil {
infra.Response.Error(c, errcode.ErrDB)
return
}
}
}
} else {
infra.Response.Error(c, errcode.ErrAlreadyExists)
return
}
if request.Workspace == "" {
request.Workspace = "def"
}
if err = models.DBService.Model(&models.MgtApplication{}).Where("workspace = ?", request.Workspace).First(&linkData).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
infra.Response.Error(c, errcode.ErrRecordNotFound)
return
}
infra.Response.Error(c, errcode.ErrDB)
return
}
salt := coreutils.UUID()
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(request.PassWord+salt), bcrypt.DefaultCost)
if err != nil {
infra.Response.Error(c, errcode.ErrInternal)
return
}
var userModel = models.MgtUser{
Account: request.Account,
Name: request.Name,
Password: string(hashedPassword),
Phone: request.Phone,
Email: request.Email,
Avatar: request.Avatar,
Salt: salt,
Std_IICUDS: coreTypes.Std_IICUDS{Identity: coreutils.UUID(), Status: 1},
}
if err = models.DBService.Transaction(func(tx *gorm.DB) error {
if err = tx.Model(&models.MgtUser{}).Create(&userModel).Error; err != nil {
return err
}
userLink := models.MgtLinkUserApp{
AppId: linkData.ID,
UserId: userModel.ID,
}
if err = tx.Model(&models.MgtLinkUserApp{}).Create(&userLink).Error; err != nil {
return err
}
return nil
}); err != nil {
infra.Response.Error(c, errcode.ErrDB)
return
}
infra.Response.Success(c, types.IdResp{Id: userModel.ID, Identity: userModel.Identity})
}

View File

@@ -0,0 +1,76 @@
package user
import (
"git.apinb.com/bsm-apps/mgt/internal/libs"
"git.apinb.com/bsm-apps/mgt/internal/models"
"git.apinb.com/bsm-apps/mgt/internal/types"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/infra"
"git.apinb.com/bsm-sdk/core/printer"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
func Del(c *gin.Context) {
var request = types.UserRequest{}
// 解析JSON请求
err := c.ShouldBindJSON(&request)
if err != nil {
infra.Response.Error(c, errcode.ErrJsonUnmarshal)
return
}
// 参数验证
if err := libs.ValidateStruct(&request); err != nil {
infra.Response.Error(c, errcode.ErrInvalidArgument)
return
}
if request.ID == 0 {
printer.Error("删除用户参数异常: ID不能为空")
infra.Response.Error(c, errcode.ErrInvalidArgument)
return
}
// 删除用户时,同时删除关联数据
if err := models.DBService.Transaction(func(tx *gorm.DB) error {
// 删除用户
if err = tx.Delete(&models.MgtUser{}, request.ID).Error; err != nil {
printer.Error("删除用户异常: %v", err)
return err
}
// 删除用户角色关联
if err = tx.Where("user_id = ?", request.ID).Delete(&models.MgtLinkUserRole{}).Error; err != nil {
printer.Error("删除用户角色关联异常: %v", err)
return err
}
// 删除用户应用关联
if err = tx.Where("user_id = ?", request.ID).Delete(&models.MgtLinkUserApp{}).Error; err != nil {
printer.Error("删除用户应用关联异常: %v", err)
return err
}
// 删除用户权限关联
if err = tx.Where("user_id = ?", request.ID).Delete(&models.MgtLinkUserPmn{}).Error; err != nil {
printer.Error("删除用户权限关联异常: %v", err)
return err
}
// 删除用户部门关联
if err = tx.Where("user_id = ?", request.ID).Delete(&models.MgtLinkUserDpt{}).Error; err != nil {
printer.Error("删除用户部门关联异常: %v", err)
return err
}
return nil
}); err != nil {
infra.Response.Error(c, errcode.ErrDB)
return
}
printer.Info("用户删除成功: ID=%d", request.ID)
infra.Response.Success(c, types.IdResp{Id: request.ID})
}

View File

@@ -0,0 +1,51 @@
package user
import (
"errors"
"git.apinb.com/bsm-apps/mgt/internal/libs"
"git.apinb.com/bsm-apps/mgt/internal/models"
"git.apinb.com/bsm-apps/mgt/internal/types"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/infra"
"git.apinb.com/bsm-sdk/core/printer"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
func Detail(c *gin.Context) {
var (
request = types.UserRequest{}
userData = types.UserResp{}
)
// 解析JSON请求
err := c.ShouldBindJSON(&request)
if err != nil {
infra.Response.Error(c, errcode.ErrJsonUnmarshal)
return
}
// 参数验证
if err := libs.ValidateStruct(&request); err != nil {
infra.Response.Error(c, errcode.ErrInvalidArgument)
return
}
if request.ID == 0 {
printer.Error("用户ID不能为空")
infra.Response.Error(c, errcode.ErrInvalidArgument)
return
}
if err = models.DBService.Model(&models.MgtUser{}).Where("id = ?", request.ID).First(&userData).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
infra.Response.Error(c, errcode.ErrRecordNotFound)
return
}
infra.Response.Error(c, errcode.ErrDB)
return
}
infra.Response.Success(c, userData)
}

View File

@@ -0,0 +1,49 @@
package user
import (
"git.apinb.com/bsm-apps/mgt/internal/libs"
"git.apinb.com/bsm-apps/mgt/internal/logic/tool"
"git.apinb.com/bsm-apps/mgt/internal/models"
"git.apinb.com/bsm-apps/mgt/internal/types"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/infra"
"github.com/gin-gonic/gin"
)
func Fetch(c *gin.Context) {
var (
request = types.UserRequest{}
count int64 = 0
data = make([]types.UserResp, 0)
db = models.DBService.Model(&models.MgtUser{})
)
// 解析JSON请求
err := c.ShouldBindJSON(&request)
if err != nil {
infra.Response.Error(c, errcode.ErrJsonUnmarshal)
return
}
// 参数验证
if err := libs.ValidateStruct(&request); err != nil {
infra.Response.Error(c, errcode.ErrInvalidArgument)
return
}
if request.Keyword != "" {
likeStr := "%" + request.Keyword + "%"
db = db.Where("name like ? or account like ? or phone like ?", likeStr, likeStr, likeStr)
}
if request.Status != 0 {
db = db.Where("status = ? ", request.Status)
}
page, size := tool.GetSizeAndPage(request.Page, request.Size)
if err := db.Count(&count).Limit(size).Offset((page - 1) * size).Find(&data).Error; err != nil {
infra.Response.Error(c, errcode.ErrDB)
return
}
infra.Response.Success(c, types.FetchResp{Data: data, Page: page, Size: size, Total: count})
}

View File

@@ -0,0 +1,49 @@
package user
import (
"git.apinb.com/bsm-apps/mgt/internal/libs"
mgtmw "git.apinb.com/bsm-apps/mgt/internal/middleware"
"git.apinb.com/bsm-apps/mgt/internal/models"
"git.apinb.com/bsm-apps/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"
)
func ApplicationsFetch(c *gin.Context) {
var (
request = types.FetchBase{}
data = make([]models.MgtUser, 0)
db = models.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
}
db = db.Where("id = ?", request.ID)
if err := db.Select("id", "identity", "name").Preload("Application").Find(&data).Error; err != nil {
infra.Response.Error(c, errcode.ErrDB)
return
}
infra.Response.Success(c, data)
}

View File

@@ -0,0 +1,226 @@
package user
import (
"git.apinb.com/bsm-apps/mgt/internal/libs"
mgtmw "git.apinb.com/bsm-apps/mgt/internal/middleware"
"git.apinb.com/bsm-apps/mgt/internal/models"
"git.apinb.com/bsm-apps/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 = models.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 := models.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 := models.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 := models.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)
}

View File

@@ -0,0 +1,53 @@
package user
import (
"git.apinb.com/bsm-apps/mgt/internal/libs"
mgtmw "git.apinb.com/bsm-apps/mgt/internal/middleware"
"git.apinb.com/bsm-apps/mgt/internal/models"
"git.apinb.com/bsm-apps/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"
)
func RoleFetch(c *gin.Context) {
var (
request = types.FetchBase{}
data = make([]models.MgtUser, 0)
db = models.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
}
db = db.Where("id = ?", request.ID)
if err := db.Select("id", "identity", "name").Preload("Roles", func(db *gorm.DB) *gorm.DB {
return db.Select("id", "identity", "name")
}).Find(&data).Error; err != nil {
infra.Response.Error(c, errcode.ErrDB)
return
}
infra.Response.Success(c, data)
}

View File

@@ -0,0 +1,40 @@
package user
import (
"git.apinb.com/bsm-apps/mgt/internal/models"
"git.apinb.com/bsm-apps/mgt/internal/types"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/infra"
"github.com/gin-gonic/gin"
)
func UserList(c *gin.Context) {
var (
request = types.FetchBase{}
data = make([]types.UserResp, 0)
)
err := c.ShouldBindJSON(&request)
if err != nil {
infra.Response.Error(c, errcode.ErrJsonUnmarshal)
return
}
if request.Workspace == "" {
infra.Response.Error(c, errcode.ErrInvalidArgument)
return
}
db := models.DBService.Model(&models.MgtUser{}).
Where("id IN (SELECT user_id FROM mgt_link_user_app WHERE app_id = (SELECT id FROM mgt_application WHERE workspace = ? LIMIT 1))", request.Workspace)
if request.Keyword != "" {
likeStr := "%" + request.Keyword + "%"
db = db.Where("name LIKE ?", likeStr)
}
if request.Status != 0 {
db = db.Where("status = ?", request.Status)
}
if err := db.Find(&data).Error; err != nil {
infra.Response.Error(c, errcode.ErrDB)
return
}
infra.Response.Success(c, types.FetchResp{Data: data})
}

View File

@@ -0,0 +1,74 @@
package user
import (
"errors"
"git.apinb.com/bsm-apps/mgt/internal/libs"
"git.apinb.com/bsm-apps/mgt/internal/models"
"git.apinb.com/bsm-apps/mgt/internal/types"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/infra"
"git.apinb.com/bsm-sdk/core/printer"
coreTypes "git.apinb.com/bsm-sdk/core/types"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
func Midify(c *gin.Context) {
var (
request = types.UserRequest{}
user = models.MgtUser{}
)
err := c.ShouldBindJSON(&request)
if err != nil {
infra.Response.Error(c, errcode.ErrJsonUnmarshal)
return
}
request.PassWord = ""
if err := libs.ValidateStruct(&request); err != nil {
infra.Response.Error(c, errcode.ErrInvalidArgument)
return
}
if request.ID == 0 {
printer.Error("更新用户参数异常: ID不能为空")
infra.Response.Error(c, errcode.ErrInvalidArgument)
return
}
if request.Account != "" {
if err := models.DBService.Model(&models.MgtUser{}).Where("account = ? and id <>?", request.Account, request.ID).First(&user).Error; err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
infra.Response.Error(c, errcode.ErrDB)
return
}
}
if user.ID != 0 {
printer.Info("账号已被使用: account=%s", request.Account)
infra.Response.Error(c, errcode.ErrAlreadyExists)
return
}
}
var userModel = models.MgtUser{
Name: request.Name,
Phone: request.Phone,
Email: request.Email,
Avatar: request.Avatar,
Std_IICUDS: coreTypes.Std_IICUDS{Status: request.Status},
}
updateFields := []string{"name", "phone", "email", "avatar", "status"}
if request.Account != "" {
userModel.Account = request.Account
updateFields = append(updateFields, "account")
}
if err := models.DBService.Model(&models.MgtUser{}).Where("id = ?", request.ID).Select(updateFields).Updates(&userModel).Error; err != nil {
infra.Response.Error(c, errcode.ErrDB)
return
}
printer.Info("用户更新成功: ID=%d", request.ID)
infra.Response.Success(c, types.IdResp{Id: request.ID, Identity: userModel.Identity})
}

View File

@@ -0,0 +1,171 @@
package user
import (
"git.apinb.com/bsm-apps/mgt/internal/libs"
"git.apinb.com/bsm-apps/mgt/internal/models"
"git.apinb.com/bsm-apps/mgt/internal/types"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/infra"
"git.apinb.com/bsm-sdk/core/printer"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
// SetPmn 给用户设置权限
func SetPmn(c *gin.Context) {
var (
request = types.AddPmnRequest{}
pmnData = make([]models.MgtLinkUserPmn, 0)
Appdta = models.MgtLinkUserApp{}
)
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
}
appModel := models.MgtApplication{Workspace: request.Workspace}
appId, err := appModel.WorkspaceToId()
if err != nil {
printer.Error("未获取到appid: %v", err)
infra.Response.Error(c, errcode.ErrRecordNotFound)
return
}
for _, v := range request.List {
if v == 0 {
printer.Error("权限ID不能为空")
infra.Response.Error(c, errcode.ErrInvalidArgument)
return
}
pmnData = append(pmnData, models.MgtLinkUserPmn{AppId: appId, PmnId: v, UserId: request.Id})
Appdta = models.MgtLinkUserApp{AppId: appId, UserId: request.Id}
}
if err := models.DBService.Transaction(func(tx *gorm.DB) error {
if err := tx.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "app_id"}, {Name: "pmn_id"}, {Name: "user_id"}},
DoUpdates: clause.AssignmentColumns([]string{"app_id", "pmn_id", "user_id"}),
}).Create(&pmnData).Error; err != nil {
return err
}
if err := tx.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "app_id"}, {Name: "user_id"}},
DoUpdates: clause.AssignmentColumns([]string{"app_id", "user_id"}),
}).Create(&Appdta).Error; err != nil {
return err
}
return nil
}); err != nil {
infra.Response.Error(c, errcode.ErrDB)
return
}
printer.Info("用户权限设置成功: userId=%d", request.Id)
infra.Response.Success(c, "")
}
// ModifyPmn 给用户修改权限
func ModifyPmn(c *gin.Context) {
var (
request = types.AddPmnRequest{}
pmnData = make([]models.MgtLinkUserPmn, 0)
Appdta = models.MgtLinkUserApp{}
)
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
}
appModel := models.MgtApplication{Workspace: request.Workspace}
appId, err := appModel.WorkspaceToId()
if err != nil {
printer.Error("未获取到appid: %v", err)
infra.Response.Error(c, errcode.ErrRecordNotFound)
return
}
for _, v := range request.List {
if v == 0 {
printer.Error("权限ID不能为空")
infra.Response.Error(c, errcode.ErrInvalidArgument)
return
}
pmnData = append(pmnData, models.MgtLinkUserPmn{AppId: appId, PmnId: v, UserId: request.Id})
Appdta = models.MgtLinkUserApp{AppId: appId, UserId: request.Id}
}
if err := models.DBService.Transaction(func(tx *gorm.DB) error {
if err := tx.Where("app_id = ? and user_id = ?", appId, request.Id).Delete(&models.MgtLinkUserPmn{}).Error; err != nil {
printer.Error("删除用户权限关联失败: %v", err)
return err
}
if len(pmnData) == 0 {
return nil
}
if err := tx.Create(&pmnData).Error; err != nil {
printer.Error("创建用户权限关联失败: %v", err)
return err
}
if err := tx.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "app_id"}, {Name: "user_id"}},
DoUpdates: clause.AssignmentColumns([]string{"app_id", "user_id"}),
}).Create(&Appdta).Error; err != nil {
printer.Error("创建用户应用关联失败: %v", err)
return err
}
return nil
}); err != nil {
infra.Response.Error(c, errcode.ErrDB)
return
}
printer.Info("用户权限修改成功: userId=%d", request.Id)
infra.Response.Success(c, "")
}
// DelPmn 用户权限移除
func DelPmn(c *gin.Context) {
var request = types.AddPmnRequest{}
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
}
appModel := models.MgtApplication{Workspace: request.Workspace}
appId, err := appModel.WorkspaceToId()
if err != nil {
printer.Error("未获取到appid: %v", err)
infra.Response.Error(c, errcode.ErrRecordNotFound)
return
}
pmnIds := make([]uint, 0, len(request.List))
for _, v := range request.List {
if v == 0 {
printer.Error("权限ID不能为空")
infra.Response.Error(c, errcode.ErrInvalidArgument)
return
}
pmnIds = append(pmnIds, v)
}
if err := models.DBService.Where("app_id = ? AND user_id = ? AND pmn_id in ?", appId, request.Id, pmnIds).
Delete(&models.MgtLinkUserPmn{}).Error; err != nil {
infra.Response.Error(c, errcode.ErrDB)
return
}
printer.Info("用户权限删除成功: userId=%d", request.Id)
infra.Response.Success(c, "")
}

View File

@@ -0,0 +1,188 @@
package user
import (
"git.apinb.com/bsm-apps/mgt/internal/libs"
"git.apinb.com/bsm-apps/mgt/internal/models"
"git.apinb.com/bsm-apps/mgt/internal/types"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/infra"
"git.apinb.com/bsm-sdk/core/printer"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
// SetRole 给用户设置角色
func SetRole(c *gin.Context) {
var (
request = types.UserRoleRequest{}
role = make([]models.MgtRole, 0)
pmnData = make([]models.MgtLinkUserPmn, 0)
roleData = make([]models.MgtLinkUserRole, 0)
appId = make([]uint, 0)
userApp = make([]models.MgtLinkUserApp, 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
}
if err := models.DBService.Model(&models.MgtRole{}).Where("id in ?", request.RoleId).Preload("Permissions").Find(&role).Error; err != nil {
infra.Response.Error(c, errcode.ErrDB)
return
}
for _, v := range role {
for _, vv := range v.Permissions {
pmnData = append(pmnData, models.MgtLinkUserPmn{
AppId: vv.Appid,
PmnId: vv.ID,
UserId: request.UserId,
})
}
roleData = append(roleData, models.MgtLinkUserRole{UserId: request.UserId, RoleId: v.ID})
}
if err := models.DBService.Model(&models.MgtLinkRoleApp{}).Select("app_id").Where("role_id in ?", request.RoleId).Find(&appId).Error; err != nil {
infra.Response.Error(c, errcode.ErrDB)
return
}
if len(appId) == 0 {
printer.Info("角色未关联应用: roleIds=%v", request.RoleId)
infra.Response.Error(c, errcode.ErrRecordNotFound)
return
}
for _, v := range appId {
userApp = append(userApp, models.MgtLinkUserApp{UserId: request.UserId, AppId: v})
}
if err := models.DBService.Transaction(func(tx *gorm.DB) error {
if err := tx.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "app_id"}, {Name: "pmn_id"}, {Name: "user_id"}},
DoUpdates: clause.AssignmentColumns([]string{"app_id", "pmn_id", "user_id"}),
}).Create(&pmnData).Error; err != nil {
printer.Error("创建用户权限关系失败: %v", err)
return err
}
if err := tx.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "app_id"}, {Name: "user_id"}},
DoUpdates: clause.AssignmentColumns([]string{"app_id", "user_id"}),
}).Create(&userApp).Error; err != nil {
printer.Error("创建用户app关系失败: %v", err)
return err
}
if err := tx.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "user_id"}, {Name: "role_id"}},
DoUpdates: clause.AssignmentColumns([]string{"user_id", "role_id"}),
}).Create(&roleData).Error; err != nil {
printer.Error("创建用户角色关系失败: %v", err)
return err
}
return nil
}); err != nil {
infra.Response.Error(c, errcode.ErrDB)
return
}
infra.Response.Success(c, "")
}
// DelRole 给用户移除角色
func DelRole(c *gin.Context) {
var (
request = types.UserRoleRequest{}
)
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
}
if err := models.DBService.Transaction(func(tx *gorm.DB) error {
var (
removedRolePmns []uint
userOtherRoles []uint
otherRolePmns []uint
toDeletePmns []uint
)
if err := tx.Model(&models.MgtLinkRolePmn{}).
Select("pmn_id").
Where("role_id in ?", request.RoleId).
Find(&removedRolePmns).Error; err != nil {
printer.Error("获取被移除角色权限异常: %v", err)
return err
}
if len(removedRolePmns) == 0 {
if err := tx.Where("user_id = ? and role_id in ?", request.UserId, request.RoleId).
Delete(&models.MgtLinkUserRole{}).Error; err != nil {
printer.Error("删除用户角色关联异常: %v", err)
return err
}
return nil
}
if err := tx.Model(&models.MgtLinkUserRole{}).
Select("role_id").
Where("user_id = ? and role_id not in ?", request.UserId, request.RoleId).
Find(&userOtherRoles).Error; err != nil {
printer.Error("获取用户其他角色异常: %v", err)
return err
}
if len(userOtherRoles) > 0 {
if err := tx.Model(&models.MgtLinkRolePmn{}).
Select("pmn_id").
Where("role_id in ?", userOtherRoles).
Find(&otherRolePmns).Error; err != nil {
printer.Error("获取用户其他角色权限异常: %v", err)
return err
}
}
otherPmnSet := make(map[uint]struct{}, len(otherRolePmns))
for _, pmnId := range otherRolePmns {
otherPmnSet[pmnId] = struct{}{}
}
toDeletePmns = make([]uint, 0, len(removedRolePmns))
for _, pmnId := range removedRolePmns {
if _, ok := otherPmnSet[pmnId]; !ok {
toDeletePmns = append(toDeletePmns, pmnId)
}
}
if err := tx.Where("user_id = ? and role_id in ?", request.UserId, request.RoleId).
Delete(&models.MgtLinkUserRole{}).Error; err != nil {
printer.Error("删除用户角色关联异常: %v", err)
return err
}
if len(toDeletePmns) > 0 {
if err := tx.Where("user_id = ? and pmn_id in ?", request.UserId, toDeletePmns).
Delete(&models.MgtLinkUserPmn{}).Error; err != nil {
printer.Error("删除用户权限关联异常: %v", err)
return err
}
printer.Info("删除用户权限关联: userId=%d, pmnIds=%v", request.UserId, toDeletePmns)
} else {
printer.Info("用户权限通过其他角色或直接拥有,无需删除: userId=%d", request.UserId)
}
return nil
}); err != nil {
infra.Response.Error(c, errcode.ErrDB)
return
}
infra.Response.Success(c, "")
}