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;
XMLProfileSerializer.class,
AnnotationProfileParser.class,
QProfileLookup.class,
- QProfileProjectOperations.class,
QProfileComparison.class,
SearchDataLoader.class,
ProfilesWs.class,
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;
// ------------- 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)}
*/
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());
*/
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 {
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);
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);
- }
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile;
-
-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");
- }
- }
-
-}
*/
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
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");
+ }
+ }
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import 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();
- }
-
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.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");
- }
-
-}
*/
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.
*/
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
}
}
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);
}
}
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()));
}
}
.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)
ImportersAction.class,
InheritanceAction.class,
QProfilesWs.class,
- ProjectAssociationFinder.class,
- ProjectAssociationParameters.class,
ProjectsAction.class,
RenameAction.class,
RemoveProjectAction.class,
*/
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
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");
+ }
+ }
}
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;
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;
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());
}
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());
}
}
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());
}
*/
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();
+ }
}
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;
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;
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);
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);
}
}
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),
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");
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import 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();
+ }
+}
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;
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;
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
new SearchDataLoader(
languages,
new QProfileLookup(dbClient),
- new QProfileFactory(dbClient, UuidFactoryFast.getInstance(), System2.INSTANCE),
dbClient,
new ComponentFinder(dbClient), qProfileWsSupport),
languages,
.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<>();
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;
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;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-
public class SearchDataLoaderTest {
@Rule
private Languages languages;
private QProfileLookup profileLookup;
- private QProfileFactory profileFactory;
private ComponentFinder componentFinder;
private ActiveRuleIndex activeRuleIndex;
private QProfileWsSupport qProfileWsSupport;
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
insertQualityProfile(organization);
assertThat(findProfiles(
new SearchWsRequest()
- .setOrganizationKey(organization.getKey())
- )).hasSize(1);
+ .setOrganizationKey(organization.getKey()))).hasSize(1);
}
@Test
assertThat(findProfiles(
new SearchWsRequest()
.setOrganizationKey(organization.getKey())
- .setDefaults(true)
- )).hasSize(1);
+ .setDefaults(true))).hasSize(1);
}
@Test
assertThat(findProfiles(
new SearchWsRequest()
.setOrganizationKey(organization.getKey())
- .setProjectKey(project1.getKey())
- )).hasSize(1);
+ .setProjectKey(project1.getKey()))).hasSize(1);
}
@Test
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);
}