From 6ed61e497222c6952cb9cd179cfb073789a21d21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Membr=C3=A9?= Date: Tue, 16 Nov 2021 01:40:10 +0100 Subject: [PATCH] Fixes #20264: Allow to customize in which menu plugins are set --- .../main/scala/bootstrap/liftweb/Boot.scala | 66 +++++++++++-------- .../bootstrap/liftweb/RudderConfig.scala | 1 - .../com/normation/plugins/PublicPlugin.scala | 29 ++++++-- 3 files changed, 62 insertions(+), 34 deletions(-) diff --git a/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/Boot.scala b/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/Boot.scala index 71a9ec7b108..6c547b074d2 100644 --- a/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/Boot.scala @@ -356,28 +356,28 @@ class Boot extends Loggable { // All the following is related to the sitemap val nodeManagerMenu = - (Menu("NodeManagerHome", ++ Node management: NodeSeq) / + (Menu(MenuUtils.nodeManagementMenu, ++ Node management: NodeSeq) / "secure" / "nodeManager" / "index" >> TestAccess( () => userIsAllowed("/secure/index",AuthorizationType.Node.Read) )).submenus ( - Menu("List Nodes", Nodes) / + Menu("110-nodes", Nodes) / "secure" / "nodeManager" / "nodes" >> LocGroup("nodeGroup") - , Menu("SearchNodes", Node search) / + , Menu("120-search-nodes", Node search) / "secure" / "nodeManager" / "searchNodes" >> LocGroup("nodeGroup") - , Menu("NodeDetails", Node details) / + , Menu("120-node-details", Node details) / "secure" / "nodeManager" / "node" >> LocGroup("nodeGroup") >> Hidden - , Menu("ManageNewNode", Pending nodes) / + , Menu("130-pending-nodes", Pending nodes) / "secure" / "nodeManager" / "manageNewNode" >> LocGroup("nodeGroup") - , Menu("Groups", Groups) / + , Menu("140-groups", Groups) / "secure" / "nodeManager" / "groups" >> LocGroup("groupGroup") >> TestAccess( () => userIsAllowed("/secure/index",AuthorizationType.Group.Read ) ) @@ -386,47 +386,47 @@ class Boot extends Loggable { def policyMenu = { val name = "configuration" - (Menu(name+"ManagerHome", ++ {name.capitalize} policy: NodeSeq) / + (Menu(MenuUtils.policyMenu, ++ {name.capitalize} policy: NodeSeq) / "secure" / (name+"Manager") / "index" >> TestAccess ( () => userIsAllowed("/secure/index",AuthorizationType.Configuration.Read) )).submenus ( - Menu(name+"RuleManagement", Rules) / + Menu("210-rules", Rules) / "secure" / (name+"Manager") / "ruleManagement" >> LocGroup(name+"Group") >> TestAccess( () => userIsAllowed("/secure/index",AuthorizationType.Rule.Read ) ) - , Menu("Rule Details", Rule) / + , Menu("210-rule-details", Rule) / "secure" / (name+"Manager") / "ruleManagement" / "rule" / * >> TemplateBox {case _ => Templates("secure" :: (name+"Manager") :: "ruleManagement" :: Nil)} >> LocGroup (name+"Group") >> TestAccess( () => userIsAllowed("/secure/index", AuthorizationType.Rule.Read) ) >> Hidden - , Menu("Rule Category Details", Rule Category) / + , Menu("210-rule-category", Rule Category) / "secure" / (name+"Manager") / "ruleManagement" / "ruleCategory" / * >> TemplateBox {case _ => Templates("secure" :: (name+"Manager") :: "ruleManagement" :: Nil)} >> LocGroup (name+"Group") >> TestAccess( () => userIsAllowed("/secure/index",AuthorizationType.Rule.Read ) ) >> Hidden - ,Menu(name+"DirectiveManagement", Directives) / + ,Menu("220-directives", Directives) / "secure" / (name+"Manager") / "directiveManagement" >> LocGroup(name+"Group") >> TestAccess( () => userIsAllowed("/secure/index",AuthorizationType.Directive.Read ) ) - , Menu("techniqueEditor", Techniques) / + , Menu("230-techniques", Techniques) / "secure" / (name+"Manager") / "techniqueEditor" >> LocGroup((name+"Manager")) >> TestAccess ( () => userIsAllowed("/secure/index",AuthorizationType.Technique.Read)) - , Menu("Technique", Technique) / + , Menu("230-technique-details", Technique) / "secure" / (name+"Manager") / "techniqueEditor" / "technique" / * >> TemplateBox {case _ => Templates("secure" :: (name+"Manager") :: "techniqueEditor" :: Nil)} >> LocGroup (name+"Group") >> TestAccess( () => userIsAllowed("/secure/index", AuthorizationType.Rule.Read) ) >> Hidden - , Menu(name+"ParameterManagement", Parameters) / + , Menu("240-global-parameters", Parameters) / "secure" / (name+"Manager") / "parameterManagement" >> LocGroup(name+"Group") >> TestAccess( () => userIsAllowed("/secure/index",AuthorizationType.Parameter.Read ) ) @@ -434,43 +434,43 @@ class Boot extends Loggable { } def administrationMenu = - (Menu("AdministrationHome", ++ Administration: NodeSeq) / + (Menu(MenuUtils.administrationMenu, ++ Administration: NodeSeq) / "secure" / "administration" / "index" >> TestAccess ( () => userIsAllowed("/secure/index",AuthorizationType.Administration.Read, AuthorizationType.Technique.Read) )).submenus ( - Menu("Setup", Setup) / + Menu("710-setup", Setup) / "secure" / "administration" / "setup" >> LocGroup("administrationGroup") >> TestAccess( () => userIsAllowed("/secure/index",AuthorizationType.Administration.Read ) ) - , Menu("policyServerManagement", Settings) / + , Menu("720-settings", Settings) / "secure" / "administration" / "policyServerManagement" >> LocGroup("administrationGroup") >> TestAccess ( () => userIsAllowed("/secure/index",AuthorizationType.Administration.Read) ) - , Menu("databaseManagement", Reports database) / + , Menu("730-database", Reports database) / "secure" / "administration" / "databaseManagement" >> LocGroup("administrationGroup") >> TestAccess ( () => userIsAllowed("/secure/administration/policyServerManagement",AuthorizationType.Administration.Read) ) - , Menu("TechniqueLibraryManagement", Techniques tree) / + , Menu("740-techniques-tree", Techniques tree) / "secure" / "administration" / "techniqueLibraryManagement" >> LocGroup("administrationGroup") >> TestAccess( () => userIsAllowed("/secure/index",AuthorizationType.Technique.Read ) ) - , Menu("apiManagement", API accounts) / + , Menu("750-api", API accounts) / "secure" / "administration" / "apiManagement" >> LocGroup("administrationGroup") >> TestAccess ( () => userIsAllowed("/secure/administration/policyServerManagement",AuthorizationType.Administration.Write) ) ) def pluginsMenu = { - (Menu("PluginsHome", ++ Plugins ++ : NodeSeq) / + (Menu(MenuUtils.pluginsMenu, ++ Plugins ++ : NodeSeq) / "secure" / "plugins" / "index" >> LocGroup("pluginsGroup") >> TestAccess ( () => userIsAllowed("/secure/index", AuthorizationType.Administration.Read) )) submenus ( - Menu("pluginInformation", Plugin information) / + Menu("910-plugins", Plugin information) / "secure" / "plugins" / "pluginInformation" >> LocGroup("pluginsGroup") >> TestAccess ( () => userIsAllowed("/secure/index", AuthorizationType.Administration.Read) ) @@ -481,7 +481,7 @@ class Boot extends Loggable { // if we can't get the workflow property, default to false // (don't give rights if you don't know) def workflowEnabled = RudderConfig.configService.rudder_workflow_enabled().either.runNow.getOrElse(false) - (Menu("UtilitiesHome", ++ Utilities: NodeSeq) / + (Menu(MenuUtils.utilitiesMenu, ++ Utilities: NodeSeq) / "secure" / "utilities" / "index" >> TestAccess ( () => if ((workflowEnabled && (CurrentUser.checkRights(AuthorizationType.Validator.Read) || CurrentUser.checkRights(AuthorizationType.Deployer.Read))) || CurrentUser.checkRights(AuthorizationType.Administration.Read) || CurrentUser.checkRights(AuthorizationType.Technique.Read)) @@ -490,16 +490,16 @@ class Boot extends Loggable { Full(RedirectWithState("/secure/index", redirection)) )).submenus ( - Menu("archivesManagement", Archives) / + Menu("610-archives", Archives) / "secure" / "utilities" / "archiveManagement" >> LocGroup("utilitiesGroup") >> TestAccess ( () => userIsAllowed("/secure/utilities/eventLogs",AuthorizationType.Administration.Write) ) - , Menu("eventLogViewer", Event logs) / + , Menu("620-event-logs", Event logs) / "secure" / "utilities" / "eventLogs" >> LocGroup("utilitiesGroup") >> TestAccess ( () => userIsAllowed("/secure/index",AuthorizationType.Administration.Read) ) - , Menu("healthCheckHome", Health check) / + , Menu("630-health-check", Health check) / "secure" / "utilities" / "healthcheck" >> LocGroup("utilitiesGroup") >> TestAccess ( () => userIsAllowed("/secure/index",AuthorizationType.Administration.Read) ) @@ -507,9 +507,9 @@ class Boot extends Loggable { } val rootMenu = List( - Menu("Dashboard", ++ Dashboard: NodeSeq) / "secure" / "index" - , Menu("Login") / "index" >> Hidden - , Menu("Templates") / "templates" / ** >> Hidden //allows access to html file use by js + Menu("000-dashboard", ++ Dashboard: NodeSeq) / "secure" / "index" + , Menu("010-login") / "index" >> Hidden + , Menu("020-templates") / "templates" / ** >> Hidden //allows access to html file use by js , nodeManagerMenu , policyMenu , utilitiesMenu @@ -626,3 +626,11 @@ class Boot extends Loggable { pluginDefs } } + +object MenuUtils { + val nodeManagementMenu = "100-nodes" + val policyMenu = "200-policy" + val administrationMenu = "700-administration" + val utilitiesMenu = "600-utilities" + val pluginsMenu = "900-plugins" +} diff --git a/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/RudderConfig.scala b/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/RudderConfig.scala index 4c5a50b7eb6..1ed17eba411 100644 --- a/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/RudderConfig.scala +++ b/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/RudderConfig.scala @@ -184,7 +184,6 @@ import com.typesafe.config.ConfigException import com.typesafe.config.ConfigFactory import com.unboundid.ldap.sdk.DN import com.unboundid.ldap.sdk.RDN -import cron4s.expr.CronExpr import net.liftweb.common.Loggable import net.liftweb.common._ import org.apache.commons.io.FileUtils diff --git a/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/plugins/PublicPlugin.scala b/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/plugins/PublicPlugin.scala index 9c05f88890c..32cd8e3872f 100644 --- a/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/plugins/PublicPlugin.scala +++ b/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/plugins/PublicPlugin.scala @@ -37,7 +37,9 @@ package com.normation.plugins +import bootstrap.liftweb.MenuUtils import com.normation.rudder.domain.logger.ApplicationLogger +import com.normation.rudder.domain.logger.PluginLogger import com.typesafe.config.ConfigException import com.typesafe.config.ConfigFactory import net.liftweb.sitemap.Menu @@ -121,14 +123,33 @@ trait DefaultPluginDef extends RudderPluginDef { * interaction with Rudder menu (at the risk of breaking it). */ def pluginMenuEntry: Option[Menu] = None + def pluginMenuParent: Option[Menu] = None override def updateSiteMap(menus:List[Menu]) : List[Menu] = { + pluginMenuEntry match { case None => menus - case Some(menu) => - menus.map { - case m@Menu(l, _* ) if(l.name == "PluginsHome") => - Menu(l , (m.kids.toSeq :+ menu):_* ) + case Some(menu@Menu(loc,_*)) => + val (parentName, updatedMenu) = pluginMenuParent match { + case None => (MenuUtils.pluginsMenu, menus) + case Some(parentMenu) => + val menu = if (menus.exists (_.loc.name == parentMenu.loc.name )) { + menus + } else { + ( parentMenu :: menus).sortBy(_.loc.name) + } + (parentMenu.loc.name,menu) + } + + updatedMenu.map { + case m@Menu(l, _* ) if(l.name == parentName) => + // We need to avoid collision on name/loc + if (m.kids.exists (_.loc.name == loc.name)) { + PluginLogger.error(s"There is already a menu with id (${loc.name}, please contact Plugin team") + m + } else { + Menu(l , (m.kids :+ menu).sortBy(_.loc.name):_* ) + } case m => m } }