*/
package org.sonar.db.qualityprofile;
+import java.util.Collection;
import java.util.List;
import org.sonar.api.utils.System2;
import org.sonar.db.Dao;
+import org.sonar.db.DatabaseUtils;
import org.sonar.db.DbSession;
import org.sonar.db.Pagination;
+import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.user.GroupDto;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
+
public class QProfileEditGroupsDao implements Dao {
private final System2 system2;
return mapper(dbSession).selectByQProfileAndGroup(profile.getKee(), group.getId()) != null;
}
- public int countByQuery(DbSession dbSession, SearchGroupsQuery query){
+ public int countByQuery(DbSession dbSession, SearchGroupsQuery query) {
return mapper(dbSession).countByQuery(query);
}
- public List<GroupMembershipDto> selectByQuery(DbSession dbSession, SearchGroupsQuery query, Pagination pagination){
+ public List<GroupMembershipDto> selectByQuery(DbSession dbSession, SearchGroupsQuery query, Pagination pagination) {
return mapper(dbSession).selectByQuery(query, pagination);
}
+ public List<String> selectQProfileUuidsByOrganizationAndGroups(DbSession dbSession, OrganizationDto organization, Collection<GroupDto> groups) {
+ return DatabaseUtils.executeLargeInputs(groups.stream().map(GroupDto::getId).collect(toList()), g ->
+ mapper(dbSession).selectQProfileUuidsByOrganizationAndGroups(organization.getUuid(), g));
+ }
+
public void insert(DbSession dbSession, QProfileEditGroupsDto dto) {
mapper(dbSession).insert(dto, system2.now());
}
List<GroupMembershipDto> selectByQuery(@Param("query") SearchGroupsQuery query, @Param("pagination") Pagination pagination);
+ List<String> selectQProfileUuidsByOrganizationAndGroups(@Param("organizationUuid") String organizationUuid, @Param("groupIds") List<Integer> groupIds);
+
void insert(@Param("dto") QProfileEditGroupsDto dto, @Param("now") long now);
void delete(@Param("qProfileUuid") String qProfileUuid, @Param("groupId") int groupId);
import org.sonar.db.Dao;
import org.sonar.db.DbSession;
import org.sonar.db.Pagination;
+import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.user.UserDto;
public class QProfileEditUsersDao implements Dao {
return mapper(dbSession).selectByQuery(query, pagination);
}
+ public List<String> selectQProfileUuidsByOrganizationAndUser(DbSession dbSession, OrganizationDto organization, UserDto userDto){
+ return mapper(dbSession).selectQProfileUuidsByOrganizationAndUser(organization.getUuid(), userDto.getId());
+ }
+
public void insert(DbSession dbSession, QProfileEditUsersDto dto) {
mapper(dbSession).insert(dto, system2.now());
}
List<UserMembershipDto> selectByQuery(@Param("query") SearchUsersQuery query, @Param("pagination") Pagination pagination);
+ List<String> selectQProfileUuidsByOrganizationAndUser(@Param("organizationUuid") String organizationUuid, @Param("userId") int userId);
+
void insert(@Param("dto") QProfileEditUsersDto dto, @Param("now") long now);
void delete(@Param("qProfileUuid") String qProfileUuid, @Param("userId") int userId);
</where>
</sql>
+ <select id="selectQProfileUuidsByOrganizationAndGroups" parameterType="map" resultType="string">
+ select distinct qeg.qprofile_uuid as qProfileUuid
+ from qprofile_edit_groups qeg
+ inner join org_qprofiles oq on qeg.qprofile_uuid=oq.uuid and oq.organization_uuid=#{organizationUuid, jdbcType=VARCHAR}
+ <where>
+ qeg.group_id in <foreach collection="groupIds" open="(" close=")" item="groupId" separator=",">#{groupId, jdbcType=INTEGER}</foreach>
+ </where>
+ </select>
+
<insert id="insert" useGeneratedKeys="false" parameterType="map">
insert into qprofile_edit_groups(
uuid,
</where>
</sql>
+ <select id="selectQProfileUuidsByOrganizationAndUser" parameterType="map" resultType="string">
+ SELECT qeu.qprofile_uuid as qProfileUuid
+ FROM qprofile_edit_users qeu
+ INNER JOIN org_qprofiles oq ON qeu.qprofile_uuid=oq.uuid AND oq.organization_uuid=#{organizationUuid, jdbcType=VARCHAR}
+ <where>
+ qeu.user_id=#{userId, jdbcType=INTEGER}
+ </where>
+ </select>
+
<insert id="insert" useGeneratedKeys="false" parameterType="map">
insert into qprofile_edit_users(
uuid,
*/
package org.sonar.db.qualityprofile;
+import java.util.Collections;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.utils.System2;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.user.GroupDto;
+import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.entry;
import static org.assertj.core.api.Assertions.tuple;
.containsExactly(group1.getId(), group2.getId(), group3.getId());
}
+ @Test
+ public void selectQProfileUuidsByOrganizationAndGroups() {
+ OrganizationDto organization = db.organizations().insert();
+ OrganizationDto anotherOrganization = db.organizations().insert();
+ QProfileDto profile1 = db.qualityProfiles().insert(organization);
+ QProfileDto profile2 = db.qualityProfiles().insert(organization);
+ QProfileDto anotherProfile = db.qualityProfiles().insert(anotherOrganization);
+ GroupDto group1 = db.users().insertGroup(organization, "group1");
+ GroupDto group2 = db.users().insertGroup(organization, "group2");
+ GroupDto group3 = db.users().insertGroup(organization, "group3");
+ db.qualityProfiles().addGroupPermission(profile1, group1);
+ db.qualityProfiles().addGroupPermission(profile1, group2);
+ db.qualityProfiles().addGroupPermission(profile2, group2);
+ db.qualityProfiles().addGroupPermission(anotherProfile, group1);
+ db.qualityProfiles().addGroupPermission(anotherProfile, group3);
+
+ assertThat(underTest.selectQProfileUuidsByOrganizationAndGroups(db.getSession(), organization, asList(group1, group2)))
+ .containsExactlyInAnyOrder(profile1.getKee(), profile2.getKee())
+ .doesNotContain(anotherProfile.getKee());
+ assertThat(underTest.selectQProfileUuidsByOrganizationAndGroups(db.getSession(), organization, asList(group1, group2, group3)))
+ .containsExactlyInAnyOrder(profile1.getKee(), profile2.getKee());
+ assertThat(underTest.selectQProfileUuidsByOrganizationAndGroups(db.getSession(), organization, Collections.emptyList())).isEmpty();
+ }
+
@Test
public void insert() {
underTest.insert(db.getSession(), new QProfileEditGroupsDto()
*/
package org.sonar.db.qualityprofile;
+import java.sql.SQLException;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.internal.TestSystem2;
import org.sonar.db.DbTester;
import static org.sonar.db.qualityprofile.SearchUsersQuery.IN;
import static org.sonar.db.qualityprofile.SearchUsersQuery.OUT;
import static org.sonar.db.qualityprofile.SearchUsersQuery.builder;
+import static org.sonar.test.ExceptionCauseMatcher.hasType;
public class QProfileEditUsersDaoTest {
private System2 system2 = new TestSystem2().setNow(NOW);
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
@Rule
public DbTester db = DbTester.create(system2);
.isEqualTo(3);
assertThat(underTest.countByQuery(db.getSession(), builder()
- .setOrganization(organization)
- .setProfile(profile)
- .setMembership(IN).build()))
+ .setOrganization(organization)
+ .setProfile(profile)
+ .setMembership(IN).build()))
.isEqualTo(2);
assertThat(underTest.countByQuery(db.getSession(), builder()
- .setOrganization(organization)
- .setProfile(profile)
- .setMembership(OUT).build()))
+ .setOrganization(organization)
+ .setProfile(profile)
+ .setMembership(OUT).build()))
.isEqualTo(1);
}
.containsExactly(user1.getId(), user2.getId(), user3.getId());
}
+ @Test
+ public void selectQProfileUuidsByOrganizationAndUser() {
+ OrganizationDto organization = db.organizations().insert();
+ OrganizationDto anotherOrganization = db.organizations().insert();
+ QProfileDto profile1 = db.qualityProfiles().insert(organization);
+ QProfileDto profile2 = db.qualityProfiles().insert(organization);
+ QProfileDto anotherProfile = db.qualityProfiles().insert(anotherOrganization);
+ UserDto user1 = db.users().insertUser(u -> u.setName("user1"));
+ UserDto user2 = db.users().insertUser(u -> u.setName("user2"));
+ db.qualityProfiles().addUserPermission(profile1, user1);
+ db.qualityProfiles().addUserPermission(profile2, user1);
+ db.qualityProfiles().addUserPermission(anotherProfile, user1);
+
+ assertThat(underTest.selectQProfileUuidsByOrganizationAndUser(db.getSession(), organization, user1))
+ .containsExactlyInAnyOrder(profile1.getKee(), profile2.getKee())
+ .doesNotContain(anotherProfile.getKee());
+ assertThat(underTest.selectQProfileUuidsByOrganizationAndUser(db.getSession(), organization, user2)).isEmpty();
+ }
+
@Test
public void insert() {
underTest.insert(db.getSession(), new QProfileEditUsersDto()
entry("createdAt", NOW));
}
+ @Test
+ public void fail_to_insert_same_row_twice() {
+ underTest.insert(db.getSession(), new QProfileEditUsersDto()
+ .setUuid("UUID-1")
+ .setUserId(100)
+ .setQProfileUuid("QPROFILE")
+ );
+
+ expectedException.expectCause(hasType(SQLException.class));
+
+ underTest.insert(db.getSession(), new QProfileEditUsersDto()
+ .setUuid("UUID-2")
+ .setUserId(100)
+ .setQProfileUuid("QPROFILE")
+ );
+ }
+
@Test
public void deleteByQProfileAndUser() {
OrganizationDto organization = db.organizations().insert();
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.api.resources.Language;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.qualityprofile.ActiveRuleCountQuery;
import org.sonar.db.qualityprofile.QProfileDto;
+import org.sonar.db.user.UserDto;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.user.UserSession;
import org.sonar.server.util.LanguageParamUtils;
import org.sonarqube.ws.QualityProfiles.SearchWsResponse;
import org.sonarqube.ws.QualityProfiles.SearchWsResponse.QualityProfile;
import static com.google.common.base.Preconditions.checkState;
import static java.lang.String.format;
+import static java.util.Collections.emptyList;
import static java.util.function.Function.identity;
import static org.sonar.api.rule.RuleStatus.DEPRECATED;
import static org.sonar.api.utils.DateUtils.formatDateTime;
import static org.sonar.core.util.Protobuf.setNullable;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
+import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_SEARCH;
.comparing(QProfileDto::getLanguage)
.thenComparing(QProfileDto::getName);
+ private final UserSession userSession;
private final Languages languages;
private final DbClient dbClient;
private final QProfileWsSupport wsSupport;
private final ComponentFinder componentFinder;
- public SearchAction(Languages languages, DbClient dbClient, QProfileWsSupport wsSupport, ComponentFinder componentFinder) {
+ public SearchAction(UserSession userSession, Languages languages, DbClient dbClient, QProfileWsSupport wsSupport, ComponentFinder componentFinder) {
+ this.userSession = userSession;
this.languages = languages;
this.dbClient = dbClient;
this.wsSupport = wsSupport;
ComponentDto project = findProject(dbSession, organization, request);
List<QProfileDto> defaultProfiles = dbClient.qualityProfileDao().selectDefaultProfiles(dbSession, organization, getLanguageKeys());
+ List<String> editableProfiles = searchEditableProfiles(dbSession, organization);
List<QProfileDto> profiles = searchProfiles(dbSession, request, organization, defaultProfiles, project);
ActiveRuleCountQuery.Builder builder = ActiveRuleCountQuery.builder().setOrganization(organization);
.setActiveDeprecatedRuleCountByProfileKey(
dbClient.activeRuleDao().countActiveRulesByQuery(dbSession, builder.setProfiles(profiles).setRuleStatus(DEPRECATED).build()))
.setProjectCountByProfileKey(dbClient.qualityProfileDao().countProjectsByOrganizationAndProfiles(dbSession, organization, profiles))
- .setDefaultProfileKeys(defaultProfiles);
+ .setDefaultProfileKeys(defaultProfiles)
+ .setEditableProfileKeys(editableProfiles)
+ .setGlobalQProfileAdmin(userSession.hasPermission(ADMINISTER_QUALITY_PROFILES, organization));
}
}
return component;
}
+ private List<String> searchEditableProfiles(DbSession dbSession, OrganizationDto organization) {
+ if (!userSession.isLoggedIn()) {
+ return emptyList();
+ }
+
+ String login = userSession.getLogin();
+ 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());
+ }
+
private List<QProfileDto> searchProfiles(DbSession dbSession, SearchWsRequest request, OrganizationDto organization, List<QProfileDto> defaultProfiles,
- @Nullable ComponentDto project) {
+ @Nullable ComponentDto project) {
Collection<QProfileDto> profiles = selectAllProfiles(dbSession, organization);
return profiles.stream()
Map<String, QProfileDto> profilesByKey = profiles.stream().collect(Collectors.toMap(QProfileDto::getKee, identity()));
SearchWsResponse.Builder response = SearchWsResponse.newBuilder();
- response.setActions(SearchWsResponse.Actions.newBuilder().setCreate(true));
+ response.setActions(SearchWsResponse.Actions.newBuilder().setCreate(data.isGlobalQProfileAdmin()));
for (QProfileDto profile : profiles) {
QualityProfile.Builder profileBuilder = response.addProfilesBuilder();
profileBuilder.setIsInherited(profile.getParentKee() != null);
profileBuilder.setIsBuiltIn(profile.isBuiltIn());
- profileBuilder.setActions(SearchWsResponse.Actions.newBuilder()
- .setEdit(true)
- .setSetAsDefault(false)
- .setCopy(false));
+ profileBuilder.setActions(SearchWsResponse.QualityProfile.Actions.newBuilder()
+ .setEdit(data.isEditable(profile))
+ .setSetAsDefault(data.isGlobalQProfileAdmin())
+ .setCopy(data.isGlobalQProfileAdmin()));
}
return response.build();
*/
package org.sonar.server.qualityprofile.ws;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.google.common.collect.ImmutableList.copyOf;
import static com.google.common.collect.ImmutableMap.copyOf;
-public class SearchData {
+class SearchData {
private OrganizationDto organization;
private List<QProfileDto> profiles;
private Map<String, Long> activeRuleCountByProfileKey;
private Map<String, Long> activeDeprecatedRuleCountByProfileKey;
private Map<String, Long> projectCountByProfileKey;
private Set<String> defaultProfileKeys;
+ private Set<String> editableProfileKeys;
+ private boolean isGlobalQProfileAdmin;
- public SearchData setOrganization(OrganizationDto organization) {
+ SearchData setOrganization(OrganizationDto organization) {
this.organization = organization;
return this;
}
- public OrganizationDto getOrganization() {
+ OrganizationDto getOrganization() {
return organization;
}
- public List<QProfileDto> getProfiles() {
+ List<QProfileDto> getProfiles() {
return profiles;
}
- public SearchData setProfiles(List<QProfileDto> profiles) {
+ SearchData setProfiles(List<QProfileDto> profiles) {
this.profiles = copyOf(profiles);
return this;
}
- public SearchData setActiveRuleCountByProfileKey(Map<String, Long> activeRuleCountByProfileKey) {
+ SearchData setActiveRuleCountByProfileKey(Map<String, Long> activeRuleCountByProfileKey) {
this.activeRuleCountByProfileKey = copyOf(activeRuleCountByProfileKey);
return this;
}
- public SearchData setActiveDeprecatedRuleCountByProfileKey(Map<String, Long> activeDeprecatedRuleCountByProfileKey) {
+ SearchData setActiveDeprecatedRuleCountByProfileKey(Map<String, Long> activeDeprecatedRuleCountByProfileKey) {
this.activeDeprecatedRuleCountByProfileKey = activeDeprecatedRuleCountByProfileKey;
return this;
}
- public SearchData setProjectCountByProfileKey(Map<String, Long> projectCountByProfileKey) {
+ SearchData setProjectCountByProfileKey(Map<String, Long> projectCountByProfileKey) {
this.projectCountByProfileKey = copyOf(projectCountByProfileKey);
return this;
}
- public long getActiveRuleCount(String profileKey) {
+ long getActiveRuleCount(String profileKey) {
return firstNonNull(activeRuleCountByProfileKey.get(profileKey), 0L);
}
- public long getProjectCount(String profileKey) {
+ long getProjectCount(String profileKey) {
return firstNonNull(projectCountByProfileKey.get(profileKey), 0L);
}
- public long getActiveDeprecatedRuleCount(String profileKey) {
+ long getActiveDeprecatedRuleCount(String profileKey) {
return firstNonNull(activeDeprecatedRuleCountByProfileKey.get(profileKey), 0L);
}
this.defaultProfileKeys = s.stream().map(QProfileDto::getKee).collect(MoreCollectors.toSet());
return this;
}
+
+ boolean isEditable(QProfileDto profile) {
+ return !profile.isBuiltIn() && (isGlobalQProfileAdmin || editableProfileKeys.contains(profile.getKee()));
+ }
+
+ SearchData setEditableProfileKeys(List<String> editableProfileKeys) {
+ this.editableProfileKeys = new HashSet<>(editableProfileKeys);
+ return this;
+ }
+
+ boolean isGlobalQProfileAdmin() {
+ return isGlobalQProfileAdmin;
+ }
+
+ SearchData setGlobalQProfileAdmin(boolean globalQProfileAdmin) {
+ isGlobalQProfileAdmin = globalQProfileAdmin;
+ return this;
+ }
}
"ruleUpdatedAt": "2016-12-22T19:10:03+0100",
"lastUsed": "2016-12-01T19:10:03+0100",
"actions": {
- "edit": true,
+ "edit": false,
"setAsDefault": false,
"copy": false
}
"ruleUpdatedAt": "2016-12-22T19:10:03+0100",
"userUpdatedAt": "2016-06-29T21:57:01+0200",
"actions": {
- "edit": true,
+ "edit": false,
"setAsDefault": false,
"copy": false
}
"isDefault": true,
"ruleUpdatedAt": "2014-12-22T19:10:03+0100",
"actions": {
- "edit": true,
+ "edit": false,
"setAsDefault": false,
"copy": false
}
}
],
"actions": {
- "create": true
+ "create": false
}
}
public class QProfilesWsTest {
@Rule
- public UserSessionRule userSessionRule = UserSessionRule.standalone();
+ public UserSessionRule userSession = UserSessionRule.standalone();
private WebService.Controller controller;
private String xoo1Key = "xoo1";
private String xoo2Key = "xoo2";
private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.fromUuid("ORG1");
- private QProfileWsSupport wsSupport = new QProfileWsSupport(mock(DbClient.class), userSessionRule, defaultOrganizationProvider);
+ private QProfileWsSupport wsSupport = new QProfileWsSupport(mock(DbClient.class), userSession, defaultOrganizationProvider);
@Before
public void setUp() {
ProfileImporter[] importers = createImporters(languages);
controller = new WsTester(new QProfilesWs(
- new CreateAction(null, null, null, languages, wsSupport, userSessionRule, null, importers),
+ new CreateAction(null, null, null, languages, wsSupport, userSession, null, importers),
new ImportersAction(importers),
- new SearchAction(languages, dbClient, wsSupport, null),
+ new SearchAction(userSession, languages, dbClient, wsSupport, null),
new SetDefaultAction(languages, null, null, wsSupport),
- new ProjectsAction(null, userSessionRule, wsSupport),
+ new ProjectsAction(null, userSession, wsSupport),
new ChangelogAction(null, wsSupport, languages, dbClient),
- new ChangeParentAction(dbClient, null, languages, wsSupport, userSessionRule),
+ new ChangeParentAction(dbClient, null, languages, wsSupport, userSession),
new CompareAction(null, null, languages),
- new DeleteAction(languages, null, null, userSessionRule, wsSupport),
+ new DeleteAction(languages, null, null, userSession, wsSupport),
new ExportersAction(),
new InheritanceAction(null, null, languages),
- new RenameAction(dbClient, userSessionRule, wsSupport))).controller(QProfilesWs.API_ENDPOINT);
+ new RenameAction(dbClient, userSession, wsSupport))).controller(QProfilesWs.API_ENDPOINT);
}
private ProfileImporter[] createImporters(Languages languages) {
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.permission.OrganizationPermission;
import org.sonar.db.qualityprofile.QProfileDto;
import org.sonar.db.qualityprofile.QualityProfileDbTester;
import org.sonar.db.rule.RuleDefinitionDto;
+import org.sonar.db.user.GroupDto;
+import org.sonar.db.user.UserDto;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.organization.DefaultOrganizationProvider;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_DEFAULTS;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_ORGANIZATION;
-import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_QUALITY_PROFILE;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_KEY;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_QUALITY_PROFILE;
public class SearchActionTest {
private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
private QProfileWsSupport qProfileWsSupport = new QProfileWsSupport(dbClient, userSession, defaultOrganizationProvider);
- private SearchAction underTest = new SearchAction(LANGUAGES, dbClient, qProfileWsSupport, new ComponentFinder(dbClient, null));
+ private SearchAction underTest = new SearchAction(userSession, LANGUAGES, dbClient, qProfileWsSupport, new ComponentFinder(dbClient, null));
private WsActionTester ws = new WsActionTester(underTest);
@Test
@Test
public void empty_when_no_language_installed() {
- WsActionTester ws = new WsActionTester(new SearchAction(new Languages(), dbClient, qProfileWsSupport, new ComponentFinder(dbClient, null)));
+ WsActionTester ws = new WsActionTester(new SearchAction(userSession, new Languages(), dbClient, qProfileWsSupport, new ComponentFinder(dbClient, null)));
db.qualityProfiles().insert(db.getDefaultOrganization());
SearchWsResponse result = call(ws.newRequest());
@Test
public void empty_when_filtering_on_project_and_no_language_installed() {
- WsActionTester ws = new WsActionTester(new SearchAction(new Languages(), dbClient, qProfileWsSupport, new ComponentFinder(dbClient, null)));
+ WsActionTester ws = new WsActionTester(new SearchAction(userSession, new Languages(), dbClient, qProfileWsSupport, new ComponentFinder(dbClient, null)));
db.qualityProfiles().insert(db.getDefaultOrganization());
ComponentDto project = db.components().insertPrivateProject();
QProfileDto profileOnXoo1 = db.qualityProfiles().insert(db.getDefaultOrganization(), q -> q.setLanguage(XOO1.getKey()));
assertThat(result.getProfilesList()).isEmpty();
}
+ @Test
+ public void actions_when_user_is_global_qprofile_administer() {
+ 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));
+ 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())
+ .containsExactlyInAnyOrder(
+ tuple(customProfile.getKee(), true, true, true),
+ tuple(builtInProfile.getKee(), false, true, true));
+ assertThat(result.getActions().getCreate()).isTrue();
+ }
+
+ @Test
+ public void actions_when_user_can_edit_profile() {
+ OrganizationDto organization = db.organizations().insert();
+ QProfileDto profile1 = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO1.getKey()));
+ QProfileDto profile2 = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO2.getKey()));
+ QProfileDto profile3 = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO2.getKey()));
+ QProfileDto builtInProfile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO2.getKey()).setIsBuiltIn(true));
+ UserDto user = db.users().insertUser();
+ GroupDto group = db.users().insertGroup(organization);
+ db.qualityProfiles().addUserPermission(profile1, user);
+ db.qualityProfiles().addGroupPermission(profile3, group);
+ userSession.logIn(user).setGroups(group);
+
+ 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(profile1.getKee(), true, false, false),
+ tuple(profile2.getKee(), false, false, false),
+ tuple(profile3.getKee(), true, false, false),
+ tuple(builtInProfile.getKee(), false, false, false));
+ assertThat(result.getActions().getCreate()).isFalse();
+ }
+
+ @Test
+ public void actions_when_not_logged_in() {
+ OrganizationDto organization = db.organizations().insert();
+ QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO1.getKey()));
+ userSession.anonymous();
+
+ 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.getActions().getCreate()).isFalse();
+ }
+
@Test
public void fail_if_project_does_not_exist() {
expectedException.expect(NotFoundException.class);
@Test
public void json_example() {
+ OrganizationDto organization = db.organizations().insertForKey("My Organization");
// languages
Language cs = newLanguage("cs", "C#");
Language java = newLanguage("java", "Java");
Language python = newLanguage("py", "Python");
// profiles
- QProfileDto sonarWayCs = db.qualityProfiles().insert(db.getDefaultOrganization(),
+ QProfileDto sonarWayCs = db.qualityProfiles().insert(organization,
p -> p.setName("Sonar way").setKee("AU-TpxcA-iU5OvuD2FL3").setIsBuiltIn(true).setLanguage(cs.getKey()));
- QProfileDto myCompanyProfile = db.qualityProfiles().insert(db.getDefaultOrganization(),
+ QProfileDto myCompanyProfile = db.qualityProfiles().insert(organization,
p -> p.setName("My Company Profile").setKee("iU5OvuD2FLz").setLanguage(java.getKey()));
- QProfileDto myBuProfile = db.qualityProfiles().insert(db.getDefaultOrganization(),
+ QProfileDto myBuProfile = db.qualityProfiles().insert(organization,
p -> p.setName("My BU Profile").setKee("AU-TpxcA-iU5OvuD2FL1").setParentKee(myCompanyProfile.getKee()).setLanguage(java.getKey()));
- QProfileDto sonarWayPython = db.qualityProfiles().insert(db.getDefaultOrganization(),
+ QProfileDto sonarWayPython = db.qualityProfiles().insert(organization,
p -> p.setName("Sonar way").setKee("AU-TpxcB-iU5OvuD2FL7").setIsBuiltIn(true).setLanguage(python.getKey()));
db.qualityProfiles().setAsDefault(sonarWayCs, myCompanyProfile, sonarWayPython);
// rules
.forEach(rule -> db.qualityProfiles().activateRule(sonarWayCs, rule));
// project
range(0, 7)
- .mapToObj(i -> db.components().insertPrivateProject())
+ .mapToObj(i -> db.components().insertPrivateProject(organization))
.forEach(project -> db.qualityProfiles().associateWithProject(project, myBuProfile));
+ // User
+ UserDto user = db.users().insertUser();
+ db.qualityProfiles().addUserPermission(sonarWayCs, user);
+ db.qualityProfiles().addUserPermission(myBuProfile, user);
+ userSession.logIn(user);
- underTest = new SearchAction(new Languages(cs, java, python), dbClient, qProfileWsSupport, new ComponentFinder(dbClient, null));
+ underTest = new SearchAction(userSession, new Languages(cs, java, python), dbClient, qProfileWsSupport, new ComponentFinder(dbClient, null));
ws = new WsActionTester(underTest);
- String result = ws.newRequest().execute().getInput();
+ String result = ws.newRequest().setParam(PARAM_ORGANIZATION, organization.getKey()).execute().getInput();
assertJson(result).ignoreFields("ruleUpdatedAt", "lastUsed", "userUpdatedAt")
.isSimilarTo(ws.getDef().responseExampleAsString());
}
optional string organization = 15;
optional bool isBuiltIn = 16;
optional Actions actions = 17;
+
+ message Actions {
+ optional bool edit = 1;
+ optional bool setAsDefault = 2;
+ optional bool copy = 3;
+ }
}
message Actions {
optional bool create = 1;
- optional bool edit = 2;
- optional bool setAsDefault = 3;
- optional bool copy = 4;
}
}
import org.sonarqube.tests.Tester;
import org.sonarqube.ws.Common;
import org.sonarqube.ws.Organizations.Organization;
+import org.sonarqube.ws.QualityProfiles;
import org.sonarqube.ws.QualityProfiles.CreateWsResponse;
import org.sonarqube.ws.QualityProfiles.SearchGroupsResponse;
import org.sonarqube.ws.QualityProfiles.SearchUsersResponse;
import org.sonarqube.ws.WsUserGroups;
import org.sonarqube.ws.WsUsers;
+import org.sonarqube.ws.client.permission.AddUserWsRequest;
import org.sonarqube.ws.client.qualityprofile.AddGroupRequest;
import org.sonarqube.ws.client.qualityprofile.AddUserRequest;
import org.sonarqube.ws.client.qualityprofile.RemoveGroupRequest;
import org.sonarqube.ws.client.qualityprofile.RemoveUserRequest;
import org.sonarqube.ws.client.qualityprofile.SearchGroupsRequest;
import org.sonarqube.ws.client.qualityprofile.SearchUsersRequest;
+import org.sonarqube.ws.client.qualityprofile.SearchWsRequest;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
WsUsers.CreateWsResponse.User user1 = tester.users().generateMember(organization, u -> u.setEmail("user1@email.com"));
WsUsers.CreateWsResponse.User user2 = tester.users().generateMember(organization, u -> u.setEmail("user2@email.com"));
CreateWsResponse.QualityProfile xooProfile = tester.qProfiles().createXooProfile(organization);
- tester.qProfiles().service().addUser(AddUserRequest.builder()
- .setOrganization(organization.getKey())
- .setQualityProfile(xooProfile.getName())
- .setLanguage(xooProfile.getLanguage())
- .setUserLogin(user1.getLogin())
- .build());
+ addUserPermission(organization, user1, xooProfile);
SearchUsersResponse users = tester.qProfiles().service().searchUsers(SearchUsersRequest.builder()
.setOrganization(organization.getKey())
.isEmpty();
// Add user 1
- tester.qProfiles().service().addUser(AddUserRequest.builder()
- .setOrganization(organization.getKey())
- .setQualityProfile(xooProfile.getName())
- .setLanguage(xooProfile.getLanguage())
- .setUserLogin(user1.getLogin())
- .build());
+ addUserPermission(organization, user1, xooProfile);
assertThat(tester.qProfiles().service().searchUsers(SearchUsersRequest.builder()
.setOrganization(organization.getKey())
.setQualityProfile(xooProfile.getName())
WsUserGroups.Group group2 = tester.groups().generate(organization);
WsUserGroups.Group group3 = tester.groups().generate(organization);
CreateWsResponse.QualityProfile xooProfile = tester.qProfiles().createXooProfile(organization);
- tester.qProfiles().service().addGroup(AddGroupRequest.builder()
- .setOrganization(organization.getKey())
- .setQualityProfile(xooProfile.getName())
- .setLanguage(xooProfile.getLanguage())
- .setGroup(group1.getName())
- .build());
- tester.qProfiles().service().addGroup(AddGroupRequest.builder()
- .setOrganization(organization.getKey())
- .setQualityProfile(xooProfile.getName())
- .setLanguage(xooProfile.getLanguage())
- .setGroup(group2.getName())
- .build());
+ addGroupPermission(organization, group1, xooProfile);
+ addGroupPermission(organization, group2, xooProfile);
SearchGroupsResponse groups = tester.qProfiles().service().searchGroups(SearchGroupsRequest.builder()
.setOrganization(organization.getKey())
.extracting(Group::getName)
.isEmpty();
- // Add user 1
- tester.qProfiles().service().addGroup(AddGroupRequest.builder()
- .setOrganization(organization.getKey())
- .setQualityProfile(xooProfile.getName())
- .setLanguage(xooProfile.getLanguage())
- .setGroup(group1.getName())
- .build());
+ // Add group 1
+ addGroupPermission(organization, group1, xooProfile);
assertThat(tester.qProfiles().service().searchGroups(SearchGroupsRequest.builder()
.setOrganization(organization.getKey())
.setQualityProfile(xooProfile.getName())
.extracting(Group::getName)
.containsExactlyInAnyOrder(group1.getName());
- // Remove user 1
+ // Remove group 1
tester.qProfiles().service().removeGroup(RemoveGroupRequest.builder()
.setOrganization(organization.getKey())
.setQualityProfile(xooProfile.getName())
.extracting(Group::getName)
.isEmpty();
}
+
+ @Test
+ public void actions_when_user_can_edit_profiles() {
+ Organization organization = tester.organizations().generate();
+ WsUsers.CreateWsResponse.User user = tester.users().generateMember(organization);
+ CreateWsResponse.QualityProfile xooProfile1 = tester.qProfiles().createXooProfile(organization);
+ addUserPermission(organization, user, xooProfile1);
+ CreateWsResponse.QualityProfile xooProfile2 = tester.qProfiles().createXooProfile(organization);
+ WsUserGroups.Group group = tester.groups().generate(organization);
+ tester.groups().addMemberToGroups(organization, user.getLogin(), group.getName());
+ addGroupPermission(organization, group, xooProfile2);
+ CreateWsResponse.QualityProfile xooProfile3 = tester.qProfiles().createXooProfile(organization);
+
+ QualityProfiles.SearchWsResponse result = tester.as(user.getLogin())
+ .qProfiles().service().search(new SearchWsRequest().setOrganizationKey(organization.getKey()));
+ assertThat(result.getActions().getCreate()).isFalse();
+ assertThat(result.getProfilesList())
+ .extracting(QualityProfiles.SearchWsResponse.QualityProfile::getKey, qp -> qp.getActions().getEdit(), qp -> qp.getActions().getCopy(), qp -> qp.getActions().getSetAsDefault())
+ .contains(
+ tuple(xooProfile1.getKey(), true, false, false),
+ tuple(xooProfile2.getKey(), true, false, false),
+ tuple(xooProfile3.getKey(), false, false, false));
+ }
+
+ @Test
+ public void actions_when_user_is_global_qprofile_administer() {
+ Organization organization = tester.organizations().generate();
+ WsUsers.CreateWsResponse.User user = tester.users().generateMember(organization);
+ CreateWsResponse.QualityProfile xooProfile = tester.qProfiles().createXooProfile(organization);
+ tester.wsClient().permissions().addUser(new AddUserWsRequest().setOrganization(organization.getKey()).setLogin(user.getLogin()).setPermission("profileadmin"));
+
+ QualityProfiles.SearchWsResponse result = tester.as(user.getLogin())
+ .qProfiles().service().search(new SearchWsRequest().setOrganizationKey(organization.getKey()));
+ assertThat(result.getActions().getCreate()).isTrue();
+ assertThat(result.getProfilesList())
+ .extracting(QualityProfiles.SearchWsResponse.QualityProfile::getKey, qp -> qp.getActions().getEdit(), qp -> qp.getActions().getCopy(), qp -> qp.getActions().getSetAsDefault())
+ .contains(
+ tuple(xooProfile.getKey(), true, true, true));
+ }
+
+ private void addUserPermission(Organization organization, WsUsers.CreateWsResponse.User user, CreateWsResponse.QualityProfile qProfile){
+ tester.qProfiles().service().addUser(AddUserRequest.builder()
+ .setOrganization(organization.getKey())
+ .setQualityProfile(qProfile.getName())
+ .setLanguage(qProfile.getLanguage())
+ .setUserLogin(user.getLogin())
+ .build());
+ }
+
+ private void addGroupPermission(Organization organization, WsUserGroups.Group group, CreateWsResponse.QualityProfile qProfile){
+ tester.qProfiles().service().addGroup(AddGroupRequest.builder()
+ .setOrganization(organization.getKey())
+ .setQualityProfile(qProfile.getName())
+ .setLanguage(qProfile.getLanguage())
+ .setGroup(group.getName())
+ .build());
+ }
}