fix: align admin behavior and Kratos integrations
This commit is contained in:
+106
-19
@@ -11,7 +11,67 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func (r *accessRepo) strictAuthorityIDs(ctx context.Context, actorID uint) (map[uint]bool, error) {
|
||||
allowed := make(map[uint]bool)
|
||||
if actorID == 0 {
|
||||
return allowed, nil
|
||||
}
|
||||
var actor authorityPO
|
||||
if err := r.data.gormDB.WithContext(ctx).Where("authority_id = ?", actorID).First(&actor).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var authorities []authorityPO
|
||||
if err := r.data.gormDB.WithContext(ctx).Find(&authorities).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
children := make(map[uint][]uint)
|
||||
for _, authority := range authorities {
|
||||
if authority.ParentID != nil {
|
||||
children[*authority.ParentID] = append(children[*authority.ParentID], authority.AuthorityID)
|
||||
}
|
||||
}
|
||||
var walk func(uint)
|
||||
walk = func(id uint) {
|
||||
for _, child := range children[id] {
|
||||
if !allowed[child] {
|
||||
allowed[child] = true
|
||||
walk(child)
|
||||
}
|
||||
}
|
||||
}
|
||||
if actor.ParentID == nil || *actor.ParentID == 0 {
|
||||
allowed[actorID] = true
|
||||
}
|
||||
walk(actorID)
|
||||
return allowed, nil
|
||||
}
|
||||
|
||||
func (r *accessRepo) checkAuthorityIDAuth(ctx context.Context, targetID uint) error {
|
||||
config := r.data.runtime.Admin()
|
||||
if config == nil || config.System == nil || !config.System.UseStrictAuth {
|
||||
return nil
|
||||
}
|
||||
actor, ok := biz.ActorFromContext(ctx)
|
||||
if !ok {
|
||||
return errors.New("您提交的角色ID不合法")
|
||||
}
|
||||
allowed, err := r.strictAuthorityIDs(ctx, actor.AuthorityID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !allowed[targetID] {
|
||||
return errors.New("您提交的角色ID不合法")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *accessRepo) CreateAuthority(ctx context.Context, value *biz.Authority) error {
|
||||
config := r.data.runtime.Admin()
|
||||
if config != nil && config.System != nil && config.System.UseStrictAuth && (value.ParentID == nil || *value.ParentID == 0) {
|
||||
if actor, ok := biz.ActorFromContext(ctx); ok {
|
||||
value.ParentID = &actor.AuthorityID
|
||||
}
|
||||
}
|
||||
return r.data.gormDB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
var count int64
|
||||
if err := tx.Model(&authorityPO{}).Where("authority_id = ?", value.AuthorityID).Count(&count).Error; err != nil {
|
||||
@@ -46,6 +106,18 @@ func (r *accessRepo) CreateAuthority(ctx context.Context, value *biz.Authority)
|
||||
}
|
||||
func (r *accessRepo) CopyAuthority(ctx context.Context, sourceID uint, value *biz.Authority) error {
|
||||
return r.data.gormDB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
config := r.data.runtime.Admin()
|
||||
actor, hasActor := biz.ActorFromContext(ctx)
|
||||
strict := hasActor && actor.AuthorityID != 888 && config != nil && config.System != nil && config.System.UseStrictAuth
|
||||
if strict {
|
||||
allowed, err := r.strictAuthorityIDs(ctx, actor.AuthorityID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if value.ParentID == nil || !allowed[*value.ParentID] {
|
||||
return errors.New("严格角色模式下只能在自己的角色树中复制角色")
|
||||
}
|
||||
}
|
||||
var count int64
|
||||
if err := tx.Model(&authorityPO{}).Where("authority_id = ?", value.AuthorityID).Count(&count).Error; err != nil {
|
||||
return err
|
||||
@@ -76,6 +148,15 @@ func (r *accessRepo) CopyAuthority(ctx context.Context, sourceID uint, value *bi
|
||||
return err
|
||||
}
|
||||
for i := range apis {
|
||||
if strict {
|
||||
var allowedCount int64
|
||||
if err := tx.Model(&authorityAPIPO{}).Where("authority_id = ? AND api_id = ?", actor.AuthorityID, apis[i].APIID).Count(&allowedCount).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if allowedCount == 0 {
|
||||
return errors.New("严格角色模式下不能复制当前角色未拥有的 API")
|
||||
}
|
||||
}
|
||||
apis[i].AuthorityID = value.AuthorityID
|
||||
}
|
||||
if len(apis) > 0 {
|
||||
@@ -95,16 +176,6 @@ func (r *accessRepo) CopyAuthority(ctx context.Context, sourceID uint, value *bi
|
||||
return err
|
||||
}
|
||||
}
|
||||
var departments []authorityDepartmentPO
|
||||
if err := copyLinks("sys_authority_departments", &departments, map[string]any{"authority_id": sourceID}); err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range departments {
|
||||
departments[i].AuthorityID = value.AuthorityID
|
||||
}
|
||||
if len(departments) > 0 {
|
||||
return tx.Create(&departments).Error
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -155,8 +226,20 @@ func (r *accessRepo) ListAuthorities(ctx context.Context) ([]*biz.Authority, err
|
||||
if err := r.data.gormDB.WithContext(ctx).Order("authority_id").Find(&pos).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var allowed map[uint]bool
|
||||
config := r.data.runtime.Admin()
|
||||
if actor, ok := biz.ActorFromContext(ctx); ok && config != nil && config.System != nil && config.System.UseStrictAuth {
|
||||
var err error
|
||||
allowed, err = r.strictAuthorityIDs(ctx, actor.AuthorityID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
out := make([]*biz.Authority, 0, len(pos))
|
||||
for _, po := range pos {
|
||||
if allowed != nil && !allowed[po.AuthorityID] {
|
||||
continue
|
||||
}
|
||||
v := toBizAuthority(po)
|
||||
out = append(out, &v)
|
||||
}
|
||||
@@ -190,11 +273,13 @@ func (r *accessRepo) SetAuthorityUsers(ctx context.Context, id uint, ids []uint)
|
||||
}
|
||||
var user userPO
|
||||
if err := tx.First(&user, uid).Error; err == nil && user.AuthorityID == id {
|
||||
if err = tx.Model(&user).Update("authority_id", 888).Error; err != nil {
|
||||
var another userAuthorityPO
|
||||
if err = tx.Where("sys_user_id = ?", uid).First(&another).Error; errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
continue
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
fallback := userAuthorityPO{SysUserID: uid, SysAuthorityAuthorityID: 888}
|
||||
if err = tx.FirstOrCreate(&fallback, fallback).Error; err != nil {
|
||||
if err = tx.Model(&user).Update("authority_id", another.SysAuthorityAuthorityID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -215,12 +300,14 @@ func (r *accessRepo) SetDataScope(ctx context.Context, id uint, scope int, deptI
|
||||
if err := tx.Where("authority_id = ?", id).Delete(&authorityDepartmentPO{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
links := make([]authorityDepartmentPO, 0, len(deptIDs))
|
||||
for _, did := range deptIDs {
|
||||
links = append(links, authorityDepartmentPO{AuthorityID: id, DepartmentID: did})
|
||||
}
|
||||
if len(links) > 0 {
|
||||
return tx.Create(&links).Error
|
||||
if scope == 5 {
|
||||
links := make([]authorityDepartmentPO, 0, len(deptIDs))
|
||||
for _, did := range deptIDs {
|
||||
links = append(links, authorityDepartmentPO{AuthorityID: id, DepartmentID: did})
|
||||
}
|
||||
if len(links) > 0 {
|
||||
return tx.Create(&links).Error
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user