]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8857 add param "organization" to api/qualityprofiles/add_project/remove_project
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Wed, 15 Mar 2017 15:27:01 +0000 (16:27 +0100)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 23 Mar 2017 16:38:34 +0000 (17:38 +0100)
19 files changed:
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileLookup.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileProjectOperations.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/AddProjectAction.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectAssociationFinder.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectAssociationParameters.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileReference.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileWsSupport.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfilesWsModule.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RemoveProjectAction.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchDataLoader.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/AddProjectActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsModuleTest.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/RemoveProjectActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchDataLoaderTest.java

index c6c29b3cf55ba8244a4d744c6c687a165a8bd49f..4eee2881c4e99429af9ea20c2550808556945736 100644 (file)
@@ -147,7 +147,6 @@ import org.sonar.server.qualityprofile.QProfileExporters;
 import org.sonar.server.qualityprofile.QProfileFactory;
 import org.sonar.server.qualityprofile.QProfileLoader;
 import org.sonar.server.qualityprofile.QProfileLookup;
-import org.sonar.server.qualityprofile.QProfileProjectOperations;
 import org.sonar.server.qualityprofile.QProfileResetImpl;
 import org.sonar.server.qualityprofile.QProfileService;
 import org.sonar.server.qualityprofile.RuleActivator;
