package org.sonar.server.notification.ws;
import com.google.common.base.Splitter;
-import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.property.PropertyDto;
import org.sonar.db.property.PropertyQuery;
import org.sonar.db.user.UserDto;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.Notifications.ListResponse;
import org.sonarqube.ws.Notifications.Notification;
+import org.sonarqube.ws.Notifications.Notification.Builder;
-import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Comparator.comparing;
import static java.util.Comparator.naturalOrder;
import static java.util.Comparator.nullsFirst;
return response -> {
List<PropertyDto> properties = dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setUserUuid(user.getUuid()).build(), dbSession);
Map<String, ComponentDto> componentsByUuid = searchProjects(dbSession, properties);
- Map<String, OrganizationDto> organizationsByUuid = getOrganizations(dbSession, componentsByUuid.values());
Predicate<PropertyDto> isNotification = prop -> prop.getKey().startsWith("notification.");
Predicate<PropertyDto> isComponentInDb = prop -> prop.getComponentUuid() == null || componentsByUuid.containsKey(prop.getComponentUuid());
.filter(isNotification)
.filter(channelAndDispatcherAuthorized())
.filter(isComponentInDb)
- .map(toWsNotification(notification, organizationsByUuid, componentsByUuid))
+ .map(toWsNotification(notification, componentsByUuid))
.sorted(comparing(Notification::getProject, nullsFirst(naturalOrder()))
.thenComparing(Notification::getChannel)
.thenComparing(Notification::getType))
.collect(MoreCollectors.uniqueIndex(ComponentDto::uuid));
}
- private Map<String, OrganizationDto> getOrganizations(DbSession dbSession, Collection<ComponentDto> values) {
- Set<String> organizationUuids = values.stream()
- .map(ComponentDto::getOrganizationUuid)
- .collect(MoreCollectors.toSet());
- return dbClient.organizationDao().selectByUuids(dbSession, organizationUuids)
- .stream()
- .collect(MoreCollectors.uniqueIndex(OrganizationDto::getUuid));
- }
-
- private static Function<PropertyDto, Notification> toWsNotification(Notification.Builder notification,
- Map<String, OrganizationDto> organizationsByUuid, Map<String, ComponentDto> projectsByUuid) {
+ private static Function<PropertyDto, Notification> toWsNotification(Notification.Builder notification, Map<String, ComponentDto> projectsByUuid) {
return property -> {
notification.clear();
List<String> propertyKey = Splitter.on(".").splitToList(property.getKey());
notification.setType(propertyKey.get(1));
notification.setChannel(propertyKey.get(2));
- ofNullable(property.getComponentUuid()).ifPresent(componentUuid -> populateProjectFields(notification, componentUuid, organizationsByUuid, projectsByUuid));
+ ofNullable(property.getComponentUuid()).ifPresent(componentUuid -> populateProjectFields(notification, componentUuid, projectsByUuid));
return notification.build();
};
}
- private static Notification.Builder populateProjectFields(Notification.Builder notification, String componentUuid,
- Map<String, OrganizationDto> organizationsByUuid, Map<String, ComponentDto> projectsByUuid) {
+ private static void populateProjectFields(Builder notification, String componentUuid,
+ Map<String, ComponentDto> projectsByUuid) {
ComponentDto project = projectsByUuid.get(componentUuid);
- String organizationUuid = project.getOrganizationUuid();
- OrganizationDto organizationDto = organizationsByUuid.get(organizationUuid);
- checkArgument(organizationDto != null, "No organization for uuid '%s'", organizationUuid);
-
- return notification.setOrganization(organizationDto.getKey())
+ notification
.setProject(project.getDbKey())
.setProjectName(project.name());
}
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"));
+ db.components().insertViewAndSnapshot(newView().setDbKey("VIEW_1"));
when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
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.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
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.assertThatThrownBy;
import static org.assertj.core.api.Assertions.tuple;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
private static final String NOTIF_NEW_QUALITY_GATE_STATUS = "NewQualityGateStatus";
@Rule
- public ExpectedException expectedException = ExpectedException.none();
+ public final UserSessionRule userSession = UserSessionRule.standalone();
@Rule
- public UserSessionRule userSession = UserSessionRule.standalone();
- @Rule
- public DbTester db = DbTester.create();
+ public final DbTester db = DbTester.create();
- private DbClient dbClient = db.getDbClient();
- private DbSession dbSession = db.getSession();
+ private final DbClient dbClient = db.getDbClient();
+ private final DbSession dbSession = db.getSession();
- private NotificationChannel emailChannel = new FakeNotificationChannel("EmailChannel");
- private NotificationChannel twitterChannel = new FakeNotificationChannel("TwitterChannel");
+ private final NotificationChannel emailChannel = new FakeNotificationChannel("EmailChannel");
+ private final NotificationChannel twitterChannel = new FakeNotificationChannel("TwitterChannel");
- private NotificationUpdater notificationUpdater = new NotificationUpdater(dbClient);
- private Dispatchers dispatchers = mock(Dispatchers.class);
+ private final NotificationUpdater notificationUpdater = new NotificationUpdater(dbClient);
+ private final Dispatchers dispatchers = mock(Dispatchers.class);
- private WsActionTester ws = new WsActionTester(new ListAction(new NotificationCenter(
+ private final WsActionTester ws = new WsActionTester(new ListAction(new NotificationCenter(
new NotificationDispatcherMetadata[] {},
new NotificationChannel[] {emailChannel, twitterChannel}),
dbClient, userSession, dispatchers));
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 = db.components().insertPrivateProject(organization);
+ ComponentDto project = db.components().insertPrivateProject();
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);
ListResponse result = call();
assertThat(result.getNotificationsList())
- .extracting(Notification::getChannel, Notification::getOrganization, Notification::getType, Notification::getProject)
+ .extracting(Notification::getChannel, Notification::getType, Notification::getProject)
.containsExactly(
- 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, 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()));
+ tuple(emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, ""),
+ tuple(emailChannel.getKey(), NOTIF_NEW_ISSUES, ""),
+ tuple(twitterChannel.getKey(), NOTIF_MY_NEW_ISSUES, ""),
+ tuple(emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, project.getKey()),
+ tuple(emailChannel.getKey(), NOTIF_NEW_QUALITY_GATE_STATUS, project.getKey()),
+ tuple(twitterChannel.getKey(), NOTIF_MY_NEW_ISSUES, project.getKey()));
}
@Test
notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
dbSession.commit();
- expectedException.expect(ForbiddenException.class);
-
- call(user.getLogin());
+ String userLogin = user.getLogin();
+ assertThatThrownBy(() -> call(userLogin))
+ .isInstanceOf(ForbiddenException.class);
}
@Test
public void fail_if_login_is_provided_and_unknown() {
userSession.logIn().setSystemAdministrator();
- expectedException.expect(NotFoundException.class);
- expectedException.expectMessage("User 'LOGIN 404' not found");
-
- call("LOGIN 404");
+ assertThatThrownBy(() -> call("LOGIN 404"))
+ .isInstanceOf(NotFoundException.class)
+ .hasMessage("User 'LOGIN 404' not found");
}
@Test
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 = db.components().insertPrivateProject(organization, p -> p.setDbKey(KEY_PROJECT_EXAMPLE_001).setName("My Project"));
+ ComponentDto project = db.components().insertPrivateProject(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);
public void fail_when_not_authenticated() {
userSession.anonymous();
- expectedException.expect(UnauthorizedException.class);
-
- call();
+ assertThatThrownBy(this::call)
+ .isInstanceOf(UnauthorizedException.class);
}
private ListResponse call() {
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.db.DbClient;
import static java.util.Collections.singletonList;
import static java.util.Optional.ofNullable;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.db.component.ComponentTesting.newView;
private static final String NOTIF_NEW_ISSUES = "Dispatcher2";
private static final String NOTIF_NEW_QUALITY_GATE_STATUS = "Dispatcher3";
@Rule
- public ExpectedException expectedException = ExpectedException.none();
+ public final UserSessionRule userSession = UserSessionRule.standalone();
@Rule
- public UserSessionRule userSession = UserSessionRule.standalone();
- @Rule
- public DbTester db = DbTester.create();
- private DbClient dbClient = db.getDbClient();
- private DbSession dbSession = db.getSession();
+ public final DbTester db = DbTester.create();
+ private final DbClient dbClient = db.getDbClient();
+ private final DbSession dbSession = db.getSession();
- private NotificationChannel emailChannel = new FakeNotificationChannel("EmailChannel");
- private NotificationChannel twitterChannel = new FakeNotificationChannel("TwitterChannel");
+ private final NotificationChannel emailChannel = new FakeNotificationChannel("EmailChannel");
+ private final NotificationChannel twitterChannel = new FakeNotificationChannel("TwitterChannel");
// default channel, based on class simple name
- private NotificationChannel defaultChannel = new FakeNotificationChannel("EmailNotificationChannel");
+ private final NotificationChannel defaultChannel = new FakeNotificationChannel("EmailNotificationChannel");
- private NotificationUpdater notificationUpdater = new NotificationUpdater(dbClient);
- private Dispatchers dispatchers = mock(Dispatchers.class);
+ private final NotificationUpdater notificationUpdater = new NotificationUpdater(dbClient);
+ private final Dispatchers dispatchers = mock(Dispatchers.class);
- private RemoveRequest request = new RemoveRequest().setType(NOTIF_MY_NEW_ISSUES);
+ private final RemoveRequest request = new RemoveRequest().setType(NOTIF_MY_NEW_ISSUES);
- private WsActionTester ws = new WsActionTester(new RemoveAction(new NotificationCenter(
+ private final WsActionTester ws = new WsActionTester(new RemoveAction(new NotificationCenter(
new NotificationDispatcherMetadata[] {},
new NotificationChannel[] {emailChannel, twitterChannel, defaultChannel}), notificationUpdater, dispatchers, dbClient, TestComponentFinder.from(db), userSession));
notificationUpdater.add(dbSession, defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, project);
dbSession.commit();
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Notification doesn't exist");
-
- call(request);
+ assertThatThrownBy(() -> call(request))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Notification doesn't exist");
}
@Test
notificationUpdater.add(dbSession, defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
dbSession.commit();
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Notification doesn't exist");
-
- call(request.setProject(project.getDbKey()));
+ RemoveRequest request = this.request.setProject(project.getDbKey());
+ assertThatThrownBy(() -> call(request))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Notification doesn't exist");
}
@Test
userSession.logIn(user).setSystemAdministrator();
when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
- expectedException.expect(NotFoundException.class);
- expectedException.expectMessage("User 'LOGIN 404' not found");
-
- call(request.setLogin("LOGIN 404"));
+ RemoveRequest request = this.request.setLogin("LOGIN 404");
+ assertThatThrownBy(() -> call(request))
+ .isInstanceOf(NotFoundException.class)
+ .hasMessage("User 'LOGIN 404' not found");
}
@Test
notificationUpdater.add(dbSession, defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
dbSession.commit();
- expectedException.expect(ForbiddenException.class);
-
- call(request.setLogin(user.getLogin()));
+ RemoveRequest request = this.request.setLogin(user.getLogin());
+ assertThatThrownBy(() -> call(request))
+ .isInstanceOf(ForbiddenException.class);
}
@Test
userSession.logIn(user);
when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Notification doesn't exist");
-
- call(request);
+ assertThatThrownBy(() -> call(request))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Notification doesn't exist");
}
@Test
userSession.logIn(user);
when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
- expectedException.expect(IllegalArgumentException.class);
-
- call(request.setChannel("Channel42"));
+ RemoveRequest request = this.request.setChannel("Channel42");
+ assertThatThrownBy(() -> call(request))
+ .isInstanceOf(IllegalArgumentException.class);
}
@Test
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]");
-
- call(request.setType("Dispatcher42"));
+ RemoveRequest request = this.request.setType("Dispatcher42");
+ assertThatThrownBy(() -> call(request))
+ .isInstanceOf(BadRequestException.class)
+ .hasMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1, Dispatcher2, Dispatcher3]");
}
@Test
when(dispatchers.getProjectDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
ComponentDto project = db.components().insertPrivateProject();
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1, Dispatcher3]");
-
- call(request.setType("Dispatcher42").setProject(project.getDbKey()));
+ RemoveRequest request = this.request.setType("Dispatcher42").setProject(project.getDbKey());
+ assertThatThrownBy(() -> call(request))
+ .isInstanceOf(BadRequestException.class)
+ .hasMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1, Dispatcher3]");
}
@Test
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();
+ TestRequest request = ws.newRequest();
+ assertThatThrownBy(request::execute)
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("The 'type' parameter is missing");
}
@Test
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"));
+ RemoveRequest request = this.request.setProject("Project-42");
+ assertThatThrownBy(() -> call(request))
+ .isInstanceOf(NotFoundException.class);
}
@Test
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);
- expectedException.expectMessage("Component 'VIEW_1' must be a project");
+ db.components().insertViewAndSnapshot(newView().setDbKey("VIEW_1"));
- call(request.setProject("VIEW_1"));
+ RemoveRequest request = this.request.setProject("VIEW_1");
+ assertThatThrownBy(() -> call(request))
+ .isInstanceOf(BadRequestException.class)
+ .hasMessage("Component 'VIEW_1' must be a project");
}
@Test
userSession.anonymous();
when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
- expectedException.expect(UnauthorizedException.class);
-
- call(request);
+ assertThatThrownBy(() -> call(request))
+ .isInstanceOf(UnauthorizedException.class);
}
@Test
ComponentDto project = db.components().insertPublicProject();
ComponentDto branch = db.components().insertProjectBranch(project);
- expectedException.expect(NotFoundException.class);
- expectedException.expectMessage(format("Component key '%s' not found", branch.getDbKey()));
-
- call(request.setProject(branch.getDbKey()));
+ RemoveRequest request = this.request.setProject(branch.getDbKey());
+ assertThatThrownBy(() -> call(request))
+ .isInstanceOf(NotFoundException.class)
+ .hasMessage(format("Component key '%s' not found", branch.getDbKey()));
}
private TestResponse call(RemoveRequest remove) {
message Notification {
optional string channel = 1;
optional string type = 2;
- optional string organization = 5;
optional string project = 3;
optional string projectName = 4;
}