1 Star 1 Fork 1

K / ginorigin

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
role.go 5.71 KB
一键复制 编辑 原始数据 按行查看 历史
package security
import (
"encoding/json"
"errors"
"fmt"
"strconv"
"time"
"gorm.io/gorm"
"gitee.com/chenhonghua/ginorigin/config/storage/database"
"gitee.com/chenhonghua/ginorigin/config/storage/localcache"
"gitee.com/chenhonghua/ginorigin/config/storage/redis"
"gitee.com/chenhonghua/ginorigin/config/system/logger"
)
type RolePolicy struct {
RoleId int `gorm:"column:rid;comment:角色ID"`
PolicySub string `gorm:"column:policy_sub;comment:权限主体标记"`
Policies []Policy `json:"policies,omitempty" gorm:"-"` // gorm:"foreignKey:id;references:policy_id;comment:权限"`
}
func (RolePolicy) TableName() string {
return "security_role_policy"
}
type Role struct {
database.BaseModel
Name string `json:"name" gorm:"column:name;type:varchar(256);comment:角色名称"`
Description string `json:"description" gorm:"column:description;type:varchar(1024);comment:描述"`
RolePolicies []RolePolicy `json:"rolePolicies,omitempty" gorm:"foreignKey:rid;references:id;comment:权限"`
ParentId int `json:"parentId,omitempty" gorm:"column:parent_id;comment:父级角色ID"`
Parent *Role `json:"parent,omitempty" gorm:"foreignKey:id;references:parent_id;comment:父级角色"`
Children []Role `json:"children,omitempty" gorm:"foreignKey:parent_id;references:id;comment:子级角色"`
}
func (Role) TableName() string {
return "security_role"
}
type UserRole struct {
Uid int `json:"uid" gorm:"column:uid;comment:用户ID"`
RoleId int `json:"roleId" gorm:"column:rid;comment:角色ID"`
Role *Role `json:"role,omitempty" gorm:"foreignKey:id;references:rid;comment:角色"`
}
func (UserRole) TableName() string {
return "security_user_role"
}
func (r Role) Match(dest *Policy) bool {
if !securityConfig.Enable {
panic(errors.New("未启用security模块"))
}
if dest == nil {
return true
}
if len(r.RolePolicies) > 0 {
for _, rp := range r.RolePolicies {
for _, p := range rp.Policies {
if match(&p, dest) {
return true
}
}
}
}
if len(r.Children) > 0 {
for _, child := range r.Children {
if child.Match(dest) {
return true
}
}
}
return false
}
// 增
func (r Role) Add() (role Role) {
checkEnable()
database.Transaction(func(tx *gorm.DB) error {
con := database.GetConnection().Model(r).Create(&r) // 增加操作
con.Where("id=?", r.ID).First(&role) // 根据id查询insert结果
return nil
})
logger.Debug("course create result:%v\n", role)
return role
}
// 改
func (r Role) Update() error {
checkEnable()
// 注意:更新操作如果携带了无ID的对象属性(如chapter,author等),则会创建这些对象
return database.GetConnection().Model(r).Where("id = ?", r.ID).Updates(&r).Error
}
// 删
func (r Role) Delete() error {
checkEnable()
tmp := Role{BaseModel: database.BaseModel{ID: r.ID}}
return database.GetConnection().Model(r).Where("id = ?", r.ID).Delete(&tmp).Error
}
// 查
func findRole(idName string, id int) ([]Role, error) {
role := Role{}
result := []Role{}
query := database.GetConnection().Model(&role).Where(idName+" = ? ", id)
query = query.Preload("RolePolicies") // 关联权限信息
err := query.Find(&result).Error
for err != nil {
return nil, err
}
for i1, r := range result {
for i2, rp := range r.RolePolicies {
rp.Policies = policyDictionary[rp.PolicySub]
r.RolePolicies[i2] = rp
}
result[i1] = r
}
return result, nil
}
func cacheKey(t, k, v string) string {
return fmt.Sprintf("%s_%s_%s", t, k, v)
}
func deepFindRole(id int) (role *Role) {
ck := cacheKey(Role{}.TableName(), "id", strconv.Itoa(id))
if s, b := localcache.Default.Get(ck); b {
json.Unmarshal([]byte(s), &role)
return role
}
rs, err := findRole("id", id)
if err != nil || len(rs) == 0 {
return nil
}
role = &rs[0]
rs, err = findRole("parent_id", role.ID)
if err != nil || len(rs) == 0 {
s, _ := json.Marshal(role)
localcache.Default.Set(ck, string(s))
return role
}
role.Children = rs
for _, r := range rs {
tmp := deepFindRole(r.ID)
if nil != tmp && len(tmp.Children) > 0 {
r.Children = tmp.Children
}
}
s, _ := json.Marshal(role)
localcache.Default.Set(ck, string(s))
return role
}
// 查询用户完整角色权限
func FindUserRoleByUid(uid int) (urs []UserRole, err error) {
checkEnable()
st1 := time.Now().UnixMicro()
urs, err = findUserRoleByUid(uid)
logger.Debug("查询用户直属角色:%#v\n", urs)
logger.Debug("查询用户直属角色耗时:%d\n", time.Now().UnixMicro()-st1)
if err != nil {
return nil, err // 数据库中查不到
}
st2 := time.Now().UnixMicro()
for i, ur := range urs {
r := deepFindRole(ur.RoleId)
if r != nil {
ur.Role = r
urs[i] = ur
}
}
logger.Debug("深度查询用户角色:%#v\n", urs)
logger.Debug("深度查询用户角色耗时:%d\n", time.Now().UnixMicro()-st2)
return urs, err
}
// 查询用户直属角色(关联)
// 用户数据量不确定,所以,此处,区分为本地化、中心化两种存储模式
func findUserRoleByUid(uid int) (urs []UserRole, err error) {
t := UserRole{}
uidstr := fmt.Sprintf("%d", uid)
urs = []UserRole{}
if securityConfig.EnableRedisCache {
s := redis.Hash.HGet(t.TableName(), uidstr)
if len(s) > 0 {
json.Unmarshal([]byte(s), &urs)
return urs, nil
}
} else {
s, b := localcache.Default.Get(cacheKey(t.TableName(), "uid", uidstr))
if b {
json.Unmarshal([]byte(s), &urs)
return urs, nil
}
}
err = database.GetConnection().Model(t).Where("uid = ?", uid).Find(&urs).Error
if err != nil {
return nil, err
}
s, _ := json.Marshal(urs)
if securityConfig.EnableRedisCache {
redis.Hash.HSet(t.TableName(), uidstr, string(s))
} else {
localcache.Default.Set(cacheKey(t.TableName(), "uid", uidstr), string(s))
}
return urs, nil
}
Go
1
https://gitee.com/chenhonghua/ginorigin.git
git@gitee.com:chenhonghua/ginorigin.git
chenhonghua
ginorigin
ginorigin
v0.1.6

搜索帮助

53164aa7 5694891 3bd8fe86 5694891