diff options
Diffstat (limited to 'sonar-server')
6 files changed, 143 insertions, 13 deletions
diff --git a/sonar-server/src/main/java/org/sonar/server/notifications/NotificationService.java b/sonar-server/src/main/java/org/sonar/server/notifications/NotificationService.java index b77fe0e6296..b88cf62146b 100644 --- a/sonar-server/src/main/java/org/sonar/server/notifications/NotificationService.java +++ b/sonar-server/src/main/java/org/sonar/server/notifications/NotificationService.java @@ -25,15 +25,18 @@ import com.google.common.collect.Sets; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.ServerComponent; +import org.sonar.api.database.DatabaseSession; +import org.sonar.api.database.configuration.Property; +import org.sonar.api.database.model.User; import org.sonar.api.notifications.Notification; import org.sonar.api.notifications.NotificationChannel; import org.sonar.api.notifications.NotificationDispatcher; import org.sonar.api.utils.TimeProfiler; import org.sonar.core.notifications.DefaultNotificationManager; import org.sonar.jpa.entity.NotificationQueueElement; +import org.sonar.jpa.session.DatabaseSessionFactory; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -49,6 +52,7 @@ public class NotificationService implements ServerComponent { private ScheduledExecutorService executorService; private long period = 10; // FIXME small value just for tests + private DatabaseSessionFactory sessionFactory; private DefaultNotificationManager manager; private NotificationChannel[] channels; private NotificationDispatcher[] dispatchers; @@ -56,12 +60,13 @@ public class NotificationService implements ServerComponent { /** * Default constructor when no channels. */ - public NotificationService(DefaultNotificationManager manager, NotificationDispatcher[] dispatchers) { - this(manager, dispatchers, new NotificationChannel[0]); + public NotificationService(DatabaseSessionFactory sessionFactory, DefaultNotificationManager manager, NotificationDispatcher[] dispatchers) { + this(sessionFactory, manager, dispatchers, new NotificationChannel[0]); LOG.warn("There is no channels - all notifications would be ignored!"); } - public NotificationService(DefaultNotificationManager manager, NotificationDispatcher[] dispatchers, NotificationChannel[] channels) { + public NotificationService(DatabaseSessionFactory sessionFactory, DefaultNotificationManager manager, NotificationDispatcher[] dispatchers, NotificationChannel[] channels) { + this.sessionFactory = sessionFactory; this.manager = manager; this.channels = channels; this.dispatchers = dispatchers; @@ -129,17 +134,34 @@ public class NotificationService implements ServerComponent { } } } - for (Map.Entry<String, NotificationChannel> entry : recipients.entries()) { + for (Map.Entry<String, Collection<NotificationChannel>> entry : recipients.asMap().entrySet()) { String username = entry.getKey(); - NotificationChannel channel = entry.getValue(); - LOG.info("For user {} via {}", username, channel); - channel.deliver(notification, username); + Collection<NotificationChannel> channels = entry.getValue(); + LOG.info("For user {} via {}", username, channels); + for (NotificationChannel channel : channels) { + channel.deliver(notification, username); + } } TIME_PROFILER.stop(); } + public List<NotificationDispatcher> getDispatchers() { + return Arrays.asList(dispatchers); + } + + public List<NotificationChannel> getChannels() { + return Arrays.asList(channels); + } + + /** + * Visibility has been relaxed for tests. + */ boolean isEnabled(String username, NotificationChannel channel, NotificationDispatcher dispatcher) { - return true; // FIXME for the moment we will accept everything + DatabaseSession session = sessionFactory.getSession(); + User user = session.getSingleResult(User.class, "login", username); + String notificationKey = "notification." + dispatcher.getKey() + "." + channel.getKey(); + Property property = session.getSingleResult(Property.class, "userId", user.getId(), "key", notificationKey); + return property != null && "true".equals(property.getValue()); } } diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/account_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/account_controller.rb index 340ce2bfc3a..807b9bb79d6 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/account_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/account_controller.rb @@ -24,7 +24,13 @@ class AccountController < ApplicationController before_filter :login_required def index - + notification_service = java_facade.getCoreComponentByClassname('org.sonar.server.notifications.NotificationService') + @channels = notification_service.getChannels() + @dispatchers = notification_service.getDispatchers() + @notifications = {} + for property in Property.find(:all, :conditions => ['prop_key like ? AND user_id = ?', 'notification.%', current_user.id]) + @notifications[property.key.sub('notification.', '')] = true + end end def change_password @@ -47,4 +53,12 @@ class AccountController < ApplicationController end redirect_to :controller => 'account', :action => 'index' end + + def update_notifications + notifications = params[:notifications] + Property.delete_all(['prop_key like ? AND user_id = ?', 'notification.%', current_user.id]) + notifications.each_key { |key| current_user.set_property(:prop_key => 'notification.' + key, :text_value => 'true') } unless notifications.nil? + redirect_to :action => 'index' + end + end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/account/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/account/index.html.erb index 23486909d89..5a2faf1a95b 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/account/index.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/account/index.html.erb @@ -62,4 +62,36 @@ $('pass_form_tag').focusFirstElement(); //]]> </script> -<% end -%>
\ No newline at end of file +<% end -%> +<br/> + +<h1>Notifications</h1> +<br/> +<% form_tag({:action => 'update_notifications'}, {:method => 'post'}) do %> + <table> + <tr> + <td></td> + <% for channel in @channels %> + <td><%= channel.getKey() %></td> + <% end %> + </tr> + <% for dispatcher in @dispatchers %> + <tr> + <td><%= dispatcher.getKey() %></td> + <td> + <% + for channel in @channels + notification_id = dispatcher.getKey() + '.' + channel.getKey() + check_box_id = 'notifications[' + notification_id + ']' + check_box_checked = @notifications[notification_id] + %> + <%= check_box_tag check_box_id, 'true', check_box_checked %> + <% end %> + </td> + </tr> + <% end %> + </table> + <br/> + <%= submit_tag %> +<% end %> +<br/> diff --git a/sonar-server/src/test/java/org/sonar/server/notifications/NotificationServiceDbTest.java b/sonar-server/src/test/java/org/sonar/server/notifications/NotificationServiceDbTest.java new file mode 100644 index 00000000000..a7a57c9044b --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/notifications/NotificationServiceDbTest.java @@ -0,0 +1,54 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.server.notifications; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.notifications.NotificationChannel; +import org.sonar.api.notifications.NotificationDispatcher; +import org.sonar.jpa.test.AbstractDbUnitTestCase; + +public class NotificationServiceDbTest extends AbstractDbUnitTestCase { + + private NotificationService notificationService; + + @Before + public void setUp() { + setupData("fixture"); + notificationService = new NotificationService(getSessionFactory(), null, null); + } + + @Test + public void should() { + NotificationChannel email = mock(NotificationChannel.class); + when(email.getKey()).thenReturn("EmailNotificationChannel"); + NotificationDispatcher commentOnReviewAssignedToMe = mock(NotificationDispatcher.class); + when(commentOnReviewAssignedToMe.getKey()).thenReturn("CommentOnReviewAssignedToMe"); + + assertThat(notificationService.isEnabled("simon", email, commentOnReviewAssignedToMe), is(true)); + assertThat(notificationService.isEnabled("godin", email, commentOnReviewAssignedToMe), is(false)); + } + +} diff --git a/sonar-server/src/test/java/org/sonar/server/notifications/NotificationServiceTest.java b/sonar-server/src/test/java/org/sonar/server/notifications/NotificationServiceTest.java index 46633e27a90..d17ada17562 100644 --- a/sonar-server/src/test/java/org/sonar/server/notifications/NotificationServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/notifications/NotificationServiceTest.java @@ -77,7 +77,7 @@ public class NotificationServiceTest { NotificationDispatcher[] dispatchers = new NotificationDispatcher[] { commentOnReviewAssignedToMe, commentOnReviewCreatedByMe }; NotificationChannel[] channels = new NotificationChannel[] { emailChannel, gtalkChannel }; manager = mock(DefaultNotificationManager.class); - service = spy(new NotificationService(manager, dispatchers, channels)); + service = spy(new NotificationService(null, manager, dispatchers, channels)); doReturn(false).when(service).isEnabled(any(String.class), any(NotificationChannel.class), any(NotificationDispatcher.class)); } diff --git a/sonar-server/src/test/resources/org/sonar/server/notifications/NotificationServiceDbTest/fixture.xml b/sonar-server/src/test/resources/org/sonar/server/notifications/NotificationServiceDbTest/fixture.xml new file mode 100644 index 00000000000..83c713eb0e7 --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/notifications/NotificationServiceDbTest/fixture.xml @@ -0,0 +1,8 @@ +<dataset> + + <users id="1" login="simon" /> + <users id="2" login="godin" /> + + <properties user_id="1" prop_key="notification.CommentOnReviewAssignedToMe.EmailNotificationChannel" text_value="true"/> + +</dataset>
\ No newline at end of file |