Browse Source

SONAR-8857 create quality profiles for specific organizations

tags/6.4-RC1
Daniel Schwarz 7 years ago
parent
commit
26acbcc8e9
20 changed files with 229 additions and 113 deletions
  1. 5
    2
      server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileCopier.java
  2. 10
    10
      server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java
  3. 10
    6
      server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileReset.java
  4. 8
    4
      server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RegisterQualityProfiles.java
  5. 7
    8
      server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java
  6. 54
    1
      server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileWsSupport.java
  7. 60
    58
      server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryMediumTest.java
  8. 1
    4
      server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryTest.java
  9. 5
    1
      server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CopyActionTest.java
  10. 32
    2
      server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionTest.java
  11. 2
    2
      server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/DeleteActionTest.java
  12. 1
    5
      server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileFactoryTest.java
  13. 4
    1
      server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java
  14. 2
    2
      server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RenameActionTest.java
  15. 5
    1
      server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreActionTest.java
  16. 4
    1
      server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInActionTest.java
  17. 1
    1
      server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java
  18. 3
    4
      server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SetDefaultActionTest.java
  19. 13
    0
      sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/CreateRequest.java
  20. 2
    0
      sonar-ws/src/main/protobuf/ws-qualityprofiles.proto

+ 5
- 2
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileCopier.java View File

@@ -34,6 +34,7 @@ import org.sonar.api.utils.TempFolder;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.server.organization.DefaultOrganizationProvider;

