aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2017-11-29 15:07:50 +0100
committerJulien Lancelot <julien.lancelot@sonarsource.com>2017-12-04 16:02:52 +0100
commitf25ece8fe820b708f08aac652cdda94183bcb2df (patch)
treebfee02036d06b5f468d906154767f14ac1a6573e
parent2ba36cab8ba668c3dfa4c6e33399bd076b356adf (diff)
downloadsonarqube-f25ece8fe820b708f08aac652cdda94183bcb2df.tar.gz
sonarqube-f25ece8fe820b708f08aac652cdda94183bcb2df.zip
SONAR-10074 Add QP actions "delete" and "associateProjects"
In api/qualityprofiles/search, the following actions are now availables : - delete : Available when not built-it, not default, and have either QP admin permission or have rights to edit - associateProjects : Available when not default and have either QP admin permission or have rights to edit
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchAction.java36
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchData.java11
-rw-r--r--server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/search-example.json16
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java34
-rw-r--r--sonar-ws/src/main/protobuf/ws-qualityprofiles.proto4
-rw-r--r--tests/src/test/java/org/sonarqube/tests/qualityProfile/QualityProfilesEditTest.java16
6 files changed, 67 insertions, 50 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchAction.java
index cd83b7f721f..d3b5ce0d12b 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchAction.java
@@ -96,11 +96,14 @@ public class SearchAction implements QProfileWsAction {
.setSince("5.2")
.setDescription("Search quality profiles")
.setHandler(this)
- .setChangelog(new Change("6.5", format("The parameters '%s', '%s' and '%s' can be combined without any constraint", PARAM_DEFAULTS, PARAM_PROJECT, PARAM_LANGUAGE)))
+ .setChangelog(
+ new Change("6.5", format("The parameters '%s', '%s' and '%s' can be combined without any constraint", PARAM_DEFAULTS, PARAM_PROJECT, PARAM_LANGUAGE)),
+ new Change("6.6", "Add available actions 'edit', 'copy' and 'setAsDefault' and global action 'create'"),
+ new Change("7.0", "Add available actions 'delete' and 'associateProjects'")
+ )
.setResponseExample(getClass().getResource("search-example.json"));
- QProfileWsSupport.createOrganizationParam(action
- )
+ QProfileWsSupport.createOrganizationParam(action)
.setSince("6.4");
action
@@ -165,8 +168,7 @@ public class SearchAction implements QProfileWsAction {
dbClient.activeRuleDao().countActiveRulesByQuery(dbSession, builder.setProfiles(profiles).setRuleStatus(DEPRECATED).build()))
.setProjectCountByProfileKey(dbClient.qualityProfileDao().countProjectsByOrganizationAndProfiles(dbSession, organization, profiles))
.setDefaultProfileKeys(defaultProfiles)
- .setEditableProfileKeys(editableProfiles)
- .setGlobalQProfileAdmin(userSession.hasPermission(ADMINISTER_QUALITY_PROFILES, organization));
+ .setEditableProfileKeys(editableProfiles);
}
}
@@ -197,15 +199,14 @@ public class SearchAction implements QProfileWsAction {
UserDto user = dbClient.userDao().selectActiveUserByLogin(dbSession, login);
checkState(user != null, "User with login '%s' is not found'", login);
- return
- Stream.concat(
- dbClient.qProfileEditUsersDao().selectQProfileUuidsByOrganizationAndUser(dbSession, organization, user).stream(),
- dbClient.qProfileEditGroupsDao().selectQProfileUuidsByOrganizationAndGroups(dbSession, organization, userSession.getGroups()).stream())
- .collect(toList());
+ return Stream.concat(
+ dbClient.qProfileEditUsersDao().selectQProfileUuidsByOrganizationAndUser(dbSession, organization, user).stream(),
+ dbClient.qProfileEditGroupsDao().selectQProfileUuidsByOrganizationAndGroups(dbSession, organization, userSession.getGroups()).stream())
+ .collect(toList());
}
private List<QProfileDto> searchProfiles(DbSession dbSession, SearchRequest request, OrganizationDto organization, List<QProfileDto> defaultProfiles,
- @Nullable ComponentDto project) {
+ @Nullable ComponentDto project) {
Collection<QProfileDto> profiles = selectAllProfiles(dbSession, organization);
return profiles.stream()
@@ -256,10 +257,10 @@ public class SearchAction implements QProfileWsAction {
private SearchWsResponse buildResponse(SearchData data) {
List<QProfileDto> profiles = data.getProfiles();
Map<String, QProfileDto> profilesByKey = profiles.stream().collect(Collectors.toMap(QProfileDto::getKee, identity()));
+ boolean isGlobalQProfileAdmin = userSession.hasPermission(ADMINISTER_QUALITY_PROFILES, data.getOrganization());
SearchWsResponse.Builder response = SearchWsResponse.newBuilder();
- response.setActions(SearchWsResponse.Actions.newBuilder().setCreate(data.isGlobalQProfileAdmin()));
-
+ response.setActions(SearchWsResponse.Actions.newBuilder().setCreate(isGlobalQProfileAdmin));
for (QProfileDto profile : profiles) {
QualityProfile.Builder profileBuilder = response.addProfilesBuilder();
@@ -284,11 +285,12 @@ public class SearchAction implements QProfileWsAction {
profileBuilder.setIsBuiltIn(profile.isBuiltIn());
profileBuilder.setActions(SearchWsResponse.QualityProfile.Actions.newBuilder()
- .setEdit(data.isEditable(profile))
- .setSetAsDefault(data.isGlobalQProfileAdmin())
- .setCopy(data.isGlobalQProfileAdmin()));
+ .setEdit(!profile.isBuiltIn() && (isGlobalQProfileAdmin || data.isEditable(profile)))
+ .setSetAsDefault(!isDefault && isGlobalQProfileAdmin)
+ .setCopy(isGlobalQProfileAdmin)
+ .setDelete(!isDefault && !profile.isBuiltIn() && (isGlobalQProfileAdmin || data.isEditable(profile)))
+ .setAssociateProjects(!isDefault && (isGlobalQProfileAdmin || data.isEditable(profile))));
}
-
return response.build();
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchData.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchData.java
index d07bfcb13d3..20e4a7ad793 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchData.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchData.java
@@ -39,7 +39,6 @@ class SearchData {
private Map<String, Long> projectCountByProfileKey;
private Set<String> defaultProfileKeys;
private Set<String> editableProfileKeys;
- private boolean isGlobalQProfileAdmin;
SearchData setOrganization(OrganizationDto organization) {
this.organization = organization;
@@ -96,7 +95,7 @@ class SearchData {
}
boolean isEditable(QProfileDto profile) {
- return !profile.isBuiltIn() && (isGlobalQProfileAdmin || editableProfileKeys.contains(profile.getKee()));
+ return editableProfileKeys.contains(profile.getKee());
}
SearchData setEditableProfileKeys(List<String> editableProfileKeys) {
@@ -104,12 +103,4 @@ class SearchData {
return this;
}
- boolean isGlobalQProfileAdmin() {
- return isGlobalQProfileAdmin;
- }
-
- SearchData setGlobalQProfileAdmin(boolean globalQProfileAdmin) {
- isGlobalQProfileAdmin = globalQProfileAdmin;
- return this;
- }
}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/search-example.json b/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/search-example.json
index 7c3eabe8acc..eb13119b881 100644
--- a/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/search-example.json
+++ b/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/search-example.json
@@ -15,7 +15,9 @@
"actions": {
"edit": false,
"setAsDefault": false,
- "copy": false
+ "copy": false,
+ "delete": false,
+ "associateProjects": false
}
},
{
@@ -37,7 +39,9 @@
"actions": {
"edit": true,
"setAsDefault": false,
- "copy": false
+ "copy": false,
+ "delete": true,
+ "associateProjects": true
}
},
{
@@ -55,7 +59,9 @@
"actions": {
"edit": true,
"setAsDefault": false,
- "copy": false
+ "copy": false,
+ "delete": false,
+ "associateProjects": false
}
},
{
@@ -72,7 +78,9 @@
"actions": {
"edit": false,
"setAsDefault": false,
- "copy": false
+ "copy": false,
+ "delete": false,
+ "associateProjects": false
}
}
],
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java
index 289ec3904f6..7beee7087de 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java
@@ -97,7 +97,10 @@ public class SearchActionTest {
assertThat(definition.changelog())
.extracting(Change::getVersion, Change::getDescription)
- .containsExactlyInAnyOrder(tuple("6.5", "The parameters 'defaults', 'project' and 'language' can be combined without any constraint"));
+ .containsExactlyInAnyOrder(
+ tuple("6.5", "The parameters 'defaults', 'project' and 'language' can be combined without any constraint"),
+ tuple("6.6", "Add available actions 'edit', 'copy' and 'setAsDefault' and global action 'create'"),
+ tuple("7.0", "Add available actions 'delete' and 'associateProjects'"));
WebService.Param organization = definition.param("organization");
assertThat(organization).isNotNull();
@@ -328,16 +331,21 @@ public class SearchActionTest {
OrganizationDto organization = db.organizations().insert();
QProfileDto customProfile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO1.getKey()));
QProfileDto builtInProfile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO1.getKey()).setIsBuiltIn(true));
+ QProfileDto defaultProfile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO1.getKey()));
+ db.qualityProfiles().setAsDefault(defaultProfile);
UserDto user = db.users().insertUser();
userSession.logIn(user).addPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization);
SearchWsResponse result = call(ws.newRequest()
.setParam(PARAM_ORGANIZATION, organization.getKey()));
- assertThat(result.getProfilesList()).extracting(QualityProfile::getKey, qp -> qp.getActions().getEdit(), qp -> qp.getActions().getCopy(), qp -> qp.getActions().getSetAsDefault())
+ assertThat(result.getProfilesList())
+ .extracting(QualityProfile::getKey, qp -> qp.getActions().getEdit(), qp -> qp.getActions().getCopy(), qp -> qp.getActions().getSetAsDefault(),
+ qp -> qp.getActions().getDelete(), qp -> qp.getActions().getAssociateProjects())
.containsExactlyInAnyOrder(
- tuple(customProfile.getKee(), true, true, true),
- tuple(builtInProfile.getKee(), false, true, true));
+ tuple(customProfile.getKee(), true, true, true, true, true),
+ tuple(builtInProfile.getKee(), false, true, true, false, true),
+ tuple(defaultProfile.getKee(), true, true, false, false, false));
assertThat(result.getActions().getCreate()).isTrue();
}
@@ -357,12 +365,14 @@ public class SearchActionTest {
SearchWsResponse result = call(ws.newRequest()
.setParam(PARAM_ORGANIZATION, organization.getKey()));
- assertThat(result.getProfilesList()).extracting(QualityProfile::getKey, qp -> qp.getActions().getEdit(), qp -> qp.getActions().getCopy(), qp -> qp.getActions().getSetAsDefault())
+ assertThat(result.getProfilesList())
+ .extracting(QualityProfile::getKey, qp -> qp.getActions().getEdit(), qp -> qp.getActions().getCopy(), qp -> qp.getActions().getSetAsDefault(),
+ qp -> qp.getActions().getDelete(), qp -> qp.getActions().getAssociateProjects())
.containsExactlyInAnyOrder(
- tuple(profile1.getKee(), true, false, false),
- tuple(profile2.getKee(), false, false, false),
- tuple(profile3.getKee(), true, false, false),
- tuple(builtInProfile.getKee(), false, false, false));
+ tuple(profile1.getKee(), true, false, false, true, true),
+ tuple(profile2.getKee(), false, false, false, false, false),
+ tuple(profile3.getKee(), true, false, false, true, true),
+ tuple(builtInProfile.getKee(), false, false, false, false, false));
assertThat(result.getActions().getCreate()).isFalse();
}
@@ -375,8 +385,10 @@ public class SearchActionTest {
SearchWsResponse result = call(ws.newRequest()
.setParam(PARAM_ORGANIZATION, organization.getKey()));
- assertThat(result.getProfilesList()).extracting(QualityProfile::getKey, qp -> qp.getActions().getEdit(), qp -> qp.getActions().getCopy(), qp -> qp.getActions().getSetAsDefault())
- .containsExactlyInAnyOrder(tuple(profile.getKee(), false, false, false));
+ assertThat(result.getProfilesList())
+ .extracting(QualityProfile::getKey, qp -> qp.getActions().getEdit(), qp -> qp.getActions().getCopy(), qp -> qp.getActions().getSetAsDefault(),
+ qp -> qp.getActions().getDelete(), qp -> qp.getActions().getAssociateProjects())
+ .containsExactlyInAnyOrder(tuple(profile.getKee(), false, false, false, false, false));
assertThat(result.getActions().getCreate()).isFalse();
}
diff --git a/sonar-ws/src/main/protobuf/ws-qualityprofiles.proto b/sonar-ws/src/main/protobuf/ws-qualityprofiles.proto
index 0b0039a2506..ddb6ebbe8ff 100644
--- a/sonar-ws/src/main/protobuf/ws-qualityprofiles.proto
+++ b/sonar-ws/src/main/protobuf/ws-qualityprofiles.proto
@@ -54,7 +54,9 @@ message SearchWsResponse {
optional bool edit = 1;
optional bool setAsDefault = 2;
optional bool copy = 3;
- }
+ optional bool associateProjects = 4;
+ optional bool delete = 5;
+ }
}
message Actions {
diff --git a/tests/src/test/java/org/sonarqube/tests/qualityProfile/QualityProfilesEditTest.java b/tests/src/test/java/org/sonarqube/tests/qualityProfile/QualityProfilesEditTest.java
index 6b6ed149993..9598bb0432f 100644
--- a/tests/src/test/java/org/sonarqube/tests/qualityProfile/QualityProfilesEditTest.java
+++ b/tests/src/test/java/org/sonarqube/tests/qualityProfile/QualityProfilesEditTest.java
@@ -24,8 +24,8 @@ import java.util.function.Predicate;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
-import org.sonarqube.tests.Category6Suite;
import org.sonarqube.qa.util.Tester;
+import org.sonarqube.tests.Category6Suite;
import org.sonarqube.ws.Common;
import org.sonarqube.ws.Organizations.Organization;
import org.sonarqube.ws.Qualityprofiles.CreateWsResponse;
@@ -213,11 +213,12 @@ public class QualityProfilesEditTest {
.qProfiles().service().search(new SearchRequest().setOrganizationKey(organization.getKey()));
assertThat(result.getActions().getCreate()).isFalse();
assertThat(result.getProfilesList())
- .extracting(SearchWsResponse.QualityProfile::getKey, qp -> qp.getActions().getEdit(), qp -> qp.getActions().getCopy(), qp -> qp.getActions().getSetAsDefault())
+ .extracting(SearchWsResponse.QualityProfile::getKey, qp -> qp.getActions().getEdit(), qp -> qp.getActions().getCopy(), qp -> qp.getActions().getSetAsDefault(),
+ qp -> qp.getActions().getDelete(), qp -> qp.getActions().getAssociateProjects())
.contains(
- tuple(xooProfile1.getKey(), true, false, false),
- tuple(xooProfile2.getKey(), true, false, false),
- tuple(xooProfile3.getKey(), false, false, false));
+ tuple(xooProfile1.getKey(), true, false, false, true, true),
+ tuple(xooProfile2.getKey(), true, false, false, true, true),
+ tuple(xooProfile3.getKey(), false, false, false, false, false));
}
@Test
@@ -231,9 +232,10 @@ public class QualityProfilesEditTest {
.qProfiles().service().search(new SearchRequest().setOrganizationKey(organization.getKey()));
assertThat(result.getActions().getCreate()).isTrue();
assertThat(result.getProfilesList())
- .extracting(SearchWsResponse.QualityProfile::getKey, qp -> qp.getActions().getEdit(), qp -> qp.getActions().getCopy(), qp -> qp.getActions().getSetAsDefault())
+ .extracting(SearchWsResponse.QualityProfile::getKey, qp -> qp.getActions().getEdit(), qp -> qp.getActions().getCopy(), qp -> qp.getActions().getSetAsDefault(),
+ qp -> qp.getActions().getDelete(), qp -> qp.getActions().getAssociateProjects())
.contains(
- tuple(xooProfile.getKey(), true, true, true));
+ tuple(xooProfile.getKey(), true, true, true, true, true));
}
@Test