@@ -263,7 +262,6 @@ public class PlatformLevel4 extends PlatformLevel {
       XMLProfileSerializer.class,
       AnnotationProfileParser.class,
       QProfileLookup.class,
-      QProfileProjectOperations.class,
       QProfileComparison.class,
       SearchDataLoader.class,
       ProfilesWs.class,
index 07c506873dbec0147a60947da8edf04a94216a23..08db76df84b3b4925e139b8db42fd0db75a8c100 100644 (file)
@@ -21,12 +21,9 @@ package org.sonar.server.qualityprofile;
 
 import com.google.common.collect.Lists;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Date;
 import java.util.List;
 import java.util.Objects;
-import java.util.Set;
-import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.utils.System2;
@@ -147,10 +144,6 @@ public class QProfileFactory {
 
   // ------------- DEFAULT PROFILE
 
-  public List<QualityProfileDto> getDefaults(DbSession session, OrganizationDto organization, Collection<String> languageKeys) {
-    return db.qualityProfileDao().selectDefaultProfiles(session, organization, languageKeys);
-  }
-
   /**
    * @deprecated replaced by {@link org.sonar.server.qualityprofile.ws.QProfileWsSupport#getProfile(DbSession, QProfileReference)}
    */
@@ -174,19 +167,6 @@ public class QProfileFactory {
     return checkFound(profile, "Unable to find a profile for language '%s' with name '%s'", language, profileName);
   }
 
-  @CheckForNull
-  public QualityProfileDto getByProjectAndLanguage(DbSession session, String projectKey, String language) {
-    return db.qualityProfileDao().selectByProjectAndLanguage(session, projectKey, language);
-  }
-
-  public List<QualityProfileDto> getByProjectAndLanguages(DbSession session, OrganizationDto organization, String projectKey, Set<String> languageKeys) {
-    return db.qualityProfileDao().selectByProjectAndLanguages(session, organization, projectKey, languageKeys);
-  }
-
-  public List<QualityProfileDto> getByNameAndLanguages(DbSession session, OrganizationDto organization, String name, Collection<String> languages) {
-    return db.qualityProfileDao().selectByNameAndLanguages(organization, name, languages, session);
-  }
-
   private static void checkNotDefault(QualityProfileDto p) {
     if (p.isDefault()) {
       throw BadRequestException.create("The profile marked as default can not be deleted: " + p.getKey());
index 2ba025e55daa79d18142008911613a1ea3ec7e5f..2a10697aa5b858db218d5ac94964b20820bd2e09 100644 (file)
  */
 package org.sonar.server.qualityprofile;
 
-import static com.google.common.collect.Lists.newArrayList;
-import static org.sonar.core.util.stream.Collectors.toList;
-
 import java.util.List;
-
-import javax.annotation.CheckForNull;
-
 import org.sonar.api.server.ServerSide;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.organization.OrganizationDto;
 import org.sonar.db.qualityprofile.QualityProfileDto;
 
+import static com.google.common.collect.Lists.newArrayList;
+import static org.sonar.core.util.stream.Collectors.toList;
+
 @ServerSide
 public class QProfileLookup {
 
@@ -49,17 +46,6 @@ public class QProfileLookup {
     return toQProfiles(db.qualityProfileDao().selectByLanguage(dbSession, language), organization);
   }
 
-  @CheckForNull
-  public QProfile profile(String name, String language) {
-    try (DbSession dbSession = db.openSession(false)) {
-      QualityProfileDto dto = findQualityProfile(name, language, dbSession);
-      if (dto != null) {
-        return QProfile.from(dto, null);
-      }
-      return null;
-    }
-  }
-
   public List<QProfile> ancestors(QualityProfileDto profile, DbSession session) {
     List<QProfile> ancestors = newArrayList();
     incrementAncestors(QProfile.from(profile, null), ancestors, session);
@@ -82,8 +68,4 @@ public class QProfileLookup {
     return dtos.stream().map(dto -> QProfile.from(dto, organization)).collect(toList(dtos.size()));
   }
 
-  @CheckForNull
-  private QualityProfileDto findQualityProfile(String name, String language, DbSession session) {
-    return db.qualityProfileDao().selectByNameAndLanguage(name, language, session);
-  }
 }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileProjectOperations.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileProjectOperations.java
deleted file mode 100644 (file)
index f9c9503..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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;
-
-import org.sonar.api.server.ServerSide;
-import org.sonar.api.web.UserRole;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.qualityprofile.QualityProfileDto;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.db.permission.OrganizationPermission;
-import org.sonar.server.user.UserSession;
-import org.sonar.server.ws.WsUtils;
-
-/**
- * Should be refactored in order to use project key. Maybe should it be move to {@link QProfileFactory}
- * Permission checks should also be done in the upper service.
- */
-@ServerSide
-public class QProfileProjectOperations {
-
-  private final DbClient db;
-  private final UserSession userSession;
-
-  public QProfileProjectOperations(DbClient db, UserSession userSession) {
-    this.db = db;
-    this.userSession = userSession;
-  }
-
-  public void addProject(DbSession dbSession, String profileKey, ComponentDto project) {
-    checkAdminOnProject(project);
-    QualityProfileDto qualityProfile = selectProfileByKey(dbSession, profileKey);
-
-    QualityProfileDto currentProfile = db.qualityProfileDao().selectByProjectAndLanguage(dbSession, project.key(), qualityProfile.getLanguage());
-
-    boolean updated = false;
-    if (currentProfile == null) {
-      db.qualityProfileDao().insertProjectProfileAssociation(project.uuid(), qualityProfile.getKey(), dbSession);
-      updated = true;
-    } else if (!profileKey.equals(currentProfile.getKey())) {
-      db.qualityProfileDao().updateProjectProfileAssociation(project.uuid(), profileKey, currentProfile.getKey(), dbSession);
-      updated = true;
-    }
-    if (updated) {
-      dbSession.commit();
-    }
-  }
-
-  public void removeProject(DbSession dbSession, String profileKey, ComponentDto project) {
-    checkAdminOnProject(project);
-    QualityProfileDto qualityProfile = selectProfileByKey(dbSession, profileKey);
-
-    db.qualityProfileDao().deleteProjectProfileAssociation(project.uuid(), qualityProfile.getKey(), dbSession);
-    dbSession.commit();
-  }
-
-  private QualityProfileDto selectProfileByKey(DbSession session, String profileKey) {
-    QualityProfileDto qualityProfile = db.qualityProfileDao().selectByKey(session, profileKey);
-    return WsUtils.checkFound(qualityProfile, "Quality profile does not exist");
-  }
-
-  private void checkAdminOnProject(ComponentDto project) {
-    if (!userSession.hasPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, project.getOrganizationUuid()) &&
-      !userSession.hasComponentPermission(UserRole.ADMIN, project)) {
-      throw new ForbiddenException("Insufficient privileges");
-    }
-  }
-
-}
index 6242c7ab145890da1b430d5babe062bc3bb7287d..abc09dd769ce5ef436fd7c03f5878ba2fe4ccd4a 100644 (file)
  */
 package org.sonar.server.qualityprofile.ws;
 
+import org.sonar.api.resources.Languages;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.api.web.UserRole;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
-import org.sonar.server.qualityprofile.QProfileProjectOperations;
-import org.sonarqube.ws.client.qualityprofile.AddProjectRequest;
+import org.sonar.db.permission.OrganizationPermission;
+import org.sonar.db.qualityprofile.QualityProfileDto;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.user.UserSession;
 
+import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_ADD_PROJECT;
-import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
-import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_KEY;
-import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_NAME;
 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_KEY;
 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_UUID;
 
 public class AddProjectAction implements QProfileWsAction {
 
-  private final ProjectAssociationParameters projectAssociationParameters;
-  private final ProjectAssociationFinder projectAssociationFinder;
-  private final QProfileProjectOperations profileProjectOperations;
   private final DbClient dbClient;
+  private final UserSession userSession;
+  private final Languages languages;
+  private final ComponentFinder componentFinder;
+  private final QProfileWsSupport wsSupport;
 
-  public AddProjectAction(ProjectAssociationParameters projectAssociationParameters, QProfileProjectOperations profileProjectOperations,
-    ProjectAssociationFinder projectAssociationFinder, DbClient dbClient) {
-    this.projectAssociationParameters = projectAssociationParameters;
-    this.profileProjectOperations = profileProjectOperations;
-    this.projectAssociationFinder = projectAssociationFinder;
+  public AddProjectAction(DbClient dbClient, UserSession userSession, Languages languages, ComponentFinder componentFinder, QProfileWsSupport wsSupport) {
     this.dbClient = dbClient;
+    this.userSession = userSession;
+    this.languages = languages;
+    this.componentFinder = componentFinder;
+    this.wsSupport = wsSupport;
   }
 
   @Override
@@ -56,31 +60,59 @@ public class AddProjectAction implements QProfileWsAction {
     NewAction action = controller.createAction(ACTION_ADD_PROJECT)
       .setSince("5.2")
       .setDescription("Associate a project with a quality profile.")
+      .setPost(true)
       .setHandler(this);
-    projectAssociationParameters.addParameters(action);
+
+    QProfileReference.defineParams(action, languages);
+    QProfileWsSupport.createOrganizationParam(action).setSince("6.4");
+
+    action.createParam(PARAM_PROJECT_UUID)
+      .setDescription("A project UUID. Either this parameter, or projectKey must be set.")
+      .setExampleValue("69e57151-be0d-4157-adff-c06741d88879");
+    action.createParam(PARAM_PROJECT_KEY)
+      .setDescription("A project key. Either this parameter, or projectUuid must be set.")
+      .setExampleValue(KEY_PROJECT_EXAMPLE_001);
   }
 
   @Override
   public void handle(Request request, Response response) throws Exception {
-    AddProjectRequest addProjectRequest = toWsRequest(request);
+    // fail fast if not logged in
+    userSession.checkLoggedIn();
 
     try (DbSession dbSession = dbClient.openSession(false)) {
-      String profileKey = projectAssociationFinder.getProfileKey(addProjectRequest.getLanguage(), addProjectRequest.getProfileName(), addProjectRequest.getProfileKey());
-      ComponentDto project = projectAssociationFinder.getProject(dbSession, addProjectRequest.getProjectKey(), addProjectRequest.getProjectUuid());
-      profileProjectOperations.addProject(dbSession, profileKey, project);
+      ComponentDto project = loadProject(dbSession, request);
+      QualityProfileDto profile = wsSupport.getProfile(dbSession, QProfileReference.from(request));
+
+      if (!profile.getOrganizationUuid().equals(project.getOrganizationUuid())) {
+        throw new IllegalArgumentException("Project and Quality profile must have same organization");
+      }
+
+      QualityProfileDto currentProfile = dbClient.qualityProfileDao().selectByProjectAndLanguage(dbSession, project.key(), profile.getLanguage());
+      if (currentProfile == null) {
+        // project uses the default profile
+        dbClient.qualityProfileDao().insertProjectProfileAssociation(project.uuid(), profile.getKey(), dbSession);
+        dbSession.commit();
+      } else if (!profile.getKey().equals(currentProfile.getKey())) {
+        dbClient.qualityProfileDao().updateProjectProfileAssociation(project.uuid(), profile.getKey(), currentProfile.getKey(), dbSession);
+        dbSession.commit();
+      }
     }
 
     response.noContent();
   }
 
-  private static AddProjectRequest toWsRequest(Request request) {
-    return AddProjectRequest.builder()
-      .setLanguage(request.param(PARAM_LANGUAGE))
-      .setProfileName(request.param(PARAM_PROFILE_NAME))
-      .setProfileKey(request.param(PARAM_PROFILE_KEY))
-      .setProjectKey(request.param(PARAM_PROJECT_KEY))
-      .setProjectUuid(request.param(PARAM_PROJECT_UUID))
-      .build();
+  private ComponentDto loadProject(DbSession dbSession, Request request) {
+    String projectKey = request.param(PARAM_PROJECT_KEY);
+    String projectUuid = request.param(PARAM_PROJECT_UUID);
+    ComponentDto project = componentFinder.getByUuidOrKey(dbSession, projectUuid, projectKey, ComponentFinder.ParamNames.PROJECT_UUID_AND_KEY);
+    checkAdministrator(project);
+    return project;
   }
 
+  private void checkAdministrator(ComponentDto project) {
+    if (!userSession.hasPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, project.getOrganizationUuid()) &&
+      !userSession.hasComponentPermission(UserRole.ADMIN, project)) {
+      throw new ForbiddenException("Insufficient privileges");
+    }
+  }
 }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectAssociationFinder.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectAssociationFinder.java
deleted file mode 100644 (file)
index 973be89..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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 javax.annotation.Nullable;
-import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.qualityprofile.QProfile;
-import org.sonar.server.qualityprofile.QProfileLookup;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static org.apache.commons.lang.StringUtils.isEmpty;
-
-public class ProjectAssociationFinder {
-
-  private static final String BAD_PROFILE_PARAMETERS_ERROR = "Either profileKey or profileName + language must be set";
-
-  private final QProfileLookup profileLookup;
-  private final ComponentFinder componentFinder;
-
-  public ProjectAssociationFinder(QProfileLookup profileLookup, ComponentFinder componentFinder) {
-    this.profileLookup = profileLookup;
-    this.componentFinder = componentFinder;
-  }
-
-  public String getProfileKey(@Nullable String language, @Nullable String profileName, @Nullable String profileKey) {
-    checkArgument((!isEmpty(language) && !isEmpty(profileName)) ^ !isEmpty(profileKey), BAD_PROFILE_PARAMETERS_ERROR);
-    return profileKey == null ? getProfileKeyFromLanguageAndName(language, profileName) : profileKey;
-  }
-
-  public ComponentDto getProject(DbSession dbSession, @Nullable String projectKey, @Nullable String projectUuid) {
-    return componentFinder.getByUuidOrKey(dbSession, projectUuid, projectKey, ComponentFinder.ParamNames.PROJECT_UUID_AND_KEY);
-  }
-
-  private String getProfileKeyFromLanguageAndName(String language, String profileName) {
-    QProfile profile = profileLookup.profile(profileName, language);
-    if (profile == null) {
-      throw new NotFoundException(String.format("Unable to find a profile for language '%s' with name '%s'", language, profileName));
-    }
-    return profile.key();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectAssociationParameters.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectAssociationParameters.java
deleted file mode 100644 (file)
index 23d8552..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.sonar.api.resources.Languages;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.core.util.Uuids;
-import org.sonar.server.util.LanguageParamUtils;
-
-import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
-import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
-import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_KEY;
-import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_NAME;
-import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_KEY;
-import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_UUID;
-
-public class ProjectAssociationParameters {
-
-  private final Languages languages;
-
-  public ProjectAssociationParameters(Languages languages) {
-    this.languages = languages;
-  }
-
-  void addParameters(WebService.NewAction action) {
-    action.setPost(true);
-    action.createParam(PARAM_PROJECT_UUID)
-      .setDescription("A project UUID. Either this parameter, or projectKey must be set.")
-      .setExampleValue("69e57151-be0d-4157-adff-c06741d88879");
-    action.createParam(PARAM_PROJECT_KEY)
-      .setDescription("A project key. Either this parameter, or projectUuid must be set.")
-      .setExampleValue(KEY_PROJECT_EXAMPLE_001);
-    action.createParam(PARAM_PROFILE_KEY)
-      .setDescription("A quality profile key. Either this parameter, or a combination of profileName + language must be set.")
-      .setExampleValue(Uuids.UUID_EXAMPLE_01);
-    action.createParam(PARAM_PROFILE_NAME)
-      .setDescription("A quality profile name. If this parameter is set, profileKey must not be set and language must be set to disambiguate.")
-      .setExampleValue("Soanr way");
-    action.createParam(PARAM_LANGUAGE)
-      .setDescription("A quality profile language. If this parameter is set, profileKey must not be set and profileName must be set to disambiguate.")
-      .setPossibleValues(LanguageParamUtils.getLanguageKeys(languages))
-      .setExampleValue("js");
-  }
-
-}
index c492fb733214810337de692fcc764ab8ca23f66c..028f3caefabb964704e44c9c1c2d1b7dd9d33ad2 100644 (file)
  */
 package org.sonar.server.qualityprofile.ws;
 
+import java.util.Arrays;
 import java.util.Optional;
 import javax.annotation.Nullable;
+import org.sonar.api.resources.Language;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.core.util.Uuids;
-import org.sonar.server.util.LanguageParamUtils;
+import org.sonar.core.util.stream.Collectors;
 
 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.apache.commons.lang.StringUtils.isEmpty;
 import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_ORGANIZATION;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_KEY;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_NAME;
 
 /**
  * Reference to a Quality profile as defined by requests to web services api/qualityprofiles.
@@ -43,10 +48,6 @@ import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_ORG
  */
 public class QProfileReference {
 
-  public static final String DEFAULT_PARAM_PROFILE_KEY = "profileKey";
-  public static final String DEFAULT_PARAM_LANGUAGE = "language";
-  public static final String DEFAULT_PARAM_PROFILE_NAME = "profileName";
-
   private enum Type {
     KEY, NAME
   }
@@ -149,10 +150,10 @@ public class QProfileReference {
   }
 
   public static QProfileReference from(Request request) {
-    String key = request.param(DEFAULT_PARAM_PROFILE_KEY);
+    String key = request.param(PARAM_PROFILE_KEY);
     String organizationKey = request.param(PARAM_ORGANIZATION);
-    String lang = request.param(DEFAULT_PARAM_LANGUAGE);
-    String name = request.param(DEFAULT_PARAM_PROFILE_NAME);
+    String lang = request.param(PARAM_LANGUAGE);
+    String name = request.param(PARAM_PROFILE_NAME);
     return from(key, organizationKey, lang, name);
   }
 
@@ -174,15 +175,14 @@ public class QProfileReference {
   }
 
   public static void defineParams(WebService.NewAction action, Languages languages) {
-    action.createParam(DEFAULT_PARAM_PROFILE_KEY)
+    action.createParam(PARAM_PROFILE_KEY)
       .setDescription("A quality profile key. Either this parameter, or a combination of profileName + language must be set.")
       .setExampleValue(Uuids.UUID_EXAMPLE_01);
-    action.createParam(DEFAULT_PARAM_PROFILE_NAME)
+    action.createParam(PARAM_PROFILE_NAME)
       .setDescription("A quality profile name. If this parameter is set, profileKey must not be set and language must be set to disambiguate.")
       .setExampleValue("Sonar way");
-    action.createParam(DEFAULT_PARAM_LANGUAGE)
+    action.createParam(PARAM_LANGUAGE)
       .setDescription("A quality profile language. If this parameter is set, profileKey must not be set and profileName must be set to disambiguate.")
-      .setPossibleValues(LanguageParamUtils.getLanguageKeys(languages))
-      .setExampleValue("js");
+      .setPossibleValues(Arrays.stream(languages.all()).map(Language::getKey).collect(Collectors.toSet()));
   }
 }
index 284c0163971495f5e0835436c4ecbb84fdb66c6c..27b728ea95913725b7c4a38bf2dfa047b9abedbd 100644 (file)
@@ -82,8 +82,8 @@ public class QProfileWsSupport {
       .checkPermission(ADMINISTER_QUALITY_PROFILES, defaultOrganizationProvider.get().getUuid());
   }
 
-  public static NewParam createOrganizationParam(NewAction create) {
-    return create
+  public static NewParam createOrganizationParam(NewAction action) {
+    return action
       .createParam(PARAM_ORGANIZATION)
       .setDescription("Organization key")
       .setRequired(false)
index 2acbcfff2472dca6f7134c60e46a5d489c454537..50eaa911c26e7455d5e9ba30054d9bb219bdb2d3 100644 (file)
@@ -41,8 +41,6 @@ public class QProfilesWsModule extends Module {
       ImportersAction.class,
       InheritanceAction.class,
       QProfilesWs.class,
-      ProjectAssociationFinder.class,
-      ProjectAssociationParameters.class,
       ProjectsAction.class,
       RenameAction.class,
       RemoveProjectAction.class,
index d0a9388a221397e22e1fee02aa7d5ecdcb113ad7..22ae324456591a12da6c88990d460485c6718009 100644 (file)
  */
 package org.sonar.server.qualityprofile.ws;
 
+import org.sonar.api.resources.Languages;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.api.web.UserRole;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
-import org.sonar.server.qualityprofile.QProfileProjectOperations;
-import org.sonarqube.ws.client.qualityprofile.RemoveProjectRequest;
+import org.sonar.db.permission.OrganizationPermission;
+import org.sonar.db.qualityprofile.QualityProfileDto;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.user.UserSession;
 
+import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_REMOVE_PROJECT;
-import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
-import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_KEY;
-import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_NAME;
 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_KEY;
 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_UUID;
 
 public class RemoveProjectAction implements QProfileWsAction {
 
-  private final ProjectAssociationParameters projectAssociationParameters;
-  private final ProjectAssociationFinder projectAssociationFinder;
-  private final QProfileProjectOperations profileProjectOperations;
   private final DbClient dbClient;
+  private final UserSession userSession;
+  private final Languages languages;
+  private final ComponentFinder componentFinder;
+  private final QProfileWsSupport wsSupport;
 
-  public RemoveProjectAction(ProjectAssociationParameters projectAssociationParameters, ProjectAssociationFinder projectAssociationFinder,
-    QProfileProjectOperations profileProjectOperations, DbClient dbClient) {
-    this.projectAssociationParameters = projectAssociationParameters;
-    this.projectAssociationFinder = projectAssociationFinder;
-    this.profileProjectOperations = profileProjectOperations;
+  public RemoveProjectAction(DbClient dbClient, UserSession userSession, Languages languages, ComponentFinder componentFinder, QProfileWsSupport wsSupport) {
     this.dbClient = dbClient;
+    this.userSession = userSession;
+    this.languages = languages;
+    this.componentFinder = componentFinder;
+    this.wsSupport = wsSupport;
   }
 
   @Override
@@ -56,29 +60,51 @@ public class RemoveProjectAction implements QProfileWsAction {
     NewAction action = controller.createAction(ACTION_REMOVE_PROJECT)
       .setSince("5.2")
       .setDescription("Remove a project's association with a quality profile.")
+      .setPost(true)
       .setHandler(this);
-    projectAssociationParameters.addParameters(action);
+    QProfileReference.defineParams(action, languages);
+    QProfileWsSupport.createOrganizationParam(action).setSince("6.4");
+
+    action.createParam(PARAM_PROJECT_UUID)
+      .setDescription("A project UUID. Either this parameter, or projectKey must be set.")
+      .setExampleValue("69e57151-be0d-4157-adff-c06741d88879");
+    action.createParam(PARAM_PROJECT_KEY)
+      .setDescription("A project key. Either this parameter, or projectUuid must be set.")
+      .setExampleValue(KEY_PROJECT_EXAMPLE_001);
   }
 
   @Override
   public void handle(Request request, Response response) throws Exception {
-    RemoveProjectRequest removeProjectRequest = toWsRequest(request);
+    // fail fast if not logged in
+    userSession.checkLoggedIn();
+
     try (DbSession dbSession = dbClient.openSession(false)) {
-      String profileKey = projectAssociationFinder.getProfileKey(removeProjectRequest.getLanguage(), removeProjectRequest.getProfileName(), removeProjectRequest.getProfileKey());
-      ComponentDto project = projectAssociationFinder.getProject(dbSession, removeProjectRequest.getProjectKey(), removeProjectRequest.getProjectUuid());
-      profileProjectOperations.removeProject(dbSession, profileKey, project);
+      ComponentDto project = loadProject(dbSession, request);
+      QualityProfileDto profile = wsSupport.getProfile(dbSession, QProfileReference.from(request));
+
+      if (!profile.getOrganizationUuid().equals(project.getOrganizationUuid())) {
+        throw new IllegalArgumentException("Project and Quality profile must have same organization");
+      }
+
+      dbClient.qualityProfileDao().deleteProjectProfileAssociation(project.uuid(), profile.getKey(), dbSession);
+      dbSession.commit();
+
+      response.noContent();
     }
-    response.noContent();
   }
 
-  private static RemoveProjectRequest toWsRequest(Request request) {
-    return RemoveProjectRequest.builder()
-      .setLanguage(request.param(PARAM_LANGUAGE))
-      .setProfileName(request.param(PARAM_PROFILE_NAME))
-      .setProfileKey(request.param(PARAM_PROFILE_KEY))
-      .setProjectKey(request.param(PARAM_PROJECT_KEY))
-      .setProjectUuid(request.param(PARAM_PROJECT_UUID))
-      .build();
+  private ComponentDto loadProject(DbSession dbSession, Request request) {
+    String projectKey = request.param(PARAM_PROJECT_KEY);
+    String projectUuid = request.param(PARAM_PROJECT_UUID);
+    ComponentDto project = componentFinder.getByUuidOrKey(dbSession, projectUuid, projectKey, ComponentFinder.ParamNames.PROJECT_UUID_AND_KEY);
+    checkAdministrator(project);
+    return project;
   }
 
+  private void checkAdministrator(ComponentDto project) {
+    if (!userSession.hasPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, project.getOrganizationUuid()) &&
+      !userSession.hasComponentPermission(UserRole.ADMIN, project)) {
+      throw new ForbiddenException("Insufficient privileges");
+    }
+  }
 }
index fdc42b1b6d0bd87889d6b3a6d142fccf699ded55..d5909fd7f221301644e250d2e8febf584b186465 100644 (file)
@@ -38,7 +38,6 @@ import org.sonar.db.component.ComponentDto;
 import org.sonar.db.organization.OrganizationDto;
 import org.sonar.server.component.ComponentFinder;
 import org.sonar.server.qualityprofile.QProfile;
-import org.sonar.server.qualityprofile.QProfileFactory;
 import org.sonar.server.qualityprofile.QProfileLookup;
 import org.sonarqube.ws.client.qualityprofile.SearchWsRequest;
 
@@ -47,21 +46,19 @@ import static java.lang.String.format;
 public class SearchDataLoader {
 
   private static final Comparator<QProfile> Q_PROFILE_COMPARATOR = Comparator
-          .comparing(QProfile::language)
-          .thenComparing(QProfile::name);
+    .comparing(QProfile::language)
+    .thenComparing(QProfile::name);
 
   private final Languages languages;
   private final QProfileLookup profileLookup;
-  private final QProfileFactory profileFactory;
   private final DbClient dbClient;
   private final ComponentFinder componentFinder;
   private final QProfileWsSupport qProfileWsSupport;
 
-  public SearchDataLoader(Languages languages, QProfileLookup profileLookup, QProfileFactory profileFactory, DbClient dbClient,
+  public SearchDataLoader(Languages languages, QProfileLookup profileLookup, DbClient dbClient,
     ComponentFinder componentFinder, QProfileWsSupport qProfileWsSupport) {
     this.languages = languages;
     this.profileLookup = profileLookup;
-    this.profileFactory = profileFactory;
     this.dbClient = dbClient;
     this.componentFinder = componentFinder;
     this.qProfileWsSupport = qProfileWsSupport;
@@ -134,7 +131,7 @@ public class SearchDataLoader {
       return languageKeys;
     }
 
-    profileFactory.getByNameAndLanguages(dbSession, organization, profileName, languageKeys)
+    dbClient.qualityProfileDao().selectByNameAndLanguages(organization, profileName, languageKeys, dbSession)
       .forEach(qualityProfile -> qualityProfiles
         .put(qualityProfile.getLanguage(), QProfile.from(qualityProfile, organization)));
     return difference(languageKeys, qualityProfiles.keySet());
@@ -147,8 +144,8 @@ public class SearchDataLoader {
     }
 
     ComponentDto project = getProject(moduleKey, dbSession);
-    profileFactory.getByProjectAndLanguages(dbSession, organization, project.getKey(), languageKeys)
-            .forEach(qualityProfile -> qualityProfiles.put(qualityProfile.getLanguage(), QProfile.from(qualityProfile, organization)));
+    dbClient.qualityProfileDao().selectByProjectAndLanguages(dbSession, organization, project.getKey(), languageKeys)
+      .forEach(qualityProfile -> qualityProfiles.put(qualityProfile.getLanguage(), QProfile.from(qualityProfile, organization)));
     return difference(languageKeys, qualityProfiles.keySet());
   }
 
@@ -182,7 +179,7 @@ public class SearchDataLoader {
   }
 
   private List<QProfile> findDefaultProfiles(final DbSession dbSession, OrganizationDto organization, Set<String> languageKeys) {
-    return profileFactory.getDefaults(dbSession, organization, languageKeys).stream()
+    return dbClient.qualityProfileDao().selectDefaultProfiles(dbSession, organization, languageKeys).stream()
       .map(result -> QProfile.from(result, organization))
       .collect(Collectors.toList());
   }
index c086786afef23f31ea5ba509dd54f50180e3c833..7c3656561db5b5e13c5e25ebf6b217cc931ae07a 100644 (file)
  */
 package org.sonar.server.qualityprofile.ws;
 
-import org.junit.Before;
+import java.net.HttpURLConnection;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.sonar.api.resources.Languages;
-import org.sonar.api.utils.System2;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.web.UserRole;
 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.component.ComponentTesting;
-import org.sonar.db.qualityprofile.QualityProfileDbTester;
+import org.sonar.db.organization.OrganizationDto;
 import org.sonar.db.qualityprofile.QualityProfileDto;
 import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.exceptions.UnauthorizedException;
 import org.sonar.server.language.LanguageTesting;
-import org.sonar.server.qualityprofile.QProfileLookup;
-import org.sonar.server.qualityprofile.QProfileName;
-import org.sonar.server.qualityprofile.QProfileProjectOperations;
+import org.sonar.server.organization.TestDefaultOrganizationProvider;
 import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.TestResponse;
 import org.sonar.server.ws.WsActionTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES;
-import static org.sonar.server.qualityprofile.QProfileTesting.newQProfileDto;
 
 public class AddProjectActionTest {
 
   private static final String LANGUAGE_1 = "xoo";
   private static final String LANGUAGE_2 = "foo";
 
-  private System2 system2 = System2.INSTANCE;
-
   @Rule
-  public DbTester dbTester = DbTester.create(system2);
-
+  public DbTester db = DbTester.create();
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
   @Rule
   public UserSessionRule userSession = UserSessionRule.standalone();
 
-  private DbClient dbClient = dbTester.getDbClient();
-  private DbSession session = dbTester.getSession();
-  private QualityProfileDbTester qualityProfileDbTester = new QualityProfileDbTester(dbTester);
-  private QProfileProjectOperations qProfileProjectOperations = new QProfileProjectOperations(dbClient, userSession);
+  private DbClient dbClient = db.getDbClient();
   private Languages languages = LanguageTesting.newLanguages(LANGUAGE_1, LANGUAGE_2);
-  private ProjectAssociationParameters projectAssociationParameters = new ProjectAssociationParameters(languages);
+  private QProfileWsSupport wsSupport = new QProfileWsSupport(dbClient, userSession, TestDefaultOrganizationProvider.from(db));
+  private AddProjectAction underTest = new AddProjectAction(dbClient, userSession, languages, new ComponentFinder(dbClient), wsSupport);
+  private WsActionTester tester = new WsActionTester(underTest);
+
+  @Test
+  public void test_definition() {
+    WebService.Action definition = tester.getDef();
+    assertThat(definition.since()).isEqualTo("5.2");
+    assertThat(definition.isPost()).isTrue();
+
+    // parameters
+    assertThat(definition.params()).extracting(WebService.Param::key).containsOnly("profileKey", "profileName", "projectKey", "language", "projectUuid", "organization");
+    WebService.Param languageParam = definition.param("language");
+    assertThat(languageParam.possibleValues()).containsOnly(LANGUAGE_1, LANGUAGE_2);
+    assertThat(languageParam.exampleValue()).isNull();
+    WebService.Param organizationParam = definition.param("organization");
+    assertThat(organizationParam.since()).isEqualTo("6.4");
+    assertThat(organizationParam.isInternal()).isTrue();
+  }
 
-  private ComponentDto project;
+  @Test
+  public void add_project_on_profile_of_default_organization() {
+    logInAsProfileAdmin(db.getDefaultOrganization());
+    ComponentDto project = db.components().insertProject(db.getDefaultOrganization());
+    QualityProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization());
+
+    TestResponse response = call(project, profile);
+    assertThat(response.getStatus()).isEqualTo(HttpURLConnection.HTTP_NO_CONTENT);
+
+    assertProjectIsAssociatedToProfile(project, profile);
+  }
+
+  @Test
+  public void add_project_on_profile_of_specified_organization() {
+    OrganizationDto org1 = db.organizations().insert();
+    logInAsProfileAdmin(org1);
+    ComponentDto project = db.components().insertProject(org1);
+    QualityProfileDto profile = db.qualityProfiles().insert(org1, p -> p.setLanguage(LANGUAGE_1));
 
-  private WsActionTester ws = new WsActionTester(new AddProjectAction(projectAssociationParameters,
-    qProfileProjectOperations, new ProjectAssociationFinder(new QProfileLookup(dbClient),
-      new ComponentFinder(dbClient)),dbClient));
+    TestResponse response = call(org1, project, profile);
+    assertThat(response.getStatus()).isEqualTo(HttpURLConnection.HTTP_NO_CONTENT);
 
-  @Before
-  public void setUp() throws Exception {
-    project = dbTester.components().insertComponent(ComponentTesting.newProjectDto(dbTester.organizations().insert()));
+    assertProjectIsAssociatedToProfile(project, profile);
   }
 
   @Test
-  public void add_project() throws Exception {
-    setUserAsQualityProfileAdmin();
-    QualityProfileDto profile = qualityProfileDbTester.insertQualityProfile(newQProfileDto("org-123", QProfileName.createFor(LANGUAGE_1, "profile1"), "Profile"));
-    session.commit();
+  public void throw_IAE_if_profile_and_project_are_in_different_organizations() {
+    OrganizationDto org1 = db.organizations().insert();
+    OrganizationDto org2 = db.organizations().insert();
+    logInAsProfileAdmin(org1);
+    ComponentDto project = db.components().insertProject(org1);
+    QualityProfileDto profileInOrg2 = db.qualityProfiles().insert(org2, p -> p.setLanguage(LANGUAGE_1));
 
-    executeRequest(project, profile);
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Project and Quality profile must have same organization");
 
-    assertProjectIsAssociatedToProfile(project.key(), LANGUAGE_1, profile.getKey());
+    call(org2, project, profileInOrg2);
+
+    assertProjectIsNotAssociatedToProfile(project, profileInOrg2);
   }
 
   @Test
-  public void change_project_association() throws Exception {
-    setUserAsQualityProfileAdmin();
-    QualityProfileDto profile1 = newQProfileDto("org-123", QProfileName.createFor(LANGUAGE_1, "profile1"), "Profile 1");
-    QualityProfileDto profile2 = newQProfileDto("org-123", QProfileName.createFor(LANGUAGE_1, "profile2"), "Profile 2");
-    qualityProfileDbTester.insertQualityProfiles(profile1, profile2);
-    qualityProfileDbTester.associateProjectWithQualityProfile(project, profile1);
-    session.commit();
+  public void throw_NotFoundException_if_profile_is_not_found_in_specified_organization() {
+    OrganizationDto org1 = db.organizations().insert();
+    OrganizationDto org2 = db.organizations().insert();
+    logInAsProfileAdmin(org1);
+    ComponentDto project = db.components().insertProject(org1);
+    QualityProfileDto profileInOrg2 = db.qualityProfiles().insert(org2, p -> p.setLanguage(LANGUAGE_1));
+
+    expectedException.expect(NotFoundException.class);
+    expectedException
+      .expectMessage("Quality Profile for language '" + LANGUAGE_1 + "' and name '" + profileInOrg2.getName() + "' does not exist in organization '" + org1.getKey() + "'");
 
-    executeRequest(project, profile2);
+    call(org1, project, profileInOrg2);
 
-    assertProjectIsAssociatedToProfile(project.key(), LANGUAGE_1, profile2.getKey());
+    assertProjectIsNotAssociatedToProfile(project, profileInOrg2);
   }
 
   @Test
-  public void change_project_association_when_project_is_linked_on_many_profiles() throws Exception {
-    setUserAsQualityProfileAdmin();
-    QualityProfileDto profile1Language1 = newQProfileDto("org-123", QProfileName.createFor(LANGUAGE_1, "profile1"), "Profile 1");
-    QualityProfileDto profile2Language2 = newQProfileDto("org-123", QProfileName.createFor(LANGUAGE_2, "profile2"), "Profile 2");
-    QualityProfileDto profile3Language1 = newQProfileDto("org-123", QProfileName.createFor(LANGUAGE_1, "profile3"), "Profile 3");
-    qualityProfileDbTester.insertQualityProfiles(profile1Language1, profile2Language2, profile3Language1);
-    qualityProfileDbTester.associateProjectWithQualityProfile(project, profile1Language1, profile2Language2);
-    session.commit();
+  public void change_association_in_default_organization() throws Exception {
+    logInAsProfileAdmin(db.getDefaultOrganization());
 
-    executeRequest(project, profile3Language1);
+    ComponentDto project = db.components().insertProject(db.getDefaultOrganization());
+    // two profiles on same language
+    QualityProfileDto profile1 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(LANGUAGE_1));
+    QualityProfileDto profile2 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(LANGUAGE_1));
+    db.qualityProfiles().associateProjectWithQualityProfile(project, profile1);
 
-    assertProjectIsAssociatedToProfile(project.key(), LANGUAGE_1, profile3Language1.getKey());
-    assertProjectIsAssociatedToProfile(project.key(), LANGUAGE_2, profile2Language2.getKey());
+    call(project, profile2);
+
+    assertProjectIsNotAssociatedToProfile(project, profile1);
+    assertProjectIsAssociatedToProfile(project, profile2);
   }
 
-  private void assertProjectIsAssociatedToProfile(String projectKey, String language, String expectedProfileKey) {
-    assertThat(dbClient.qualityProfileDao().selectByProjectAndLanguage(session, projectKey, language).getKey()).isEqualTo(expectedProfileKey);
+  @Test
+  public void changing_association_does_not_change_other_language_associations() throws Exception {
+    logInAsProfileAdmin(db.getDefaultOrganization());
+    ComponentDto project = db.components().insertProject(db.getDefaultOrganization());
+    QualityProfileDto profile1Language1 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(LANGUAGE_1));
+    QualityProfileDto profile2Language2 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(LANGUAGE_2));
+    QualityProfileDto profile3Language1 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(LANGUAGE_1));
+    db.qualityProfiles().associateProjectWithQualityProfile(project, profile1Language1, profile2Language2);
+
+    call(project, profile3Language1);
+
+    assertProjectIsAssociatedToProfile(project, profile3Language1);
+    assertProjectIsAssociatedToProfile(project, profile2Language2);
   }
 
-  private void setUserAsQualityProfileAdmin() {
-    userSession.logIn().addPermission(ADMINISTER_QUALITY_PROFILES, project.getOrganizationUuid());
+  @Test
+  public void project_administrator_can_change_profile() throws Exception {
+    ComponentDto project = db.components().insertProject(db.getDefaultOrganization());
+    QualityProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization());
+    userSession.logIn().addProjectUuidPermissions(UserRole.ADMIN, project.uuid());
+
+    call(project, profile);
+
+    assertProjectIsAssociatedToProfile(project, profile);
   }
 
-  private void executeRequest(ComponentDto project, QualityProfileDto qualityProfile) {
-    TestRequest request = ws.newRequest()
+  @Test
+  public void throw_ForbiddenException_if_not_project_nor_organization_administrator() {
+    userSession.logIn();
+    ComponentDto project = db.components().insertProject(db.getDefaultOrganization());
+    QualityProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization());
+
+    expectedException.expect(ForbiddenException.class);
+    expectedException.expectMessage("Insufficient privileges");
+
+    call(project, profile);
+  }
+
+  @Test
+  public void throw_UnauthorizedException_if_not_logged_in() {
+    userSession.anonymous();
+    ComponentDto project = db.components().insertProject(db.getDefaultOrganization());
+    QualityProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization());
+
+    expectedException.expect(UnauthorizedException.class);
+    expectedException.expectMessage("Authentication is required");
+
+    call(project, profile);
+  }
+
+  @Test
+  public void throw_NotFoundException_if_project_does_not_exist() {
+    logInAsProfileAdmin(db.getDefaultOrganization());
+    QualityProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization());
+
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Component id 'unknown' not found");
+
+    tester.newRequest()
+      .setParam("projectUuid", "unknown")
+      .setParam("profileKey", profile.getKey())
+      .execute();
+  }
+
+  @Test
+  public void throw_NotFoundException_if_profile_does_not_exist() {
+    logInAsProfileAdmin(db.getDefaultOrganization());
+    ComponentDto project = db.components().insertProject(db.getDefaultOrganization());
+
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Quality Profile with key 'unknown' does not exist");
+
+    tester.newRequest()
+      .setParam("projectUuid", project.uuid())
+      .setParam("profileKey", "unknown")
+      .execute();
+  }
+
+  private void assertProjectIsAssociatedToProfile(ComponentDto project, QualityProfileDto profile) {
+    QualityProfileDto loaded = dbClient.qualityProfileDao().selectByProjectAndLanguage(db.getSession(), project.getKey(), profile.getLanguage());
+    assertThat(loaded.getKey()).isEqualTo(profile.getKey());
+  }
+
+  private void assertProjectIsNotAssociatedToProfile(ComponentDto project, QualityProfileDto profile) {
+    QualityProfileDto loaded = dbClient.qualityProfileDao().selectByProjectAndLanguage(db.getSession(), project.getKey(), profile.getLanguage());
+    assertThat(loaded == null || !loaded.getKey().equals(profile.getKey())).isTrue();
+  }
+
+  private void logInAsProfileAdmin(OrganizationDto organization) {
+    userSession.logIn().addPermission(ADMINISTER_QUALITY_PROFILES, organization);
+  }
+
+  private TestResponse call(ComponentDto project, QualityProfileDto qualityProfile) {
+    TestRequest request = tester.newRequest()
       .setParam("projectUuid", project.uuid())
       .setParam("profileKey", qualityProfile.getKey());
-    request.execute();
+    return request.execute();
   }
 
+  private TestResponse call(OrganizationDto organization, ComponentDto project, QualityProfileDto qualityProfile) {
+    TestRequest request = tester.newRequest()
+      .setParam("organization", organization.getKey())
+      .setParam("projectUuid", project.uuid())
+      .setParam("language", qualityProfile.getLanguage())
+      .setParam("profileName", qualityProfile.getName());
+    return request.execute();
+  }
 }
index 1ccc3ed515563a420af4bb522d40a5599dea1580..f36dd9f10e08188eda72666fd61d679f29596f49 100644 (file)
@@ -32,10 +32,6 @@ import org.sonar.api.rule.Severity;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentTesting;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.organization.OrganizationTesting;
 import org.sonar.db.qualityprofile.ActiveRuleDao;
 import org.sonar.db.qualityprofile.ActiveRuleDto;
 import org.sonar.db.qualityprofile.ActiveRuleKey;
@@ -44,8 +40,6 @@ import org.sonar.db.rule.RuleDto;
 import org.sonar.db.rule.RuleTesting;
 import org.sonar.server.es.SearchOptions;
 import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.qualityprofile.QProfileFactory;
 import org.sonar.server.qualityprofile.QProfileName;
 import org.sonar.server.qualityprofile.QProfileTesting;
 import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
@@ -436,143 +430,6 @@ public class QProfilesWsMediumTest {
     assertThat(db.activeRuleDao().selectOrFailByKey(session, active2.getKey()).getSeverityString()).isNotEqualTo("MINOR");
   }
 
-  @Test
-  public void add_project_with_key_and_uuid() throws Exception {
-    OrganizationDto organizationDto = OrganizationTesting.newOrganizationDto();
-    db.organizationDao().insert(session, organizationDto);
-    ComponentDto project = ComponentTesting.newProjectDto(organizationDto, "ABCD").setId(1L);
-    db.componentDao().insert(session, project);
-    QualityProfileDto profile = QProfileTesting.newXooP1("org-123");
-    db.qualityProfileDao().insert(session, profile);
-
-    session.commit();
-
-    wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "add_project")
-      .setParam("profileKey", profile.getKee()).setParam("projectUuid", project.uuid())
-      .execute().assertNoContent();
-    assertThat(tester.get(QProfileFactory.class).getByProjectAndLanguage(session, project.getKey(), "xoo").getKee()).isEqualTo(profile.getKee());
-
-    // Second call must not fail, do nothing
-    wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "add_project")
-      .setParam("profileKey", profile.getKee()).setParam("projectUuid", project.uuid())
-      .execute().assertNoContent();
-    assertThat(tester.get(QProfileFactory.class).getByProjectAndLanguage(session, project.getKey(), "xoo").getKee()).isEqualTo(profile.getKee());
-  }
-
-  @Test
-  public void change_project_association_with_key_and_uuid() throws Exception {
-    OrganizationDto organizationDto = OrganizationTesting.newOrganizationDto();
-    db.organizationDao().insert(session, organizationDto);
-    ComponentDto project = ComponentTesting.newProjectDto(organizationDto, "ABCD").setId(1L);
-    db.componentDao().insert(session, project);
-    QualityProfileDto profile1 = QProfileTesting.newXooP1("org-123");
-    QualityProfileDto profile2 = QProfileTesting.newXooP2("org-123");
-    db.qualityProfileDao().insert(session, profile1, profile2);
-    db.qualityProfileDao().insertProjectProfileAssociation(project.uuid(), profile1.getKey(), session);
-
-    session.commit();
-
-    wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "add_project")
-      .setParam("profileKey", profile2.getKee()).setParam("projectUuid", project.uuid())
-      .execute().assertNoContent();
-    assertThat(tester.get(QProfileFactory.class).getByProjectAndLanguage(session, project.getKey(), "xoo").getKee()).isEqualTo(profile2.getKee());
-  }
-
-  @Test
-  public void add_project_with_name_language_and_key() throws Exception {
-    OrganizationDto organizationDto = OrganizationTesting.newOrganizationDto();
-    db.organizationDao().insert(session, organizationDto);
-    ComponentDto project = ComponentTesting.newProjectDto(organizationDto, "ABCD").setId(1L);
-    db.componentDao().insert(session, project);
-    QualityProfileDto profile = QProfileTesting.newXooP1("org-123");
-    db.qualityProfileDao().insert(session, profile);
-
-    session.commit();
-
-    wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "add_project")
-      .setParam("language", "xoo").setParam("profileName", profile.getName()).setParam("projectKey", project.getKey())
-      .execute().assertNoContent();
-    assertThat(tester.get(QProfileFactory.class).getByProjectAndLanguage(session, project.getKey(), "xoo").getKee()).isEqualTo(profile.getKee());
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void add_project_missing_language() throws Exception {
-    wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "add_project")
-      .setParam("profileName", "polop").setParam("projectKey", "palap")
-      .execute();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void add_project_missing_name() throws Exception {
-    wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "add_project")
-      .setParam("language", "xoo").setParam("projectKey", "palap")
-      .execute();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void add_project_too_many_profile_parameters() throws Exception {
-    wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "add_project")
-      .setParam("profileKey", "plouf").setParam("language", "xoo").setParam("profileName", "polop").setParam("projectUuid", "palap")
-      .execute();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void add_project_missing_project() throws Exception {
-    wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "add_project")
-      .setParam("profileKey", "plouf")
-      .execute();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void add_project_too_many_project_parameters() throws Exception {
-    wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "add_project")
-      .setParam("profileKey", "plouf").setParam("projectUuid", "polop").setParam("projectKey", "palap")
-      .execute();
-  }
-
-  @Test(expected = NotFoundException.class)
-  public void add_project_unknown_profile() throws Exception {
-    wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "add_project")
-      .setParam("projectUuid", "plouf").setParam("profileName", "polop").setParam("language", "xoo")
-      .execute();
-  }
-
-  @Test
-  public void remove_project_with_key_and_uuid() throws Exception {
-    OrganizationDto organizationDto = OrganizationTesting.newOrganizationDto();
-    db.organizationDao().insert(session, organizationDto);
-    ComponentDto project = ComponentTesting.newProjectDto(organizationDto, "ABCD").setId(1L);
-    db.componentDao().insert(session, project);
-    QualityProfileDto profile = QProfileTesting.newXooP1("org-123");
-    db.qualityProfileDao().insert(session, profile);
-    db.qualityProfileDao().insertProjectProfileAssociation(project.uuid(), profile.getKee(), session);
-
-    session.commit();
-
-    wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "remove_project")
-      .setParam("profileKey", profile.getKee()).setParam("projectUuid", project.uuid())
-      .execute().assertNoContent();
-    assertThat(tester.get(QProfileFactory.class).getByProjectAndLanguage(session, project.getKey(), "xoo")).isNull();
-  }
-
-  @Test
-  public void remove_project_with_name_language_and_key() throws Exception {
-    OrganizationDto organizationDto = OrganizationTesting.newOrganizationDto();
-    db.organizationDao().insert(session, organizationDto);
-    ComponentDto project = ComponentTesting.newProjectDto(organizationDto, "ABCD").setId(1L);
-    db.componentDao().insert(session, project);
-    QualityProfileDto profile = QProfileTesting.newXooP1("org-123");
-    db.qualityProfileDao().insert(session, profile);
-    db.qualityProfileDao().insertProjectProfileAssociation(project.uuid(), profile.getKee(), session);
-
-    session.commit();
-
-    wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "remove_project")
-      .setParam("language", "xoo").setParam("profileName", profile.getName()).setParam("projectKey", project.getKey())
-      .execute().assertNoContent();
-    assertThat(tester.get(QProfileFactory.class).getByProjectAndLanguage(session, project.getKey(), "xoo")).isNull();
-  }
-
   private QualityProfileDto createProfile(String lang) {
     QualityProfileDto profile = QProfileTesting.newQProfileDto("org-123", new QProfileName(lang, "P" + lang), "p" + lang);
     db.qualityProfileDao().insert(session, profile);
index 60f84b6d05cd81947b77dcec47e707cc33f0f460..4c66f747be148822e4ed1ef5eba2ff5629cd9a43 100644 (file)
@@ -29,6 +29,6 @@ public class QProfilesWsModuleTest {
   public void verify_count_of_added_components() {
     ComponentContainer container = new ComponentContainer();
     new QProfilesWsModule().configure(container);
-    assertThat(container.size()).isEqualTo(26 + 2);
+    assertThat(container.size()).isEqualTo(24 + 2);
   }
 }
index bc60c29e51cb1ccd2e9becf43f7d5a6927ba17eb..defbe820c1a23e39b61478e6f2b0e8cafacb29d8 100644 (file)
@@ -57,15 +57,12 @@ public class QProfilesWsTest {
     DbClient dbClient = mock(DbClient.class);
 
     Languages languages = LanguageTesting.newLanguages(xoo1Key, xoo2Key);
-    ProjectAssociationParameters projectAssociationParameters = new ProjectAssociationParameters(languages);
 
     ProfileImporter[] importers = createImporters(languages);
 
     controller = new WsTester(new QProfilesWs(
       new RuleActivationActions(profileService),
       new BulkRuleActivationActions(profileService, null),
-      new AddProjectAction(projectAssociationParameters, null, null, dbClient),
-      new RemoveProjectAction(projectAssociationParameters, null, null, dbClient),
       new CreateAction(null, null, null, languages, wsSupport, userSessionRule, null, importers),
       new ImportersAction(importers),
       new SearchAction(null, languages, null, dbClient),
@@ -133,22 +130,6 @@ public class QProfilesWsTest {
     assertThat(restoreProfiles.params()).hasSize(2);
   }
 
-  @Test
-  public void define_add_project_action() {
-    WebService.Action addProject = controller.action("add_project");
-    assertThat(addProject).isNotNull();
-    assertThat(addProject.isPost()).isTrue();
-    assertThat(addProject.params()).hasSize(5);
-  }
-
-  @Test
-  public void define_remove_project_action() {
-    WebService.Action removeProject = controller.action("remove_project");
-    assertThat(removeProject).isNotNull();
-    assertThat(removeProject.isPost()).isTrue();
-    assertThat(removeProject.params()).hasSize(5);
-  }
-
   @Test
   public void define_set_default_action() {
     WebService.Action setDefault = controller.action("set_default");
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RemoveProjectActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RemoveProjectActionTest.java
new file mode 100644 (file)
index 0000000..5ff0737
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * 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 java.net.HttpURLConnection;
+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.api.web.UserRole;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.qualityprofile.QualityProfileDto;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.language.LanguageTesting;
+import org.sonar.server.organization.TestDefaultOrganizationProvider;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.TestResponse;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES;
+
+public class RemoveProjectActionTest {
+  private static final String LANGUAGE_1 = "xoo";
+  private static final String LANGUAGE_2 = "foo";
+
+  @Rule
+  public DbTester db = DbTester.create();
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+  @Rule
+  public UserSessionRule userSession = UserSessionRule.standalone();
+
+  private DbClient dbClient = db.getDbClient();
+  private Languages languages = LanguageTesting.newLanguages(LANGUAGE_1, LANGUAGE_2);
+  private QProfileWsSupport wsSupport = new QProfileWsSupport(dbClient, userSession, TestDefaultOrganizationProvider.from(db));
+  private RemoveProjectAction underTest = new RemoveProjectAction(dbClient, userSession, languages, new ComponentFinder(dbClient), wsSupport);
+  private WsActionTester tester = new WsActionTester(underTest);
+
+  @Test
+  public void test_definition() {
+    WebService.Action definition = tester.getDef();
+    assertThat(definition.since()).isEqualTo("5.2");
+    assertThat(definition.isPost()).isTrue();
+
+    // parameters
+    assertThat(definition.params()).extracting(WebService.Param::key).containsOnly("profileKey", "profileName", "projectKey", "language", "projectUuid", "organization");
+    WebService.Param languageParam = definition.param("language");
+    assertThat(languageParam.possibleValues()).containsOnly(LANGUAGE_1, LANGUAGE_2);
+    assertThat(languageParam.exampleValue()).isNull();
+    WebService.Param organizationParam = definition.param("organization");
+    assertThat(organizationParam.since()).isEqualTo("6.4");
+    assertThat(organizationParam.isInternal()).isTrue();
+  }
+
+  @Test
+  public void remove_profile_from_project_in_default_organization() {
+    logInAsProfileAdmin();
+
+    ComponentDto project = db.components().insertProject(db.getDefaultOrganization());
+    QualityProfileDto profileLang1 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(LANGUAGE_1));
+    QualityProfileDto profileLang2 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(LANGUAGE_2));
+    db.qualityProfiles().associateProjectWithQualityProfile(project, profileLang1);
+    db.qualityProfiles().associateProjectWithQualityProfile(project, profileLang2);
+
+    TestResponse response = call(project, profileLang1);
+    assertThat(response.getStatus()).isEqualTo(HttpURLConnection.HTTP_NO_CONTENT);
+
+    assertProjectIsNotAssociatedToProfile(project, profileLang1);
+    assertProjectIsAssociatedToProfile(project, profileLang2);
+  }
+
+  @Test
+  public void removal_does_not_fail_if_profile_is_not_associated_to_project() {
+    logInAsProfileAdmin();
+
+    ComponentDto project = db.components().insertProject(db.getDefaultOrganization());
+    QualityProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization());
+
+    TestResponse response = call(project, profile);
+    assertThat(response.getStatus()).isEqualTo(HttpURLConnection.HTTP_NO_CONTENT);
+
+    assertProjectIsNotAssociatedToProfile(project, profile);
+  }
+
+  @Test
+  public void project_administrator_can_remove_profile() throws Exception {
+    ComponentDto project = db.components().insertProject(db.getDefaultOrganization());
+    QualityProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization());
+    db.qualityProfiles().associateProjectWithQualityProfile(project, profile);
+    userSession.logIn().addProjectUuidPermissions(UserRole.ADMIN, project.uuid());
+
+    call(project, profile);
+
+    assertProjectIsNotAssociatedToProfile(project, profile);
+  }
+
+  @Test
+  public void throw_ForbiddenException_if_not_project_nor_organization_administrator() {
+    userSession.logIn();
+    ComponentDto project = db.components().insertProject(db.getDefaultOrganization());
+    QualityProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization());
+
+    expectedException.expect(ForbiddenException.class);
+    expectedException.expectMessage("Insufficient privileges");
+
+    call(project, profile);
+  }
+
+  @Test
+  public void throw_UnauthorizedException_if_not_logged_in() {
+    userSession.anonymous();
+    ComponentDto project = db.components().insertProject(db.getDefaultOrganization());
+    QualityProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization());
+
+    expectedException.expect(UnauthorizedException.class);
+    expectedException.expectMessage("Authentication is required");
+
+    call(project, profile);
+  }
+
+  @Test
+  public void throw_NotFoundException_if_project_does_not_exist() {
+    logInAsProfileAdmin();
+    QualityProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization());
+
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Component id 'unknown' not found");
+
+    tester.newRequest()
+      .setParam("projectUuid", "unknown")
+      .setParam("profileKey", profile.getKey())
+      .execute();
+  }
+
+  @Test
+  public void throw_NotFoundException_if_profile_does_not_exist() {
+    logInAsProfileAdmin();
+    ComponentDto project = db.components().insertProject(db.getDefaultOrganization());
+
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Quality Profile with key 'unknown' does not exist");
+
+    tester.newRequest()
+      .setParam("projectUuid", project.uuid())
+      .setParam("profileKey", "unknown")
+      .execute();
+  }
+
+  private void assertProjectIsAssociatedToProfile(ComponentDto project, QualityProfileDto profile) {
+    QualityProfileDto loaded = dbClient.qualityProfileDao().selectByProjectAndLanguage(db.getSession(), project.getKey(), profile.getLanguage());
+    assertThat(loaded.getKey()).isEqualTo(profile.getKey());
+  }
+
+  private void assertProjectIsNotAssociatedToProfile(ComponentDto project, QualityProfileDto profile) {
+    QualityProfileDto loaded = dbClient.qualityProfileDao().selectByProjectAndLanguage(db.getSession(), project.getKey(), profile.getLanguage());
+    assertThat(loaded == null || !loaded.getKey().equals(profile.getKey())).isTrue();
+  }
+
+  private void logInAsProfileAdmin() {
+    userSession.logIn().addPermission(ADMINISTER_QUALITY_PROFILES, db.getDefaultOrganization());
+  }
+
+  private TestResponse call(ComponentDto project, QualityProfileDto qualityProfile) {
+    TestRequest request = tester.newRequest()
+      .setParam("projectUuid", project.uuid())
+      .setParam("profileKey", qualityProfile.getKey());
+    return request.execute();
+  }
+}
index f2dcb0fb894867befb6c9bb66783aa616118aed9..fccaa2af6f994b196ed928aa41f2c3cb14bdc118 100644 (file)
@@ -33,7 +33,6 @@ import org.sonar.api.resources.Language;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.System2;
-import org.sonar.core.util.UuidFactoryFast;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
@@ -51,7 +50,6 @@ import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.language.LanguageTesting;
 import org.sonar.server.organization.DefaultOrganizationProvider;
 import org.sonar.server.organization.TestDefaultOrganizationProvider;
-import org.sonar.server.qualityprofile.QProfileFactory;
 import org.sonar.server.qualityprofile.QProfileLookup;
 import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
 import org.sonar.server.tester.UserSessionRule;
@@ -78,7 +76,6 @@ import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.
 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_NAME;
 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_KEY;
 
-
 public class SearchActionTest {
 
   @Rule
@@ -113,7 +110,6 @@ public class SearchActionTest {
       new SearchDataLoader(
         languages,
         new QProfileLookup(dbClient),
-        new QProfileFactory(dbClient, UuidFactoryFast.getInstance(), System2.INSTANCE),
         dbClient,
         new ComponentFinder(dbClient), qProfileWsSupport),
       languages,
@@ -301,6 +297,7 @@ public class SearchActionTest {
       .contains("sonar-way-xoo1-12345", "sonar-way-xoo2-12345")
       .doesNotContain("sonar-way-xoo1-45678");
   }
+
   @Test
   public void search_default_profile_by_profile_name_and_org() {
     List<QualityProfileDto> profiles = new ArrayList<>();
index 215f30a9543022cbbc692beeb1f6378383bca0ab..78d35c3c47c42bc80ce72dbc810959e5be124e7e 100644 (file)
@@ -29,8 +29,6 @@ import org.junit.rules.ExpectedException;
 import org.sonar.api.resources.Language;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
-import org.sonar.core.util.UuidFactoryFast;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
@@ -39,11 +37,9 @@ import org.sonar.db.organization.OrganizationDto;
 import org.sonar.db.qualityprofile.QualityProfileDto;
 import org.sonar.db.qualityprofile.QualityProfileTesting;
 import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.language.LanguageTesting;
 import org.sonar.server.organization.TestDefaultOrganizationProvider;
 import org.sonar.server.qualityprofile.QProfile;
-import org.sonar.server.qualityprofile.QProfileFactory;
 import org.sonar.server.qualityprofile.QProfileLookup;
 import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
 import org.sonarqube.ws.client.qualityprofile.SearchWsRequest;
@@ -55,7 +51,6 @@ import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
-
 public class SearchDataLoaderTest {
 
   @Rule
@@ -66,7 +61,6 @@ public class SearchDataLoaderTest {
 
   private Languages languages;
   private QProfileLookup profileLookup;
-  private QProfileFactory profileFactory;
   private ComponentFinder componentFinder;
   private ActiveRuleIndex activeRuleIndex;
   private QProfileWsSupport qProfileWsSupport;
@@ -80,23 +74,20 @@ public class SearchDataLoaderTest {
     profileLookup = new QProfileLookup(dbClient);
     TestDefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(dbTester);
     qProfileWsSupport = new QProfileWsSupport(dbClient, null, defaultOrganizationProvider);
-    profileFactory = new QProfileFactory(dbClient, UuidFactoryFast.getInstance(), new AlwaysIncreasingSystem2());
     componentFinder = mock(ComponentFinder.class);
   }
 
   @Test
   public void find_no_profiles_if_database_is_empty() throws Exception {
     assertThat(findProfiles(
-      new SearchWsRequest()
-    )).isEmpty();
+      new SearchWsRequest())).isEmpty();
   }
 
   @Test
   public void findAll_in_default_organization() throws Exception {
     insertQualityProfile(dbTester.getDefaultOrganization());
     assertThat(findProfiles(
-      new SearchWsRequest()
-    )).hasSize(1);
+      new SearchWsRequest())).hasSize(1);
   }
 
   @Test
@@ -104,8 +95,7 @@ public class SearchDataLoaderTest {
     insertQualityProfile(organization);
     assertThat(findProfiles(
       new SearchWsRequest()
-        .setOrganizationKey(organization.getKey())
-    )).hasSize(1);
+        .setOrganizationKey(organization.getKey()))).hasSize(1);
   }
 
   @Test