@ServerSide
public class QProfileCopier {
@@ -42,12 +43,14 @@ public class QProfileCopier {
private final QProfileFactory factory;
private final QProfileBackuper backuper;
private final TempFolder temp;
private final DefaultOrganizationProvider defaultOrganizationProvider;

public QProfileCopier(DbClient db, QProfileFactory factory, QProfileBackuper backuper, TempFolder temp) {
public QProfileCopier(DbClient db, QProfileFactory factory, QProfileBackuper backuper, TempFolder temp, DefaultOrganizationProvider defaultOrganizationProvider) {
this.db = db;
this.factory = factory;
this.backuper = backuper;
this.temp = temp;
this.defaultOrganizationProvider = defaultOrganizationProvider;
}

public QualityProfileDto copyToName(String fromProfileKey, String toName) {
@@ -72,7 +75,7 @@ public class QProfileCopier {
if (toProfile == null) {
// Do not delegate creation to QProfileBackuper because we need to keep
// the parent-child association, if exists.
toProfile = factory.create(dbSession, toProfileName);
toProfile = factory.create(dbSession, defaultOrganizationProvider.get().getUuid(), toProfileName);
toProfile.setParentKee(fromProfile.getParentKee());
db.qualityProfileDao().update(dbSession, toProfile);
dbSession.commit();

+ 10
- 10
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java View File

@@ -19,6 +19,7 @@
*/
package org.sonar.server.qualityprofile;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Collection;
@@ -35,7 +36,6 @@ import org.sonar.db.qualityprofile.ActiveRuleDto;
import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.organization.DefaultOrganizationProvider;

import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.DEACTIVATED;
import static org.sonar.server.ws.WsUtils.checkFound;
@@ -47,30 +47,30 @@ import static org.sonar.server.ws.WsUtils.checkRequest;
public class QProfileFactory {

private final DbClient db;
private final DefaultOrganizationProvider defaultOrganizationProvider;

public QProfileFactory(DbClient db, DefaultOrganizationProvider defaultOrganizationProvider) {
public QProfileFactory(DbClient db) {
this.db = db;
this.defaultOrganizationProvider = defaultOrganizationProvider;
}

// ------------- CREATION

QualityProfileDto getOrCreate(DbSession dbSession, QProfileName name) {
QualityProfileDto getOrCreate(DbSession dbSession, String organizationUuid, QProfileName name) {
Preconditions.checkArgument(StringUtils.isNotEmpty(organizationUuid), "Organization is required, when creating a quality profile.");
QualityProfileDto profile = db.qualityProfileDao().selectByNameAndLanguage(name.getName(), name.getLanguage(), dbSession);
if (profile == null) {
profile = doCreate(dbSession, name);
profile = doCreate(dbSession, organizationUuid, name);
}
return profile;
}

public QualityProfileDto create(DbSession dbSession, QProfileName name) {
public QualityProfileDto create(DbSession dbSession, String organizationUuid, QProfileName name) {
Preconditions.checkArgument(StringUtils.isNotEmpty(organizationUuid), "Organization is required, when creating a quality profile.");
QualityProfileDto dto = db.qualityProfileDao().selectByNameAndLanguage(name.getName(), name.getLanguage(), dbSession);
checkRequest(dto == null, "Quality profile already exists: %s", name);
return doCreate(dbSession, name);
return doCreate(dbSession, organizationUuid, name);
}

private QualityProfileDto doCreate(DbSession dbSession, QProfileName name) {
private QualityProfileDto doCreate(DbSession dbSession, String organizationUuid, QProfileName name) {
if (StringUtils.isEmpty(name.getName())) {
throw BadRequestException.create("quality_profiles.profile_name_cant_be_blank");
}
@@ -79,7 +79,7 @@ public class QProfileFactory {
String key = Slug.slugify(String.format("%s %s %s", name.getLanguage(), name.getName(), RandomStringUtils.randomNumeric(5)));
QualityProfileDto dto = QualityProfileDto.createFor(key)
.setName(name.getName())
.setOrganizationUuid(defaultOrganizationProvider.get().getUuid())
.setOrganizationUuid(organizationUuid)
.setLanguage(name.getLanguage())
.setRulesUpdatedAtAsDate(now);
if (db.qualityProfileDao().selectByKey(dbSession, dto.getKey()) == null) {

+ 10
- 6
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileReset.java View File

@@ -43,6 +43,7 @@ import org.sonar.db.qualityprofile.ActiveRuleKey;
import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.db.rule.RuleParamDto;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;

import static org.sonar.server.ws.WsUtils.checkRequest;
@@ -54,19 +55,22 @@ public class QProfileReset {
private final QProfileFactory factory;
private final RuleActivator activator;
private final ActiveRuleIndexer activeRuleIndexer;
private final DefaultOrganizationProvider defaultOrganizationProvider;
private final ProfileDefinition[] definitions;

public QProfileReset(DbClient db, RuleActivator activator, ActiveRuleIndexer activeRuleIndexer, QProfileFactory factory,
ProfileDefinition[] definitions) {
public QProfileReset(DbClient db, RuleActivator activator, ActiveRuleIndexer activeRuleIndexer, QProfileFactory factory, DefaultOrganizationProvider defaultOrganizationProvider,
ProfileDefinition... definitions) {
this.db = db;
this.activator = activator;
this.activeRuleIndexer = activeRuleIndexer;
this.factory = factory;
this.defaultOrganizationProvider = defaultOrganizationProvider;
this.definitions = definitions;
}

public QProfileReset(DbClient db, RuleActivator activator, QProfileFactory factory, ActiveRuleIndexer activeRuleIndexer) {
this(db, activator, activeRuleIndexer, factory, new ProfileDefinition[0]);
public QProfileReset(DbClient db, RuleActivator activator, ActiveRuleIndexer activeRuleIndexer, QProfileFactory factory,
DefaultOrganizationProvider defaultOrganizationProvider) {
this(db, activator, activeRuleIndexer, factory, defaultOrganizationProvider, new ProfileDefinition[0]);
}

/**
@@ -79,7 +83,7 @@ public class QProfileReset {
ListMultimap<QProfileName, RulesProfile> profilesByName = loadDefinitionsGroupedByName(language);
for (Map.Entry<QProfileName, Collection<RulesProfile>> entry : profilesByName.asMap().entrySet()) {
QProfileName profileName = entry.getKey();
QualityProfileDto profile = factory.getOrCreate(dbSession, profileName);
QualityProfileDto profile = factory.getOrCreate(dbSession, defaultOrganizationProvider.get().getUuid(), profileName);
List<RuleActivation> activations = Lists.newArrayList();
for (RulesProfile def : entry.getValue()) {
for (ActiveRule activeRule : def.getActiveRules()) {
@@ -110,7 +114,7 @@ public class QProfileReset {
BulkChangeResult reset(QProfileName profileName, Collection<RuleActivation> activations) {
DbSession dbSession = db.openSession(false);
try {
QualityProfileDto profile = factory.getOrCreate(dbSession, profileName);
QualityProfileDto profile = factory.getOrCreate(dbSession, defaultOrganizationProvider.get().getUuid(), profileName);
return doReset(dbSession, profile, activations);
} finally {
dbSession.close();

+ 8
- 4
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RegisterQualityProfiles.java View File

@@ -46,6 +46,7 @@ import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.loadedtemplate.LoadedTemplateDto;
import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;

/**
@@ -63,24 +64,27 @@ public class RegisterQualityProfiles {
private final RuleActivator ruleActivator;
private final Languages languages;
private final ActiveRuleIndexer activeRuleIndexer;
private final DefaultOrganizationProvider defaultOrganizationProvider;

/**
* To be kept when no ProfileDefinition are injected
*/
public RegisterQualityProfiles(DbClient dbClient,
QProfileFactory profileFactory, RuleActivator ruleActivator, Languages languages, ActiveRuleIndexer activeRuleIndexer) {
this(dbClient, profileFactory, ruleActivator, Collections.emptyList(), languages, activeRuleIndexer);
QProfileFactory profileFactory, RuleActivator ruleActivator, Languages languages, ActiveRuleIndexer activeRuleIndexer,
DefaultOrganizationProvider defaultOrganizationProvider) {
this(dbClient, profileFactory, ruleActivator, Collections.emptyList(), languages, activeRuleIndexer, defaultOrganizationProvider);
}

public RegisterQualityProfiles(DbClient dbClient,
QProfileFactory profileFactory, RuleActivator ruleActivator,
List<ProfileDefinition> definitions, Languages languages, ActiveRuleIndexer activeRuleIndexer) {
List<ProfileDefinition> definitions, Languages languages, ActiveRuleIndexer activeRuleIndexer, DefaultOrganizationProvider defaultOrganizationProvider) {
this.dbClient = dbClient;
this.profileFactory = profileFactory;
this.ruleActivator = ruleActivator;
this.definitions = definitions;
this.languages = languages;
this.activeRuleIndexer = activeRuleIndexer;
this.defaultOrganizationProvider = defaultOrganizationProvider;
}

public void start() {
@@ -141,7 +145,7 @@ public class RegisterQualityProfiles {
if (profileDto != null) {
changes.addAll(profileFactory.delete(session, profileDto.getKey(), true));
}
profileFactory.create(session, name);
profileFactory.create(session, defaultOrganizationProvider.get().getUuid(), name);
for (RulesProfile profile : profiles) {
for (org.sonar.api.rules.ActiveRule activeRule : profile.getActiveRules()) {
RuleKey ruleKey = RuleKey.of(activeRule.getRepositoryKey(), activeRule.getRuleKey());

+ 7
- 8
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java View File

@@ -58,7 +58,7 @@ public class CreateAction implements QProfileWsAction {
private final ActiveRuleIndexer activeRuleIndexer;

public CreateAction(DbClient dbClient, QProfileFactory profileFactory, QProfileExporters exporters, Languages languages,
QProfileWsSupport qProfileWsSupport, ActiveRuleIndexer activeRuleIndexer, ProfileImporter[] importers) {
QProfileWsSupport qProfileWsSupport, ActiveRuleIndexer activeRuleIndexer, ProfileImporter... importers) {
this.dbClient = dbClient;
this.profileFactory = profileFactory;
this.exporters = exporters;
@@ -83,12 +83,8 @@ public class CreateAction implements QProfileWsAction {
.setResponseExample(getClass().getResource("example-create.json"))
.setHandler(this);

create
.createParam(PARAM_ORGANIZATION)
.setDescription("Organization key")
.setRequired(false)
.setInternal(true)
.setExampleValue("my-org")
qProfileWsSupport
.createOrganizationParam(create)
.setSince("6.4");

create.createParam(PARAM_PROFILE_NAME)
@@ -121,7 +117,8 @@ public class CreateAction implements QProfileWsAction {

private CreateWsResponse doHandle(DbSession dbSession, CreateRequest createRequest, Request request) {
QProfileResult result = new QProfileResult();
QualityProfileDto profile = profileFactory.create(dbSession, QProfileName.createFor(createRequest.getLanguage(), createRequest.getProfileName()));
QualityProfileDto profile = profileFactory.create(dbSession, qProfileWsSupport.getOrganizationUuidByKey(createRequest.getOrganizationKey()),
QProfileName.createFor(createRequest.getLanguage(), createRequest.getProfileName()));
result.setProfile(profile);
for (ProfileImporter importer : importers) {
String importerKey = importer.getKey();
@@ -137,6 +134,7 @@ public class CreateAction implements QProfileWsAction {

private static CreateRequest toRequest(Request request) {
CreateRequest.Builder builder = CreateRequest.builder()
.setOrganizationKey(request.param(PARAM_ORGANIZATION))
.setLanguage(request.mandatoryParam(PARAM_LANGUAGE))
.setProfileName(request.mandatoryParam(PARAM_PROFILE_NAME));
return builder.build();
@@ -145,6 +143,7 @@ public class CreateAction implements QProfileWsAction {
private CreateWsResponse buildResponse(QProfileResult result) {
String language = result.profile().getLanguage();
CreateWsResponse.QualityProfile.Builder builder = CreateWsResponse.QualityProfile.newBuilder()
.setOrganization(qProfileWsSupport.getOrganizationKey(result.profile()))
.setKey(result.profile().getKey())
.setName(result.profile().getName())
.setLanguage(language)

+ 54
- 1
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileWsSupport.java View File

@@ -19,26 +19,79 @@
*/
package org.sonar.server.qualityprofile.ws;

import java.util.Optional;
import javax.annotation.Nullable;
import org.sonar.api.server.ServerSide;
import org.sonar.api.server.ws.WebService.NewAction;
import org.sonar.api.server.ws.WebService.NewParam;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.user.UserSession;
import org.sonar.server.ws.WsUtils;

import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_ORGANIZATION;

@ServerSide
public class QProfileWsSupport {

private final DbClient dbClient;
private final UserSession userSession;
private final DefaultOrganizationProvider defaultOrganizationProvider;

public QProfileWsSupport(UserSession userSession, DefaultOrganizationProvider defaultOrganizationProvider) {
public QProfileWsSupport(DbClient dbClient, UserSession userSession, DefaultOrganizationProvider defaultOrganizationProvider) {
this.dbClient = dbClient;
this.userSession = userSession;
this.defaultOrganizationProvider = defaultOrganizationProvider;
}

public String getOrganizationKey(QualityProfileDto profile) {
return getOrganizationKeyByUuid(profile.getOrganizationUuid());
}

public String getOrganizationUuidByKey(String organizationKey) {
try (DbSession dbSession = dbClient.openSession(false)) {
return getOrganizationByKey(dbSession, organizationKey)
.getUuid();
}
}

public OrganizationDto getOrganizationByKey(DbSession dbSession, @Nullable String organizationKey) {
String organizationOrDefaultKey = Optional.ofNullable(organizationKey)
.orElseGet(defaultOrganizationProvider.get()::getKey);
return WsUtils.checkFoundWithOptional(
dbClient.organizationDao().selectByKey(dbSession, organizationOrDefaultKey),
"No organizationDto with key '%s'", organizationOrDefaultKey);
}

public String getOrganizationKeyByUuid(String organizationUuid) {
return getOrganizationByUuid(organizationUuid)
.orElseThrow(() -> new IllegalStateException(String.format("Requested the key for non-existing organization uuid '%s'.", organizationUuid)))
.getKey();
}

private Optional<OrganizationDto> getOrganizationByUuid(String organizationUuid) {
try (DbSession dbSession = dbClient.openSession(false)) {
return dbClient.organizationDao()
.selectByUuid(dbSession, organizationUuid);
}
}

public void checkQProfileAdminPermission() {
userSession
.checkLoggedIn()
.checkPermission(ADMINISTER_QUALITY_PROFILES, defaultOrganizationProvider.get().getUuid());
}

public NewParam createOrganizationParam(NewAction create) {
return create
.createParam(PARAM_ORGANIZATION)
.setDescription("Organization key")
.setRequired(false)
.setInternal(true)
.setExampleValue("my-org");
}
}

+ 60
- 58
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryMediumTest.java View File

@@ -30,13 +30,14 @@ import org.sonar.api.server.rule.RuleParamType;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.RowNotFoundException;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.organization.OrganizationTesting;
import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.db.rule.RuleDto;
import org.sonar.db.rule.RuleParamDto;
import org.sonar.db.rule.RuleTesting;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
import org.sonar.server.rule.index.RuleIndex;
import org.sonar.server.rule.index.RuleIndexer;
@@ -59,12 +60,12 @@ public class QProfileFactoryMediumTest {
@Rule
public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester);

DbClient db;
DbSession dbSession;
ActiveRuleIndex activeRuleIndex;
ActiveRuleIndexer activeRuleIndexer;
RuleIndexer ruleIndexer;
QProfileFactory factory;
private DbClient db;
private DbSession dbSession;
private ActiveRuleIndexer activeRuleIndexer;
private RuleIndexer ruleIndexer;
private QProfileFactory factory;
private OrganizationDto organization = OrganizationTesting.newOrganizationDto();

@Before
public void before() {
@@ -72,7 +73,6 @@ public class QProfileFactoryMediumTest {
db = tester.get(DbClient.class);
dbSession = db.openSession(false);
factory = tester.get(QProfileFactory.class);
activeRuleIndex = tester.get(ActiveRuleIndex.class);
activeRuleIndexer = tester.get(ActiveRuleIndexer.class);
ruleIndexer = tester.get(RuleIndexer.class);
}
@@ -84,62 +84,63 @@ public class QProfileFactoryMediumTest {

@Test
public void create() {
QualityProfileDto dto = factory.create(dbSession, new QProfileName("xoo", "P1"));
String uuid = organization.getUuid();

QualityProfileDto writtenDto = factory.create(dbSession, uuid, new QProfileName("xoo", "P1"));
dbSession.commit();
dbSession.clearCache();
assertThat(dto.getKey()).startsWith("xoo-p1-");
assertThat(dto.getName()).isEqualTo("P1");
assertThat(dto.getLanguage()).isEqualTo("xoo");
assertThat(dto.getId()).isNotNull();
assertThat(writtenDto.getOrganizationUuid()).isEqualTo(uuid);
assertThat(writtenDto.getKey()).startsWith("xoo-p1-");
assertThat(writtenDto.getName()).isEqualTo("P1");
assertThat(writtenDto.getLanguage()).isEqualTo("xoo");
assertThat(writtenDto.getId()).isNotNull();

// reload the dto
dto = db.qualityProfileDao().selectByNameAndLanguage("P1", "xoo", dbSession);
assertThat(dto.getLanguage()).isEqualTo("xoo");
assertThat(dto.getName()).isEqualTo("P1");
assertThat(dto.getKey()).startsWith("xoo-p1");
assertThat(dto.getId()).isNotNull();
assertThat(dto.getParentKee()).isNull();
QualityProfileDto readDto = db.qualityProfileDao().selectByNameAndLanguage("P1", "xoo", dbSession);
assertThat(readDto.getOrganizationUuid()).isEqualTo(uuid);
assertThat(readDto.getName()).isEqualTo("P1");
assertThat(readDto.getKey()).startsWith("xoo-p1");
assertThat(readDto.getLanguage()).isEqualTo("xoo");
assertThat(readDto.getId()).isNotNull();
assertThat(readDto.getParentKee()).isNull();

assertThat(db.qualityProfileDao().selectAll(dbSession)).hasSize(1);
}

@Test
public void fail_to_create_if_name_empty() {
public void fail_to_create_if_name_null() {
QProfileName name = new QProfileName("xoo", null);
try {
factory.create(dbSession, name);
fail();
} catch (BadRequestException e) {
assertThat(e).hasMessage("quality_profiles.profile_name_cant_be_blank");
}
String organizationUuid = organization.getUuid();

name = new QProfileName("xoo", "");
try {
factory.create(dbSession, name);
fail();
} catch (BadRequestException e) {
assertThat(e).hasMessage("quality_profiles.profile_name_cant_be_blank");
}
expectBadRequestException("quality_profiles.profile_name_cant_be_blank");

factory.create(dbSession, organizationUuid, name);
}

@Test
public void fail_to_create_if_name_empty() {
QProfileName name = new QProfileName("xoo", "");

expectBadRequestException("quality_profiles.profile_name_cant_be_blank");

factory.create(dbSession, organization.getUuid(), name);
}

@Test
public void fail_to_create_if_already_exists() {
QProfileName name = new QProfileName("xoo", "P1");
factory.create(dbSession, name);
factory.create(dbSession, organization.getUuid(), name);
dbSession.commit();
dbSession.clearCache();

try {
factory.create(dbSession, name);
fail();
} catch (BadRequestException e) {
assertThat(e).hasMessage("Quality profile already exists: {lang=xoo, name=P1}");
}
expectBadRequestException("Quality profile already exists: {lang=xoo, name=P1}");

factory.create(dbSession, organization.getUuid(), name);
}

@Test
public void rename() {
QualityProfileDto dto = factory.create(dbSession, new QProfileName("xoo", "P1"));
QualityProfileDto dto = factory.create(dbSession, organization.getUuid(), new QProfileName("xoo", "P1"));
dbSession.commit();
dbSession.clearCache();
String key = dto.getKey();
@@ -148,13 +149,14 @@ public class QProfileFactoryMediumTest {
dbSession.clearCache();

QualityProfileDto reloaded = db.qualityProfileDao().selectByKey(dbSession, dto.getKee());
assertThat(reloaded.getOrganizationUuid()).isEqualTo(organization.getUuid());
assertThat(reloaded.getKey()).isEqualTo(key);
assertThat(reloaded.getName()).isEqualTo("the new name");
}

@Test
public void ignore_renaming_if_same_name() {
QualityProfileDto dto = factory.create(dbSession, new QProfileName("xoo", "P1"));
QualityProfileDto dto = factory.create(dbSession, organization.getUuid(), new QProfileName("xoo", "P1"));
dbSession.commit();
dbSession.clearCache();
String key = dto.getKey();
@@ -163,23 +165,21 @@ public class QProfileFactoryMediumTest {
dbSession.clearCache();

QualityProfileDto reloaded = db.qualityProfileDao().selectByKey(dbSession, dto.getKee());
assertThat(reloaded.getOrganizationUuid()).isEqualTo(organization.getUuid());
assertThat(reloaded.getKey()).isEqualTo(key);
assertThat(reloaded.getName()).isEqualTo("P1");
}

@Test
public void fail_if_blank_renaming() {
QualityProfileDto dto = factory.create(dbSession, new QProfileName("xoo", "P1"));
QualityProfileDto dto = factory.create(dbSession, organization.getUuid(), new QProfileName("xoo", "P1"));
dbSession.commit();
dbSession.clearCache();
String key = dto.getKey();

try {
factory.rename(key, " ");
fail();
} catch (BadRequestException e) {
assertThat(e).hasMessage("Name must be set");
}
expectBadRequestException("Name must be set");

factory.rename(key, " ");
}

@Test
@@ -192,23 +192,20 @@ public class QProfileFactoryMediumTest {

@Test
public void fail_renaming_if_name_already_exists() {
QualityProfileDto p1 = factory.create(dbSession, new QProfileName("xoo", "P1"));
QualityProfileDto p2 = factory.create(dbSession, new QProfileName("xoo", "P2"));
QualityProfileDto p1 = factory.create(dbSession, organization.getUuid(), new QProfileName("xoo", "P1"));
QualityProfileDto p2 = factory.create(dbSession, organization.getUuid(), new QProfileName("xoo", "P2"));
dbSession.commit();
dbSession.clearCache();

try {
factory.rename(p1.getKey(), "P2");
fail();
} catch (BadRequestException e) {
assertThat(e).hasMessage("Quality profile already exists: P2");
}
expectBadRequestException("Quality profile already exists: P2");

factory.rename(p1.getKey(), "P2");
}

@Test
public void delete() {
initRules();
db.qualityProfileDao().insert(dbSession, QProfileTesting.newXooP1("org-123"));
db.qualityProfileDao().insert(dbSession, QProfileTesting.newXooP1(organization.getUuid()));
tester.get(RuleActivator.class).activate(dbSession, new RuleActivation(RuleTesting.XOO_X1), XOO_P1_KEY);
dbSession.commit();
dbSession.clearCache();
@@ -338,4 +335,9 @@ public class QProfileFactoryMediumTest {
dbSession.clearCache();
ruleIndexer.index();
}

private void expectBadRequestException(String message) {
thrown.expect(BadRequestException.class);
thrown.expectMessage(message);
}
}

+ 1
- 4
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryTest.java View File

@@ -29,8 +29,6 @@ import org.sonar.db.DbTester;
import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.db.qualityprofile.QualityProfileTesting;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.organization.TestDefaultOrganizationProvider;

import static org.assertj.core.api.Assertions.assertThat;

@@ -42,9 +40,8 @@ public class QProfileFactoryTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();

private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(dbTester);
private DbSession dbSession = dbTester.getSession();
private QProfileFactory underTest = new QProfileFactory(dbTester.getDbClient(), defaultOrganizationProvider);
private QProfileFactory underTest = new QProfileFactory(dbTester.getDbClient());

@Before
public void setUp() throws Exception {

+ 5
- 1
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CopyActionTest.java View File

@@ -26,6 +26,7 @@ import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.sonar.db.DbTester;
import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.UnauthorizedException;
@@ -46,6 +47,9 @@ public class CopyActionTest {

private static final String DEFAULT_ORG_UUID = "U1";

@Rule
public DbTester db = DbTester.create();

@Rule
public ExpectedException expectedException = ExpectedException.none();

@@ -64,7 +68,7 @@ public class CopyActionTest {
tester = new WsTester(new QProfilesWs(
mock(RuleActivationActions.class),
mock(BulkRuleActivationActions.class),
new CopyAction(qProfileCopier, LanguageTesting.newLanguages("xoo"), new QProfileWsSupport(userSessionRule, defaultOrganizationProvider))));
new CopyAction(qProfileCopier, LanguageTesting.newLanguages("xoo"), new QProfileWsSupport(db.getDbClient(), userSessionRule, defaultOrganizationProvider))));
}

@Test

+ 32
- 2
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionTest.java View File

@@ -24,6 +24,7 @@ import java.io.IOException;
import java.io.Reader;
import java.util.Collections;
import java.util.Map;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -36,6 +37,7 @@ import org.sonar.api.utils.ValidationMessages;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.db.rule.RuleDto;
import org.sonar.db.rule.RuleTesting;
@@ -95,12 +97,18 @@ public class CreateActionTest {
private QProfileExporters qProfileExporters = new QProfileExporters(dbClient, null,
new RuleActivator(mock(System2.class), dbClient, ruleIndex, new RuleActivatorContextFactory(dbClient), null, activeRuleIndexer, userSession),
profileImporters);
private OrganizationDto organization;

private CreateAction underTest = new CreateAction(dbClient, new QProfileFactory(dbClient, defaultOrganizationProvider), qProfileExporters,
newLanguages(XOO_LANGUAGE), new QProfileWsSupport(userSession, defaultOrganizationProvider),
private CreateAction underTest = new CreateAction(dbClient, new QProfileFactory(dbClient), qProfileExporters,
newLanguages(XOO_LANGUAGE), new QProfileWsSupport(dbClient, userSession, defaultOrganizationProvider),
activeRuleIndexer, profileImporters);
private WsActionTester wsTester = new WsActionTester(underTest);

@Before
public void before() {
organization = dbTester.organizations().insert();
}

@Test
public void create_profile() {
logInAsQProfileAdministrator();
@@ -146,6 +154,23 @@ public class CreateActionTest {
assertThat(profile.getWarnings().getWarningsList()).containsOnly("a warning");
}

@Test
public void create_profile_for_specific_organization() {
logInAsQProfileAdministrator();
String orgKey = organization.getKey();

TestRequest request = wsTester.newRequest()
.setMediaType(MediaTypes.PROTOBUF)
.setParam("organization", orgKey)
.setParam("name", "Profile with messages")
.setParam("language", XOO_LANGUAGE)
.setParam("backup_with_messages", "<xml/>");
assertThat(executeRequest(request).getProfile().getOrganization())
.isEqualTo(orgKey);
}

@Test
public void fail_if_import_generate_error() {
logInAsQProfileAdministrator();
@@ -182,11 +207,16 @@ public class CreateActionTest {
private CreateWsResponse executeRequest(String name, String language, Map<String, String> xmls) {
TestRequest request = wsTester.newRequest()
.setMediaType(MediaTypes.PROTOBUF)
.setParam("organization", organization.getKey())
.setParam("name", name)
.setParam("language", language);
for (Map.Entry<String, String> entry : xmls.entrySet()) {
request.setParam("backup_" + entry.getKey(), entry.getValue());
}
return executeRequest(request);
}

private CreateWsResponse executeRequest(TestRequest request) {
try {
return parseFrom(request.execute().getInputStream());
} catch (IOException e) {

+ 2
- 2
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/DeleteActionTest.java View File

@@ -77,8 +77,8 @@ public class DeleteActionTest {
tester = new WsTester(new QProfilesWs(
mock(RuleActivationActions.class),
mock(BulkRuleActivationActions.class),
new DeleteAction(new Languages(xoo1, xoo2), new QProfileFactory(dbClient, defaultOrganizationProvider), dbClient,
new QProfileWsSupport(userSessionRule, defaultOrganizationProvider))));
new DeleteAction(new Languages(xoo1, xoo2), new QProfileFactory(dbClient), dbClient,
new QProfileWsSupport(dbClient, userSessionRule, defaultOrganizationProvider))));
}

@After

+ 1
- 5
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileFactoryTest.java View File

@@ -29,8 +29,6 @@ import org.sonar.db.DbTester;
import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.db.qualityprofile.QualityProfileTesting;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.organization.TestDefaultOrganizationProvider;
import org.sonar.server.qualityprofile.QProfileFactory;
import org.sonar.server.qualityprofile.QProfileRef;

@@ -45,9 +43,7 @@ public class QProfileFactoryTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();

private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(dbTester);

private QProfileFactory underTest = new QProfileFactory(dbTester.getDbClient(), defaultOrganizationProvider);
private QProfileFactory underTest = new QProfileFactory(dbTester.getDbClient());

@Before
public void setUp() throws Exception {

+ 4
- 1
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java View File

@@ -31,6 +31,7 @@ import org.sonar.api.resources.Languages;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.ValidationMessages;
import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
import org.sonar.server.language.LanguageTesting;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.organization.TestDefaultOrganizationProvider;
@@ -46,12 +47,14 @@ import static org.mockito.Mockito.mock;
public class QProfilesWsTest {
@Rule
public UserSessionRule userSessionRule = UserSessionRule.standalone();
@Rule
public DbTester db = DbTester.create();

private WebService.Controller controller;
private String xoo1Key = "xoo1";
private String xoo2Key = "xoo2";
private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.fromUuid("ORG1");
private QProfileWsSupport wsSupport = new QProfileWsSupport(userSessionRule, defaultOrganizationProvider);
private QProfileWsSupport wsSupport = new QProfileWsSupport(db.getDbClient(), userSessionRule, defaultOrganizationProvider);

@Before
public void setUp() {

+ 2
- 2
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RenameActionTest.java View File

@@ -55,7 +55,7 @@ public class RenameActionTest {
private String xoo2Key = "xoo2";
private WsTester tester;
private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.fromUuid("ORG1");
private QProfileWsSupport wsSupport = new QProfileWsSupport(userSessionRule, defaultOrganizationProvider);
private QProfileWsSupport wsSupport = new QProfileWsSupport(dbClient, userSessionRule, defaultOrganizationProvider);

@Before
public void setUp() {
@@ -64,7 +64,7 @@ public class RenameActionTest {
tester = new WsTester(new QProfilesWs(
mock(RuleActivationActions.class),
mock(BulkRuleActivationActions.class),
new RenameAction(new QProfileFactory(dbClient, defaultOrganizationProvider), wsSupport)));
new RenameAction(new QProfileFactory(dbClient), wsSupport)));
}

@Test

+ 5
- 1
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreActionTest.java View File

@@ -27,6 +27,7 @@ import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.sonar.db.DbTester;
import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.UnauthorizedException;
@@ -48,6 +49,9 @@ import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_

@RunWith(MockitoJUnitRunner.class)
public class RestoreActionTest {
@Rule
public DbTester db = DbTester.create();

@Rule
public UserSessionRule userSessionRule = UserSessionRule.standalone();

@@ -59,7 +63,7 @@ public class RestoreActionTest {
public ExpectedException expectedException = ExpectedException.none();

private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.fromUuid("ORG1");
private QProfileWsSupport wsSupport = new QProfileWsSupport(userSessionRule, defaultOrganizationProvider);
private QProfileWsSupport wsSupport = new QProfileWsSupport(db.getDbClient(), userSessionRule, defaultOrganizationProvider);
private WsTester tester;

@Before

+ 4
- 1
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInActionTest.java View File

@@ -23,6 +23,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.resources.Languages;
import org.sonar.db.DbTester;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.UnauthorizedException;
import org.sonar.server.language.LanguageTesting;
@@ -39,6 +40,8 @@ import static org.mockito.Mockito.verify;
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES;

public class RestoreBuiltInActionTest {
@Rule
public DbTester db = DbTester.create();

@Rule
public ExpectedException expectedException = ExpectedException.none();
@@ -49,7 +52,7 @@ public class RestoreBuiltInActionTest {
private QProfileReset reset = mock(QProfileReset.class);
private Languages languages = LanguageTesting.newLanguages("xoo");
private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.fromUuid("ORG1");
private QProfileWsSupport wsSupport = new QProfileWsSupport(userSession, defaultOrganizationProvider);
private QProfileWsSupport wsSupport = new QProfileWsSupport(db.getDbClient(), userSession, defaultOrganizationProvider);

private WsActionTester tester = new WsActionTester(new RestoreBuiltInAction(reset, languages, wsSupport));


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

@@ -97,7 +97,7 @@ public class SearchActionTest {
new SearchDataLoader(
languages,
new QProfileLookup(dbClient),
new QProfileFactory(dbClient, defaultOrganizationProvider),
new QProfileFactory(dbClient),
dbClient,
new ComponentFinder(dbClient), activeRuleIndex),
languages));

+ 3
- 4
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SetDefaultActionTest.java View File

@@ -24,7 +24,6 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
import org.sonar.db.qualityprofile.QualityProfileDto;
@@ -48,7 +47,7 @@ public class SetDefaultActionTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Rule
public DbTester db = DbTester.create(System2.INSTANCE);
public DbTester db = DbTester.create();
@Rule
public UserSessionRule userSessionRule = UserSessionRule.standalone();

@@ -56,8 +55,8 @@ public class SetDefaultActionTest {
private String xoo2Key = "xoo2";
private WsTester tester;
private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
private QProfileWsSupport wsSupport = new QProfileWsSupport(userSessionRule, defaultOrganizationProvider);
private DbClient dbClient = db.getDbClient();
private QProfileWsSupport wsSupport = new QProfileWsSupport(dbClient, userSessionRule, defaultOrganizationProvider);

@Before
public void setUp() {
@@ -66,7 +65,7 @@ public class SetDefaultActionTest {
tester = new WsTester(new QProfilesWs(
mock(RuleActivationActions.class),
mock(BulkRuleActivationActions.class),
new SetDefaultAction(LanguageTesting.newLanguages(xoo1Key, xoo2Key), new QProfileLookup(dbClient), new QProfileFactory(dbClient, defaultOrganizationProvider), wsSupport)));
new SetDefaultAction(LanguageTesting.newLanguages(xoo1Key, xoo2Key), new QProfileLookup(dbClient), new QProfileFactory(dbClient), wsSupport)));
}

@Test

+ 13
- 0
sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/CreateRequest.java View File

@@ -29,10 +29,12 @@ public class CreateRequest {

private final String profileName;
private final String language;
private final String organizationKey;

private CreateRequest(Builder builder) {
this.profileName = builder.profileName;
this.language = builder.language;
this.organizationKey = builder.organizationKey;
}

public String getLanguage() {
@@ -43,6 +45,10 @@ public class CreateRequest {
return profileName;
}

public String getOrganizationKey() {
return organizationKey;
}

public static Builder builder() {
return new Builder();
}
@@ -50,6 +56,7 @@ public class CreateRequest {
public static class Builder {
private String language;
private String profileName;
private String organizationKey;

private Builder() {
// enforce factory method use
@@ -65,9 +72,15 @@ public class CreateRequest {
return this;
}

public Builder setOrganizationKey(@Nullable String organizationKey) {
this.organizationKey = organizationKey;
return this;
}

public CreateRequest build() {
checkArgument(language != null && !language.isEmpty(), "Language is mandatory and must not be empty.");
checkArgument(profileName != null && !profileName.isEmpty(), "Profile name is mandatory and must not be empty.");
checkArgument(organizationKey == null || !organizationKey.isEmpty(), "Organization key may be either null or not empty. Empty organization key is invalid.");
return new CreateRequest(this);
}
}

+ 2
- 0
sonar-ws/src/main/protobuf/ws-qualityprofiles.proto View File

@@ -43,6 +43,7 @@ message SearchWsResponse {
optional string rulesUpdatedAt = 11;
optional string lastUsed = 13;
optional string userUpdatedAt = 14;
optional string organization = 15;
}
}

@@ -59,6 +60,7 @@ message CreateWsResponse {
optional bool isDefault = 6;
optional Infos infos = 7;
optional Warnings warnings = 8;
optional string organization = 9;

message Infos {
repeated string infos = 1;

Loading…
Cancel
Save