mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-10 17:30:29 +08:00
[系统用户]实现基础的权限校验
This commit is contained in:
@@ -1,6 +1,11 @@
|
|||||||
package configloaders
|
package configloaders
|
||||||
|
|
||||||
import "github.com/iwind/TeaGo/maps"
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
)
|
||||||
|
|
||||||
type AdminModuleCode = string
|
type AdminModuleCode = string
|
||||||
|
|
||||||
@@ -13,60 +18,115 @@ const (
|
|||||||
AdminModuleCodeSetting AdminModuleCode = "setting"
|
AdminModuleCodeSetting AdminModuleCode = "setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
var adminModuleMapping = map[int64]*AdminModuleList{} // adminId => AdminModuleList
|
var sharedAdminModuleMapping = map[int64]*AdminModuleList{} // adminId => AdminModuleList
|
||||||
|
|
||||||
func LoadAdminModuleMapping() (map[int64]*AdminModuleList, error) {
|
func loadAdminModuleMapping() (map[int64]*AdminModuleList, error) {
|
||||||
locker.Lock()
|
if len(sharedAdminModuleMapping) > 0 {
|
||||||
defer locker.Unlock()
|
return sharedAdminModuleMapping, nil
|
||||||
|
|
||||||
if len(adminModuleMapping) > 0 {
|
|
||||||
return adminModuleMapping, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
rpcClient, err := rpc.SharedRPC()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
modulesResp, err := rpcClient.AdminRPC().FindAllAdminModules(rpcClient.Context(0), &pb.FindAllAdminModulesRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
mapping := map[int64]*AdminModuleList{}
|
||||||
|
for _, m := range modulesResp.AdminModules {
|
||||||
|
list := &AdminModuleList{
|
||||||
|
IsSuper: m.IsSuper,
|
||||||
|
}
|
||||||
|
|
||||||
return nil, nil
|
for _, pbModule := range m.Modules {
|
||||||
|
list.Modules = append(list.Modules, &systemconfigs.AdminModule{
|
||||||
|
Code: pbModule.Code,
|
||||||
|
AllowAll: pbModule.AllowAll,
|
||||||
|
Actions: pbModule.Actions,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
mapping[m.AdminId] = list
|
||||||
|
}
|
||||||
|
|
||||||
|
sharedAdminModuleMapping = mapping
|
||||||
|
|
||||||
|
return sharedAdminModuleMapping, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NotifyAdminModuleMappingChange() error {
|
func NotifyAdminModuleMappingChange() error {
|
||||||
locker.Lock()
|
locker.Lock()
|
||||||
adminModuleMapping = map[int64]*AdminModuleList{}
|
defer locker.Unlock()
|
||||||
locker.Unlock() // 这里结束是为了避免和LoadAdminModuleMapping()造成死锁
|
sharedAdminModuleMapping = map[int64]*AdminModuleList{}
|
||||||
_, err := LoadAdminModuleMapping()
|
_, err := loadAdminModuleMapping()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsAllowModule(adminId int64, module string) bool {
|
// 检查模块是否允许访问
|
||||||
// TODO
|
func AllowModule(adminId int64, module string) bool {
|
||||||
|
locker.Lock()
|
||||||
|
defer locker.Unlock()
|
||||||
|
|
||||||
|
if len(sharedAdminModuleMapping) == 0 {
|
||||||
|
_, _ = loadAdminModuleMapping()
|
||||||
|
}
|
||||||
|
|
||||||
|
list, ok := sharedAdminModuleMapping[adminId]
|
||||||
|
if ok {
|
||||||
|
return list.Allow(module)
|
||||||
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取管理员第一个可访问模块
|
||||||
|
func FindFirstAdminModule(adminId int64) (module AdminModuleCode, ok bool) {
|
||||||
|
locker.Lock()
|
||||||
|
defer locker.Unlock()
|
||||||
|
list, ok2 := sharedAdminModuleMapping[adminId]
|
||||||
|
if ok2 {
|
||||||
|
if list.IsSuper {
|
||||||
|
return AdminModuleCodeServer, true
|
||||||
|
} else if len(list.Modules) > 0 {
|
||||||
|
return list.Modules[0].Code, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 所有权限列表
|
// 所有权限列表
|
||||||
func AllModuleMaps() []maps.Map {
|
func AllModuleMaps() []maps.Map {
|
||||||
return []maps.Map{
|
return []maps.Map{
|
||||||
{
|
{
|
||||||
"name": "网站服务",
|
"name": "网站服务",
|
||||||
"code": AdminModuleCodeServer,
|
"code": AdminModuleCodeServer,
|
||||||
|
"url": "/servers",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "边缘节点",
|
"name": "边缘节点",
|
||||||
"code": AdminModuleCodeNode,
|
"code": AdminModuleCodeNode,
|
||||||
|
"url": "/clusters",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "域名解析",
|
"name": "域名解析",
|
||||||
"code": AdminModuleCodeDNS,
|
"code": AdminModuleCodeDNS,
|
||||||
|
"url": "/dns",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "系统用户",
|
"name": "系统用户",
|
||||||
"code": AdminModuleCodeAdmin,
|
"code": AdminModuleCodeAdmin,
|
||||||
|
"url": "/admins",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "日志审计",
|
"name": "日志审计",
|
||||||
"code": AdminModuleCodeLog,
|
"code": AdminModuleCodeLog,
|
||||||
|
"url": "/log",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "系统设置",
|
"name": "系统设置",
|
||||||
"code": AdminModuleCodeSetting,
|
"code": AdminModuleCodeSetting,
|
||||||
|
"url": "/settings",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,3 +6,15 @@ type AdminModuleList struct {
|
|||||||
IsSuper bool
|
IsSuper bool
|
||||||
Modules []*systemconfigs.AdminModule
|
Modules []*systemconfigs.AdminModule
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *AdminModuleList) Allow(module string) bool {
|
||||||
|
if this.IsSuper {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for _, m := range this.Modules {
|
||||||
|
if m.Code == module {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
14
internal/configloaders/admin_module_test.go
Normal file
14
internal/configloaders/admin_module_test.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package configloaders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/iwind/TeaGo/logs"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLoadAdminModuleMapping(t *testing.T) {
|
||||||
|
m, err := LoadAdminModuleMapping()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
logs.PrintAsJSON(m, t)
|
||||||
|
}
|
||||||
@@ -88,7 +88,16 @@ func (this *CreatePopupAction) RunPost(params struct {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
defer this.CreateLogInfo("创建系统用户 %d", createResp.AdminId)
|
defer this.CreateLogInfo("创建系统用户 %d", createResp.AdminId)
|
||||||
|
|
||||||
|
// 通知更改
|
||||||
|
err = configloaders.NotifyAdminModuleMappingChange()
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package admins
|
package admins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
)
|
)
|
||||||
@@ -20,5 +21,12 @@ func (this *DeleteAction) RunPost(params struct {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 通知更改
|
||||||
|
err = configloaders.NotifyAdminModuleMappingChange()
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,12 @@ func init() {
|
|||||||
server.
|
server.
|
||||||
Helper(helpers.NewUserMustAuth()).
|
Helper(helpers.NewUserMustAuth()).
|
||||||
Data("teaMenu", "admins").
|
Data("teaMenu", "admins").
|
||||||
|
Data("teaModule", "admin").
|
||||||
Prefix("/admins").
|
Prefix("/admins").
|
||||||
Get("", new(IndexAction)).
|
Get("", new(IndexAction)).
|
||||||
GetPost("/createPopup", new(CreatePopupAction)).
|
GetPost("/createPopup", new(CreatePopupAction)).
|
||||||
GetPost("/updatePopup", new(UpdatePopupAction)).
|
GetPost("/updatePopup", new(UpdatePopupAction)).
|
||||||
Post("/delete", new(DeleteAction)).
|
Post("/delete", new(DeleteAction)).
|
||||||
Post("/updateOn", new(UpdateOnAction)).
|
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
package admins
|
|
||||||
|
|
||||||
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
|
|
||||||
type UpdateOnAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *UpdateOnAction) RunPost(params struct{}) {
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -125,5 +125,12 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 通知更改
|
||||||
|
err = configloaders.NotifyAdminModuleMappingChange()
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ func init() {
|
|||||||
server.
|
server.
|
||||||
Helper(helpers.NewUserMustAuth()).
|
Helper(helpers.NewUserMustAuth()).
|
||||||
Helper(clusterutils.NewClustersHelper()).
|
Helper(clusterutils.NewClustersHelper()).
|
||||||
|
Data("teaModule", "node").
|
||||||
Prefix("/clusters").
|
Prefix("/clusters").
|
||||||
Get("", new(IndexAction)).
|
Get("", new(IndexAction)).
|
||||||
GetPost("/create", new(CreateAction)).
|
GetPost("/create", new(CreateAction)).
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package dashboard
|
package dashboard
|
||||||
|
|
||||||
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
)
|
||||||
|
|
||||||
type IndexAction struct {
|
type IndexAction struct {
|
||||||
actionutils.ParentAction
|
actionutils.ParentAction
|
||||||
@@ -11,5 +14,14 @@ func (this *IndexAction) Init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *IndexAction) RunGet(params struct{}) {
|
func (this *IndexAction) RunGet(params struct{}) {
|
||||||
this.RedirectURL("/servers")
|
// 取得用户的权限
|
||||||
|
module, ok := configloaders.FindFirstAdminModule(this.AdminId())
|
||||||
|
if ok {
|
||||||
|
for _, m := range configloaders.AllModuleMaps() {
|
||||||
|
if m.GetString("code") == module {
|
||||||
|
this.RedirectURL(m.GetString("url"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ func init() {
|
|||||||
server.
|
server.
|
||||||
Helper(new(helpers.UserMustAuth)).
|
Helper(new(helpers.UserMustAuth)).
|
||||||
Helper(new(Helper)).
|
Helper(new(Helper)).
|
||||||
|
Data("teaModule", "dns").
|
||||||
Prefix("/dns").
|
Prefix("/dns").
|
||||||
Get("", new(IndexAction)).
|
Get("", new(IndexAction)).
|
||||||
GetPost("/updateClusterPopup", new(UpdateClusterPopupAction)).
|
GetPost("/updateClusterPopup", new(UpdateClusterPopupAction)).
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ func init() {
|
|||||||
server.
|
server.
|
||||||
Helper(new(helpers.UserMustAuth)).
|
Helper(new(helpers.UserMustAuth)).
|
||||||
Helper(new(Helper)).
|
Helper(new(Helper)).
|
||||||
|
Data("teaModule", "log").
|
||||||
Prefix("/log").
|
Prefix("/log").
|
||||||
Get("", new(IndexAction)).
|
Get("", new(IndexAction)).
|
||||||
Get("/exportExcel", new(ExportExcelAction)).
|
Get("/exportExcel", new(ExportExcelAction)).
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ func init() {
|
|||||||
server.
|
server.
|
||||||
Helper(helpers.NewUserMustAuth()).
|
Helper(helpers.NewUserMustAuth()).
|
||||||
Helper(NewHelper()).
|
Helper(NewHelper()).
|
||||||
|
Data("teaModule", "server").
|
||||||
Prefix("/servers").
|
Prefix("/servers").
|
||||||
Get("", new(IndexAction)).
|
Get("", new(IndexAction)).
|
||||||
GetPost("/create", new(CreateAction)).
|
GetPost("/create", new(CreateAction)).
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ func init() {
|
|||||||
server.
|
server.
|
||||||
Helper(helpers.NewUserMustAuth()).
|
Helper(helpers.NewUserMustAuth()).
|
||||||
Helper(NewHelper()).
|
Helper(NewHelper()).
|
||||||
|
Data("teaModule", "setting").
|
||||||
Prefix("/settings").
|
Prefix("/settings").
|
||||||
Get("", new(IndexAction)).
|
Get("", new(IndexAction)).
|
||||||
EndAll()
|
EndAll()
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
|
|
||||||
// 认证拦截
|
// 认证拦截
|
||||||
type UserMustAuth struct {
|
type UserMustAuth struct {
|
||||||
AdminId int
|
AdminId int64
|
||||||
Grant string
|
Grant string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,12 +48,19 @@ func (this *UserMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramNam
|
|||||||
}
|
}
|
||||||
|
|
||||||
var session = action.Session()
|
var session = action.Session()
|
||||||
var adminId = session.GetInt("adminId")
|
var adminId = session.GetInt64("adminId")
|
||||||
if adminId <= 0 {
|
if adminId <= 0 {
|
||||||
this.login(action)
|
this.login(action)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查用户权限
|
||||||
|
teaModule := action.Data.GetString("teaModule")
|
||||||
|
if len(teaModule) > 0 && !configloaders.AllowModule(adminId, teaModule) {
|
||||||
|
action.WriteString("Permission Denied.")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// 检查用户是否存在
|
// 检查用户是否存在
|
||||||
rpc, err := nodes.SharedRPC()
|
rpc, err := nodes.SharedRPC()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -111,7 +118,7 @@ func (this *UserMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramNam
|
|||||||
if !action.Data.Has("teaMenu") {
|
if !action.Data.Has("teaMenu") {
|
||||||
action.Data["teaMenu"] = ""
|
action.Data["teaMenu"] = ""
|
||||||
}
|
}
|
||||||
action.Data["teaModules"] = this.modules()
|
action.Data["teaModules"] = this.modules(adminId)
|
||||||
action.Data["teaSubMenus"] = []map[string]interface{}{}
|
action.Data["teaSubMenus"] = []map[string]interface{}{}
|
||||||
action.Data["teaTabbar"] = []map[string]interface{}{}
|
action.Data["teaTabbar"] = []map[string]interface{}{}
|
||||||
if len(config.Version) == 0 {
|
if len(config.Version) == 0 {
|
||||||
@@ -142,10 +149,11 @@ func (this *UserMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramNam
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 菜单配置
|
// 菜单配置
|
||||||
func (this *UserMustAuth) modules() []maps.Map {
|
func (this *UserMustAuth) modules(adminId int64) []maps.Map {
|
||||||
return []maps.Map{
|
allMaps := []maps.Map{
|
||||||
{
|
{
|
||||||
"code": "servers",
|
"code": "servers",
|
||||||
|
"module": configloaders.AdminModuleCodeServer,
|
||||||
"name": "网站服务",
|
"name": "网站服务",
|
||||||
"icon": "clone outsize",
|
"icon": "clone outsize",
|
||||||
"subItems": []maps.Map{
|
"subItems": []maps.Map{
|
||||||
@@ -178,6 +186,7 @@ func (this *UserMustAuth) modules() []maps.Map {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"code": "clusters",
|
"code": "clusters",
|
||||||
|
"module": configloaders.AdminModuleCodeNode,
|
||||||
"name": "边缘节点",
|
"name": "边缘节点",
|
||||||
"icon": "cloud",
|
"icon": "cloud",
|
||||||
"subItems": []maps.Map{
|
"subItems": []maps.Map{
|
||||||
@@ -190,6 +199,7 @@ func (this *UserMustAuth) modules() []maps.Map {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"code": "dns",
|
"code": "dns",
|
||||||
|
"module": configloaders.AdminModuleCodeDNS,
|
||||||
"name": "域名解析",
|
"name": "域名解析",
|
||||||
"icon": "globe",
|
"icon": "globe",
|
||||||
"subItems": []maps.Map{
|
"subItems": []maps.Map{
|
||||||
@@ -207,20 +217,32 @@ func (this *UserMustAuth) modules() []maps.Map {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"code": "admins",
|
"code": "admins",
|
||||||
|
"module": configloaders.AdminModuleCodeAdmin,
|
||||||
"name": "系统用户",
|
"name": "系统用户",
|
||||||
"icon": "users",
|
"icon": "users",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"code": "log",
|
"code": "log",
|
||||||
|
"module": configloaders.AdminModuleCodeLog,
|
||||||
"name": "日志审计",
|
"name": "日志审计",
|
||||||
"icon": "history",
|
"icon": "history",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"code": "settings",
|
"code": "settings",
|
||||||
|
"module": configloaders.AdminModuleCodeSetting,
|
||||||
"name": "系统设置",
|
"name": "系统设置",
|
||||||
"icon": "setting",
|
"icon": "setting",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result := []maps.Map{}
|
||||||
|
for _, m := range allMaps {
|
||||||
|
module := m.GetString("module")
|
||||||
|
if configloaders.AllowModule(adminId, module) {
|
||||||
|
result = append(result, m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// 跳转到登录页
|
// 跳转到登录页
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
<label-on :v-is-on="admin.isOn"></label-on>
|
<label-on :v-is-on="admin.isOn"></label-on>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="" @click.prevent="updateAdmin(admin.id)">修改</a> <a href="" v-if="!admin.isSuper" @click.prevent="deleteAdmin(admin.id)">删除</a>
|
<a href="" @click.prevent="updateAdmin(admin.id)" v-if="!admin.isSuper">修改</a> <a href="" v-if="!admin.isSuper" @click.prevent="deleteAdmin(admin.id)">删除</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
Reference in New Issue
Block a user