aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>2016-12-16 15:27:24 +0100
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>2016-12-19 10:12:54 +0100
commit95ab6f6776c4b8e4ead3a4f6215c9c03c9b475c5 (patch)
tree6c5fc22660b58ba557cab2be13c7d2f9789f79df
parent6a94b3b976758fb094488c36b9c178e6ef811f81 (diff)
downloadsonarqube-95ab6f6776c4b8e4ead3a4f6215c9c03c9b475c5.tar.gz
sonarqube-95ab6f6776c4b8e4ead3a4f6215c9c03c9b475c5.zip
SONAR-7288 Create WS api/favorites/remove
-rw-r--r--it/it-tests/src/test/java/it/user/FavoritesWsTest.java3
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/favorite/FavoriteModule.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/favorite/FavoriteUpdater.java24
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/favorite/ws/RemoveAction.java82
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/favorite/FavoriteModuleTest.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/favorite/ws/RemoveActionTest.java131
-rw-r--r--sonar-db/src/test/java/org/sonar/db/DbTester.java9
-rw-r--r--sonar-db/src/test/java/org/sonar/db/favorite/FavoriteDbTester.java61
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/favorite/FavoritesService.java9
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/favorite/FavoritesWsParameters.java1
-rw-r--r--sonar-ws/src/test/java/org/sonarqube/ws/client/favorite/FavoritesServiceTest.java10
11 files changed, 328 insertions, 8 deletions
diff --git a/it/it-tests/src/test/java/it/user/FavoritesWsTest.java b/it/it-tests/src/test/java/it/user/FavoritesWsTest.java
index af4dd0740d1..62ec54251e8 100644
--- a/it/it-tests/src/test/java/it/user/FavoritesWsTest.java
+++ b/it/it-tests/src/test/java/it/user/FavoritesWsTest.java
@@ -28,7 +28,6 @@ import org.junit.ClassRule;
import org.junit.Test;
import org.sonar.wsclient.Sonar;
import org.sonar.wsclient.services.Favourite;
-import org.sonar.wsclient.services.FavouriteDeleteQuery;
import org.sonar.wsclient.services.FavouriteQuery;
import org.sonarqube.ws.client.WsClient;
@@ -69,7 +68,7 @@ public class FavoritesWsTest {
assertThat(favourites.stream().map(Favourite::getKey)).containsOnly("sample", "sample:src/main/xoo/sample/Sample.xoo");
// DELETE (a favorite)
- oldWsClient.delete(new FavouriteDeleteQuery("sample"));
+ adminClient.favorites().remove("sample");
favourites = oldWsClient.findAll(new FavouriteQuery());
assertThat(favourites.stream().map(Favourite::getKey)).containsOnly("sample:src/main/xoo/sample/Sample.xoo");
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/favorite/FavoriteModule.java b/server/sonar-server/src/main/java/org/sonar/server/favorite/FavoriteModule.java
index 7107b6df851..0a0da3ecedd 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/favorite/FavoriteModule.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/favorite/FavoriteModule.java
@@ -23,6 +23,7 @@ package org.sonar.server.favorite;
import org.sonar.core.platform.Module;
import org.sonar.server.favorite.ws.AddAction;
import org.sonar.server.favorite.ws.FavoritesWs;
+import org.sonar.server.favorite.ws.RemoveAction;
public class FavoriteModule extends Module {
@@ -31,7 +32,8 @@ public class FavoriteModule extends Module {
add(
FavoriteUpdater.class,
FavoritesWs.class,
- AddAction.class);
+ AddAction.class,
+ RemoveAction.class);
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/favorite/FavoriteUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/favorite/FavoriteUpdater.java
index 8aaf771f4dd..540e20fdb7f 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/favorite/FavoriteUpdater.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/favorite/FavoriteUpdater.java
@@ -22,9 +22,13 @@ package org.sonar.server.favorite;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
+import org.sonar.db.component.ComponentDto;
import org.sonar.db.property.PropertyDto;
+import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.user.UserSession;
+import static org.sonar.server.ws.WsUtils.checkRequest;
+
public class FavoriteUpdater {
private static final String PROP_FAVORITE_KEY = "favourite";
@@ -39,14 +43,30 @@ public class FavoriteUpdater {
/**
* Set favorite to the logged in user. If no user is logged, no action is done
*/
- public void add(DbSession dbSession, long componentDbId) {
+ public void add(DbSession dbSession, long componentDtoId) {
if (!userSession.isLoggedIn()) {
return;
}
dbClient.propertiesDao().saveProperty(dbSession, new PropertyDto()
.setKey(PROP_FAVORITE_KEY)
- .setResourceId(componentDbId)
+ .setResourceId(componentDtoId)
+ .setUserId(Long.valueOf(userSession.getUserId())));
+ }
+
+ /**
+ * Remove a favorite to the logged in user.
+ * @throws BadRequestException if the component is not a favorite
+ */
+ public void remove(DbSession dbSession, ComponentDto component) {
+ if (!userSession.isLoggedIn()) {
+ return;
+ }
+
+ int result = dbClient.propertiesDao().delete(dbSession, new PropertyDto()
+ .setKey(PROP_FAVORITE_KEY)
+ .setResourceId(component.getId())
.setUserId(Long.valueOf(userSession.getUserId())));
+ checkRequest(result == 1, "Component '%s' is not a favorite", component.key());
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/favorite/ws/RemoveAction.java b/server/sonar-server/src/main/java/org/sonar/server/favorite/ws/RemoveAction.java
new file mode 100644
index 00000000000..32591f84b9e
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/favorite/ws/RemoveAction.java
@@ -0,0 +1,82 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.favorite.ws;
+
+import java.util.function.Consumer;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+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.server.component.ComponentFinder;
+import org.sonar.server.favorite.FavoriteUpdater;
+import org.sonar.server.user.UserSession;
+import org.sonar.server.ws.KeyExamples;
+
+import static org.sonarqube.ws.client.favorite.FavoritesWsParameters.PARAM_COMPONENT;
+
+public class RemoveAction implements FavoritesWsAction {
+ private final UserSession userSession;
+ private final DbClient dbClient;
+ private final FavoriteUpdater favoriteUpdater;
+ private final ComponentFinder componentFinder;
+
+ public RemoveAction(UserSession userSession, DbClient dbClient, FavoriteUpdater favoriteUpdater, ComponentFinder componentFinder) {
+ this.userSession = userSession;
+ this.dbClient = dbClient;
+ this.favoriteUpdater = favoriteUpdater;
+ this.componentFinder = componentFinder;
+ }
+
+ @Override
+ public void define(WebService.NewController context) {
+ WebService.NewAction action = context.createAction("remove")
+ .setDescription("Remove a component (project, directory, file etc.) as favorite for the authenticated user.<br>" +
+ "Requires authentication.")
+ .setSince("6.3")
+ .setPost(true)
+ .setHandler(this);
+
+ action.createParam("component")
+ .setDescription("Component key")
+ .setRequired(true)
+ .setExampleValue(KeyExamples.KEY_PROJECT_EXAMPLE_001);
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ removeFavorite().accept(request);
+ response.noContent();
+ }
+
+ private Consumer<Request> removeFavorite() {
+ return request -> {
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ ComponentDto component = componentFinder.getByKey(dbSession, request.mandatoryParam(PARAM_COMPONENT));
+ userSession
+ .checkLoggedIn();
+ favoriteUpdater.remove(dbSession, component);
+ dbSession.commit();
+ }
+ };
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/favorite/FavoriteModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/favorite/FavoriteModuleTest.java
index 22c4bf1de6c..1affa2ca117 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/favorite/FavoriteModuleTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/favorite/FavoriteModuleTest.java
@@ -30,6 +30,6 @@ public class FavoriteModuleTest {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new FavoriteModule().configure(container);
- assertThat(container.size()).isEqualTo(3 + 2);
+ assertThat(container.size()).isEqualTo(4 + 2);
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/favorite/ws/RemoveActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/favorite/ws/RemoveActionTest.java
new file mode 100644
index 00000000000..eb0659339a5
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/favorite/ws/RemoveActionTest.java
@@ -0,0 +1,131 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.favorite.ws;
+
+import javax.annotation.Nullable;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.favorite.FavoriteUpdater;
+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 java.net.HttpURLConnection.HTTP_NO_CONTENT;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.core.util.Protobuf.setNullable;
+import static org.sonar.db.component.ComponentTesting.newFileDto;
+import static org.sonar.db.component.ComponentTesting.newProjectDto;
+import static org.sonarqube.ws.client.favorite.FavoritesWsParameters.PARAM_COMPONENT;
+
+public class RemoveActionTest {
+ private static final String PROJECT_KEY = "project-key";
+ private static final String PROJECT_UUID = "project-uuid";
+ private static final int USER_ID = 123;
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+ @Rule
+ public DbTester db = DbTester.create();
+ private DbClient dbClient = db.getDbClient();
+
+ private FavoriteUpdater favoriteUpdater = new FavoriteUpdater(dbClient, userSession);
+ private WsActionTester ws = new WsActionTester(new RemoveAction(userSession, dbClient, favoriteUpdater, new ComponentFinder(dbClient)));
+
+ @Test
+ public void remove_a_favorite_project() {
+ ComponentDto project = insertProjectAndPermissions();
+ ComponentDto file = db.components().insertComponent(newFileDto(project));
+ db.favorites().add(project, USER_ID);
+ db.favorites().add(file, USER_ID);
+
+ TestResponse result = call(PROJECT_KEY);
+
+ assertThat(result.getStatus()).isEqualTo(HTTP_NO_CONTENT);
+ assertThat(db.favorites().hasFavorite(project, USER_ID)).isFalse();
+ assertThat(db.favorites().hasFavorite(file, USER_ID)).isTrue();
+ }
+
+ @Test
+ public void fail_if_not_already_a_favorite() {
+ insertProjectAndPermissions();
+
+ expectedException.expect(BadRequestException.class);
+ expectedException.expectMessage("Component '" + PROJECT_KEY + "' is not a favorite");
+
+ call(PROJECT_KEY);
+ }
+
+ @Test
+ public void fail_when_component_is_not_found() {
+ userSession.login();
+
+ expectedException.expect(NotFoundException.class);
+
+ call("P42");
+ }
+
+ @Test
+ public void fail_when_user_is_not_authenticated() {
+ insertProject();
+
+ expectedException.expect(UnauthorizedException.class);
+
+ call(PROJECT_KEY);
+ }
+
+ @Test
+ public void definition() {
+ WebService.Action definition = ws.getDef();
+
+ assertThat(definition.key()).isEqualTo("remove");
+ assertThat(definition.isPost()).isTrue();
+ assertThat(definition.param("component").isRequired()).isTrue();
+ }
+
+ private ComponentDto insertProject() {
+ return db.components().insertComponent(newProjectDto(PROJECT_UUID).setKey(PROJECT_KEY));
+ }
+
+ private ComponentDto insertProjectAndPermissions() {
+ userSession.login().setUserId(USER_ID);
+
+ return insertProject();
+ }
+
+ private TestResponse call(@Nullable String componentKey) {
+ TestRequest request = ws.newRequest();
+ setNullable(componentKey, c -> request.setParam(PARAM_COMPONENT, c));
+
+ return request.execute();
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/DbTester.java b/sonar-db/src/test/java/org/sonar/db/DbTester.java
index 9d4a3e2bd1c..48fbd8494c3 100644
--- a/sonar-db/src/test/java/org/sonar/db/DbTester.java
+++ b/sonar-db/src/test/java/org/sonar/db/DbTester.java
@@ -65,6 +65,7 @@ import org.sonar.api.utils.log.Loggers;
import org.sonar.core.util.SequenceUuidFactory;
import org.sonar.db.component.ComponentDbTester;
import org.sonar.db.event.EventDbTester;
+import org.sonar.db.favorite.FavoriteDbTester;
import org.sonar.db.issue.IssueDbTester;
import org.sonar.db.organization.OrganizationDbTester;
import org.sonar.db.organization.OrganizationDto;
@@ -102,6 +103,7 @@ public class DbTester extends ExternalResource {
private final UserDbTester userTester;
private final ComponentDbTester componentTester;
+ private final FavoriteDbTester favoriteTester;
private final EventDbTester eventTester;
private final OrganizationDbTester organizationTester;
private final PermissionTemplateDbTester permissionTemplateTester;
@@ -116,6 +118,7 @@ public class DbTester extends ExternalResource {
initDbClient();
this.userTester = new UserDbTester(this);
this.componentTester = new ComponentDbTester(this);
+ this.favoriteTester = new FavoriteDbTester(this);
this.eventTester = new EventDbTester(this);
this.organizationTester = new OrganizationDbTester(this);
this.permissionTemplateTester = new PermissionTemplateDbTester(this);
@@ -190,6 +193,10 @@ public class DbTester extends ExternalResource {
return componentTester;
}
+ public FavoriteDbTester favorites() {
+ return favoriteTester;
+ }
+
public EventDbTester events() {
return eventTester;
}
@@ -587,7 +594,7 @@ public class DbTester extends ExternalResource {
*/
public void assertIndexDoesNotExist(String tableName, String indexName) {
try (Connection connection = getConnection();
- ResultSet rs = connection.getMetaData().getIndexInfo(null, null, tableName.toUpperCase(Locale.ENGLISH), false, false)) {
+ ResultSet rs = connection.getMetaData().getIndexInfo(null, null, tableName.toUpperCase(Locale.ENGLISH), false, false)) {
List<String> indices = new ArrayList<>();
while (rs.next()) {
indices.add(rs.getString("INDEX_NAME").toLowerCase(Locale.ENGLISH));
diff --git a/sonar-db/src/test/java/org/sonar/db/favorite/FavoriteDbTester.java b/sonar-db/src/test/java/org/sonar/db/favorite/FavoriteDbTester.java
new file mode 100644
index 00000000000..452bfbac197
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/favorite/FavoriteDbTester.java
@@ -0,0 +1,61 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.db.favorite;
+
+import java.util.List;
+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.property.PropertyDto;
+import org.sonar.db.property.PropertyQuery;
+
+public class FavoriteDbTester {
+ private static final String PROP_FAVORITE_KEY = "favourite";
+
+ private final DbTester db;
+ private final DbClient dbClient;
+ private final DbSession dbSession;
+
+ public FavoriteDbTester(DbTester db) {
+ this.db = db;
+ this.dbClient = db.getDbClient();
+ this.dbSession = db.getSession();
+ }
+
+ public void add(ComponentDto componentDto, long userId) {
+ dbClient.propertiesDao().saveProperty(dbSession, new PropertyDto()
+ .setKey(PROP_FAVORITE_KEY)
+ .setUserId(userId)
+ .setResourceId(componentDto.getId()));
+ dbSession.commit();
+ }
+
+ public boolean hasFavorite(ComponentDto componentDto, long userId) {
+ List<PropertyDto> result = dbClient.propertiesDao().selectByQuery(PropertyQuery.builder()
+ .setKey(PROP_FAVORITE_KEY)
+ .setComponentId(componentDto.getId())
+ .setUserId((int) userId)
+ .build(), dbSession);
+
+ return !result.isEmpty();
+ }
+}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/favorite/FavoritesService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/favorite/FavoritesService.java
index dab17b13317..91eede2140b 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/favorite/FavoritesService.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/favorite/FavoritesService.java
@@ -25,10 +25,11 @@ import org.sonarqube.ws.client.PostRequest;
import org.sonarqube.ws.client.WsConnector;
import static org.sonarqube.ws.client.favorite.FavoritesWsParameters.ACTION_ADD;
+import static org.sonarqube.ws.client.favorite.FavoritesWsParameters.ACTION_REMOVE;
import static org.sonarqube.ws.client.favorite.FavoritesWsParameters.CONTROLLER_FAVORITES;
import static org.sonarqube.ws.client.favorite.FavoritesWsParameters.PARAM_COMPONENT;
-public class FavoritesService extends BaseService{
+public class FavoritesService extends BaseService {
public FavoritesService(WsConnector wsConnector) {
super(wsConnector, CONTROLLER_FAVORITES);
}
@@ -38,4 +39,10 @@ public class FavoritesService extends BaseService{
call(post);
}
+
+ public void remove(String component) {
+ PostRequest post = new PostRequest(path(ACTION_REMOVE)).setParam(PARAM_COMPONENT, component);
+
+ call(post);
+ }
}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/favorite/FavoritesWsParameters.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/favorite/FavoritesWsParameters.java
index 5349f5fcf34..3c39c735ede 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/favorite/FavoritesWsParameters.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/favorite/FavoritesWsParameters.java
@@ -24,6 +24,7 @@ public class FavoritesWsParameters {
public static final String CONTROLLER_FAVORITES = "api/favorites";
public static final String ACTION_ADD = "add";
+ public static final String ACTION_REMOVE = "remove";
public static final String PARAM_COMPONENT = "component";
diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/favorite/FavoritesServiceTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/favorite/FavoritesServiceTest.java
index 4b6c8a40feb..b6ce72fa1da 100644
--- a/sonar-ws/src/test/java/org/sonarqube/ws/client/favorite/FavoritesServiceTest.java
+++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/favorite/FavoritesServiceTest.java
@@ -43,4 +43,14 @@ public class FavoritesServiceTest {
.hasParam(PARAM_COMPONENT, "my_project")
.andNoOtherParam();
}
+
+ @Test
+ public void remove() {
+ underTest.remove("my_project");
+
+ serviceTester.assertThat(serviceTester.getPostRequest())
+ .hasPath("remove")
+ .hasParam(PARAM_COMPONENT, "my_project")
+ .andNoOtherParam();
+ }
}