diff --git a/src/main/java/com/sonyericsson/jenkins/plugins/bfa/CauseManagement.java b/src/main/java/com/sonyericsson/jenkins/plugins/bfa/CauseManagement.java index 8b87aed0..33dd2843 100644 --- a/src/main/java/com/sonyericsson/jenkins/plugins/bfa/CauseManagement.java +++ b/src/main/java/com/sonyericsson/jenkins/plugins/bfa/CauseManagement.java @@ -115,7 +115,8 @@ public class CauseManagement extends BfaGraphAction { @Override public String getIconFileName() { - if (Hudson.getInstance().hasPermission(PluginImpl.UPDATE_PERMISSION)) { + if (Hudson.getInstance().hasPermission(PluginImpl.UPDATE_PERMISSION) + || Hudson.getInstance().hasPermission(PluginImpl.VIEW_PERMISSION)) { return PluginImpl.getDefaultIcon(); } else { return null; @@ -126,6 +127,8 @@ public String getIconFileName() { public String getDisplayName() { if (Hudson.getInstance().hasPermission(PluginImpl.UPDATE_PERMISSION)) { return Messages.CauseManagement_DisplayName(); + } else if (Hudson.getInstance().hasPermission(PluginImpl.VIEW_PERMISSION)) { + return Messages.CauseList_DisplayName(); } else { return null; } diff --git a/src/main/java/com/sonyericsson/jenkins/plugins/bfa/PluginImpl.java b/src/main/java/com/sonyericsson/jenkins/plugins/bfa/PluginImpl.java index befea244..1ca16602 100644 --- a/src/main/java/com/sonyericsson/jenkins/plugins/bfa/PluginImpl.java +++ b/src/main/java/com/sonyericsson/jenkins/plugins/bfa/PluginImpl.java @@ -86,6 +86,13 @@ public class PluginImpl extends Plugin { new Permission(PERMISSION_GROUP, "UpdateCauses", Messages._PermissionUpdate_Description(), Hudson.ADMINISTER); + /** + * Permission to view the causes. E.e. Access {@link CauseManagement}. + */ + public static final Permission VIEW_PERMISSION = + new Permission(PERMISSION_GROUP, "ViewCauses", + Messages._PermissionView_Description(), UPDATE_PERMISSION); + /** * Permission to remove causes. */ diff --git a/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/CauseManagement/index.groovy b/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/CauseManagement/index.groovy index 8018c51b..8abc9d62 100644 --- a/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/CauseManagement/index.groovy +++ b/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/CauseManagement/index.groovy @@ -32,7 +32,7 @@ def f = namespace(lib.FormTagLib) def l = namespace(lib.LayoutTagLib) def j = namespace(lib.JenkinsTagLib) -l.layout(permission: PluginImpl.UPDATE_PERMISSION) { +l.layout(permission: PluginImpl.VIEW_PERMISSION) { l.header(title: _("Failure Cause Management - Confirm Remove")) def management = CauseManagement.getInstance(); @@ -55,7 +55,11 @@ l.layout(permission: PluginImpl.UPDATE_PERMISSION) { + "z-index: -100;" + "background-image: url(\'" + bgImageUrl + "');") {} - h1(_("Update Failure Causes")) + if (h.hasPermission(PluginImpl.UPDATE_PERMISSION)) { + h1(_("Update Failure Causes")) + } else { + h1(_("List of Failure Causes")) + } def shallowCauses = management.getShallowCauses() if (management.isError(request)) { @@ -73,28 +77,30 @@ l.layout(permission: PluginImpl.UPDATE_PERMISSION) { } //The New Cause link - div(style: "margin-top: 10px; margin-bottom: 10px; width: 90%;") { - a(style: "font-weight: bold; " - + "font-size: larger; " - + "padding-left: 30px; " - + "min-height: 30px; " - + "padding-top: 5px; " - + "padding-bottom: 5px; " - + "background-image: url( \'" + newImageUrl + "\'); " - + "background-position: left center; " - + "background-repeat: no-repeat;", - href: "new", - alt: _("New")) {text(_("Create new"))} + if (h.hasPermission(PluginImpl.UPDATE_PERMISSION)) { + div(style: "margin-top: 10px; margin-bottom: 10px; width: 90%;") { + a(style: "font-weight: bold; " + + "font-size: larger; " + + "padding-left: 30px; " + + "min-height: 30px; " + + "padding-top: 5px; " + + "padding-bottom: 5px; " + + "background-image: url( \'" + newImageUrl + "\'); " + + "background-position: left center; " + + "background-repeat: no-repeat;", + href: "new", + alt: _("New")) { text(_("Create new")) } - if (PluginImpl.getInstance().isGraphsEnabled()) { - a(style: "font-weight: bold; " - + "font-size: larger; " - + "padding-top: 5px; " - + "padding-bottom: 5px; " - + "float: right;", - href: "detailedgraphs", - alt: _("Graphs/statistics")) {text(_("Graphs/Statistics"))} - } + if (PluginImpl.getInstance().isGraphsEnabled()) { + a(style: "font-weight: bold; " + + "font-size: larger; " + + "padding-top: 5px; " + + "padding-bottom: 5px; " + + "float: right;", + href: "detailedgraphs", + alt: _("Graphs/statistics")) { text(_("Graphs/Statistics")) } + } + } } //One time check so we don't do it for every iteration below @@ -118,7 +124,11 @@ l.layout(permission: PluginImpl.UPDATE_PERMISSION) { shallowCauses.each{ cause -> tr { td{ - a(href: cause.getId()){ text(cause.getName())} + if (h.hasPermission(PluginImpl.UPDATE_PERMISSION)) { + a(href: cause.getId()) { text(cause.getName()) } + } else { + text(cause.getName()) + } } td{ text(cause.getCategoriesAsString()) diff --git a/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/Messages.properties b/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/Messages.properties index c931640f..0d525776 100644 --- a/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/Messages.properties +++ b/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/Messages.properties @@ -1,10 +1,12 @@ #I18n messages. PermissionGroup_Title=Build Failure Analyzer +PermissionView_Description=View Failure causes. PermissionUpdate_Description=Add and Update Failure causes. PermissionRemove_Description=Remove Failure causes. BuildLogIndication_DisplayName=Build Log Indication MultilineBuildLogIndication_DisplayName=Multi-Line Build Log Indication CauseManagement_DisplayName=Failure Cause Management +CauseList_DisplayName=Failure Causes ScannerJobProperty_DisplayName=Do not Scan failed builds LocalFileKnowledgeBase_DisplayName=Jenkins Local MongoDBKnowledgeBase_DisplayName=Mongo DB diff --git a/src/test/java/com/sonyericsson/jenkins/plugins/bfa/CauseManagementPermissionTest.java b/src/test/java/com/sonyericsson/jenkins/plugins/bfa/CauseManagementPermissionTest.java new file mode 100644 index 00000000..94a0948c --- /dev/null +++ b/src/test/java/com/sonyericsson/jenkins/plugins/bfa/CauseManagementPermissionTest.java @@ -0,0 +1,131 @@ +package com.sonyericsson.jenkins.plugins.bfa; + +import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; +import com.gargoylesoftware.htmlunit.html.HtmlPage; +import hudson.model.Hudson; +import hudson.security.GlobalMatrixAuthorizationStrategy; +import hudson.security.SecurityRealm; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.jvnet.hudson.test.JenkinsRule; + +import javax.servlet.http.HttpServletResponse; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +/** + * Tests the permissions for the Cause Management. + * + * @author Damien Coraboeuf + */ +public class CauseManagementPermissionTest { + + /** + * The Jenkins Rule. + */ + @Rule + //CS IGNORE VisibilityModifier FOR NEXT 1 LINES. REASON: Jenkins Rule + public JenkinsRule j = new JenkinsRule(); + + /** + * Configures Jenkins to use security and defines several users with different rights for the + * management or view of failure causes. + */ + @Before + public void jenkinsConfiguration() { + SecurityRealm securityRealm = j.createDummySecurityRealm(); + j.getInstance().setSecurityRealm(securityRealm); + + GlobalMatrixAuthorizationStrategy authorizationStrategy = new GlobalMatrixAuthorizationStrategy(); + authorizationStrategy.add(Hudson.READ, "anonymous"); + authorizationStrategy.add(PluginImpl.VIEW_PERMISSION, "view"); + authorizationStrategy.add(PluginImpl.UPDATE_PERMISSION, "update"); + authorizationStrategy.add(PluginImpl.VIEW_PERMISSION, "all"); + authorizationStrategy.add(PluginImpl.UPDATE_PERMISSION, "all"); + j.getInstance().setAuthorizationStrategy(authorizationStrategy); + } + + /** + * Checks that a non authorised user cannot access the failure management page at all. + * + * @throws java.lang.Exception If Jenkins cannot be accessed + */ + @Test + public void notAllowedToUpdateCausesWhenNotGrantedAnything() throws Exception { + JenkinsRule.WebClient webClient = j.createWebClient(); + // Logs in + webClient.goTo(""); + webClient.login("none"); + // Gets to the Failure Cause page + try { + webClient.goTo("failure-cause-management"); + fail("Access to the page should have failed"); + } catch (FailingHttpStatusCodeException ex) { + assertEquals(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex.getStatusCode()); + } + } + + /** + * Checks that a user granted with "viewCauses" only can access the failure management page + * but not create a new failure. + * + * @throws java.lang.Exception If Jenkins cannot be accessed + */ + @Test + public void allowedToViewCausesWhenGrantedOnlyView() throws Exception { + JenkinsRule.WebClient webClient = j.createWebClient(); + // Logs in + webClient.goTo(""); + webClient.login("view"); + // Gets to the Failure Cause page + HtmlPage page = webClient.goTo("failure-cause-management"); + // Checks we are actually on the page + assertNotNull(page.selectSingleNode("//h1[.='List of Failure Causes']")); + // Checks the "Create New" button is NOT available + assertNull(page.selectSingleNode("//a[.='Create new']")); + } + + /** + * Checks that a user granted with "updateCauses" only can access the failure management page + * and create a new failure. + * + * @throws java.lang.Exception If Jenkins cannot be accessed + */ + @Test + public void allowedToUpdateCausesWhenGrantedOnlyUpdate() throws Exception { + JenkinsRule.WebClient webClient = j.createWebClient(); + // Logs in + webClient.goTo(""); + webClient.login("update"); + // Gets to the Failure Cause page + HtmlPage page = webClient.goTo("failure-cause-management"); + // Checks we are actually on the page + assertNotNull(page.selectSingleNode("//h1[.='Update Failure Causes']")); + // Checks the "Create New" button is available + assertNotNull(page.selectSingleNode("//a[.='Create new']")); + } + + /** + * Checks that a user granted with "updateCauses" and "viewCauses" only can access the failure management page + * and create a new failure. + * + * @throws java.lang.Exception If Jenkins cannot be accessed + */ + @Test + public void allowedToUpdateCausesWhenGrantedBothUpdateAndView() throws Exception { + JenkinsRule.WebClient webClient = j.createWebClient(); + // Logs in + webClient.goTo(""); + webClient.login("all"); + // Gets to the Failure Cause page + HtmlPage page = webClient.goTo("failure-cause-management"); + // Checks we are actually on the page + assertNotNull(page.selectSingleNode("//h1[.='Update Failure Causes']")); + // Checks the "Create New" button is available + assertNotNull(page.selectSingleNode("//a[.='Create new']")); + } +}