next-terminal/server/service/role.go
2022-10-23 20:05:13 +08:00

269 lines
6.3 KiB
Go

package service
import (
"context"
"errors"
"sync"
"next-terminal/server/common/sets"
"next-terminal/server/model"
"next-terminal/server/repository"
"next-terminal/server/utils"
)
var RoleService = new(roleService)
type roleService struct {
baseService
roleMenus sync.Map
}
func (s *roleService) Init() error {
ctx := context.Background()
// 创建默认的角色
if err := s.CreateDefaultRoles(); err != nil {
return err
}
// 重载角色对应权限的缓存
roles, err := repository.RoleRepository.FindAll(ctx)
if err != nil {
return err
}
for _, role := range roles {
refs, err := s.FindMenuByRoleId(ctx, role.ID)
if err != nil {
return err
}
var menus []string
for _, ref := range refs {
menus = append(menus, ref.MenuId)
}
s.setRoleMenus(role.ID, menus)
}
return nil
}
func (s *roleService) mapRoleMenus(keys []string) []model.RoleMenuRef {
var roleMenus []model.RoleMenuRef
for _, key := range keys {
roleMenus = append(roleMenus, model.RoleMenuRef{
MenuId: key,
Checked: true,
})
}
return roleMenus
}
func (s *roleService) Create(c context.Context, role *model.Role) error {
return s.Transaction(c, func(ctx context.Context) error {
if err := repository.RoleRepository.Create(ctx, role); err != nil {
return err
}
if err := s.createRolePermissionRefs(ctx, role); err != nil {
return err
}
return nil
})
}
func (s *roleService) createRolePermissionRefs(ctx context.Context, role *model.Role) error {
var menuIds = sets.NewStringSet()
var refIds = sets.NewStringSet()
var refs []*model.RoleMenuRef
for _, menu := range role.Menus {
refId := utils.Sign([]string{role.ID, menu.MenuId})
if refIds.Contains(refId) {
continue
}
ref := &model.RoleMenuRef{
ID: refId,
RoleId: role.ID,
MenuId: menu.MenuId,
Checked: menu.Checked,
}
refs = append(refs, ref)
refIds.Add(ref.ID)
menuIds.Add(menu.MenuId)
}
if err := repository.RoleMenuRefRepository.DeleteByIdIn(ctx, refIds.ToArray()); err != nil {
return err
}
if err := repository.RoleMenuRefRepository.CreateInBatches(ctx, refs); err != nil {
return err
}
s.setRoleMenus(role.ID, menuIds.ToArray())
return nil
}
func (s *roleService) UpdateById(c context.Context, role *model.Role, id string, force bool) error {
return s.Transaction(c, func(ctx context.Context) error {
dbRole, err := repository.RoleRepository.FindById(ctx, id)
if err != nil {
return err
}
if !force {
if !dbRole.Modifiable {
return errors.New("prohibit to modify " + dbRole.Name)
}
}
if err := repository.RoleRepository.UpdateById(ctx, role, id); err != nil {
return err
}
if err := repository.RoleMenuRefRepository.DeleteByRoleId(ctx, id); err != nil {
return err
}
if err := s.createRolePermissionRefs(ctx, role); err != nil {
return err
}
return nil
})
}
func (s *roleService) DeleteByIds(c context.Context, ids []string, force bool) error {
return s.Transaction(c, func(ctx context.Context) error {
for i := range ids {
id := ids[i]
if !force {
role, err := repository.RoleRepository.FindById(ctx, id)
if err != nil {
return err
}
if !role.Deletable {
return errors.New("prohibit to delete " + role.Name)
}
}
if err := repository.RoleRepository.DeleteById(ctx, id); err != nil {
return err
}
if err := repository.RoleMenuRefRepository.DeleteByRoleId(ctx, id); err != nil {
return err
}
if err := repository.UserRoleRefRepository.DeleteByRoleId(ctx, id); err != nil {
return err
}
// 删除缓存
s.removeRole(id)
}
return nil
})
}
func (s *roleService) FindById(ctx context.Context, id string) (*model.Role, error) {
role, err := repository.RoleRepository.FindById(ctx, id)
if err != nil {
return nil, err
}
permissions, err := s.FindMenuByRoleId(ctx, id)
if err != nil {
return nil, err
}
for i := range permissions {
permissions[i].ID = ""
permissions[i].RoleId = ""
}
role.Menus = permissions
return &role, nil
}
func (s *roleService) FindMenuByRoleId(ctx context.Context, id string) ([]model.RoleMenuRef, error) {
refs, err := repository.RoleMenuRefRepository.FindByRoleId(ctx, id)
if err != nil {
return nil, err
}
return refs, nil
}
func (s *roleService) GetRolesByUserId(userId string) ([]string, error) {
refs, err := repository.UserRoleRefRepository.FindByUserId(context.Background(), userId)
if err != nil {
return nil, err
}
var roles []string
for _, ref := range refs {
roles = append(roles, ref.RoleId)
}
return roles, nil
}
func (s *roleService) GetMenuListByRole(role string) []string {
value, ok := s.roleMenus.Load(role)
if ok {
return value.([]string)
}
return nil
}
func (s *roleService) setRoleMenus(role string, items []string) {
s.roleMenus.Store(role, items)
}
func (s *roleService) removeRole(role string) {
s.roleMenus.Delete(role)
}
func (s *roleService) CreateDefaultRoles() error {
var menus []string
for _, menu := range DefaultMenu {
menus = append(menus, menu.ID)
}
var auditPermissions = []string{
"dashboard",
"log-audit",
"online-session",
"offline-session",
"login-log",
"online-session-paging",
"online-session-disconnect",
"online-session-monitor",
"offline-session-paging",
"offline-session-playback",
"offline-session-del",
"offline-session-clear",
"offline-session-reviewed",
"offline-session-unreviewed",
"offline-session-reviewed-all",
"login-log-paging",
"login-log-del",
"login-log-clear",
}
var securityPermissions = []string{
"security",
"access-security-paging",
"access-security-add",
"access-security-edit",
"access-security-del",
}
var DefaultRoles = []*model.Role{
model.NewRole("system-administrator", "系统管理员", "default", false, false, s.mapRoleMenus(menus)),
model.NewRole("audit-administrator", "审计管理员", "default", false, false, s.mapRoleMenus(auditPermissions)),
model.NewRole("security-administrator", "安全管理员", "default", false, false, s.mapRoleMenus(securityPermissions)),
}
ctx := context.Background()
for _, role := range DefaultRoles {
exists, err := repository.RoleRepository.ExistsById(ctx, role.ID)
if err != nil {
return err
}
if exists {
if err := s.UpdateById(ctx, role, role.ID, true); err != nil {
return err
}
continue
}
if err := s.Create(ctx, role); err != nil {
return err
}
}
return nil
}