]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8857 create quality profiles for specific organizations
authorDaniel Schwarz <daniel.schwarz@sonarsource.com>
Thu, 2 Mar 2017 11:21:09 +0000 (12:21 +0100)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 23 Mar 2017 16:38:34 +0000 (17:38 +0100)
20 files changed:
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileCopier.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileReset.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RegisterQualityProfiles.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileWsSupport.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CopyActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/DeleteActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileFactoryTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RenameActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SetDefaultActionTest.java
sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/CreateRequest.java
sonar-ws/src/main/protobuf/ws-qualityprofiles.proto

index e1b14c2e7ba9064cb96760c0394a0c18880441cb..abe8d964224109bfb3de52a24f583e3edb67bbf2 100644 (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();
index f286ae506710134564ab11ea7927673d89e4eb9e..b6bcee7cc1224fc025ea143692054823f929650e 100644 (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) {
index 009dfe692b7635c133650c50a0938856a30dc211..a311735592a79583c55ff10c2aa6917f415d452e 100644 (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();
index 9a28f87214c8d37c1d002d77f4cef915c8199f32..6f5c3de65b1619131b1931b42b9dcddd9a08bff6 100644 (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());
index a439f724cfba958f82e15ef6208c97fa84e18e10..148f5bd4b8509cbe4cd46f4de3aba74b20bed546 100644 (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)
index f5ed489ed8f96e8517476441f081a1aff5f25e90..94f87289a1c4029be8fe99fe49b0a4845bb58ace 100644 (file)
  */
 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");
+  }
 }
index 9c482b9cb4ae43480c27745ce1b438d2891c9549..703947036900be79f7408bb5fc23a22529b45c19 100644 (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);
+  }
 }
index de9ae43fc1cbba46bf8cdedc5e4bea63ab488120..121d2a4e7256d929e90b8833503003df52a7b61a 100644 (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 {
index e3f998bc71652618834c12528fbcf8d7d6482f50..fcd2d71ae0408674784108159055f2f5ec65a4f5 100644 (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
index c11c21af8c4f77878ce4c8168c34df2a59c41d80..e1d0354d4d636d50ab4c647c50fc2fd91d743eae 100644 (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) {
index d052fa142905fbcea21f343666abfff4786e8294..df85bbdb6780140afc7f3da9d175ee0c27a79319 100644 (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
index 7ed522e1d195906039d85b956e5c5789830d32a4..86ca34419bc50a1d73d4bc5e557f33fb79ae2b19 100644 (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 {
index 635789312b0740d2417e344570ae8491cb7d88fa..b4071b2eb9bee3936a720cde1a6b03c1b31f0c40 100644 (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() {
index 3e3122605297984d3bd3bb694509bee474762bbb..0d6c3225b2a19f3af55157673e3538adb6992777 100644 (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
index 11ed2c4fadf1fd059aa761754870ad0ed19561ec..ddf5965448b7421f1684bf4c0780b19980e36883 100644 (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
index 80490d2382109e26cb6d37010d4288e795d2d4b4..71b8e585a1c5116928e4ac31f49f963ca22c2b48 100644 (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));
 
index a03b65e143cb9d895fc2f9a94902144ef998611d..3adc4ab1646f0d3dd8dd8ec024e9cc72cb28d056 100644 (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));
index d08f7144bea7d3c2b776de3d14207ecad65f4c27..1eb8f262470fed30ad32a1a875650c40397bf9e2 100644 (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
index f7d3b1936bcb15d0991c016aa59cbe73393289e9..85319cb1c3589dd5e2acb7718cfbc18af89e8303 100644 (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);
     }
   }
index 2c85b0e46820d119996505aaa644a46f7f114785..fa8c312be2bc054c94f1ebb304da9f012d2353f0 100644 (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;