@@ -114,8 +104,7 @@ public class SearchDataLoaderTest {
     assertThat(findProfiles(
       new SearchWsRequest()
         .setOrganizationKey(organization.getKey())
-        .setDefaults(true)
-    )).hasSize(1);
+        .setDefaults(true))).hasSize(1);
   }
 
   @Test
@@ -125,8 +114,7 @@ public class SearchDataLoaderTest {
     assertThat(findProfiles(
       new SearchWsRequest()
         .setOrganizationKey(organization.getKey())
-        .setProjectKey(project1.getKey())
-    )).hasSize(1);
+        .setProjectKey(project1.getKey()))).hasSize(1);
   }
 
   @Test
@@ -135,17 +123,15 @@ public class SearchDataLoaderTest {
     assertThat(findProfiles(
       new SearchWsRequest()
         .setOrganizationKey(organization.getKey())
-        .setLanguage(qualityProfile.getLanguage())
-    )).hasSize(1);
+        .setLanguage(qualityProfile.getLanguage()))).hasSize(1);
     assertThat(findProfiles(
       new SearchWsRequest()
         .setOrganizationKey(organization.getKey())
-        .setLanguage("other language")
-    )).hasSize(0);
+        .setLanguage("other language"))).hasSize(0);
   }
 
   private List<QProfile> findProfiles(SearchWsRequest request) {
-    return new SearchDataLoader(languages, profileLookup, profileFactory, dbTester.getDbClient(), componentFinder, qProfileWsSupport)
+    return new SearchDataLoader(languages, profileLookup, dbTester.getDbClient(), componentFinder, qProfileWsSupport)
       .findProfiles(dbTester.getSession(), request);
   }