diff --git a/internal/configloaders/admin_module.go b/internal/configloaders/admin_module.go index ced2a48b..07c1c232 100644 --- a/internal/configloaders/admin_module.go +++ b/internal/configloaders/admin_module.go @@ -1,6 +1,11 @@ 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 @@ -13,60 +18,115 @@ const ( AdminModuleCodeSetting AdminModuleCode = "setting" ) -var adminModuleMapping = map[int64]*AdminModuleList{} // adminId => AdminModuleList +var sharedAdminModuleMapping = map[int64]*AdminModuleList{} // adminId => AdminModuleList -func LoadAdminModuleMapping() (map[int64]*AdminModuleList, error) { - locker.Lock() - defer locker.Unlock() - - if len(adminModuleMapping) > 0 { - return adminModuleMapping, nil +func loadAdminModuleMapping() (map[int64]*AdminModuleList, error) { + if len(sharedAdminModuleMapping) > 0 { + return sharedAdminModuleMapping, 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 { locker.Lock() - adminModuleMapping = map[int64]*AdminModuleList{} - locker.Unlock() // 这里结束是为了避免和LoadAdminModuleMapping()造成死锁 - _, err := LoadAdminModuleMapping() + defer locker.Unlock() + sharedAdminModuleMapping = map[int64]*AdminModuleList{} + _, err := loadAdminModuleMapping() 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 } +// 获取管理员第一个可访问模块 +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 { return []maps.Map{ { "name": "网站服务", "code": AdminModuleCodeServer, + "url": "/servers", }, { "name": "边缘节点", "code": AdminModuleCodeNode, + "url": "/clusters", }, { "name": "域名解析", "code": AdminModuleCodeDNS, + "url": "/dns", }, { "name": "系统用户", "code": AdminModuleCodeAdmin, + "url": "/admins", }, { "name": "日志审计", "code": AdminModuleCodeLog, + "url": "/log", }, { "name": "系统设置", "code": AdminModuleCodeSetting, + "url": "/settings", }, } } diff --git a/internal/configloaders/admin_module_list.go b/internal/configloaders/admin_module_list.go index fb2447e1..336ad40f 100644 --- a/internal/configloaders/admin_module_list.go +++ b/internal/configloaders/admin_module_list.go @@ -6,3 +6,15 @@ type AdminModuleList struct { IsSuper bool 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 +} diff --git a/internal/configloaders/admin_module_test.go b/internal/configloaders/admin_module_test.go new file mode 100644 index 00000000..f6c020a3 --- /dev/null +++ b/internal/configloaders/admin_module_test.go @@ -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) +} diff --git a/internal/web/actions/default/admins/createPopup.go b/internal/web/actions/default/admins/createPopup.go index eaa3a162..b12acab1 100644 --- a/internal/web/actions/default/admins/createPopup.go +++ b/internal/web/actions/default/admins/createPopup.go @@ -88,7 +88,16 @@ func (this *CreatePopupAction) RunPost(params struct { return } + + defer this.CreateLogInfo("创建系统用户 %d", createResp.AdminId) + // 通知更改 + err = configloaders.NotifyAdminModuleMappingChange() + if err != nil { + this.ErrorPage(err) + return + } + this.Success() } diff --git a/internal/web/actions/default/admins/delete.go b/internal/web/actions/default/admins/delete.go index 87669adb..7c33078d 100644 --- a/internal/web/actions/default/admins/delete.go +++ b/internal/web/actions/default/admins/delete.go @@ -1,6 +1,7 @@ package admins import ( + "github.com/TeaOSLab/EdgeAdmin/internal/configloaders" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" ) @@ -20,5 +21,12 @@ func (this *DeleteAction) RunPost(params struct { return } + // 通知更改 + err = configloaders.NotifyAdminModuleMappingChange() + if err != nil { + this.ErrorPage(err) + return + } + this.Success() } diff --git a/internal/web/actions/default/admins/init.go b/internal/web/actions/default/admins/init.go index 8d2e71f1..8ef5e76a 100644 --- a/internal/web/actions/default/admins/init.go +++ b/internal/web/actions/default/admins/init.go @@ -10,12 +10,12 @@ func init() { server. Helper(helpers.NewUserMustAuth()). Data("teaMenu", "admins"). + Data("teaModule", "admin"). Prefix("/admins"). Get("", new(IndexAction)). GetPost("/createPopup", new(CreatePopupAction)). GetPost("/updatePopup", new(UpdatePopupAction)). Post("/delete", new(DeleteAction)). - Post("/updateOn", new(UpdateOnAction)). EndAll() }) } diff --git a/internal/web/actions/default/admins/updateOn.go b/internal/web/actions/default/admins/updateOn.go deleted file mode 100644 index b2199750..00000000 --- a/internal/web/actions/default/admins/updateOn.go +++ /dev/null @@ -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() -} diff --git a/internal/web/actions/default/admins/updatePopup.go b/internal/web/actions/default/admins/updatePopup.go index ac52658a..9edbc96d 100644 --- a/internal/web/actions/default/admins/updatePopup.go +++ b/internal/web/actions/default/admins/updatePopup.go @@ -125,5 +125,12 @@ func (this *UpdatePopupAction) RunPost(params struct { return } + // 通知更改 + err = configloaders.NotifyAdminModuleMappingChange() + if err != nil { + this.ErrorPage(err) + return + } + this.Success() } diff --git a/internal/web/actions/default/clusters/init.go b/internal/web/actions/default/clusters/init.go index c31302e4..02589dd1 100644 --- a/internal/web/actions/default/clusters/init.go +++ b/internal/web/actions/default/clusters/init.go @@ -11,6 +11,7 @@ func init() { server. Helper(helpers.NewUserMustAuth()). Helper(clusterutils.NewClustersHelper()). + Data("teaModule", "node"). Prefix("/clusters"). Get("", new(IndexAction)). GetPost("/create", new(CreateAction)). diff --git a/internal/web/actions/default/dashboard/index.go b/internal/web/actions/default/dashboard/index.go index eed3cba6..f77ec229 100644 --- a/internal/web/actions/default/dashboard/index.go +++ b/internal/web/actions/default/dashboard/index.go @@ -1,6 +1,9 @@ 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 { actionutils.ParentAction @@ -11,5 +14,14 @@ func (this *IndexAction) Init() { } 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 + } + } + } } diff --git a/internal/web/actions/default/dns/init.go b/internal/web/actions/default/dns/init.go index 5a6a798e..b6834e15 100644 --- a/internal/web/actions/default/dns/init.go +++ b/internal/web/actions/default/dns/init.go @@ -14,6 +14,7 @@ func init() { server. Helper(new(helpers.UserMustAuth)). Helper(new(Helper)). + Data("teaModule", "dns"). Prefix("/dns"). Get("", new(IndexAction)). GetPost("/updateClusterPopup", new(UpdateClusterPopupAction)). diff --git a/internal/web/actions/default/log/init.go b/internal/web/actions/default/log/init.go index 14c428a2..90bfa139 100644 --- a/internal/web/actions/default/log/init.go +++ b/internal/web/actions/default/log/init.go @@ -10,6 +10,7 @@ func init() { server. Helper(new(helpers.UserMustAuth)). Helper(new(Helper)). + Data("teaModule", "log"). Prefix("/log"). Get("", new(IndexAction)). Get("/exportExcel", new(ExportExcelAction)). diff --git a/internal/web/actions/default/servers/init.go b/internal/web/actions/default/servers/init.go index ab88851a..f6fb1b60 100644 --- a/internal/web/actions/default/servers/init.go +++ b/internal/web/actions/default/servers/init.go @@ -10,6 +10,7 @@ func init() { server. Helper(helpers.NewUserMustAuth()). Helper(NewHelper()). + Data("teaModule", "server"). Prefix("/servers"). Get("", new(IndexAction)). GetPost("/create", new(CreateAction)). diff --git a/internal/web/actions/default/settings/init.go b/internal/web/actions/default/settings/init.go index f7935152..08aefac0 100644 --- a/internal/web/actions/default/settings/init.go +++ b/internal/web/actions/default/settings/init.go @@ -10,6 +10,7 @@ func init() { server. Helper(helpers.NewUserMustAuth()). Helper(NewHelper()). + Data("teaModule", "setting"). Prefix("/settings"). Get("", new(IndexAction)). EndAll() diff --git a/internal/web/helpers/user_must_auth.go b/internal/web/helpers/user_must_auth.go index 1756142b..d6ae4e28 100644 --- a/internal/web/helpers/user_must_auth.go +++ b/internal/web/helpers/user_must_auth.go @@ -15,7 +15,7 @@ import ( // 认证拦截 type UserMustAuth struct { - AdminId int + AdminId int64 Grant string } @@ -48,12 +48,19 @@ func (this *UserMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramNam } var session = action.Session() - var adminId = session.GetInt("adminId") + var adminId = session.GetInt64("adminId") if adminId <= 0 { this.login(action) 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() if err != nil { @@ -111,7 +118,7 @@ func (this *UserMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramNam if !action.Data.Has("teaMenu") { action.Data["teaMenu"] = "" } - action.Data["teaModules"] = this.modules() + action.Data["teaModules"] = this.modules(adminId) action.Data["teaSubMenus"] = []map[string]interface{}{} action.Data["teaTabbar"] = []map[string]interface{}{} if len(config.Version) == 0 { @@ -142,12 +149,13 @@ func (this *UserMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramNam } // 菜单配置 -func (this *UserMustAuth) modules() []maps.Map { - return []maps.Map{ +func (this *UserMustAuth) modules(adminId int64) []maps.Map { + allMaps := []maps.Map{ { - "code": "servers", - "name": "网站服务", - "icon": "clone outsize", + "code": "servers", + "module": configloaders.AdminModuleCodeServer, + "name": "网站服务", + "icon": "clone outsize", "subItems": []maps.Map{ { "name": "通用设置", @@ -177,9 +185,10 @@ func (this *UserMustAuth) modules() []maps.Map { }, }, { - "code": "clusters", - "name": "边缘节点", - "icon": "cloud", + "code": "clusters", + "module": configloaders.AdminModuleCodeNode, + "name": "边缘节点", + "icon": "cloud", "subItems": []maps.Map{ { "name": "SSH认证", @@ -189,9 +198,10 @@ func (this *UserMustAuth) modules() []maps.Map { }, }, { - "code": "dns", - "name": "域名解析", - "icon": "globe", + "code": "dns", + "module": configloaders.AdminModuleCodeDNS, + "name": "域名解析", + "icon": "globe", "subItems": []maps.Map{ { "name": "问题修复", @@ -206,21 +216,33 @@ func (this *UserMustAuth) modules() []maps.Map { }, }, { - "code": "admins", - "name": "系统用户", - "icon": "users", + "code": "admins", + "module": configloaders.AdminModuleCodeAdmin, + "name": "系统用户", + "icon": "users", }, { - "code": "log", - "name": "日志审计", - "icon": "history", + "code": "log", + "module": configloaders.AdminModuleCodeLog, + "name": "日志审计", + "icon": "history", }, { - "code": "settings", - "name": "系统设置", - "icon": "setting", + "code": "settings", + "module": configloaders.AdminModuleCodeSetting, + "name": "系统设置", + "icon": "setting", }, } + + result := []maps.Map{} + for _, m := range allMaps { + module := m.GetString("module") + if configloaders.AllowModule(adminId, module) { + result = append(result, m) + } + } + return result } // 跳转到登录页 diff --git a/web/views/@default/admins/index.html b/web/views/@default/admins/index.html index 73360f56..2f27f15f 100644 --- a/web/views/@default/admins/index.html +++ b/web/views/@default/admins/index.html @@ -23,7 +23,7 @@ - 修改   删除 + 修改   删除