picoContainer.getComponentAdapters().stream()
.map(ComponentAdapter::getComponentImplementation)
.collect(Collectors.toList())).contains((Class) StartableHazelcastMember.class,
- (Class) CeDistributedInformationImpl.class);
+ (Class) CeDistributedInformationImpl.class);
underTest.stop();
}
+ 4 // content of ReportAnalysisFailureNotificationModule
+ 3 // CeCleaningModule + its content
+ 1 // CeDistributedInformation
- );
+ );
assertThat(picoContainer.getParent().getComponentAdapters()).hasSize(
CONTAINER_ITSELF
+ 5 // level 3
assertThat(picoContainer.getParent().getParent().getParent().getComponentAdapters()).hasSize(
COMPONENTS_IN_LEVEL_1_AT_CONSTRUCTION
+ 26 // level 1
- + 49 // content of DaoModule
+ + 50 // content of DaoModule
+ 3 // content of EsSearchModule
+ 65 // content of CorePropertyDefinitions
+ 1 // StopFlagContainer
picoContainer.getComponentAdapters().stream()
.map(ComponentAdapter::getComponentImplementation)
.collect(Collectors.toList())).doesNotContain((Class) StartableHazelcastMember.class,
- (Class) CeDistributedInformationImpl.class).contains(
- (Class) StandaloneCeDistributedInformation.class);
+ (Class) CeDistributedInformationImpl.class).contains(
+ (Class) StandaloneCeDistributedInformation.class);
assertThat(picoContainer.getParent().getParent().getParent().getParent()).isNull();
underTest.stop();
"project_qprofiles",
"properties",
"qprofile_changes",
+ "qprofile_edit_users",
"quality_gates",
"quality_gate_conditions",
"rules",
import org.sonar.db.qualityprofile.ActiveRuleDao;
import org.sonar.db.qualityprofile.DefaultQProfileDao;
import org.sonar.db.qualityprofile.QProfileChangeDao;
+import org.sonar.db.qualityprofile.QProfileEditUsersDao;
import org.sonar.db.qualityprofile.QualityProfileDao;
import org.sonar.db.rule.RuleDao;
import org.sonar.db.rule.RuleRepositoryDao;
PropertiesDao.class,
PurgeDao.class,
QProfileChangeDao.class,
+ QProfileEditUsersDao.class,
QualityGateConditionDao.class,
QualityGateDao.class,
QualityProfileDao.class,
import org.sonar.db.qualityprofile.ActiveRuleDao;
import org.sonar.db.qualityprofile.DefaultQProfileDao;
import org.sonar.db.qualityprofile.QProfileChangeDao;
+import org.sonar.db.qualityprofile.QProfileEditUsersDao;
import org.sonar.db.qualityprofile.QualityProfileDao;
import org.sonar.db.rule.RuleDao;
import org.sonar.db.rule.RuleRepositoryDao;
private final EsQueueDao esQueueDao;
private final PluginDao pluginDao;
private final BranchDao branchDao;
+ private final QProfileEditUsersDao qProfileEditUsersDao;
public DbClient(Database database, MyBatis myBatis, DBSessions dbSessions, Dao... daos) {
this.database = database;
esQueueDao = getDao(map, EsQueueDao.class);
pluginDao = getDao(map, PluginDao.class);
branchDao = getDao(map, BranchDao.class);
+ qProfileEditUsersDao = getDao(map, QProfileEditUsersDao.class);
}
public DbSession openSession(boolean batch) {
return branchDao;
}
+ public QProfileEditUsersDao qProfileEditUsersDao() {
+ return qProfileEditUsersDao;
+ }
+
protected <K extends Dao> K getDao(Map<Class, Dao> map, Class<K> clazz) {
return (K) map.get(clazz);
}
import org.sonar.db.qualityprofile.ActiveRuleParamDto;
import org.sonar.db.qualityprofile.DefaultQProfileMapper;
import org.sonar.db.qualityprofile.QProfileChangeMapper;
+import org.sonar.db.qualityprofile.QProfileEditUsersMapper;
import org.sonar.db.qualityprofile.QualityProfileMapper;
import org.sonar.db.rule.RuleDto;
import org.sonar.db.rule.RuleMapper;
PropertiesMapper.class,
PurgeMapper.class,
QProfileChangeMapper.class,
+ QProfileEditUsersMapper.class,
QualityGateConditionMapper.class,
QualityGateMapper.class,
QualityProfileMapper.class,
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.db.qualityprofile;
+
+import org.sonar.api.utils.System2;
+import org.sonar.db.Dao;
+import org.sonar.db.DbSession;
+import org.sonar.db.user.UserDto;
+
+public class QProfileEditUsersDao implements Dao {
+
+ private final System2 system2;
+
+ public QProfileEditUsersDao(System2 system2) {
+ this.system2 = system2;
+ }
+
+ public boolean exists(DbSession dbSession, QProfileDto profile, UserDto user) {
+ return mapper(dbSession).selectByQProfileAndUser(profile.getKee(), user.getId()) != null;
+ }
+
+ public void insert(DbSession dbSession, QProfileEditUsersDto dto) {
+ mapper(dbSession).insert(dto, system2.now());
+ }
+
+ private static QProfileEditUsersMapper mapper(DbSession dbSession) {
+ return dbSession.getMapper(QProfileEditUsersMapper.class);
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.db.qualityprofile;
+
+public class QProfileEditUsersDto {
+
+ private String uuid;
+ private int userId;
+ private String qProfileUuid;
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public QProfileEditUsersDto setUuid(String uuid) {
+ this.uuid = uuid;
+ return this;
+ }
+
+ public int getUserId() {
+ return userId;
+ }
+
+ public QProfileEditUsersDto setUserId(int userId) {
+ this.userId = userId;
+ return this;
+ }
+
+ public String getQProfileUuid() {
+ return qProfileUuid;
+ }
+
+ public QProfileEditUsersDto setQProfileUuid(String qProfileUuid) {
+ this.qProfileUuid = qProfileUuid;
+ return this;
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.db.qualityprofile;
+
+import org.apache.ibatis.annotations.Param;
+
+public interface QProfileEditUsersMapper {
+
+ QProfileEditUsersDto selectByQProfileAndUser(@Param("qProfileUuid") String qProfileUuid, @Param("userId") int userId);
+
+ void insert(@Param("dto") QProfileEditUsersDto dto, @Param("now") long now);
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd">
+
+<mapper namespace="org.sonar.db.qualityprofile.QProfileEditUsersMapper">
+
+ <sql id="sqlColumns">
+ qeu.uuid as "uuid",
+ qeu.user_id as "userId",
+ qeu.qprofile_uuid as "qProfileUuid"
+ </sql>
+
+ <select id="selectByQProfileAndUser" parameterType="map" resultType="org.sonar.db.qualityprofile.QProfileEditUsersDto">
+ select
+ <include refid="sqlColumns"/>
+ from qprofile_edit_users qeu
+ where
+ qeu.user_id = #{userId, jdbcType=INTEGER}
+ and qeu.qprofile_uuid = #{qProfileUuid, jdbcType=VARCHAR}
+ </select>
+
+ <insert id="insert" useGeneratedKeys="false" parameterType="map">
+ insert into qprofile_edit_users(
+ uuid,
+ user_id,
+ qprofile_uuid,
+ created_at,
+ ) values (
+ #{dto.uuid, jdbcType=VARCHAR},
+ #{dto.userId, jdbcType=INTEGER},
+ #{dto.qProfileUuid, jdbcType=VARCHAR},
+ #{now, jdbcType=BIGINT}
+ )
+ </insert>
+
+</mapper>
+
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new DaoModule().configure(container);
- assertThat(container.size()).isEqualTo(2 + 49);
+ assertThat(container.size()).isEqualTo(2 + 50);
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.db.qualityprofile;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.db.DbTester;
+import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.user.UserDto;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.entry;
+
+public class QProfileEditUsersDaoTest {
+
+ private static final long NOW = 10_000_000_000L;
+
+ private System2 system2 = new TestSystem2().setNow(NOW);
+
+ @Rule
+ public DbTester db = DbTester.create(system2);
+
+ private QProfileEditUsersDao underTest = db.getDbClient().qProfileEditUsersDao();
+
+ @Test
+ public void exists() {
+ OrganizationDto organization = db.organizations().insert();
+ QProfileDto profile = db.qualityProfiles().insert(organization);
+ QProfileDto anotherProfile = db.qualityProfiles().insert(organization);
+ UserDto user = db.users().insertUser();
+ UserDto anotherUser = db.users().insertUser();
+ db.qualityProfiles().addUserPermission(profile, user);
+
+ assertThat(underTest.exists(db.getSession(), profile, user)).isTrue();
+ assertThat(underTest.exists(db.getSession(), profile, anotherUser)).isFalse();
+ assertThat(underTest.exists(db.getSession(), anotherProfile, user)).isFalse();
+ assertThat(underTest.exists(db.getSession(), anotherProfile, anotherUser)).isFalse();
+ }
+
+ @Test
+ public void insert() {
+ underTest.insert(db.getSession(), new QProfileEditUsersDto()
+ .setUuid("ABCD")
+ .setUserId(100)
+ .setQProfileUuid("QPROFILE")
+ );
+
+ assertThat(db.selectFirst(db.getSession(), "select uuid as \"uuid\", user_id as \"userId\", qprofile_uuid as \"qProfileUuid\", created_at as \"createdAt\" from qprofile_edit_users")).contains(
+ entry("uuid", "ABCD"),
+ entry("userId", 100L),
+ entry("qProfileUuid", "QPROFILE"),
+ entry("createdAt", NOW));
+ }
+
+}
import java.util.Optional;
import java.util.function.Consumer;
import org.sonar.api.rule.Severity;
+import org.sonar.core.util.UuidFactoryFast;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.rule.RuleDefinitionDto;
+import org.sonar.db.user.UserDto;
import static org.apache.commons.lang.math.RandomUtils.nextInt;
import static org.apache.commons.lang.math.RandomUtils.nextLong;
dbSession.commit();
return this;
}
+
+ public void addUserPermission(QProfileDto profile, UserDto user){
+ dbClient.qProfileEditUsersDao().insert(dbSession, new QProfileEditUsersDto()
+ .setUuid(UuidFactoryFast.getInstance().create())
+ .setUserId(user.getId())
+ .setQProfileUuid(profile.getKee())
+ );
+ dbSession.commit();
+
+ }
}
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.qualityprofile.QProfileDto;
+import org.sonar.db.qualityprofile.QProfileEditUsersDto;
+import org.sonar.db.user.UserDto;
import static org.sonar.core.util.stream.MoreCollectors.toSet;
import static org.sonar.server.qualityprofile.ws.QProfileWsSupport.createOrganizationParam;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_ADD_USER;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LOGIN;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_ORGANIZATION;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_QUALITY_PROFILE;
public class AddUserAction implements QProfileWsAction {
+ private final DbClient dbClient;
+ private final UuidFactory uuidFactory;
+ private final QProfileWsSupport wsSupport;
private final Languages languages;
- public AddUserAction(Languages languages) {
+ public AddUserAction(DbClient dbClient, UuidFactory uuidFactory, QProfileWsSupport wsSupport, Languages languages) {
+ this.dbClient = dbClient;
+ this.uuidFactory = uuidFactory;
+ this.wsSupport = wsSupport;
this.languages = languages;
}
@Override
public void handle(Request request, Response response) throws Exception {
- // TODO
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ OrganizationDto organization = wsSupport.getOrganizationByKey(dbSession, request.param(PARAM_ORGANIZATION));
+ QProfileDto profile = wsSupport.getProfile(dbSession, organization, request.mandatoryParam(PARAM_QUALITY_PROFILE), request.mandatoryParam(PARAM_LANGUAGE));
+ wsSupport.checkCanEdit(dbSession, profile);
+ UserDto user = wsSupport.getUser(dbSession, organization, request.mandatoryParam(PARAM_LOGIN));
+ addUser(dbSession, profile, user);
+ }
+ response.noContent();
}
+
+ private void addUser(DbSession dbSession, QProfileDto profile, UserDto user) {
+ if (dbClient.qProfileEditUsersDao().exists(dbSession, profile, user)) {
+ return;
+ }
+ dbClient.qProfileEditUsersDao().insert(dbSession,
+ new QProfileEditUsersDto()
+ .setUuid(uuidFactory.create())
+ .setUserId(user.getId())
+ .setQProfileUuid(profile.getKee()));
+ dbSession.commit();
+ }
+
}
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.permission.OrganizationPermission;
import org.sonar.db.qualityprofile.QProfileDto;
+import org.sonar.db.user.UserDto;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.user.UserSession;
import org.sonar.server.ws.WsUtils;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
+import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
import static org.sonar.server.ws.WsUtils.checkFound;
import static org.sonar.server.ws.WsUtils.checkRequest;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_ORGANIZATION;
return profile;
}
- public void checkPermission(DbSession dbSession, QProfileDto rulesProfile) {
- OrganizationDto organization = getOrganization(dbSession, rulesProfile);
+ public QProfileDto getProfile(DbSession dbSession, OrganizationDto organization, String name, String language) {
+ QProfileDto profile = dbClient.qualityProfileDao().selectByNameAndLanguage(dbSession, organization, name, language);
+ checkFound(profile, "Quality Profile for language '%s' and name '%s' does not exist in organization '%s'", language, name, organization.getKey());
+ return profile;
+ }
+
+ public UserDto getUser(DbSession dbSession, OrganizationDto organization, String login) {
+ UserDto user = dbClient.userDao().selectActiveUserByLogin(dbSession, login);
+ checkFound(user, "User with login '%s' is not found'", login);
+ checkMembership(dbSession, organization, user);
+ return user;
+ }
+
+ public void checkPermission(DbSession dbSession, QProfileDto profile) {
+ OrganizationDto organization = getOrganization(dbSession, profile);
userSession.checkPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization);
}
+ public void checkCanEdit(DbSession dbSession, QProfileDto profile) {
+ checkNotBuiltInt(profile);
+ OrganizationDto organization = getOrganization(dbSession, profile);
+ userSession.checkLoggedIn();
+ if (userSession.hasPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization)) {
+ return;
+ }
+ UserDto user = dbClient.userDao().selectByLogin(dbSession, userSession.getLogin());
+ checkState(user != null, "User from session does not exist");
+ if (dbClient.qProfileEditUsersDao().exists(dbSession, profile, user)) {
+ return;
+ }
+ throw insufficientPrivilegesException();
+ }
+
public void checkNotBuiltInt(QProfileDto profile) {
checkRequest(!profile.isBuiltIn(), "Operation forbidden for built-in Quality Profile '%s' with language '%s'", profile.getName(), profile.getLanguage());
}
+
+ public void checkMembership(DbSession dbSession, OrganizationDto organization, UserDto user) {
+ checkArgument(dbClient.organizationMemberDao().select(dbSession, organization.getUuid(), user.getId()).isPresent(),
+ "User '%s' is not member of organization '%s'", user.getLogin(), organization.getKey());
+ }
+
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.core.util.UuidFactoryFast;
+import org.sonar.db.DbTester;
+import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.permission.OrganizationPermission;
+import org.sonar.db.qualityprofile.QProfileDto;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.language.LanguageTesting;
+import org.sonar.server.organization.TestDefaultOrganizationProvider;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestResponse;
+import org.sonar.server.ws.WsActionTester;
+
+import static java.lang.String.format;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LOGIN;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_ORGANIZATION;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_QUALITY_PROFILE;
+
+public class AddUserActionTest {
+
+ private static final String XOO = "xoo";
+ private static final Languages LANGUAGES = LanguageTesting.newLanguages(XOO);
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+ @Rule
+ public DbTester db = DbTester.create();
+
+ private QProfileWsSupport wsSupport = new QProfileWsSupport(db.getDbClient(), userSession, TestDefaultOrganizationProvider.from(db));
+ private UuidFactory uuidFactory = UuidFactoryFast.getInstance();
+
+ private WsActionTester ws = new WsActionTester(new AddUserAction(db.getDbClient(), uuidFactory, wsSupport, LANGUAGES));
+
+ @Test
+ public void test_definition() {
+ WebService.Action def = ws.getDef();
+ assertThat(def.key()).isEqualTo("add_user");
+ assertThat(def.isPost()).isTrue();
+ assertThat(def.isInternal()).isTrue();
+ assertThat(def.params()).extracting(WebService.Param::key).containsExactlyInAnyOrder("organization", "qualityProfile", "language", "login");
+ }
+
+ @Test
+ public void add_user() {
+ OrganizationDto organization = db.organizations().insert();
+ QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO));
+ UserDto user = db.users().insertUser();
+ db.organizations().addMember(organization, user);
+ userSession.logIn().addPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization);
+
+ TestResponse response = ws.newRequest()
+ .setParam(PARAM_QUALITY_PROFILE, profile.getName())
+ .setParam(PARAM_LANGUAGE, XOO)
+ .setParam(PARAM_LOGIN, user.getLogin())
+ .setParam(PARAM_ORGANIZATION, organization.getKey())
+ .execute();
+
+ assertThat(response.getStatus()).isEqualTo(204);
+ assertThat(db.getDbClient().qProfileEditUsersDao().exists(db.getSession(), profile, user)).isTrue();
+ }
+
+ @Test
+ public void does_nothing_when_user_can_already_edit_profile() {
+ OrganizationDto organization = db.organizations().insert();
+ QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO));
+ UserDto user = db.users().insertUser();
+ db.organizations().addMember(organization, user);
+ db.qualityProfiles().addUserPermission(profile, user);
+ assertThat(db.getDbClient().qProfileEditUsersDao().exists(db.getSession(), profile, user)).isTrue();
+ userSession.logIn().addPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization);
+
+ ws.newRequest()
+ .setParam(PARAM_QUALITY_PROFILE, profile.getName())
+ .setParam(PARAM_LANGUAGE, XOO)
+ .setParam(PARAM_LOGIN, user.getLogin())
+ .setParam(PARAM_ORGANIZATION, organization.getKey())
+ .execute();
+
+ assertThat(db.getDbClient().qProfileEditUsersDao().exists(db.getSession(), profile, user)).isTrue();
+ }
+
+ @Test
+ public void qp_administers_can_add_user() {
+ OrganizationDto organization = db.organizations().insert();
+ QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO));
+ UserDto user = db.users().insertUser();
+ db.organizations().addMember(organization, user);
+ userSession.logIn().addPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization);
+
+ ws.newRequest()
+ .setParam(PARAM_QUALITY_PROFILE, profile.getName())
+ .setParam(PARAM_LANGUAGE, XOO)
+ .setParam(PARAM_LOGIN, user.getLogin())
+ .setParam(PARAM_ORGANIZATION, organization.getKey())
+ .execute();
+
+ assertThat(db.getDbClient().qProfileEditUsersDao().exists(db.getSession(), profile, user)).isTrue();
+ }
+
+ @Test
+ public void qp_editors_can_add_user() {
+ OrganizationDto organization = db.organizations().insert();
+ QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO));
+ UserDto user = db.users().insertUser();
+ db.organizations().addMember(organization, user);
+ UserDto userAllowedToEditProfile = db.users().insertUser();
+ db.qualityProfiles().addUserPermission(profile, userAllowedToEditProfile);
+ userSession.logIn(userAllowedToEditProfile);
+
+ ws.newRequest()
+ .setParam(PARAM_QUALITY_PROFILE, profile.getName())
+ .setParam(PARAM_LANGUAGE, XOO)
+ .setParam(PARAM_LOGIN, user.getLogin())
+ .setParam(PARAM_ORGANIZATION, organization.getKey())
+ .execute();
+
+ assertThat(db.getDbClient().qProfileEditUsersDao().exists(db.getSession(), profile, user)).isTrue();
+ }
+
+ @Test
+ public void uses_default_organization_when_no_organization() {
+ OrganizationDto organization = db.getDefaultOrganization();
+ QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO));
+ UserDto user = db.users().insertUser();
+ db.organizations().addMember(organization, user);
+ userSession.logIn().addPermission(ADMINISTER_QUALITY_PROFILES, organization);
+
+ ws.newRequest()
+ .setParam(PARAM_QUALITY_PROFILE, profile.getName())
+ .setParam(PARAM_LANGUAGE, XOO)
+ .setParam(PARAM_LOGIN, user.getLogin() )
+ .execute();
+
+ assertThat(db.getDbClient().qProfileEditUsersDao().exists(db.getSession(), profile, user)).isTrue();
+ }
+
+ @Test
+ public void fail_when_user_does_not_exist() {
+ OrganizationDto organization = db.organizations().insert();
+ QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO));
+ userSession.logIn().addPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization);
+
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("User with login 'unknown' is not found");
+
+ ws.newRequest()
+ .setParam(PARAM_QUALITY_PROFILE, profile.getName())
+ .setParam(PARAM_LANGUAGE, XOO)
+ .setParam(PARAM_LOGIN, "unknown")
+ .setParam(PARAM_ORGANIZATION, organization.getKey())
+ .execute();
+ }
+
+ @Test
+ public void fail_when_qprofile_does_not_exist() {
+ OrganizationDto organization = db.organizations().insert();
+ UserDto user = db.users().insertUser();
+ db.organizations().addMember(organization, user);
+ userSession.logIn().addPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization);
+
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage(format("Quality Profile for language 'xoo' and name 'unknown' does not exist in organization '%s'", organization.getKey()));
+
+ ws.newRequest()
+ .setParam(PARAM_QUALITY_PROFILE, "unknown")
+ .setParam(PARAM_LANGUAGE, XOO)
+ .setParam(PARAM_LOGIN, user.getLogin())
+ .setParam(PARAM_ORGANIZATION, organization.getKey())
+ .execute();
+ }
+
+ @Test
+ public void fail_when_qprofile_does_not_belong_to_organization() {
+ OrganizationDto organization = db.organizations().insert();
+ UserDto user = db.users().insertUser();
+ db.organizations().addMember(organization, user);
+ OrganizationDto anotherOrganization = db.organizations().insert();
+ QProfileDto profile = db.qualityProfiles().insert(anotherOrganization, p -> p.setLanguage(XOO));
+ userSession.logIn().addPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization);
+
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage(format("Quality Profile for language 'xoo' and name '%s' does not exist in organization '%s'", profile.getName(), organization.getKey()));
+
+ ws.newRequest()
+ .setParam(PARAM_QUALITY_PROFILE, profile.getName())
+ .setParam(PARAM_LANGUAGE, XOO)
+ .setParam(PARAM_LOGIN, user.getLogin())
+ .setParam(PARAM_ORGANIZATION, organization.getKey())
+ .execute();
+ }
+
+ @Test
+ public void fail_when_wrong_language() {
+ OrganizationDto organization = db.organizations().insert();
+ QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage("unknown"));
+ UserDto user = db.users().insertUser();
+ db.organizations().addMember(organization, user);
+ userSession.logIn().addPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization);
+
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage(format("Quality Profile for language 'xoo' and name '%s' does not exist in organization '%s'", profile.getName(), organization.getKey()));
+
+ ws.newRequest()
+ .setParam(PARAM_QUALITY_PROFILE, profile.getName())
+ .setParam(PARAM_LANGUAGE, XOO)
+ .setParam(PARAM_LOGIN, user.getLogin())
+ .setParam(PARAM_ORGANIZATION, organization.getKey())
+ .execute();
+ }
+
+ @Test
+ public void fail_when_user_is_not_member_of_organization() {
+ OrganizationDto organization = db.organizations().insert();
+ OrganizationDto anotherOrganization = db.organizations().insert();
+ UserDto user = db.users().insertUser();
+ db.organizations().addMember(anotherOrganization, user);
+ QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO));
+ userSession.logIn().addPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization);
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage(format("User '%s' is not member of organization '%s'", user.getLogin(), organization.getKey()));
+
+ ws.newRequest()
+ .setParam(PARAM_QUALITY_PROFILE, profile.getName())
+ .setParam(PARAM_LANGUAGE, XOO)
+ .setParam(PARAM_LOGIN, user.getLogin())
+ .setParam(PARAM_ORGANIZATION, organization.getKey())
+ .execute();
+ }
+
+ @Test
+ public void fail_when_qp_is_built_in() {
+ OrganizationDto organization = db.organizations().insert();
+ UserDto user = db.users().insertUser();
+ db.organizations().addMember(organization, user);
+ QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO).setIsBuiltIn(true));
+ userSession.logIn().addPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization);
+
+ expectedException.expect(BadRequestException.class);
+ expectedException.expectMessage(String.format("Operation forbidden for built-in Quality Profile '%s' with language 'xoo'", profile.getName()));
+
+ ws.newRequest()
+ .setParam(PARAM_QUALITY_PROFILE, profile.getName())
+ .setParam(PARAM_LANGUAGE, XOO)
+ .setParam(PARAM_LOGIN, user.getLogin())
+ .setParam(PARAM_ORGANIZATION, organization.getKey())
+ .execute();
+ }
+
+ @Test
+ public void fail_when_not_enough_permission() {
+ OrganizationDto organization = db.organizations().insert();
+ QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO));
+ UserDto user = db.users().insertUser();
+ db.organizations().addMember(organization, user);
+ userSession.logIn(db.users().insertUser()).addPermission(OrganizationPermission.ADMINISTER_QUALITY_GATES, organization);
+
+ expectedException.expect(ForbiddenException.class);
+
+ ws.newRequest()
+ .setParam(PARAM_QUALITY_PROFILE, profile.getName())
+ .setParam(PARAM_LANGUAGE, XOO)
+ .setParam(PARAM_LOGIN, user.getLogin())
+ .setParam(PARAM_ORGANIZATION, organization.getKey())
+ .execute();
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonarqube.ws.client.qualityprofile;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+public class AddUserRequest {
+
+ private final String organization;
+ private final String language;
+ private final String qualityProfile;
+ private final String userLogin;
+
+ private AddUserRequest(Builder builder) {
+ this.language = builder.language;
+ this.organization = builder.organization;
+ this.qualityProfile = builder.qualityProfile;
+ this.userLogin = builder.userLogin;
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+
+ public String getOrganization() {
+ return organization;
+ }
+
+ public String getQualityProfile() {
+ return qualityProfile;
+ }
+
+ public String getUserLogin() {
+ return userLogin;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private String organization;
+ private String qualityProfile;
+ private String language;
+ private String userLogin;
+
+ private Builder() {
+ // enforce factory method use
+ }
+
+ public Builder setLanguage(String language) {
+ this.language = language;
+ return this;
+ }
+
+ public Builder setOrganization(String organization) {
+ this.organization = organization;
+ return this;
+ }
+
+ public Builder setQualityProfile(String qualityProfile) {
+ this.qualityProfile = qualityProfile;
+ return this;
+ }
+
+ public Builder setUserLogin(String userLogin) {
+ this.userLogin = userLogin;
+ return this;
+ }
+
+ public AddUserRequest build() {
+ return new AddUserRequest(this);
+ }
+ }
+}
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_ACTIVATE_RULE;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_ADD_PROJECT;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_ADD_USER;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_CHANGE_PARENT;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_COPY;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_CREATE;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_FROM_KEY;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_NAME;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LOGIN;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_ORGANIZATION;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PARAMS;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PARENT_QUALITY_PROFILE;
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_PROJECT_UUID;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_QUALITY_PROFILE;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_RESET;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_RULE;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_SEVERITY;
call(postRequest);
}
+
+ public void addUser(AddUserRequest request) {
+ call(new PostRequest(path(ACTION_ADD_USER))
+ .setParam(PARAM_ORGANIZATION, request.getOrganization())
+ .setParam(PARAM_QUALITY_PROFILE, request.getQualityProfile())
+ .setParam(PARAM_LANGUAGE, request.getLanguage())
+ .setParam(PARAM_LOGIN, request.getUserLogin()));
+ }
}
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_FROM_KEY;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_NAME;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LOGIN;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_ORGANIZATION;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PARAMS;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_KEY;
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;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_RULE;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_SEVERITY;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_TO_NAME;
.hasParam(PARAM_SEVERITY, Severity.INFO.toString())
.andNoOtherParam();
}
+
+ @Test
+ public void add_user() {
+ underTest.addUser(AddUserRequest.builder()
+ .setOrganization("O1")
+ .setQualityProfile("P1")
+ .setLanguage("Xoo")
+ .setUserLogin("john")
+ .build());
+ PostRequest request = serviceTester.getPostRequest();
+
+ serviceTester.assertThat(request)
+ .hasPath("add_user")
+ .hasParam(PARAM_ORGANIZATION, "O1")
+ .hasParam(PARAM_QUALITY_PROFILE, "P1")
+ .hasParam(PARAM_LANGUAGE, "Xoo")
+ .hasParam(PARAM_LOGIN, "john")
+ .andNoOtherParam();
+ }
}