]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-4950 Add a transaction to prevent multiple connection to add multiple lines...
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 9 Oct 2014 14:35:05 +0000 (16:35 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Fri, 10 Oct 2014 06:39:49 +0000 (08:39 +0200)
server/sonar-web/src/main/webapp/WEB-INF/db/migrate/602_remove_duplication_in_group_roles.rb [new file with mode: 0644]
server/sonar-web/src/main/webapp/WEB-INF/lib/need_authentication.rb
sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java
sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql

diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/602_remove_duplication_in_group_roles.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/602_remove_duplication_in_group_roles.rb
new file mode 100644 (file)
index 0000000..168fa37
--- /dev/null
@@ -0,0 +1,44 @@
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube 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.
+#
+# SonarQube 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.
+#
+
+#
+# SonarQube 4.5
+# SONAR-4950 Unique constraint cannot be created because it would be on resource_id that is nullable
+#
+class RemoveDuplicationInGroupRoles < ActiveRecord::Migration
+
+  class GroupRole < ActiveRecord::Base
+  end
+
+  def self.up
+    GroupRole.reset_column_information
+
+    duplicated_ids = ActiveRecord::Base.connection.select_rows('select group_id,resource_id,role from group_roles group by group_id,resource_id,role having count(*) > 1')
+    say_with_time "Remove #{duplicated_ids.size} duplicated group roles" do
+      duplicated_ids.each do |fields|
+        rows = GroupRole.find(:all, :conditions => {:group_id => fields[0], :resource_id => fields[1], :role => fields[2]})
+        # delete all rows except the last one
+        rows[0...-1].each do |row|
+          GroupRole.delete(row.id)
+        end
+      end
+    end
+  end
+end
index 400ccbad2f18529ec6882c76207d9bac1efffbb2..61b266fc66df4e7435bfeac0b764af8527f3faec 100644 (file)
@@ -64,6 +64,10 @@ class PluginRealm
     result = nil
     if !username.blank? && !password.blank?
       user = User.find_active_by_login(username)
+      # SONAR-4950 Use a transaction to prevent multiple insertion of same groups
+      User.transaction do
+        user.save(false)
+      end
       result = user if user && user.authenticated?(password)
     end
     result
@@ -117,40 +121,46 @@ class PluginRealm
   def synchronize(username, password, details)
     username=details.getName() if username.blank? && details
     user = User.find_by_login(username)
-    if !user
-      # No such user in Sonar database
-      return nil if !Api::Utils.java_facade.getSettings().getBoolean('sonar.authenticator.createUsers')
-      # Automatically create a user in the sonar db if authentication has been successfully done
-      user = User.new(:login => username, :name => username, :email => '')
-      if details
-        user.name = details.getName()
-        user.email = details.getEmail()
-      end
-      default_group_name = Api::Utils.java_facade.getSettings().getString('sonar.defaultGroup')
-      default_group = Group.find_by_name(default_group_name)
-      if default_group
-        user.groups << default_group
+
+    # SONAR-4950 Use a transaction to prevent multiple insertion of same groups
+    User.transaction do
+      if !user
+        # No such user in Sonar database
+        return nil if !Api::Utils.java_facade.getSettings().getBoolean('sonar.authenticator.createUsers')
+        # Automatically create a user in the sonar db if authentication has been successfully done
+        user = User.new(:login => username, :name => username, :email => '')
+        if details
+          user.name = details.getName()
+          user.email = details.getEmail()
+        end
+        default_group_name = Api::Utils.java_facade.getSettings().getString('sonar.defaultGroup')
+        default_group = Group.find_by_name(default_group_name)
+        if default_group
+          user.groups << default_group
+        else
+          Rails.logger.error("The default user group does not exist: #{default_group_name}. Please check the parameter 'Default user group' in general settings.")
+        end
       else
-        Rails.logger.error("The default user group does not exist: #{default_group_name}. Please check the parameter 'Default user group' in general settings.")
+        # Existing user
+        if details && Api::Utils.java_facade.getSettings().getBoolean('sonar.security.updateUserAttributes')
+          user.name = details.getName()
+          user.email = details.getEmail()
+        end
       end
-    else
-      # Existing user
-      if details && Api::Utils.java_facade.getSettings().getBoolean('sonar.security.updateUserAttributes')
-        user.name = details.getName()
-        user.email = details.getEmail()
+      if @save_password
+        user.password = password
+        user.password_confirmation = password
       end
+
+      # A user that is synchronized with an external system is always set to 'active' (see SONAR-3258 for the deactivation concept)
+      user.active=true
+      # Note that validation disabled
+      user.save(false)
+
+      synchronize_groups(user)
+      user.notify_creation_handlers
+      user
     end
-    if @save_password
-      user.password = password
-      user.password_confirmation = password
-    end
-    synchronize_groups(user)
-    # A user that is synchronized with an external system is always set to 'active' (see SONAR-3258 for the deactivation concept)
-    user.active=true
-    # Note that validation disabled
-    user.save(false)
-    user.notify_creation_handlers
-    user
   end
 
   def synchronize_groups(user)
index af91a6ae928d96f6faa182259288655751cdf8ce..9045874e393751a40120465effd71c9b920b0d8c 100644 (file)
@@ -33,7 +33,7 @@ import java.util.List;
  */
 public class DatabaseVersion implements BatchComponent, ServerComponent {
 
-  public static final int LAST_VERSION = 601;
+  public static final int LAST_VERSION = 602;
 
   public static enum Status {
     UP_TO_DATE, REQUIRES_UPGRADE, REQUIRES_DOWNGRADE, FRESH_INSTALL
index 53b8dcc9d122fc2c921e2721181e8dc42980a093..7987b78321e1930a58722a40f86f66a852c2b9a9 100644 (file)
@@ -256,6 +256,7 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('583');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('584');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('600');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('601');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('602');
 
 INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '2011-09-26 22:27:48.0', '2011-09-26 22:27:48.0', null, null);
 ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;