Browse Source

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
tags/7.0-RC1
Julien Lancelot 6 years ago
parent
commit
f25ece8fe8

+ 19
- 17
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchAction.java View File

@@ -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();
}


+ 1
- 10
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchData.java View File

@@ -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;
}
}

+ 12
- 4
server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/search-example.json View File

@@ -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
}
}
],

+ 23
- 11
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java View File

@@ -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();
}


+ 3
- 1
sonar-ws/src/main/protobuf/ws-qualityprofiles.proto View File

@@ -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 {

+ 9
- 7
tests/src/test/java/org/sonarqube/tests/qualityProfile/QualityProfilesEditTest.java View File

@@ -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

Loading…
Cancel
Save