service.xpcool.com/internal/service/admin/system/role/role.go
夏犀麟 4aca0c7f6f
Some checks failed
Build and Deploy (service.xpcool.com) / build-and-deploy (push) Failing after 5m7s
feat(house): 实现看房模块后端功能
- 新增 9 张房屋相关数据表(社区/楼宇/房源/价格快照/交易/设施/社区设施/学区/偏好)
- 添加菜单权限种子数据并绑定超级管理员角色
- 生成 DAO 层代码和实体对象
- 实现房屋模块 API 接口(社区/房源/看板)和控制器服务层
- 支持多平台软关联匹配、笋盘标记和低可信度标记功能
- 更新超级管理员账号为 xxcool/xxCool@2026
- 调整 RBAC 菜单结构,移除管理员管理功能,新增日志管理菜单
- 修复 RBAC 安全漏洞,确保禁用角色权限失效
- 重构认证模块,将登录相关接口迁移到统一包结构下
- 移除废弃的管理模块和工具类接口定义
- 为通用工具包添加中文注释和文档说明
2026-08-26 23:42:38 +08:00

129 lines
4.1 KiB
Go

package admin_system_role
import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"service.xpcool.com/internal/consts"
"service.xpcool.com/internal/dao"
"service.xpcool.com/internal/library/response"
"service.xpcool.com/internal/model/do"
"service.xpcool.com/internal/model/dto"
"service.xpcool.com/internal/model/entity"
)
// IRoleManage 管理角色及其菜单绑定。
type IRoleManage interface {
List(context.Context, dto.PageQuery) ([]*dto.RoleItem, int, error)
Create(context.Context, dto.RoleCreateInput) (uint64, error)
Update(context.Context, dto.RoleUpdateInput) error
Delete(context.Context, uint64) error
}
type roleManage struct{}
var localRoleManage IRoleManage
func NewRoleManage() IRoleManage { return &roleManage{} }
func RoleManage() IRoleManage {
if localRoleManage == nil {
panic("RoleManage implementation not registered")
}
return localRoleManage
}
func RegisterRoleManage(i IRoleManage) { localRoleManage = i }
// ---------------------- Role manage ----------------------
func (s *roleManage) List(ctx context.Context, q dto.PageQuery) ([]*dto.RoleItem, int, error) {
total, err := dao.AdminRole.Ctx(ctx).Count()
if err != nil {
return nil, 0, gerror.Wrap(err, "count roles")
}
if total == 0 {
return nil, 0, nil
}
var list []entity.AdminRole
if err = dao.AdminRole.Ctx(ctx).Page(q.Page, q.Size).OrderAsc("id").Scan(&list); err != nil {
return nil, 0, gerror.Wrap(err, "query roles")
}
items := make([]*dto.RoleItem, 0, len(list))
for i := range list {
r := &list[i]
menuIds, err := roleMenuIDs(ctx, r.Id)
if err != nil {
return nil, 0, err
}
items = append(items, &dto.RoleItem{
Id: r.Id, Code: r.Code, Name: r.Name, Status: r.Status, MenuIds: menuIds,
CreatedAt: r.CreatedAt.Layout("2006-01-02 15:04:05"),
})
}
return items, total, nil
}
func (s *roleManage) Create(ctx context.Context, in dto.RoleCreateInput) (uint64, error) {
count, err := dao.AdminRole.Ctx(ctx).Where(do.AdminRole{Code: in.Code}).Count()
if err != nil {
return 0, gerror.Wrap(err, "check role code")
}
if count > 0 {
return 0, response.Error(consts.CodeInvalidParam, "role code already exists")
}
id, err := dao.AdminRole.Ctx(ctx).Data(do.AdminRole{Code: in.Code, Name: in.Name, Status: in.Status}).InsertAndGetId()
if err != nil {
return 0, gerror.Wrap(err, "insert role")
}
if err = bindRoleMenus(ctx, uint64(id), in.MenuIds); err != nil {
return 0, err
}
return uint64(id), nil
}
func (s *roleManage) Update(ctx context.Context, in dto.RoleUpdateInput) error {
if _, err := dao.AdminRole.Ctx(ctx).Where(do.AdminRole{Id: in.Id}).Data(do.AdminRole{Name: in.Name, Status: in.Status}).Update(); err != nil {
return gerror.Wrap(err, "update role")
}
return bindRoleMenus(ctx, in.Id, in.MenuIds)
}
func (s *roleManage) Delete(ctx context.Context, id uint64) error {
if _, err := dao.AdminRole.Ctx(ctx).Where(do.AdminRole{Id: id}).Delete(); err != nil {
return gerror.Wrap(err, "delete role")
}
if _, err := dao.AdminRoleMenu.Ctx(ctx).Unscoped().Where(do.AdminRoleMenu{RoleId: id}).Delete(); err != nil {
return gerror.Wrap(err, "delete role menu bindings")
}
if _, err := dao.AdminUserRole.Ctx(ctx).Unscoped().Where(do.AdminUserRole{RoleId: id}).Delete(); err != nil {
return gerror.Wrap(err, "delete user role bindings")
}
return nil
}
func roleMenuIDs(ctx context.Context, roleID uint64) ([]uint64, error) {
var rels []entity.AdminRoleMenu
if err := dao.AdminRoleMenu.Ctx(ctx).Where(do.AdminRoleMenu{RoleId: roleID}).Scan(&rels); err != nil {
return nil, gerror.Wrap(err, "query role menus")
}
ids := make([]uint64, 0, len(rels))
for _, r := range rels {
ids = append(ids, r.MenuId)
}
return ids, nil
}
// bindRoleMenus 全量重绑角色-菜单关系。
func bindRoleMenus(ctx context.Context, roleID uint64, menuIds []uint64) error {
if _, err := dao.AdminRoleMenu.Ctx(ctx).Unscoped().Where(do.AdminRoleMenu{RoleId: roleID}).Delete(); err != nil {
return gerror.Wrap(err, "clear role menus")
}
for _, mid := range menuIds {
if _, err := dao.AdminRoleMenu.Ctx(ctx).Data(do.AdminRoleMenu{RoleId: roleID, MenuId: mid}).Insert(); err != nil {
return gerror.Wrap(err, "bind role menu")
}
}
return nil
}