From: Julien HENRY Date: Mon, 18 Jun 2018 11:19:01 +0000 (+0200) Subject: SONAR-10887 Create a new permission: Administer Security Hotspots X-Git-Tag: 7.5~884 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=342a903643585e886c5ec099ebc66d38fc0d3af7;p=sonarqube.git SONAR-10887 Create a new permission: Administer Security Hotspots --- diff --git a/server/sonar-db-dao/src/main/java/org/sonar/core/permission/ProjectPermissions.java b/server/sonar-db-dao/src/main/java/org/sonar/core/permission/ProjectPermissions.java index 04b47d1c1d3..f797d699e00 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/core/permission/ProjectPermissions.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/core/permission/ProjectPermissions.java @@ -36,9 +36,10 @@ public final class ProjectPermissions { public static final Set PUBLIC_PERMISSIONS = ImmutableSet.of(UserRole.USER, UserRole.CODEVIEWER); /** - * All the component permissions values, ordered from {@link UserRole#USER} to {@link GlobalPermissions#SCAN_EXECUTION}. + * All the component permissions values */ - public static final List ALL = ImmutableList.of(UserRole.ADMIN, UserRole.CODEVIEWER, UserRole.ISSUE_ADMIN, GlobalPermissions.SCAN_EXECUTION, UserRole.USER); + public static final List ALL = ImmutableList.of(UserRole.ADMIN, UserRole.CODEVIEWER, UserRole.ISSUE_ADMIN, UserRole.SECURITYHOTSPOT_ADMIN, + GlobalPermissions.SCAN_EXECUTION, UserRole.USER); public static final String ALL_ON_ONE_LINE = Joiner.on(", ").join(ProjectPermissions.ALL); diff --git a/server/sonar-db-dao/src/test/java/org/sonar/core/permission/ProjectPermissionsTest.java b/server/sonar-db-dao/src/test/java/org/sonar/core/permission/ProjectPermissionsTest.java index dd86d8d7099..d78726c74b2 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/core/permission/ProjectPermissionsTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/core/permission/ProjectPermissionsTest.java @@ -28,11 +28,11 @@ public class ProjectPermissionsTest { @Test public void all_permissions() { - assertThat(ProjectPermissions.ALL).containsExactly(UserRole.ADMIN, UserRole.CODEVIEWER, UserRole.ISSUE_ADMIN, GlobalPermissions.SCAN_EXECUTION, UserRole.USER); + assertThat(ProjectPermissions.ALL).containsExactly(UserRole.ADMIN, UserRole.CODEVIEWER, UserRole.ISSUE_ADMIN, UserRole.SECURITYHOTSPOT_ADMIN, GlobalPermissions.SCAN_EXECUTION, UserRole.USER); } @Test public void all_permissions_as_string() { - assertThat(ProjectPermissions.ALL_ON_ONE_LINE).isEqualTo("admin, codeviewer, issueadmin, scan, user"); + assertThat(ProjectPermissions.ALL_ON_ONE_LINE).isEqualTo("admin, codeviewer, issueadmin, securityhotspotadmin, scan, user"); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/workflow/IssueWorkflow.java b/server/sonar-server/src/main/java/org/sonar/server/issue/workflow/IssueWorkflow.java index aec49fbf75e..d2a3bf1c671 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/workflow/IssueWorkflow.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/workflow/IssueWorkflow.java @@ -147,25 +147,25 @@ public class IssueWorkflow implements Startable { .from(Issue.STATUS_OPEN).to(Issue.STATUS_OPEN) .conditions(new HasType(RuleType.SECURITY_HOTSPOT)) .functions(new SetType(RuleType.VULNERABILITY)) - .requiredProjectPermission(UserRole.ISSUE_ADMIN) // TODO need to check new permission + .requiredProjectPermission(UserRole.SECURITYHOTSPOT_ADMIN) .build()) .transition(Transition.builder(DefaultTransitions.DETECT) .from(Issue.STATUS_REOPENED).to(Issue.STATUS_OPEN) .conditions(new HasType(RuleType.SECURITY_HOTSPOT)) .functions(new SetType(RuleType.VULNERABILITY)) - .requiredProjectPermission(UserRole.ISSUE_ADMIN) // TODO need to check new permission + .requiredProjectPermission(UserRole.SECURITYHOTSPOT_ADMIN) .build()) .transition(Transition.builder(DefaultTransitions.DETECT) .from(Issue.STATUS_RESOLVED).to(Issue.STATUS_OPEN) .conditions(new HasType(RuleType.SECURITY_HOTSPOT), new HasResolution(Issue.RESOLUTION_WONT_FIX)) .functions(new SetType(RuleType.VULNERABILITY), new SetResolution(null)) - .requiredProjectPermission(UserRole.ISSUE_ADMIN) // TODO need to check new permission + .requiredProjectPermission(UserRole.SECURITYHOTSPOT_ADMIN) .build()) .transition(Transition.builder(DefaultTransitions.DISMISS) .from(Issue.STATUS_OPEN).to(Issue.STATUS_REOPENED) .conditions(IsManualVulnerability.INSTANCE) .functions(new SetType(RuleType.SECURITY_HOTSPOT)) - .requiredProjectPermission(UserRole.ISSUE_ADMIN) // TODO need to check new permission + .requiredProjectPermission(UserRole.SECURITYHOTSPOT_ADMIN) .build()) .transition(Transition.builder(DefaultTransitions.REQUEST_REVIEW) .from(Issue.STATUS_OPEN).to(Issue.STATUS_RESOLVED) @@ -181,31 +181,31 @@ public class IssueWorkflow implements Startable { .from(Issue.STATUS_RESOLVED).to(Issue.STATUS_REOPENED) .conditions(new HasType(RuleType.SECURITY_HOTSPOT), new HasResolution(Issue.RESOLUTION_FIXED)) .functions(new SetType(RuleType.VULNERABILITY), new SetResolution(null)) - .requiredProjectPermission(UserRole.ISSUE_ADMIN) // TODO need to check new permission + .requiredProjectPermission(UserRole.SECURITYHOTSPOT_ADMIN) .build()) .transition(Transition.builder(DefaultTransitions.ACCEPT) .from(Issue.STATUS_RESOLVED).to(Issue.STATUS_RESOLVED) .conditions(new HasType(RuleType.SECURITY_HOTSPOT), new HasResolution(Issue.RESOLUTION_FIXED)) .functions(new SetResolution(Issue.RESOLUTION_WONT_FIX)) - .requiredProjectPermission(UserRole.ISSUE_ADMIN) // TODO need to check new permission + .requiredProjectPermission(UserRole.SECURITYHOTSPOT_ADMIN) .build()) .transition(Transition.builder(DefaultTransitions.CLEAR) .from(Issue.STATUS_OPEN).to(Issue.STATUS_RESOLVED) .conditions(new HasType(RuleType.SECURITY_HOTSPOT)) .functions(new SetResolution(Issue.RESOLUTION_WONT_FIX)) - .requiredProjectPermission(UserRole.ISSUE_ADMIN) // TODO need to check new permission + .requiredProjectPermission(UserRole.SECURITYHOTSPOT_ADMIN) .build()) .transition(Transition.builder(DefaultTransitions.CLEAR) .from(Issue.STATUS_REOPENED).to(Issue.STATUS_RESOLVED) .conditions(new HasType(RuleType.SECURITY_HOTSPOT)) .functions(new SetResolution(Issue.RESOLUTION_WONT_FIX)) - .requiredProjectPermission(UserRole.ISSUE_ADMIN) // TODO need to check new permission + .requiredProjectPermission(UserRole.SECURITYHOTSPOT_ADMIN) .build()) .transition(Transition.builder(DefaultTransitions.REOPEN_HOTSPOT) .from(Issue.STATUS_RESOLVED).to(Issue.STATUS_REOPENED) .conditions(new HasType(RuleType.SECURITY_HOTSPOT), new HasResolution(Issue.RESOLUTION_WONT_FIX)) .functions(new SetResolution(null)) - .requiredProjectPermission(UserRole.ISSUE_ADMIN) // TODO need to check new permission + .requiredProjectPermission(UserRole.SECURITYHOTSPOT_ADMIN) .build()); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationUpdater.java index 5748e200790..60bb5006439 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationUpdater.java +++ b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationUpdater.java @@ -58,6 +58,7 @@ public interface OrganizationUpdater { *
    *
  • group {@link #OWNERS_GROUP_NAME Owners} : {@link UserRole#ADMIN ADMIN}
  • *
  • group {@link #OWNERS_GROUP_NAME Owners} : {@link UserRole#ISSUE_ADMIN ISSUE_ADMIN}
  • + *
  • group {@link #OWNERS_GROUP_NAME Owners} : {@link UserRole#SECURITYHOTSPOT_ADMIN SECURITYHOTSPOT_ADMIN}
  • *
  • group {@link #OWNERS_GROUP_NAME Owners} : {@link GlobalPermissions#SCAN_EXECUTION SCAN_EXECUTION}
  • *
  • group {@link DefaultGroupCreatorImpl#DEFAULT_GROUP_NAME members} : {@link UserRole#USER USER}
  • *
  • group {@link DefaultGroupCreatorImpl#DEFAULT_GROUP_NAME members} : {@link UserRole#CODEVIEWER CODEVIEWER}
  • @@ -102,6 +103,7 @@ public interface OrganizationUpdater { *
      *
    • project creator : {@link UserRole#ADMIN ADMIN}
    • *
    • project creator : {@link UserRole#ISSUE_ADMIN ISSUE_ADMIN}
    • + *
    • project creator : {@link UserRole#SECURITYHOTSPOT_ADMIN SECURITYHOTSPOT_ADMIN}
    • *
    • project creator : {@link GlobalPermissions#SCAN_EXECUTION SCAN_EXECUTION}
    • *
    • group {@link DefaultGroupCreatorImpl#DEFAULT_GROUP_NAME members} : {@link UserRole#USER USER}
    • *
    • group {@link DefaultGroupCreatorImpl#DEFAULT_GROUP_NAME members} : {@link UserRole#CODEVIEWER CODEVIEWER}
    • diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationUpdaterImpl.java b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationUpdaterImpl.java index 7d7f756c18e..3d9b20dfe52 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationUpdaterImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationUpdaterImpl.java @@ -59,6 +59,7 @@ import static java.util.Objects.requireNonNull; import static org.sonar.api.web.UserRole.ADMIN; import static org.sonar.api.web.UserRole.CODEVIEWER; import static org.sonar.api.web.UserRole.ISSUE_ADMIN; +import static org.sonar.api.web.UserRole.SECURITYHOTSPOT_ADMIN; import static org.sonar.api.web.UserRole.USER; import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex; import static org.sonar.db.permission.OrganizationPermission.SCAN; @@ -229,6 +230,7 @@ public class OrganizationUpdaterImpl implements OrganizationUpdater { insertGroupPermission(dbSession, permissionTemplateDto, ADMIN, ownerGroup); insertGroupPermission(dbSession, permissionTemplateDto, ISSUE_ADMIN, ownerGroup); + insertGroupPermission(dbSession, permissionTemplateDto, SECURITYHOTSPOT_ADMIN, ownerGroup); insertGroupPermission(dbSession, permissionTemplateDto, SCAN.getKey(), ownerGroup); insertGroupPermission(dbSession, permissionTemplateDto, USER, defaultGroup); insertGroupPermission(dbSession, permissionTemplateDto, CODEVIEWER, defaultGroup); @@ -254,6 +256,7 @@ public class OrganizationUpdaterImpl implements OrganizationUpdater { insertProjectCreatorPermission(dbSession, permissionTemplateDto, ADMIN, now); insertProjectCreatorPermission(dbSession, permissionTemplateDto, ISSUE_ADMIN, now); + insertProjectCreatorPermission(dbSession, permissionTemplateDto, SECURITYHOTSPOT_ADMIN, now); insertProjectCreatorPermission(dbSession, permissionTemplateDto, SCAN.getKey(), now); insertGroupPermission(dbSession, permissionTemplateDto, USER, defaultGroup); insertGroupPermission(dbSession, permissionTemplateDto, CODEVIEWER, defaultGroup); diff --git a/server/sonar-server/src/main/java/org/sonar/server/startup/RegisterPermissionTemplates.java b/server/sonar-server/src/main/java/org/sonar/server/startup/RegisterPermissionTemplates.java index 7cb69d01ce7..045eda15b6e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/startup/RegisterPermissionTemplates.java +++ b/server/sonar-server/src/main/java/org/sonar/server/startup/RegisterPermissionTemplates.java @@ -94,6 +94,7 @@ public class RegisterPermissionTemplates { if (admins.isPresent()) { insertGroupPermission(dbSession, template, UserRole.ADMIN, admins.get()); insertGroupPermission(dbSession, template, UserRole.ISSUE_ADMIN, admins.get()); + insertGroupPermission(dbSession, template, UserRole.SECURITYHOTSPOT_ADMIN, admins.get()); } else { LOG.error("Cannot setup default permission for group: " + DefaultGroups.ADMINISTRATORS); } diff --git a/server/sonar-server/src/main/resources/org/sonar/server/permission/ws/template/search_templates-example.json b/server/sonar-server/src/main/resources/org/sonar/server/permission/ws/template/search_templates-example.json index 643c7bf9111..b5f0d50a8e1 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/permission/ws/template/search_templates-example.json +++ b/server/sonar-server/src/main/resources/org/sonar/server/permission/ws/template/search_templates-example.json @@ -25,6 +25,12 @@ "groupsCount": 0, "withProjectCreator": false }, + { + "key": "securityhotspotadmin", + "usersCount": 0, + "groupsCount": 0, + "withProjectCreator": false + }, { "key": "scan", "usersCount": 0, @@ -65,6 +71,12 @@ "groupsCount": 3, "withProjectCreator": false }, + { + "key": "securityhotspotadmin", + "usersCount": 0, + "groupsCount": 0, + "withProjectCreator": false + }, { "key": "scan", "usersCount": 0, diff --git a/server/sonar-server/src/test/java/org/sonar/server/i18n/I18nRule.java b/server/sonar-server/src/test/java/org/sonar/server/i18n/I18nRule.java index 07e117034e2..e1a4892607c 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/i18n/I18nRule.java +++ b/server/sonar-server/src/test/java/org/sonar/server/i18n/I18nRule.java @@ -60,6 +60,8 @@ public class I18nRule implements TestRule, I18n { put("projects_role.issueadmin", "Administer Issues"); put("projects_role.issueadmin.desc", "Grants the permission to perform advanced editing on issues: marking an issue " + "False Positive / Won't Fix or changing an Issue's severity. (Users will also need \"Browse\" permission)"); + put("projects_role.securityhotspotadmin", "Administer Security Hotspots"); + put("projects_role.securityhotspotadmin.desc", "Detect a Vulnerability from a \"Security Hotspot\". Reject, clear, accept, reopen a \"Security Hotspot\" (users also need \"Browse\" permissions)."); put("projects_role.user", "Browse"); put("projects_role.user.desc", "Ability to access a project, browse its measures, and create/edit issues for it."); put("projects_role.codeviewer", "See Source Code"); diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java index 9e08bc95ebd..be832a90a8d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java @@ -267,7 +267,7 @@ public class OrganizationUpdaterImplTest { assertThat(dbClient.permissionTemplateDao().selectGroupPermissionsByTemplateId(dbSession, defaultTemplate.getId())) .extracting(PermissionTemplateGroupDto::getGroupId, PermissionTemplateGroupDto::getPermission) .containsOnly( - tuple(ownersGroup.getId(), UserRole.ADMIN), tuple(ownersGroup.getId(), UserRole.ISSUE_ADMIN), tuple(ownersGroup.getId(), GlobalPermissions.SCAN_EXECUTION), + tuple(ownersGroup.getId(), UserRole.ADMIN), tuple(ownersGroup.getId(), UserRole.ISSUE_ADMIN), tuple(ownersGroup.getId(), UserRole.SECURITYHOTSPOT_ADMIN), tuple(ownersGroup.getId(), GlobalPermissions.SCAN_EXECUTION), tuple(defaultGroupId, UserRole.USER), tuple(defaultGroupId, UserRole.CODEVIEWER)); } @@ -445,7 +445,7 @@ public class OrganizationUpdaterImplTest { assertThat(dbClient.permissionTemplateCharacteristicDao().selectByTemplateIds(dbSession, Collections.singletonList(defaultTemplate.getId()))) .extracting(PermissionTemplateCharacteristicDto::getWithProjectCreator, PermissionTemplateCharacteristicDto::getPermission) .containsOnly( - tuple(true, UserRole.ADMIN), tuple(true, UserRole.ISSUE_ADMIN), tuple(true, GlobalPermissions.SCAN_EXECUTION)); + tuple(true, UserRole.ADMIN), tuple(true, UserRole.ISSUE_ADMIN), tuple(true, UserRole.SECURITYHOTSPOT_ADMIN), tuple(true, GlobalPermissions.SCAN_EXECUTION)); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/CreateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/CreateActionTest.java index 01af1c6d535..076d906a9fa 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/CreateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/CreateActionTest.java @@ -362,7 +362,7 @@ public class CreateActionTest { assertThat(dbClient.permissionTemplateDao().selectGroupPermissionsByTemplateId(dbSession, defaultTemplate.getId())) .extracting(PermissionTemplateGroupDto::getGroupId, PermissionTemplateGroupDto::getPermission) .containsOnly( - tuple(ownersGroup.getId(), UserRole.ADMIN), tuple(ownersGroup.getId(), UserRole.ISSUE_ADMIN), tuple(ownersGroup.getId(), GlobalPermissions.SCAN_EXECUTION), + tuple(ownersGroup.getId(), UserRole.ADMIN), tuple(ownersGroup.getId(), UserRole.ISSUE_ADMIN), tuple(ownersGroup.getId(), UserRole.SECURITYHOTSPOT_ADMIN), tuple(ownersGroup.getId(), GlobalPermissions.SCAN_EXECUTION), tuple(defaultGroup.getId(), UserRole.USER), tuple(defaultGroup.getId(), UserRole.CODEVIEWER)); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/GroupPermissionChangerTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/GroupPermissionChangerTest.java index b9406c5eb1e..54ae041674c 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/GroupPermissionChangerTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/GroupPermissionChangerTest.java @@ -321,7 +321,7 @@ public class GroupPermissionChangerTest { apply(new GroupPermissionChange(PermissionChange.Operation.ADD, perm, new ProjectId(privateProject), groupId)); fail("a BadRequestException should have been thrown for permission " + perm); } catch (BadRequestException e) { - assertThat(e).hasMessage("Invalid project permission '" + perm + "'. Valid values are [admin, codeviewer, issueadmin, scan, user]"); + assertThat(e).hasMessage("Invalid project permission '" + perm + "'. Valid values are [admin, codeviewer, issueadmin, securityhotspotadmin, scan, user]"); } }); } @@ -338,7 +338,7 @@ public class GroupPermissionChangerTest { apply(new GroupPermissionChange(PermissionChange.Operation.ADD, perm, new ProjectId(publicProject), groupId)); fail("a BadRequestException should have been thrown for permission " + perm); } catch (BadRequestException e) { - assertThat(e).hasMessage("Invalid project permission '" + perm + "'. Valid values are [admin, codeviewer, issueadmin, scan, user]"); + assertThat(e).hasMessage("Invalid project permission '" + perm + "'. Valid values are [admin, codeviewer, issueadmin, securityhotspotadmin, scan, user]"); } }); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/PermissionTemplateServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/PermissionTemplateServiceTest.java index 4805954e0e5..9c55b543b39 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/PermissionTemplateServiceTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/PermissionTemplateServiceTest.java @@ -102,7 +102,7 @@ public class PermissionTemplateServiceTest { underTest.applyAndCommit(session, permissionTemplate, singletonList(publicProject)); assertThat(selectProjectPermissionsOfGroup(organization, null, publicProject)) - .containsOnly("p1", UserRole.ADMIN, UserRole.ISSUE_ADMIN, GlobalPermissions.SCAN_EXECUTION); + .containsOnly("p1", UserRole.ADMIN, UserRole.ISSUE_ADMIN, UserRole.SECURITYHOTSPOT_ADMIN, GlobalPermissions.SCAN_EXECUTION); } @Test @@ -118,7 +118,7 @@ public class PermissionTemplateServiceTest { underTest.applyDefault(session, organization.getUuid(), publicProject, null); assertThat(selectProjectPermissionsOfGroup(organization, null, publicProject)) - .containsOnly("p1", UserRole.ADMIN, UserRole.ISSUE_ADMIN, GlobalPermissions.SCAN_EXECUTION); + .containsOnly("p1", UserRole.ADMIN, UserRole.ISSUE_ADMIN, UserRole.SECURITYHOTSPOT_ADMIN, GlobalPermissions.SCAN_EXECUTION); } @Test @@ -134,7 +134,7 @@ public class PermissionTemplateServiceTest { underTest.applyAndCommit(session, permissionTemplate, singletonList(privateProject)); assertThat(selectProjectPermissionsOfGroup(organization, group, privateProject)) - .containsOnly("p1", UserRole.USER, UserRole.CODEVIEWER, UserRole.ADMIN, UserRole.ISSUE_ADMIN, GlobalPermissions.SCAN_EXECUTION); + .containsOnly("p1", UserRole.USER, UserRole.CODEVIEWER, UserRole.ADMIN, UserRole.ISSUE_ADMIN, UserRole.SECURITYHOTSPOT_ADMIN, GlobalPermissions.SCAN_EXECUTION); } @Test @@ -151,7 +151,7 @@ public class PermissionTemplateServiceTest { underTest.applyDefault(session, organization.getUuid(), privateProject, null); assertThat(selectProjectPermissionsOfGroup(organization, group, privateProject)) - .containsOnly("p1", UserRole.USER, UserRole.CODEVIEWER, UserRole.ADMIN, UserRole.ISSUE_ADMIN, GlobalPermissions.SCAN_EXECUTION); + .containsOnly("p1", UserRole.USER, UserRole.CODEVIEWER, UserRole.ADMIN, UserRole.ISSUE_ADMIN, UserRole.SECURITYHOTSPOT_ADMIN, GlobalPermissions.SCAN_EXECUTION); } @Test @@ -167,7 +167,7 @@ public class PermissionTemplateServiceTest { underTest.applyAndCommit(session, permissionTemplate, singletonList(publicProject)); assertThat(selectProjectPermissionsOfGroup(organization, group, publicProject)) - .containsOnly("p1", UserRole.ADMIN, UserRole.ISSUE_ADMIN, GlobalPermissions.SCAN_EXECUTION); + .containsOnly("p1", UserRole.ADMIN, UserRole.ISSUE_ADMIN, UserRole.SECURITYHOTSPOT_ADMIN, GlobalPermissions.SCAN_EXECUTION); } @Test @@ -184,7 +184,7 @@ public class PermissionTemplateServiceTest { underTest.applyDefault(session, organization.getUuid(), publicProject, null); assertThat(selectProjectPermissionsOfGroup(organization, group, publicProject)) - .containsOnly("p1", UserRole.ADMIN, UserRole.ISSUE_ADMIN, GlobalPermissions.SCAN_EXECUTION); + .containsOnly("p1", UserRole.ADMIN, UserRole.ISSUE_ADMIN, UserRole.SECURITYHOTSPOT_ADMIN, GlobalPermissions.SCAN_EXECUTION); } @Test @@ -200,7 +200,7 @@ public class PermissionTemplateServiceTest { underTest.applyAndCommit(session, permissionTemplate, singletonList(publicProject)); assertThat(selectProjectPermissionsOfUser(user, publicProject)) - .containsOnly("p1", UserRole.ADMIN, UserRole.ISSUE_ADMIN, GlobalPermissions.SCAN_EXECUTION); + .containsOnly("p1", UserRole.ADMIN, UserRole.ISSUE_ADMIN, UserRole.SECURITYHOTSPOT_ADMIN, GlobalPermissions.SCAN_EXECUTION); } @Test @@ -217,7 +217,7 @@ public class PermissionTemplateServiceTest { underTest.applyDefault(session, organization.getUuid(), publicProject, null); assertThat(selectProjectPermissionsOfUser(user, publicProject)) - .containsOnly("p1", UserRole.ADMIN, UserRole.ISSUE_ADMIN, GlobalPermissions.SCAN_EXECUTION); + .containsOnly("p1", UserRole.ADMIN, UserRole.ISSUE_ADMIN, UserRole.SECURITYHOTSPOT_ADMIN, GlobalPermissions.SCAN_EXECUTION); } @Test @@ -233,7 +233,7 @@ public class PermissionTemplateServiceTest { underTest.applyAndCommit(session, permissionTemplate, singletonList(privateProject)); assertThat(selectProjectPermissionsOfUser(user, privateProject)) - .containsOnly("p1", UserRole.USER, UserRole.CODEVIEWER, UserRole.ADMIN, UserRole.ISSUE_ADMIN, GlobalPermissions.SCAN_EXECUTION); + .containsOnly("p1", UserRole.USER, UserRole.CODEVIEWER, UserRole.ADMIN, UserRole.ISSUE_ADMIN, UserRole.SECURITYHOTSPOT_ADMIN, GlobalPermissions.SCAN_EXECUTION); } @Test @@ -250,7 +250,7 @@ public class PermissionTemplateServiceTest { underTest.applyDefault(session, organization.getUuid(), privateProject, null); assertThat(selectProjectPermissionsOfUser(user, privateProject)) - .containsOnly("p1", UserRole.USER, UserRole.CODEVIEWER, UserRole.ADMIN, UserRole.ISSUE_ADMIN, GlobalPermissions.SCAN_EXECUTION); + .containsOnly("p1", UserRole.USER, UserRole.CODEVIEWER, UserRole.ADMIN, UserRole.ISSUE_ADMIN, UserRole.SECURITYHOTSPOT_ADMIN, GlobalPermissions.SCAN_EXECUTION); } @Test @@ -267,7 +267,7 @@ public class PermissionTemplateServiceTest { underTest.applyDefault(session, organization.getUuid(), publicProject, user.getId()); assertThat(selectProjectPermissionsOfUser(user, publicProject)) - .containsOnly("p1", UserRole.ADMIN, UserRole.ISSUE_ADMIN, GlobalPermissions.SCAN_EXECUTION); + .containsOnly("p1", UserRole.ADMIN, UserRole.ISSUE_ADMIN, UserRole.SECURITYHOTSPOT_ADMIN, GlobalPermissions.SCAN_EXECUTION); } @Test @@ -284,7 +284,7 @@ public class PermissionTemplateServiceTest { underTest.applyDefault(session, organization.getUuid(), privateProject, user.getId()); assertThat(selectProjectPermissionsOfUser(user, privateProject)) - .containsOnly("p1", UserRole.USER, UserRole.CODEVIEWER, UserRole.ADMIN, UserRole.ISSUE_ADMIN, GlobalPermissions.SCAN_EXECUTION); + .containsOnly("p1", UserRole.USER, UserRole.CODEVIEWER, UserRole.ADMIN, UserRole.ISSUE_ADMIN, UserRole.SECURITYHOTSPOT_ADMIN, GlobalPermissions.SCAN_EXECUTION); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/UserPermissionChangerTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/UserPermissionChangerTest.java index 10621035974..0bdff5b6434 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/UserPermissionChangerTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/UserPermissionChangerTest.java @@ -251,7 +251,7 @@ public class UserPermissionChangerTest { @Test public void fail_to_add_global_permission_on_project() { expectedException.expect(BadRequestException.class); - expectedException.expectMessage("Invalid project permission 'gateadmin'. Valid values are [admin, codeviewer, issueadmin, scan, user]"); + expectedException.expectMessage("Invalid project permission 'gateadmin'. Valid values are [admin, codeviewer, issueadmin, securityhotspotadmin, scan, user]"); UserPermissionChange change = new UserPermissionChange(ADD, org1.getUuid(), QUALITY_GATE_ADMIN, new ProjectId(privateProject), UserId.from(user1)); apply(change); diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SearchTemplatesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SearchTemplatesActionTest.java index 1d7d77f15e2..98f70e4e038 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SearchTemplatesActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SearchTemplatesActionTest.java @@ -224,6 +224,11 @@ public class SearchTemplatesActionTest extends BasePermissionWsTest groupPermissions = selectGroupPermissions(defaultTemplate); - assertThat(groupPermissions).hasSize(4); + assertThat(groupPermissions).hasSize(5); expectGroupPermission(groupPermissions, UserRole.ADMIN, DefaultGroups.ADMINISTRATORS); expectGroupPermission(groupPermissions, UserRole.ISSUE_ADMIN, DefaultGroups.ADMINISTRATORS); + expectGroupPermission(groupPermissions, UserRole.SECURITYHOTSPOT_ADMIN, DefaultGroups.ADMINISTRATORS); expectGroupPermission(groupPermissions, UserRole.CODEVIEWER, defaultGroup.getName()); expectGroupPermission(groupPermissions, UserRole.USER, defaultGroup.getName()); diff --git a/server/sonar-web/src/main/js/apps/permission-templates/utils.js b/server/sonar-web/src/main/js/apps/permission-templates/utils.js index a5bcb8aca3d..e7afc8ed47e 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/utils.js +++ b/server/sonar-web/src/main/js/apps/permission-templates/utils.js @@ -19,7 +19,14 @@ */ import { sortBy } from 'lodash'; -export const PERMISSIONS_ORDER = ['user', 'codeviewer', 'issueadmin', 'admin', 'scan']; +export const PERMISSIONS_ORDER = [ + 'user', + 'codeviewer', + 'issueadmin', + 'securityhotspotadmin', + 'admin', + 'scan' +]; /** * Sort list of permissions based on predefined order diff --git a/server/sonar-web/src/main/js/apps/permissions/project/constants.js b/server/sonar-web/src/main/js/apps/permissions/project/constants.js index ad87e07029d..13a6bee92c5 100644 --- a/server/sonar-web/src/main/js/apps/permissions/project/constants.js +++ b/server/sonar-web/src/main/js/apps/permissions/project/constants.js @@ -17,7 +17,14 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -export const PERMISSIONS_ORDER_FOR_PROJECT = ['user', 'codeviewer', 'issueadmin', 'admin', 'scan']; +export const PERMISSIONS_ORDER_FOR_PROJECT = [ + 'user', + 'codeviewer', + 'issueadmin', + 'securityhotspotadmin', + 'admin', + 'scan' +]; export const PERMISSIONS_ORDER_FOR_VIEW = ['user', 'admin']; diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 60d21398eed..5717d41eaf9 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -2024,6 +2024,8 @@ projects_role.admin=Administer projects_role.admin.desc=Access project settings and perform administration tasks. (Users will also need "Browse" permission) projects_role.issueadmin=Administer Issues projects_role.issueadmin.desc=Change the type and severity of issues, resolve issues as being "won't fix" or "false-positive" (users also need "Browse" permission). +projects_role.securityhotspotadmin=Administer Security Hotspots +projects_role.securityhotspotadmin.desc=Detect a Vulnerability from a "Security Hotspot". Reject, clear, accept, reopen a "Security Hotspot" (users also need "Browse" permissions). projects_role.user=Browse projects_role.user.desc=Access a project, browse its measures and issues, confirm or resolve issues as "fixed", change the assignee, comment on issues and change tags. projects_role.codeviewer=See Source Code diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/web/UserRole.java b/sonar-plugin-api/src/main/java/org/sonar/api/web/UserRole.java index c768712a333..196218cdc51 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/web/UserRole.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/web/UserRole.java @@ -42,6 +42,11 @@ public @interface UserRole { String CODEVIEWER = "codeviewer"; String ISSUE_ADMIN = "issueadmin"; + /** + * @since 7.3 + */ + String SECURITYHOTSPOT_ADMIN = "securityhotspotadmin"; + String[] value() default {}; }