* SONAR-8964 Remove some global notifications in api/notifications/list on SonarCloud
* SONAR-8964 Remove some global notifications in api/notifications/add on SonarCloud
* In WebServiceEngine, define web services in start()
* SONAR-8964 Remove some global notifications in api/notifications/remove on SonarCloud
* Move some user ITs to their own suite
* SONAR-8964 Add ITs on notifications (not for SonarCloud)
* SONAR-8964 Add ITs on notifications for SonarCloud
;;
Category4)
- CATEGORY="Category4|duplication"
+ CATEGORY="Category4|duplication|user"
;;
Category5)
import static java.util.Optional.empty;
import static org.sonar.core.util.Protobuf.setNullable;
-import static org.sonar.core.util.stream.MoreCollectors.toList;
-import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION;
-import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION;
-import static org.sonar.server.ws.WsUtils.checkFound;
-import static org.sonar.server.ws.WsUtils.checkRequest;
import static org.sonar.server.notification.ws.NotificationsWsParameters.ACTION_ADD;
import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_CHANNEL;
import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_LOGIN;
import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_PROJECT;
import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_TYPE;
+import static org.sonar.server.ws.WsUtils.checkFound;
+import static org.sonar.server.ws.WsUtils.checkRequest;
public class AddAction implements NotificationsWsAction {
private final NotificationCenter notificationCenter;
private final NotificationUpdater notificationUpdater;
+ private final Dispatchers dispatchers;
private final DbClient dbClient;
private final ComponentFinder componentFinder;
private final UserSession userSession;
- private final List<String> globalDispatchers;
- private final List<String> projectDispatchers;
- public AddAction(NotificationCenter notificationCenter, NotificationUpdater notificationUpdater, DbClient dbClient, ComponentFinder componentFinder, UserSession userSession) {
+ public AddAction(NotificationCenter notificationCenter, NotificationUpdater notificationUpdater, Dispatchers dispatchers, DbClient dbClient, ComponentFinder componentFinder,
+ UserSession userSession) {
this.notificationCenter = notificationCenter;
this.notificationUpdater = notificationUpdater;
+ this.dispatchers = dispatchers;
this.dbClient = dbClient;
this.componentFinder = componentFinder;
this.userSession = userSession;
- this.globalDispatchers = notificationCenter.getDispatcherKeysForProperty(GLOBAL_NOTIFICATION, "true").stream().sorted().collect(toList());
- this.projectDispatchers = notificationCenter.getDispatcherKeysForProperty(PER_PROJECT_NOTIFICATION, "true").stream().sorted().collect(toList());
}
@Override
" <li>Global notifications: %s</li>" +
" <li>Per project notifications: %s</li>" +
"</ul>",
- String.join(", ", globalDispatchers),
- String.join(", ", projectDispatchers))
+ String.join(", ", dispatchers.getGlobalDispatchers()),
+ String.join(", ", dispatchers.getProjectDispatchers()))
.setRequired(true)
.setExampleValue(MyNewIssuesNotificationDispatcher.KEY);
setNullable(request.param(PARAM_LOGIN), add::setLogin);
if (add.getProject() == null) {
- checkRequest(globalDispatchers.contains(add.getType()), "Value of parameter '%s' (%s) must be one of: %s",
+ checkRequest(dispatchers.getGlobalDispatchers().contains(add.getType()), "Value of parameter '%s' (%s) must be one of: %s",
PARAM_TYPE,
add.getType(),
- globalDispatchers);
+ dispatchers.getGlobalDispatchers());
} else {
- checkRequest(projectDispatchers.contains(add.getType()), "Value of parameter '%s' (%s) must be one of: %s",
+ checkRequest(dispatchers.getProjectDispatchers().contains(add.getType()), "Value of parameter '%s' (%s) must be one of: %s",
PARAM_TYPE,
add.getType(),
- projectDispatchers);
+ dispatchers.getProjectDispatchers());
}
return add;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.notification.ws;
+
+import java.util.List;
+
+public interface Dispatchers {
+
+ List<String> getGlobalDispatchers();
+
+ List<String> getProjectDispatchers();
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.notification.ws;
+
+import com.google.common.collect.ImmutableSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Predicate;
+import org.sonar.api.Startable;
+import org.sonar.api.config.Configuration;
+import org.sonar.process.ProcessProperties;
+import org.sonar.server.event.NewAlerts;
+import org.sonar.server.issue.notification.DoNotFixNotificationDispatcher;
+import org.sonar.server.issue.notification.NewIssuesNotificationDispatcher;
+import org.sonar.server.notification.NotificationCenter;
+
+import static org.sonar.core.util.stream.MoreCollectors.toList;
+import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION;
+import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION;
+
+public class DispatchersImpl implements Dispatchers, Startable {
+
+ private static final Set<String> GLOBAL_DISPATCHERS_TO_IGNORE_ON_SONAR_CLOUD = ImmutableSet.of(
+ NewAlerts.KEY,
+ DoNotFixNotificationDispatcher.KEY,
+ NewIssuesNotificationDispatcher.KEY);
+
+ private final NotificationCenter notificationCenter;
+ private final Configuration configuration;
+
+ private List<String> projectDispatchers;
+ private List<String> globalDispatchers;
+
+ public DispatchersImpl(NotificationCenter notificationCenter, Configuration configuration) {
+ this.notificationCenter = notificationCenter;
+ this.configuration = configuration;
+ }
+
+ @Override
+ public List<String> getGlobalDispatchers() {
+ return globalDispatchers;
+ }
+
+ @Override
+ public List<String> getProjectDispatchers() {
+ return projectDispatchers;
+ }
+
+ @Override
+ public void start() {
+ boolean isOnSonarCloud = configuration.getBoolean(ProcessProperties.Property.SONARCLOUD_ENABLED.getKey()).orElse(false);
+ this.globalDispatchers = notificationCenter.getDispatcherKeysForProperty(GLOBAL_NOTIFICATION, "true")
+ .stream()
+ .filter(filterDispatcherForSonarCloud(isOnSonarCloud))
+ .sorted()
+ .collect(toList());
+ this.projectDispatchers = notificationCenter.getDispatcherKeysForProperty(PER_PROJECT_NOTIFICATION, "true")
+ .stream()
+ .sorted()
+ .collect(toList());
+ }
+
+ private static Predicate<String> filterDispatcherForSonarCloud(boolean isOnSonarCloud) {
+ return dispatcher -> !(isOnSonarCloud && GLOBAL_DISPATCHERS_TO_IGNORE_ON_SONAR_CLOUD.contains(dispatcher));
+ }
+
+ @Override
+ public void stop() {
+ // nothing to do
+ }
+}
import static java.util.Comparator.nullsFirst;
import static org.sonar.core.util.Protobuf.setNullable;
import static org.sonar.core.util.stream.MoreCollectors.toOneElement;
-import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION;
-import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION;
-import static org.sonar.server.ws.WsUtils.checkFound;
-import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonar.server.notification.ws.NotificationsWsParameters.ACTION_LIST;
import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_LOGIN;
+import static org.sonar.server.ws.WsUtils.checkFound;
+import static org.sonar.server.ws.WsUtils.writeProtobuf;
public class ListAction implements NotificationsWsAction {
+
private static final Splitter PROPERTY_KEY_SPLITTER = Splitter.on(".");
private final DbClient dbClient;
private final UserSession userSession;
- private final List<String> globalDispatchers;
- private final List<String> perProjectDispatchers;
private final List<String> channels;
+ private final Dispatchers dispatchers;
- public ListAction(NotificationCenter notificationCenter, DbClient dbClient, UserSession userSession) {
+ public ListAction(NotificationCenter notificationCenter, DbClient dbClient, UserSession userSession, Dispatchers dispatchers) {
this.dbClient = dbClient;
this.userSession = userSession;
- this.globalDispatchers = notificationCenter.getDispatcherKeysForProperty(GLOBAL_NOTIFICATION, "true").stream().sorted().collect(MoreCollectors.toList());
- this.perProjectDispatchers = notificationCenter.getDispatcherKeysForProperty(PER_PROJECT_NOTIFICATION, "true").stream().sorted().collect(MoreCollectors.toList());
this.channels = notificationCenter.getChannels().stream().map(NotificationChannel::getKey).sorted().collect(MoreCollectors.toList());
+ this.dispatchers = dispatchers;
}
@Override
return Stream
.of(ListResponse.newBuilder())
.map(r -> r.addAllChannels(channels))
- .map(r -> r.addAllGlobalTypes(globalDispatchers))
- .map(r -> r.addAllPerProjectTypes(perProjectDispatchers))
+ .map(r -> r.addAllGlobalTypes(dispatchers.getGlobalDispatchers()))
+ .map(r -> r.addAllPerProjectTypes(dispatchers.getProjectDispatchers()))
.map(addNotifications(dbSession, user))
.map(ListResponse.Builder::build)
.collect(toOneElement());
}
private boolean isDispatcherAuthorized(PropertyDto prop, String dispatcher) {
- return (prop.getResourceId() != null && perProjectDispatchers.contains(dispatcher)) || globalDispatchers.contains(dispatcher);
+ return (prop.getResourceId() != null && dispatchers.getProjectDispatchers().contains(dispatcher)) || dispatchers.getGlobalDispatchers().contains(dispatcher);
}
private Map<Long, ComponentDto> searchProjects(DbSession dbSession, List<PropertyDto> properties) {
@Override
protected void configureModule() {
add(
+ DispatchersImpl.class,
// WS
NotificationsWs.class,
AddAction.class,
import static java.util.Optional.empty;
import static org.sonar.core.util.Protobuf.setNullable;
-import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION;
-import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION;
-import static org.sonar.server.ws.WsUtils.checkFound;
-import static org.sonar.server.ws.WsUtils.checkRequest;
import static org.sonar.server.notification.ws.NotificationsWsParameters.ACTION_REMOVE;
import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_CHANNEL;
import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_LOGIN;
import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_PROJECT;
import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_TYPE;
+import static org.sonar.server.ws.WsUtils.checkFound;
+import static org.sonar.server.ws.WsUtils.checkRequest;
public class RemoveAction implements NotificationsWsAction {
private final NotificationCenter notificationCenter;
private final NotificationUpdater notificationUpdater;
+ private final Dispatchers dispatchers;
private final DbClient dbClient;
private final ComponentFinder componentFinder;
private final UserSession userSession;
- private final List<String> globalDispatchers;
- private final List<String> projectDispatchers;
- public RemoveAction(NotificationCenter notificationCenter, NotificationUpdater notificationUpdater, DbClient dbClient, ComponentFinder componentFinder, UserSession userSession) {
+ public RemoveAction(NotificationCenter notificationCenter, NotificationUpdater notificationUpdater, Dispatchers dispatchers, DbClient dbClient, ComponentFinder componentFinder,
+ UserSession userSession) {
this.notificationCenter = notificationCenter;
this.notificationUpdater = notificationUpdater;
+ this.dispatchers = dispatchers;
this.dbClient = dbClient;
this.componentFinder = componentFinder;
this.userSession = userSession;
- this.globalDispatchers = notificationCenter.getDispatcherKeysForProperty(GLOBAL_NOTIFICATION, "true");
- this.projectDispatchers = notificationCenter.getDispatcherKeysForProperty(PER_PROJECT_NOTIFICATION, "true");
}
@Override
" <li>Global notifications: %s</li>" +
" <li>Per project notifications: %s</li>" +
"</ul>",
- globalDispatchers.stream().sorted().collect(Collectors.joining(", ")),
- projectDispatchers.stream().sorted().collect(Collectors.joining(", ")))
+ dispatchers.getGlobalDispatchers().stream().sorted().collect(Collectors.joining(", ")),
+ dispatchers.getProjectDispatchers().stream().sorted().collect(Collectors.joining(", ")))
.setRequired(true)
.setExampleValue(MyNewIssuesNotificationDispatcher.KEY);
setNullable(request.param(PARAM_LOGIN), remove::setLogin);
if (remove.getProject() == null) {
- checkRequest(globalDispatchers.contains(remove.getType()), "Value of parameter '%s' (%s) must be one of: %s",
+ checkRequest(dispatchers.getGlobalDispatchers().contains(remove.getType()), "Value of parameter '%s' (%s) must be one of: %s",
PARAM_TYPE,
remove.getType(),
- globalDispatchers);
+ dispatchers.getGlobalDispatchers());
} else {
- checkRequest(projectDispatchers.contains(remove.getType()), "Value of parameter '%s' (%s) must be one of: %s",
+ checkRequest(dispatchers.getProjectDispatchers().contains(remove.getType()), "Value of parameter '%s' (%s) must be one of: %s",
PARAM_TYPE,
remove.getType(),
- projectDispatchers);
+ dispatchers.getProjectDispatchers());
}
return remove;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.Collections.singletonList;
+import static java.util.Objects.requireNonNull;
import static org.apache.commons.lang.StringUtils.substring;
import static org.apache.commons.lang.StringUtils.substringAfterLast;
import static org.apache.commons.lang.StringUtils.substringBeforeLast;
private static final Logger LOGGER = Loggers.get(WebServiceEngine.class);
- private final WebService.Context context;
+ private final WebService[] webServices;
+
+ private WebService.Context context;
public WebServiceEngine(WebService[] webServices) {
- context = new WebService.Context();
- for (WebService webService : webServices) {
- webService.define(context);
- }
+ this.webServices = webServices;
}
@Override
public void start() {
- // Force execution of constructor to be sure that web services
- // are validated and initialized at server startup.
+ context = new WebService.Context();
+ for (WebService webService : webServices) {
+ webService.define(context);
+ }
}
@Override
// nothing
}
+ private WebService.Context getContext() {
+ return requireNonNull(context, "Web services has not yet been initialized");
+ }
+
List<WebService.Controller> controllers() {
- return context.controllers();
+ return getContext().controllers();
}
@Override
private WebService.Action getAction(ActionExtractor actionExtractor) {
String controllerPath = actionExtractor.getController();
String actionKey = actionExtractor.getAction();
- WebService.Controller controller = context.controller(controllerPath);
+ WebService.Controller controller = getContext().controller(controllerPath);
return controller == null ? null : controller.action(actionKey);
}
package org.sonar.server.notification.ws;
import javax.annotation.Nullable;
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.notifications.Notification;
import org.sonar.api.notifications.NotificationChannel;
-import org.sonar.api.web.UserRole;
import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
import static java.lang.String.format;
import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.api.web.UserRole.USER;
import static org.sonar.core.util.Protobuf.setNullable;
import static org.sonar.db.component.ComponentTesting.newView;
-import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION;
-import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION;
import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_CHANNEL;
import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_LOGIN;
import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_PROJECT;
private static final String NOTIF_MY_NEW_ISSUES = "Dispatcher1";
private static final String NOTIF_NEW_ISSUES = "Dispatcher2";
private static final String NOTIF_NEW_QUALITY_GATE_STATUS = "Dispatcher3";
- private static final String USER_LOGIN = "george.orwell";
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Rule
- public UserSessionRule userSession;
+ public UserSessionRule userSession = UserSessionRule.standalone();
@Rule
public DbTester db = DbTester.create();
// default channel, based on class simple name
private NotificationChannel defaultChannel = new FakeNotificationChannel("EmailNotificationChannel");
- private UserDto user;
-
- private NotificationCenter notificationCenter;
- private AddAction underTest;
- private WsActionTester ws;
-
- @Before
- public void setUp() {
- NotificationDispatcherMetadata metadata1 = NotificationDispatcherMetadata.create(NOTIF_MY_NEW_ISSUES)
- .setProperty(GLOBAL_NOTIFICATION, "true")
- .setProperty(PER_PROJECT_NOTIFICATION, "true");
- NotificationDispatcherMetadata metadata2 = NotificationDispatcherMetadata.create(NOTIF_NEW_ISSUES)
- .setProperty(GLOBAL_NOTIFICATION, "true");
- NotificationDispatcherMetadata metadata3 = NotificationDispatcherMetadata.create(NOTIF_NEW_QUALITY_GATE_STATUS)
- .setProperty(GLOBAL_NOTIFICATION, "true")
- .setProperty(PER_PROJECT_NOTIFICATION, "true");
-
- user = db.users().insertUser(USER_LOGIN);
- userSession = UserSessionRule.standalone().logIn(user);
-
- notificationCenter = new NotificationCenter(
- new NotificationDispatcherMetadata[] {metadata1, metadata2, metadata3},
- new NotificationChannel[] {emailChannel, twitterChannel, defaultChannel});
- underTest = new AddAction(notificationCenter, new NotificationUpdater(dbClient), dbClient, TestComponentFinder.from(db), userSession);
- ws = new WsActionTester(underTest);
- }
+ private Dispatchers dispatchers = mock(Dispatchers.class);
+
+ private WsActionTester ws = new WsActionTester(new AddAction(new NotificationCenter(
+ new NotificationDispatcherMetadata[] {},
+ new NotificationChannel[] {emailChannel, twitterChannel, defaultChannel}),
+ new NotificationUpdater(dbClient), dispatchers, dbClient, TestComponentFinder.from(db), userSession));
@Test
public void add_to_email_channel_by_default() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+
call(NOTIF_MY_NEW_ISSUES, null, null, null);
db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUserId(), null);
@Test
public void add_to_a_specific_channel() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
+
call(NOTIF_NEW_QUALITY_GATE_STATUS, twitterChannel.getKey(), null, null);
db.notifications().assertExists(twitterChannel.getKey(), NOTIF_NEW_QUALITY_GATE_STATUS, userSession.getUserId(), null);
@Test
public void add_notification_on_private_with_USER_permission() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
ComponentDto project = db.components().insertPrivateProject();
- userSession.addProjectPermission(UserRole.USER, project);
+ userSession.addProjectPermission(USER, project);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
call(NOTIF_MY_NEW_ISSUES, null, project.getDbKey(), null);
@Test
public void add_notification_on_public_project() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
ComponentDto project = db.components().insertPublicProject();
userSession.registerComponents(project);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+
call(NOTIF_MY_NEW_ISSUES, null, project.getDbKey(), null);
db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUserId(), project);
@Test
public void add_a_global_notification_when_a_project_one_exists() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES));
ComponentDto project = db.components().insertPrivateProject();
- userSession.addProjectPermission(UserRole.USER, project);
+ userSession.addProjectPermission(USER, project);
call(NOTIF_MY_NEW_ISSUES, null, project.getDbKey(), null);
call(NOTIF_MY_NEW_ISSUES, null, null, null);
@Test
public void add_a_notification_on_private_project_when_a_global_one_exists() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
ComponentDto project = db.components().insertPrivateProject();
call(NOTIF_MY_NEW_ISSUES, null, null, null);
- userSession.addProjectPermission(UserRole.USER, project);
+ userSession.addProjectPermission(USER, project);
call(NOTIF_MY_NEW_ISSUES, null, project.getDbKey(), null);
db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUserId(), project);
db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUserId(), null);
}
-
@Test
public void add_a_notification_on_public_project_when_a_global_one_exists() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
ComponentDto project = db.components().insertPublicProject();
userSession.registerComponents(project);
call(NOTIF_MY_NEW_ISSUES, null, null, null);
@Test
public void http_no_content() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+
TestResponse result = call(NOTIF_MY_NEW_ISSUES, null, null, null);
assertThat(result.getStatus()).isEqualTo(HTTP_NO_CONTENT);
@Test
public void add_a_notification_to_a_user_as_system_administrator() {
- userSession.logIn().setSystemAdministrator();
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user).setSystemAdministrator();
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
call(NOTIF_MY_NEW_ISSUES, null, null, user.getLogin());
@Test
public void fail_if_login_is_provided_and_unknown() {
- userSession.logIn().setSystemAdministrator();
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user).setSystemAdministrator();
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
expectedException.expect(NotFoundException.class);
expectedException.expectMessage("User 'LOGIN 404' not found");
@Test
public void fail_if_login_provided_and_not_system_administrator() {
- userSession.logIn().setNonSystemAdministrator();
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user).setNonSystemAdministrator();
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
expectedException.expect(ForbiddenException.class);
@Test
public void fail_when_notification_already_exists() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
call(NOTIF_MY_NEW_ISSUES, null, null, null);
expectedException.expect(IllegalArgumentException.class);
@Test
public void fail_when_unknown_global_dispatcher() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+
expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1, Dispatcher2, Dispatcher3]");
+ expectedException.expectMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1]");
call("Dispatcher42", null, null, null);
}
@Test
public void fail_when_unknown_project_dispatcher_on_private_project() {
ComponentDto project = db.components().insertPrivateProject();
- userSession.addProjectPermission(UserRole.USER, project);
+ userSession.addProjectPermission(USER, project);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES));
expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1, Dispatcher3]");
+ expectedException.expectMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1, Dispatcher2]");
- call("Dispatcher42", null, project.getDbKey(), null);
+ call("Dispatcher42", null, project.getKey(), null);
}
@Test
public void fail_when_unknown_project_dispatcher_on_public_project() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
ComponentDto project = db.components().insertPublicProject();
+ when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES));
expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1, Dispatcher3]");
+ expectedException.expectMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1, Dispatcher2]");
- call("Dispatcher42", null, project.getDbKey(), null);
+ call("Dispatcher42", null, project.getKey(), null);
}
@Test
@Test
public void fail_when_project_is_unknown() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+
expectedException.expect(NotFoundException.class);
call(NOTIF_MY_NEW_ISSUES, null, "Project-42", null);
@Test
public void fail_when_component_is_not_a_project() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
db.components().insertViewAndSnapshot(newView(db.organizations().insert()).setDbKey("VIEW_1"));
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("Component 'VIEW_1' must be a project");
@Test
public void fail_when_not_authenticated() {
userSession.anonymous();
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
expectedException.expect(UnauthorizedException.class);
@Test
public void fail_when_using_branch_db_key() throws Exception {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
ComponentDto project = db.components().insertMainBranch();
ComponentDto branch = db.components().insertProjectBranch(project);
public void fail_when_user_does_not_have_USER_permission_on_private_project() {
ComponentDto project = db.components().insertPrivateProject();
userSession.logIn().setNonRoot().setNonSystemAdministrator();
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
expectedException.expect(ForbiddenException.class);
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.notification.ws;
+
+import org.junit.Test;
+import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.notifications.NotificationChannel;
+import org.sonar.server.event.NewAlerts;
+import org.sonar.server.issue.notification.DoNotFixNotificationDispatcher;
+import org.sonar.server.issue.notification.MyNewIssuesNotificationDispatcher;
+import org.sonar.server.issue.notification.NewIssuesNotificationDispatcher;
+import org.sonar.server.notification.NotificationCenter;
+import org.sonar.server.notification.NotificationDispatcherMetadata;
+
+import static org.assertj.core.api.Java6Assertions.assertThat;
+import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION;
+import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION;
+
+public class DispatchersImplTest {
+
+ private NotificationCenter notificationCenter = new NotificationCenter(
+ new NotificationDispatcherMetadata[] {
+ NotificationDispatcherMetadata.create(MyNewIssuesNotificationDispatcher.KEY)
+ .setProperty(GLOBAL_NOTIFICATION, "true")
+ .setProperty(PER_PROJECT_NOTIFICATION, "true"),
+ NotificationDispatcherMetadata.create(NewIssuesNotificationDispatcher.KEY)
+ .setProperty(GLOBAL_NOTIFICATION, "true"),
+ NotificationDispatcherMetadata.create(NewAlerts.KEY)
+ .setProperty(GLOBAL_NOTIFICATION, "true")
+ .setProperty(PER_PROJECT_NOTIFICATION, "true"),
+ NotificationDispatcherMetadata.create(DoNotFixNotificationDispatcher.KEY)
+ .setProperty(GLOBAL_NOTIFICATION, "true")
+ .setProperty(PER_PROJECT_NOTIFICATION, "true")
+ },
+ new NotificationChannel[] {});
+
+ private final MapSettings settings = new MapSettings();
+
+ private DispatchersImpl underTest = new DispatchersImpl(notificationCenter, settings.asConfig());
+
+ @Test
+ public void get_sorted_global_dispatchers() {
+ underTest.start();
+
+ assertThat(underTest.getGlobalDispatchers()).containsExactly(
+ NewAlerts.KEY, DoNotFixNotificationDispatcher.KEY, NewIssuesNotificationDispatcher.KEY, MyNewIssuesNotificationDispatcher.KEY);
+ }
+
+ @Test
+ public void get_global_dispatchers_on_sonar_cloud() {
+ settings.setProperty("sonar.sonarcloud.enabled", "true");
+
+ underTest.start();
+
+ assertThat(underTest.getGlobalDispatchers()).containsOnly(MyNewIssuesNotificationDispatcher.KEY);
+ }
+
+ @Test
+ public void get_sorted_project_dispatchers() {
+ underTest.start();
+
+ assertThat(underTest.getProjectDispatchers()).containsExactly(
+ NewAlerts.KEY, DoNotFixNotificationDispatcher.KEY, MyNewIssuesNotificationDispatcher.KEY);
+ }
+
+ @Test
+ public void get_project_dispatchers_on_sonar_cloud() {
+ settings.setProperty("sonar.sonarcloud.enabled", "true");
+
+ underTest.start();
+
+ assertThat(underTest.getProjectDispatchers()).containsOnly(
+ MyNewIssuesNotificationDispatcher.KEY, NewAlerts.KEY, DoNotFixNotificationDispatcher.KEY);
+ }
+}
*/
package org.sonar.server.notification.ws;
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.notifications.NotificationChannel;
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.organization.OrganizationDto;
-import org.sonar.db.permission.UserPermissionDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
import org.sonarqube.ws.Notifications.ListResponse;
import org.sonarqube.ws.Notifications.Notification;
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
-import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION;
-import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.api.web.UserRole.USER;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
import static org.sonar.test.JsonAssert.assertJson;
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Rule
- public UserSessionRule userSession;
+ public UserSessionRule userSession = UserSessionRule.standalone();
@Rule
public DbTester db = DbTester.create();
private NotificationChannel emailChannel = new FakeNotificationChannel("EmailChannel");
private NotificationChannel twitterChannel = new FakeNotificationChannel("TwitterChannel");
- private UserDto user;
-
- private NotificationUpdater notificationUpdater;
-
- private WsActionTester ws;
-
- @Before
- public void setUp() {
- NotificationDispatcherMetadata metadata1 = NotificationDispatcherMetadata.create(NOTIF_MY_NEW_ISSUES)
- .setProperty(GLOBAL_NOTIFICATION, "true")
- .setProperty(PER_PROJECT_NOTIFICATION, "true");
- NotificationDispatcherMetadata metadata2 = NotificationDispatcherMetadata.create(NOTIF_NEW_ISSUES)
- .setProperty(GLOBAL_NOTIFICATION, "true");
- NotificationDispatcherMetadata metadata3 = NotificationDispatcherMetadata.create(NOTIF_NEW_QUALITY_GATE_STATUS)
- .setProperty(GLOBAL_NOTIFICATION, "true")
- .setProperty(PER_PROJECT_NOTIFICATION, "true");
-
- user = db.users().insertUser();
- userSession = UserSessionRule.standalone().logIn(user);
-
- NotificationCenter notificationCenter = new NotificationCenter(
- new NotificationDispatcherMetadata[] {metadata1, metadata2, metadata3},
- new NotificationChannel[] {emailChannel, twitterChannel});
- notificationUpdater = new NotificationUpdater(dbClient);
- ListAction underTest = new ListAction(notificationCenter, dbClient, userSession);
- ws = new WsActionTester(underTest);
- }
+
+ private NotificationUpdater notificationUpdater = new NotificationUpdater(dbClient);
+ private Dispatchers dispatchers = mock(Dispatchers.class);
+
+ private WsActionTester ws = new WsActionTester(new ListAction(new NotificationCenter(
+ new NotificationDispatcherMetadata[] {},
+ new NotificationChannel[] {emailChannel, twitterChannel}),
+ dbClient, userSession, dispatchers));
@Test
public void channels() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+
ListResponse result = call();
assertThat(result.getChannelsList()).containsExactly(emailChannel.getKey(), twitterChannel.getKey());
@Test
public void overall_dispatchers() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
+
ListResponse result = call();
assertThat(result.getGlobalTypesList()).containsExactly(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS);
@Test
public void per_project_dispatchers() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getProjectDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
+
ListResponse result = call();
assertThat(result.getPerProjectTypesList()).containsExactly(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS);
@Test
public void filter_unauthorized_projects() {
- ComponentDto project = addComponent(ComponentTesting.newPrivateProjectDto(db.organizations().insert()).setDbKey("K1"));
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ ComponentDto project = db.components().insertPrivateProject();
+ db.users().insertProjectPermissionOnUser(user, USER, project);
ComponentDto anotherProject = db.components().insertPrivateProject();
notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, project);
notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, anotherProject);
ListResponse result = call();
- assertThat(result.getNotificationsList()).extracting(Notification::getProject).containsOnly("K1");
+ assertThat(result.getNotificationsList()).extracting(Notification::getProject).containsOnly(project.getKey());
}
@Test
public void filter_channels() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
notificationUpdater.add(dbSession, "Unknown Channel", NOTIF_MY_NEW_ISSUES, user, null);
dbSession.commit();
@Test
public void filter_overall_dispatchers() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
notificationUpdater.add(dbSession, emailChannel.getKey(), "Unknown Notification", user, null);
dbSession.commit();
@Test
public void filter_per_project_dispatchers() {
- ComponentDto project = addComponent(ComponentTesting.newPrivateProjectDto(db.organizations().insert()).setDbKey("K1"));
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ ComponentDto project = db.components().insertPrivateProject();
+ db.users().insertProjectPermissionOnUser(user, USER, project);
notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, project);
notificationUpdater.add(dbSession, emailChannel.getKey(), "Unknown Notification", user, project);
dbSession.commit();
@Test
public void order_with_global_then_by_channel_and_dispatcher() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
+ when(dispatchers.getProjectDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
OrganizationDto organization = db.organizations().insert();
- ComponentDto project = addComponent(ComponentTesting.newPrivateProjectDto(organization).setDbKey("K1"));
+ ComponentDto project = db.components().insertPrivateProject(organization);
+ db.users().insertProjectPermissionOnUser(user, USER, project);
notificationUpdater.add(dbSession, twitterChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_NEW_ISSUES, user, null);
tuple(emailChannel.getKey(), "", NOTIF_MY_NEW_ISSUES, ""),
tuple(emailChannel.getKey(), "", NOTIF_NEW_ISSUES, ""),
tuple(twitterChannel.getKey(), "", NOTIF_MY_NEW_ISSUES, ""),
- tuple(emailChannel.getKey(), organization.getKey(), NOTIF_MY_NEW_ISSUES, "K1"),
- tuple(emailChannel.getKey(), organization.getKey(), NOTIF_NEW_QUALITY_GATE_STATUS, "K1"),
- tuple(twitterChannel.getKey(), organization.getKey(), NOTIF_MY_NEW_ISSUES, "K1"));
+ tuple(emailChannel.getKey(), organization.getKey(), NOTIF_MY_NEW_ISSUES, project.getKey()),
+ tuple(emailChannel.getKey(), organization.getKey(), NOTIF_NEW_QUALITY_GATE_STATUS, project.getKey()),
+ tuple(twitterChannel.getKey(), organization.getKey(), NOTIF_MY_NEW_ISSUES, project.getKey()));
}
@Test
public void list_user_notifications_as_system_admin() {
- userSession.logIn().setSystemAdministrator();
-
+ UserDto user = db.users().insertUser();
+ when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
+ userSession.logIn(user).setSystemAdministrator();
notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_NEW_ISSUES, user, null);
dbSession.commit();
@Test
public void fail_if_login_and_not_system_admin() {
- userSession.logIn().setNonSystemAdministrator();
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user).setNonSystemAdministrator();
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
dbSession.commit();
@Test
public void json_example() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
+ when(dispatchers.getProjectDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
OrganizationDto organization = db.organizations().insertForKey("my-org-1");
- ComponentDto project = addComponent(ComponentTesting.newPrivateProjectDto(organization).setDbKey(KEY_PROJECT_EXAMPLE_001).setName("My Project"));
+ ComponentDto project = db.components().insertPrivateProject(organization, p -> p.setDbKey(KEY_PROJECT_EXAMPLE_001).setName("My Project"));
+ db.users().insertProjectPermissionOnUser(user, USER, project);
notificationUpdater.add(dbSession, twitterChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_NEW_ISSUES, user, null);
return ws.newRequest().setParam("login", login).executeProtobuf(ListResponse.class);
}
- private ComponentDto addComponent(ComponentDto component) {
- db.components().insertComponent(component);
- dbClient.userPermissionDao().insert(dbSession, new UserPermissionDto(component.getOrganizationUuid(), UserRole.USER, user.getId(), component.getId()));
- db.commit();
-
- return component;
- }
-
private static class FakeNotificationChannel extends NotificationChannel {
private final String key;
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new NotificationWsModule().configure(container);
- assertThat(container.size()).isEqualTo(4 + 2);
+ assertThat(container.size()).isEqualTo(5 + 2);
}
}
*/
package org.sonar.server.notification.ws;
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static java.lang.String.format;
import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import static org.sonar.core.util.Protobuf.setNullable;
import static org.sonar.db.component.ComponentTesting.newView;
-import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION;
-import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION;
import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_CHANNEL;
import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_LOGIN;
import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_PROJECT;
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Rule
- public UserSessionRule userSession;
+ public UserSessionRule userSession = UserSessionRule.standalone();
@Rule
public DbTester db = DbTester.create();
private DbClient dbClient = db.getDbClient();
// default channel, based on class simple name
private NotificationChannel defaultChannel = new FakeNotificationChannel("EmailNotificationChannel");
- private NotificationCenter notificationCenter;
- private NotificationUpdater notificationUpdater;
- private RemoveAction underTest;
+ private NotificationUpdater notificationUpdater = new NotificationUpdater(dbClient);
+ private Dispatchers dispatchers = mock(Dispatchers.class);
- private WsActionTester ws;
private RemoveRequest request = new RemoveRequest().setType(NOTIF_MY_NEW_ISSUES);
- private UserDto user;
-
- @Before
- public void setUp() {
- user = db.users().insertUser();
- userSession = UserSessionRule.standalone().logIn(user);
-
- NotificationDispatcherMetadata metadata1 = NotificationDispatcherMetadata.create(NOTIF_MY_NEW_ISSUES)
- .setProperty(GLOBAL_NOTIFICATION, "true")
- .setProperty(PER_PROJECT_NOTIFICATION, "true");
- NotificationDispatcherMetadata metadata2 = NotificationDispatcherMetadata.create(NOTIF_NEW_ISSUES)
- .setProperty(GLOBAL_NOTIFICATION, "true");
- NotificationDispatcherMetadata metadata3 = NotificationDispatcherMetadata.create(NOTIF_NEW_QUALITY_GATE_STATUS)
- .setProperty(GLOBAL_NOTIFICATION, "true")
- .setProperty(PER_PROJECT_NOTIFICATION, "true");
-
- notificationCenter = new NotificationCenter(
- new NotificationDispatcherMetadata[] {metadata1, metadata2, metadata3},
- new NotificationChannel[] {emailChannel, twitterChannel, defaultChannel});
- notificationUpdater = new NotificationUpdater(dbClient);
- underTest = new RemoveAction(notificationCenter, notificationUpdater, dbClient, TestComponentFinder.from(db), userSession);
- ws = new WsActionTester(underTest);
- }
+ private WsActionTester ws = new WsActionTester(new RemoveAction(new NotificationCenter(
+ new NotificationDispatcherMetadata[] {},
+ new NotificationChannel[] {emailChannel, twitterChannel, defaultChannel}), notificationUpdater, dispatchers, dbClient, TestComponentFinder.from(db), userSession));
@Test
public void remove_to_email_channel_by_default() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
notificationUpdater.add(dbSession, defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
dbSession.commit();
@Test
public void remove_from_a_specific_channel() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_NEW_QUALITY_GATE_STATUS));
notificationUpdater.add(dbSession, twitterChannel.getKey(), NOTIF_NEW_QUALITY_GATE_STATUS, user, null);
dbSession.commit();
@Test
public void remove_a_project_notification() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
ComponentDto project = db.components().insertPrivateProject();
notificationUpdater.add(dbSession, defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, project);
dbSession.commit();
@Test
public void fail_when_remove_a_global_notification_when_a_project_one_exists() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
ComponentDto project = db.components().insertPrivateProject();
notificationUpdater.add(dbSession, defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, project);
dbSession.commit();
@Test
public void fail_when_remove_a_project_notification_when_a_global_one_exists() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
ComponentDto project = db.components().insertPrivateProject();
notificationUpdater.add(dbSession, defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
dbSession.commit();
@Test
public void http_no_content() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
notificationUpdater.add(dbSession, defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
dbSession.commit();
@Test
public void remove_a_notification_from_a_user_as_system_administrator() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
notificationUpdater.add(dbSession, defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user.getId(), null);
userSession.logIn().setSystemAdministrator();
@Test
public void fail_if_login_is_provided_and_unknown() {
- userSession.logIn().setSystemAdministrator();
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user).setSystemAdministrator();
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
expectedException.expect(NotFoundException.class);
expectedException.expectMessage("User 'LOGIN 404' not found");
@Test
public void fail_if_login_provided_and_not_system_administrator() {
- userSession.logIn().setNonSystemAdministrator();
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user).setNonSystemAdministrator();
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
notificationUpdater.add(dbSession, defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
dbSession.commit();
@Test
public void fail_when_notification_does_not_exist() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Notification doesn't exist");
@Test
public void fail_when_unknown_channel() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+
expectedException.expect(IllegalArgumentException.class);
call(request.setChannel("Channel42"));
@Test
public void fail_when_unknown_global_dispatcher() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
+
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1, Dispatcher2, Dispatcher3]");
@Test
public void fail_when_unknown_project_dispatcher() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
ComponentDto project = db.components().insertPrivateProject();
expectedException.expect(BadRequestException.class);
}
@Test
- public void fail_when_no_dispatcher() {
+ public void fail_when_no_type_parameter() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+
expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("The 'type' parameter is missing");
ws.newRequest().execute();
}
@Test
public void fail_when_project_is_unknown() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+
expectedException.expect(NotFoundException.class);
call(request.setProject("Project-42"));
@Test
public void fail_when_component_is_not_a_project() {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
db.components().insertViewAndSnapshot(newView(db.organizations().insert()).setDbKey("VIEW_1"));
expectedException.expect(BadRequestException.class);
@Test
public void fail_when_not_authenticated() {
userSession.anonymous();
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
expectedException.expect(UnauthorizedException.class);
@Test
public void fail_when_using_branch_db_key() throws Exception {
+ UserDto user = db.users().insertUser();
+ userSession.logIn(user);
+ when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+ when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
ComponentDto project = db.components().insertMainBranch();
ComponentDto branch = db.components().insertProjectBranch(project);
import org.junit.rules.ExpectedException;
import org.sonar.api.server.ws.WebService;
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.organization.OrganizationDto;
public DbTester db = DbTester.create();
private DbClient dbClient = db.getDbClient();
- private DbSession dbSession = db.getSession();
private TestDefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
private SearchAction underTest = new SearchAction(dbClient, userSession, new QualityGateFinder(dbClient),
@Test
public void load_ws_definitions_at_startup() {
WebServiceEngine underTest = new WebServiceEngine(new WebService[] {
- newWs("api/foo/index", a -> {}),
- newWs("api/bar/index", a -> {})
+ newWs("api/foo/index", a -> {
+ }),
+ newWs("api/bar/index", a -> {
+ })
});
underTest.start();
try {
public void fail_if_reading_an_undefined_parameter() {
Request request = new TestRequest().setPath("api/foo").setParam("unknown", "Unknown");
- DumbResponse response = run(request, newWs("api/foo", a ->
- a.setHandler((req, resp) -> request.param("unknown"))));
+ DumbResponse response = run(request, newWs("api/foo", a -> a.setHandler((req, resp) -> request.param("unknown"))));
assertThat(response.stream().outputAsString()).isEqualTo("{\"errors\":[{\"msg\":\"BUG - parameter 'unknown' is undefined for action 'foo'\"}]}");
assertThat(response.stream().status()).isEqualTo(400);
assertThat(logTester.logs(LoggerLevel.ERROR)).contains("Fail to process request api/foo");
}
+ @Test
+ public void fail_when_start_in_not_called() {
+ Request request = new TestRequest().setPath("/api/ping");
+ DumbResponse response = new DumbResponse();
+ WebServiceEngine underTest = new WebServiceEngine(new WebService[] {newPingWs(a -> {
+ })});
+
+ underTest.execute(request, response);
+
+ assertThat(logTester.logs(LoggerLevel.ERROR)).contains("Fail to process request /api/ping");
+ }
+
private static WebService newWs(String path, Consumer<WebService.NewAction> consumer) {
return context -> {
WebService.NewController controller = context.createController(substringBeforeLast(path, "/"));
private static DumbResponse run(Request request, WebService... webServices) {
DumbResponse response = new DumbResponse();
- return (DumbResponse)run(request, response, webServices);
+ return (DumbResponse) run(request, response, webServices);
}
private static Response run(Request request, Response response, WebService... webServices) {
import org.sonarqube.tests.settings.EmailsTest;
import org.sonarqube.tests.settings.PropertySetsTest;
import org.sonarqube.tests.settings.SettingsTest;
-import org.sonarqube.tests.user.UsersPageTest;
import static util.ItUtils.pluginArtifact;
import static util.ItUtils.xooPlugin;
@Deprecated
@RunWith(Suite.class)
@Suite.SuiteClasses({
- UsersPageTest.class,
BackgroundTasksTest.class,
DeprecatedPropertiesWsTest.class,
EmailsTest.class,
// Used in SettingsTest.should_get_settings_default_value
.addPlugin(pluginArtifact("server-plugin"))
-
// Used in I18nTest
.addPlugin(pluginArtifact("l10n-fr-pack"))
import org.sonarqube.tests.serverSystem.SystemInfoTest;
import org.sonarqube.tests.ui.UiExtensionsTest;
import org.sonarqube.tests.ui.UiTest;
-import org.sonarqube.tests.user.BaseIdentityProviderTest;
-import org.sonarqube.tests.user.FavoritesWsTest;
-import org.sonarqube.tests.user.ForceAuthenticationTest;
-import org.sonarqube.tests.user.LocalAuthenticationTest;
-import org.sonarqube.tests.user.MyAccountPageTest;
-import org.sonarqube.tests.user.OAuth2IdentityProviderTest;
-import org.sonarqube.tests.user.RootUserInStandaloneModeTest;
import org.sonarqube.tests.ws.WsLocalCallTest;
import org.sonarqube.tests.ws.WsTest;
@Deprecated
@RunWith(Suite.class)
@Suite.SuiteClasses({
- // organization
- RootUserInStandaloneModeTest.class,
// server system
ServerSystemTest.class,
SystemInfoTest.class,
PingTest.class,
- // user
- MyAccountPageTest.class,
- FavoritesWsTest.class,
- // authentication
- ForceAuthenticationTest.class,
- LocalAuthenticationTest.class,
- BaseIdentityProviderTest.class,
- OAuth2IdentityProviderTest.class,
// analysis exclusion
FileExclusionsTest.class,
IssueExclusionsTest.class,
public static final Orchestrator ORCHESTRATOR = Orchestrator.builderEnv()
.addPlugin(xooPlugin())
- // Used in BaseIdentityProviderTest
- .addPlugin(pluginArtifact("base-auth-plugin"))
-
- // Used in OAuth2IdentityProviderTest
- .addPlugin(pluginArtifact("oauth2-auth-plugin"))
-
// Used in UiExtensionsTest
.addPlugin(pluginArtifact("ui-extensions-plugin"))
// reduce memory for Elasticsearch to 128M
.setServerProperty("sonar.search.javaOpts", "-Xms128m -Xmx128m")
- .setServerProperty("sonar.web.javaAdditionalOpts", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8001")
-
.build();
}
import org.junit.Test;
import org.junit.rules.RuleChain;
import org.sonarqube.qa.util.pageobjects.Navigation;
-import org.sonarqube.tests.Category4Suite;
import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.WsClient;
import org.sonarqube.ws.client.users.CreateRequest;
public class BaseIdentityProviderTest {
@ClassRule
- public static Orchestrator ORCHESTRATOR = Category4Suite.ORCHESTRATOR;
+ public static Orchestrator ORCHESTRATOR = UserSuite.ORCHESTRATOR;
private static UserRule userRule = UserRule.from(ORCHESTRATOR);
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
-import org.sonarqube.tests.Category4Suite;
import org.sonarqube.ws.Favorites.Favorite;
import org.sonarqube.ws.client.WsClient;
import org.sonarqube.ws.client.favorites.AddRequest;
public class FavoritesWsTest {
@ClassRule
- public static final Orchestrator orchestrator = Category4Suite.ORCHESTRATOR;
+ public static final Orchestrator orchestrator = UserSuite.ORCHESTRATOR;
+
private static WsClient adminClient;
@Before
package org.sonarqube.tests.user;
import com.sonar.orchestrator.Orchestrator;
-import org.sonarqube.tests.Category4Suite;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.sonarqube.qa.util.Tester;
+import org.sonarqube.qa.util.pageobjects.Navigation;
import org.sonarqube.ws.Users.CreateWsResponse.User;
import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.PostRequest;
import org.sonarqube.ws.client.WsConnector;
import org.sonarqube.ws.client.WsRequest;
import org.sonarqube.ws.client.WsResponse;
-import org.sonarqube.qa.util.pageobjects.Navigation;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonarqube.ws.client.WsRequest.Method.GET;
public class ForceAuthenticationTest {
@ClassRule
- public static final Orchestrator orchestrator = Category4Suite.ORCHESTRATOR;
+ public static final Orchestrator orchestrator = UserSuite.ORCHESTRATOR;
@Rule
public Tester tester = new Tester(orchestrator).disableOrganizations();
import org.sonarqube.qa.util.Tester;
import org.sonarqube.qa.util.pageobjects.LoginPage;
import org.sonarqube.qa.util.pageobjects.Navigation;
-import org.sonarqube.tests.Category4Suite;
import org.sonarqube.ws.UserTokens;
import org.sonarqube.ws.Users;
import org.sonarqube.ws.Users.CreateWsResponse.User;
public class LocalAuthenticationTest {
@ClassRule
- public static Orchestrator orchestrator = Category4Suite.ORCHESTRATOR;
+ public static Orchestrator orchestrator = UserSuite.ORCHESTRATOR;
@Rule
public Tester tester = new Tester(orchestrator).disableOrganizations();
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
-import org.sonarqube.qa.util.pageobjects.Navigation;
-import org.sonarqube.tests.Category4Suite;
import org.sonarqube.qa.util.Tester;
+import org.sonarqube.qa.util.pageobjects.Navigation;
import org.sonarqube.ws.Users.CreateWsResponse.User;
import org.sonarqube.ws.client.PostRequest;
public class MyAccountPageTest {
@ClassRule
- public static Orchestrator orchestrator = Category4Suite.ORCHESTRATOR;
+ public static Orchestrator orchestrator = UserSuite.ORCHESTRATOR;
@Rule
public Tester tester = new Tester(orchestrator).disableOrganizations();
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.sonarqube.tests.user;
+
+import com.sonar.orchestrator.Orchestrator;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonarqube.qa.util.Tester;
+import org.sonarqube.ws.Notifications;
+import org.sonarqube.ws.Notifications.Notification;
+import org.sonarqube.ws.Projects;
+import org.sonarqube.ws.Users;
+import org.sonarqube.ws.client.notifications.AddRequest;
+import org.sonarqube.ws.client.notifications.ListRequest;
+import org.sonarqube.ws.client.notifications.RemoveRequest;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+
+public class NotificationsWsTest {
+
+ @ClassRule
+ public static final Orchestrator orchestrator = UserSuite.ORCHESTRATOR;
+
+ @Rule
+ public Tester tester = new Tester(orchestrator).disableOrganizations();
+
+ @Test
+ public void list_notifications() {
+ Users.CreateWsResponse.User user = tester.users().generate();
+
+ Notifications.ListResponse list = tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest());
+
+ assertThat(list.getNotificationsList()).isEmpty();
+ assertThat(list.getChannelsList()).containsExactlyInAnyOrder("EmailNotificationChannel");
+ assertThat(list.getGlobalTypesList()).containsExactlyInAnyOrder(
+ "CeReportTaskFailure", "ChangesOnMyIssue", "NewAlerts", "NewFalsePositiveIssue", "NewIssues", "SQ-MyNewIssues");
+ assertThat(list.getPerProjectTypesList()).containsExactlyInAnyOrder(
+ "CeReportTaskFailure", "ChangesOnMyIssue", "NewAlerts", "NewFalsePositiveIssue", "NewIssues", "SQ-MyNewIssues");
+ }
+
+ @Test
+ public void add_global_and_project_notifications() {
+ Users.CreateWsResponse.User user = tester.users().generate();
+ assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList()).isEmpty();
+ Projects.CreateWsResponse.Project project = tester.projects().provision();
+
+ tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("ChangesOnMyIssue"));
+ tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("NewIssues").setProject(project.getKey()));
+
+ assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList())
+ .extracting(Notification::getChannel, Notification::getType, Notification::getProject, Notification::getProjectName)
+ .containsExactlyInAnyOrder(
+ tuple("EmailNotificationChannel", "ChangesOnMyIssue", "", ""),
+ tuple("EmailNotificationChannel", "NewIssues", project.getKey(), project.getName()));
+ }
+
+ @Test
+ public void remove_global_and_project_notifications() {
+ Users.CreateWsResponse.User user = tester.users().generate();
+ assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList()).isEmpty();
+ Projects.CreateWsResponse.Project project = tester.projects().provision();
+ // These 2 notifications will be removed
+ tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("ChangesOnMyIssue"));
+ tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("NewIssues").setProject(project.getKey()));
+ // These 2 notifications will not be removed
+ tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("NewAlerts"));
+ tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("SQ-MyNewIssues").setProject(project.getKey()));
+
+ tester.as(user.getLogin()).wsClient().notifications().remove(new RemoveRequest().setChannel("EmailNotificationChannel").setType("ChangesOnMyIssue"));
+ tester.as(user.getLogin()).wsClient().notifications().remove(new RemoveRequest().setChannel("EmailNotificationChannel").setType("NewIssues").setProject(project.getKey()));
+
+ assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList())
+ .extracting(Notification::getType, Notification::getProject)
+ .containsExactlyInAnyOrder(
+ tuple("NewAlerts", ""),
+ tuple("SQ-MyNewIssues", project.getKey()));
+ }
+
+ @Test
+ public void add_global_and_project_notifications_on_another_user_as_a_system_administrator() {
+ Users.CreateWsResponse.User admin = tester.users().generateAdministratorOnDefaultOrganization();
+ Users.CreateWsResponse.User user = tester.users().generate();
+ assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList()).isEmpty();
+ Projects.CreateWsResponse.Project project = tester.projects().provision();
+
+ tester.as(admin.getLogin()).wsClient().notifications().add(new AddRequest().setLogin(user.getLogin()).setChannel("EmailNotificationChannel").setType("ChangesOnMyIssue"));
+ tester.as(admin.getLogin()).wsClient().notifications().add(new AddRequest().setLogin(user.getLogin()).setChannel("EmailNotificationChannel").setType("NewIssues").setProject(project.getKey()));
+
+ assertThat(tester.as(admin.getLogin()).wsClient().notifications().list(new ListRequest().setLogin(user.getLogin())).getNotificationsList())
+ .extracting(Notification::getChannel, Notification::getType, Notification::getProject, Notification::getProjectName)
+ .containsExactlyInAnyOrder(
+ tuple("EmailNotificationChannel", "ChangesOnMyIssue", "", ""),
+ tuple("EmailNotificationChannel", "NewIssues", project.getKey(), project.getName()));
+ }
+
+ @Test
+ public void remove_global_and_project_notifications_on_another_user_as_a_system_administrator() {
+ Users.CreateWsResponse.User admin = tester.users().generateAdministratorOnDefaultOrganization();
+ Users.CreateWsResponse.User user = tester.users().generate();
+ assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList()).isEmpty();
+ Projects.CreateWsResponse.Project project = tester.projects().provision();
+ // These 2 notifications will be removed
+ tester.as(admin.getLogin()).wsClient().notifications().add(new AddRequest().setLogin(user.getLogin()).setChannel("EmailNotificationChannel").setType("ChangesOnMyIssue"));
+ tester.as(admin.getLogin()).wsClient().notifications().add(new AddRequest().setLogin(user.getLogin()).setChannel("EmailNotificationChannel").setType("NewIssues").setProject(project.getKey()));
+ // These 2 notifications will not be removed
+ tester.as(admin.getLogin()).wsClient().notifications().add(new AddRequest().setLogin(user.getLogin()).setChannel("EmailNotificationChannel").setType("NewAlerts"));
+ tester.as(admin.getLogin()).wsClient().notifications().add(new AddRequest().setLogin(user.getLogin()).setChannel("EmailNotificationChannel").setType("SQ-MyNewIssues").setProject(project.getKey()));
+
+ tester.as(admin.getLogin()).wsClient().notifications().remove(new RemoveRequest().setLogin(user.getLogin()).setChannel("EmailNotificationChannel").setType("ChangesOnMyIssue"));
+ tester.as(admin.getLogin()).wsClient().notifications().remove(new RemoveRequest().setLogin(user.getLogin()).setChannel("EmailNotificationChannel").setType("NewIssues").setProject(project.getKey()));
+
+ assertThat(tester.as(admin.getLogin()).wsClient().notifications().list(new ListRequest().setLogin(user.getLogin())).getNotificationsList())
+ .extracting(Notification::getType, Notification::getProject)
+ .containsExactlyInAnyOrder(
+ tuple("NewAlerts", ""),
+ tuple("SQ-MyNewIssues", project.getKey()));
+ }
+}
import org.junit.Test;
import org.sonarqube.qa.util.Tester;
import org.sonarqube.qa.util.pageobjects.Navigation;
-import org.sonarqube.tests.Category4Suite;
import org.sonarqube.ws.Users.SearchWsResponse.User;
import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.permissions.AddUserRequest;
public class OAuth2IdentityProviderTest {
@ClassRule
- public static Orchestrator orchestrator = Category4Suite.ORCHESTRATOR;
+ public static Orchestrator orchestrator = UserSuite.ORCHESTRATOR;
private static String FAKE_PROVIDER_KEY = "fake-oauth2-id-provider";
package org.sonarqube.tests.user;
import com.sonar.orchestrator.Orchestrator;
-import org.sonarqube.tests.Category4Suite;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
public class RootUserInStandaloneModeTest {
@ClassRule
- public static Orchestrator orchestrator = Category4Suite.ORCHESTRATOR;
+ public static Orchestrator orchestrator = UserSuite.ORCHESTRATOR;
@Rule
public Tester tester = new Tester(orchestrator).disableOrganizations();
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.sonarqube.tests.user;
+
+import com.sonar.orchestrator.Orchestrator;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonarqube.qa.util.Tester;
+import org.sonarqube.ws.Notifications;
+import org.sonarqube.ws.Notifications.Notification;
+import org.sonarqube.ws.Projects;
+import org.sonarqube.ws.Users;
+import org.sonarqube.ws.client.notifications.AddRequest;
+import org.sonarqube.ws.client.notifications.ListRequest;
+import org.sonarqube.ws.client.notifications.RemoveRequest;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+import static util.ItUtils.expectHttpError;
+
+public class SonarCloudNotificationsWsTest {
+
+ @ClassRule
+ public static final Orchestrator orchestrator = SonarCloudUserSuite.ORCHESTRATOR;
+
+ @Rule
+ public Tester tester = new Tester(orchestrator);
+
+ @Test
+ public void list_notifications() {
+ Users.CreateWsResponse.User user = tester.users().generate();
+
+ Notifications.ListResponse list = tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest());
+
+ assertThat(list.getNotificationsList()).isEmpty();
+ assertThat(list.getChannelsList()).containsExactlyInAnyOrder("EmailNotificationChannel");
+ assertThat(list.getGlobalTypesList())
+ .containsExactlyInAnyOrder(
+ "CeReportTaskFailure", "ChangesOnMyIssue", "SQ-MyNewIssues")
+ .doesNotContain("NewAlerts", "NewFalsePositiveIssue", "NewIssues");
+ assertThat(list.getPerProjectTypesList()).containsExactlyInAnyOrder(
+ "CeReportTaskFailure", "ChangesOnMyIssue", "NewAlerts", "NewFalsePositiveIssue", "NewIssues", "SQ-MyNewIssues");
+ }
+
+ @Test
+ public void add_global_and_project_notifications() {
+ Users.CreateWsResponse.User user = tester.users().generate();
+ assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList()).isEmpty();
+ Projects.CreateWsResponse.Project project = tester.projects().provision();
+
+ tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("ChangesOnMyIssue"));
+ tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("NewIssues").setProject(project.getKey()));
+
+ assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList())
+ .extracting(Notification::getChannel, Notification::getType, Notification::getProject, Notification::getProjectName)
+ .containsExactlyInAnyOrder(
+ tuple("EmailNotificationChannel", "ChangesOnMyIssue", "", ""),
+ tuple("EmailNotificationChannel", "NewIssues", project.getKey(), project.getName()));
+ }
+
+ @Test
+ public void remove_global_and_project_notifications() {
+ Users.CreateWsResponse.User user = tester.users().generate();
+ assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList()).isEmpty();
+ Projects.CreateWsResponse.Project project = tester.projects().provision();
+ tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("ChangesOnMyIssue"));
+ tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("NewIssues").setProject(project.getKey()));
+
+ tester.as(user.getLogin()).wsClient().notifications().remove(new RemoveRequest().setChannel("EmailNotificationChannel").setType("ChangesOnMyIssue"));
+ tester.as(user.getLogin()).wsClient().notifications().remove(new RemoveRequest().setChannel("EmailNotificationChannel").setType("NewIssues").setProject(project.getKey()));
+
+ assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList()).isEmpty();
+ }
+
+ @Test
+ public void fail_to_add_global_new_issues_notification() {
+ Users.CreateWsResponse.User user = tester.users().generate();
+
+ expectHttpError(400,
+ "Value of parameter 'type' (NewIssues) must be one of: [CeReportTaskFailure, ChangesOnMyIssue, SQ-MyNewIssues]",
+ () -> tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("NewIssues")));
+ }
+
+ @Test
+ public void fail_to_remove_global_new_issues_notification() {
+ Users.CreateWsResponse.User user = tester.users().generate();
+
+ expectHttpError(400,
+ "Value of parameter 'type' (NewIssues) must be one of: [CeReportTaskFailure, ChangesOnMyIssue, SQ-MyNewIssues]",
+ () -> tester.as(user.getLogin()).wsClient().notifications().remove(new RemoveRequest().setChannel("EmailNotificationChannel").setType("NewIssues")));
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.sonarqube.tests.user;
+
+import com.sonar.orchestrator.Orchestrator;
+import org.junit.ClassRule;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+import static util.ItUtils.xooPlugin;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ SonarCloudNotificationsWsTest.class
+})
+public class SonarCloudUserSuite {
+
+ @ClassRule
+ public static final Orchestrator ORCHESTRATOR = Orchestrator.builderEnv()
+ .addPlugin(xooPlugin())
+
+ .setServerProperty("sonar.sonarcloud.enabled", "true")
+
+ // reduce memory for Elasticsearch
+ .setServerProperty("sonar.search.javaOpts", "-Xms128m -Xmx128m")
+
+ .build();
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.sonarqube.tests.user;
+
+import com.sonar.orchestrator.Orchestrator;
+import org.junit.ClassRule;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+import static util.ItUtils.pluginArtifact;
+import static util.ItUtils.xooPlugin;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ BaseIdentityProviderTest.class,
+ FavoritesWsTest.class,
+ ForceAuthenticationTest.class,
+ LocalAuthenticationTest.class,
+ MyAccountPageTest.class,
+ NotificationsWsTest.class,
+ OAuth2IdentityProviderTest.class,
+ RootUserInStandaloneModeTest.class,
+ UsersPageTest.class
+})
+public class UserSuite {
+
+ @ClassRule
+ public static final Orchestrator ORCHESTRATOR = Orchestrator.builderEnv()
+ .addPlugin(xooPlugin())
+
+ // Used in BaseIdentityProviderTest
+ .addPlugin(pluginArtifact("base-auth-plugin"))
+
+ // Used in OAuth2IdentityProviderTest
+ .addPlugin(pluginArtifact("oauth2-auth-plugin"))
+
+ // reduce memory for Elasticsearch
+ .setServerProperty("sonar.search.javaOpts", "-Xms128m -Xmx128m")
+
+ .build();
+
+}
import org.junit.Test;
import org.sonarqube.qa.util.Tester;
import org.sonarqube.qa.util.pageobjects.UsersManagementPage;
-import org.sonarqube.tests.Category1Suite;
import org.sonarqube.ws.Users;
import org.sonarqube.ws.Users.CreateWsResponse.User;
import org.sonarqube.ws.client.users.GroupsRequest;
private User adminUser;
@ClassRule
- public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR;
+ public static Orchestrator orchestrator = UserSuite.ORCHESTRATOR;
@Rule
public UserRule userRule = UserRule.from(orchestrator);