diff options
author | Simon Brandhof <simon.brandhof@gmail.com> | 2012-07-11 20:29:18 +0200 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@gmail.com> | 2012-07-11 20:29:35 +0200 |
commit | 3869be4f9026d8b677a98041d7591586e35b2942 (patch) | |
tree | c07539ed52b22af0592caeeacdc37b1f38f03b76 /sonar-server | |
parent | aceadd9dd9a7b835ce67c505013f090f06ebe642 (diff) | |
download | sonarqube-3869be4f9026d8b677a98041d7591586e35b2942.tar.gz sonarqube-3869be4f9026d8b677a98041d7591586e35b2942.zip |
SONAR-3646 API : new extension point to be notified on user creation
Diffstat (limited to 'sonar-server')
6 files changed, 139 insertions, 29 deletions
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/NewUserNotifier.java b/sonar-server/src/main/java/org/sonar/server/platform/NewUserNotifier.java new file mode 100644 index 00000000000..a6f1d22869b --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/platform/NewUserNotifier.java @@ -0,0 +1,47 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 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.platform; + +import org.slf4j.LoggerFactory; +import org.sonar.api.ServerComponent; +import org.sonar.api.platform.NewUserHandler; + +/** + * @since 3.2 + */ +public class NewUserNotifier implements ServerComponent { + + private NewUserHandler[] handlers; + + public NewUserNotifier(NewUserHandler[] handlers) { + this.handlers = handlers; + } + + public NewUserNotifier() { + this(new NewUserHandler[0]); + } + + public void onNewUser(NewUserHandler.Context context) { + LoggerFactory.getLogger(NewUserNotifier.class).debug("User created: " + context.getLogin() + ". Notifying " + NewUserHandler.class.getSimpleName() + " handlers..."); + for (NewUserHandler handler : handlers) { + handler.doOnNewUser(context); + } + } +}
\ No newline at end of file diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index 2ce18b2e881..e20fed0c4c0 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -241,6 +241,7 @@ public final class Platform { servicesContainer.addSingleton(RuleI18nManager.class); servicesContainer.addSingleton(GwtI18n.class); servicesContainer.addSingleton(ResourceTypes.class); + servicesContainer.addSingleton(NewUserNotifier.class); // Notifications servicesContainer.addSingleton(EmailSettings.class); diff --git a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java index 76ba04b7168..d2f4a2bb449 100644 --- a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java +++ b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java @@ -27,6 +27,7 @@ import org.sonar.api.config.License; import org.sonar.api.config.PropertyDefinitions; import org.sonar.api.config.Settings; import org.sonar.api.platform.ComponentContainer; +import org.sonar.api.platform.NewUserHandler; import org.sonar.api.platform.PluginMetadata; import org.sonar.api.platform.PluginRepository; import org.sonar.api.profiles.ProfileExporter; @@ -37,11 +38,7 @@ import org.sonar.api.resources.ResourceTypes; import org.sonar.api.rules.RulePriority; import org.sonar.api.rules.RuleRepository; import org.sonar.api.utils.ValidationMessages; -import org.sonar.api.web.Footer; -import org.sonar.api.web.NavigationSection; -import org.sonar.api.web.Page; -import org.sonar.api.web.RubyRailsWebservice; -import org.sonar.api.web.Widget; +import org.sonar.api.web.*; import org.sonar.api.workflow.Review; import org.sonar.api.workflow.internal.DefaultReview; import org.sonar.api.workflow.internal.DefaultWorkflowContext; @@ -61,19 +58,15 @@ import org.sonar.server.filters.FilterExecutor; import org.sonar.server.filters.FilterResult; import org.sonar.server.notifications.reviews.ReviewsNotificationManager; import org.sonar.server.platform.GlobalSettingsUpdater; +import org.sonar.server.platform.NewUserNotifier; import org.sonar.server.platform.Platform; import org.sonar.server.platform.ServerIdGenerator; -import org.sonar.server.plugins.DefaultServerPluginRepository; -import org.sonar.server.plugins.PluginDeployer; -import org.sonar.server.plugins.PluginDownloader; -import org.sonar.server.plugins.UpdateCenterMatrix; -import org.sonar.server.plugins.UpdateCenterMatrixFactory; +import org.sonar.server.plugins.*; import org.sonar.server.rules.ProfilesConsole; import org.sonar.server.rules.RulesConsole; import org.sonar.updatecenter.common.Version; import javax.annotation.Nullable; - import java.net.InetAddress; import java.sql.Connection; import java.util.Collection; @@ -319,7 +312,7 @@ public final class JRubyFacade { public void ruleSeverityChanged(int parentProfileId, int activeRuleId, int oldSeverityId, int newSeverityId, String userName) { getProfilesManager().ruleSeverityChanged(parentProfileId, activeRuleId, RulePriority.values()[oldSeverityId], - RulePriority.values()[newSeverityId], userName); + RulePriority.values()[newSeverityId], userName); } public void ruleDeactivated(int parentProfileId, int deactivatedRuleId, String userName) { @@ -524,4 +517,13 @@ public final class JRubyFacade { getContainer().getComponentByType(ResourceKeyUpdaterDao.class).bulkUpdateKey(projectId, stringToReplace, replacementString); } + + // USERS + public void onNewUser(Map<String, String> fields) { + getContainer().getComponentByType(NewUserNotifier.class).onNewUser(NewUserHandler.Context.builder() + .setLogin(fields.get("login")) + .setName(fields.get("name")) + .setEmail(fields.get("email")) + .build()); + } } diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/users_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/users_controller.rb index b238a0bf709..a187754727c 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/users_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/users_controller.rb @@ -116,8 +116,7 @@ class UsersController < ApplicationController def reactivate user = User.find_by_login(params[:user][:login]) if user - user.reactivate(java_facade.getSettings().getString('sonar.defaultGroup')) - user.save! + user.reactivate!(java_facade.getSettings().getString('sonar.defaultGroup')) flash[:notice] = 'User was successfully reactivated.' else flash[:error] = "A user with login #{params[:user][:login]} does not exist." diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/user.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/user.rb index 2e25ac4dad7..c70d33985a4 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/user.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/user.rb @@ -23,6 +23,7 @@ class User < ActiveRecord::Base FAVOURITE_PROPERTY_KEY='favourite' + after_create :on_create has_and_belongs_to_many :groups has_many :user_roles, :dependent => :delete_all @@ -37,17 +38,17 @@ class User < ActiveRecord::Base include NeedAuthorization::ForUser include NeedAuthentication::ForUser - validates_length_of :name, :maximum => 200, :allow_blank => true, :allow_nil => true - validates_length_of :email, :maximum => 100, :allow_blank => true, :allow_nil => true + validates_length_of :name, :maximum => 200, :allow_blank => true, :allow_nil => true + validates_length_of :email, :maximum => 100, :allow_blank => true, :allow_nil => true # The following two validations not needed, because they come with Authentication::ByPassword - see SONAR-2656 #validates_length_of :password, :within => 4..40, :if => :password_required? #validates_confirmation_of :password, :if => :password_required? - validates_presence_of :login - validates_length_of :login, :within => 2..40 - validates_uniqueness_of :login, :case_sensitive => true - validates_format_of :login, :with => Authentication.login_regex, :message => Authentication.bad_login_message + validates_presence_of :login + validates_length_of :login, :within => 2..40 + validates_uniqueness_of :login, :case_sensitive => true + validates_format_of :login, :with => Authentication.login_regex, :message => Authentication.bad_login_message # HACK HACK HACK -- how to do attr_accessible from here? @@ -90,20 +91,22 @@ class User < ActiveRecord::Base # do not validate user, for example when user created via SSO has no password self.save(false) - self.user_roles.each {|role| role.delete} - self.properties.each {|prop| prop.delete} - self.filters.each {|f| f.destroy} - self.dashboards.each {|d| d.destroy} - self.active_dashboards.each {|ad| ad.destroy} + self.user_roles.each { |role| role.delete } + self.properties.each { |prop| prop.delete } + self.filters.each { |f| f.destroy } + self.dashboards.each { |d| d.destroy } + self.active_dashboards.each { |ad| ad.destroy } end # SONAR-3258 - def reactivate(default_group_name) + def reactivate!(default_group_name) if default_group_name default_group=Group.find_by_name(default_group_name) self.groups<<default_group if default_group end self.active = true + save! + on_create end def self.find_active_by_login(login) @@ -149,7 +152,7 @@ class User < ActiveRecord::Base def self.logins_to_ids(logins=[]) if logins.size>0 - User.find(:all, :select => 'id', :conditions => ['login in (?)', logins]).map{|user| user.id} + User.find(:all, :select => 'id', :conditions => ['login in (?)', logins]).map { |user| user.id } else [] end @@ -162,7 +165,7 @@ class User < ActiveRecord::Base def favourite_ids @favourite_ids ||= begin - properties().select{|p| p.key==FAVOURITE_PROPERTY_KEY}.map{|p| p.resource_id} + properties().select { |p| p.key==FAVOURITE_PROPERTY_KEY }.map { |p| p.resource_id } end @favourite_ids end @@ -187,7 +190,7 @@ class User < ActiveRecord::Base rid = resource.id if resource end if rid - props=properties().select{|p| p.key==FAVOURITE_PROPERTY_KEY && p.resource_id==rid} + props=properties().select { |p| p.key==FAVOURITE_PROPERTY_KEY && p.resource_id==rid } if props.size>0 properties().delete(props) return true @@ -199,4 +202,11 @@ class User < ActiveRecord::Base def favourite?(resource_id) favourite_ids().include?(resource_id.to_i) end + + + private + + def on_create + Java::OrgSonarServerUi::JRubyFacade.getInstance().onNewUser({'login' => self.login, 'name' => self.name, 'email' => self.email}) + end end diff --git a/sonar-server/src/test/java/org/sonar/server/platform/NewUserNotifierTest.java b/sonar-server/src/test/java/org/sonar/server/platform/NewUserNotifierTest.java new file mode 100644 index 00000000000..62618af3936 --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/platform/NewUserNotifierTest.java @@ -0,0 +1,51 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 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.platform; + +import org.junit.Test; +import org.sonar.api.platform.NewUserHandler; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +public class NewUserNotifierTest { + + private NewUserHandler.Context context = NewUserHandler.Context.builder().setLogin("marius").setName("Marius").build(); + + @Test + public void do_not_fail_if_no_handlers() { + NewUserNotifier notifier = new NewUserNotifier(); + + notifier.onNewUser(context); + } + + @Test + public void execute_handlers_on_new_user() { + NewUserHandler handler1 = mock(NewUserHandler.class); + NewUserHandler handler2 = mock(NewUserHandler.class); + NewUserNotifier notifier = new NewUserNotifier(new NewUserHandler[]{handler1, handler2}); + + + notifier.onNewUser(context); + + verify(handler1).doOnNewUser(context); + verify(handler2).doOnNewUser(context); + } +} |