]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-3618 move default permissions to PROPERTIES
authorSimon Brandhof <simon.brandhof@gmail.com>
Mon, 2 Jul 2012 09:35:43 +0000 (11:35 +0200)
committerSimon Brandhof <simon.brandhof@gmail.com>
Thu, 5 Jul 2012 14:56:53 +0000 (16:56 +0200)
* add MyBatis mappers for GROUPS, GROUP_ROLES, USERS and USER_ROLES.

24 files changed:
sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java
sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java
sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java
sonar-core/src/main/java/org/sonar/core/user/GroupDto.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/user/GroupRoleDto.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/user/RoleDao.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/user/RoleMapper.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/user/UserDao.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/user/UserDto.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/user/UserMapper.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/user/UserRoleDto.java [new file with mode: 0644]
sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql
sonar-core/src/main/resources/org/sonar/core/user/RoleMapper.xml [new file with mode: 0644]
sonar-core/src/main/resources/org/sonar/core/user/UserMapper.xml [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/user/RoleDaoTest.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/user/UserDaoTest.java [new file with mode: 0644]
sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/insertGroupRoles-result.xml [new file with mode: 0644]
sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/insertGroupRoles.xml [new file with mode: 0644]
sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/insertUserRoles-result.xml [new file with mode: 0644]
sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/insertUserRoles.xml [new file with mode: 0644]
sonar-core/src/test/resources/org/sonar/core/user/UserDaoTest/selectGroupByName.xml [new file with mode: 0644]
sonar-core/src/test/resources/org/sonar/core/user/UserDaoTest/selectUserByLogin.xml [new file with mode: 0644]
sonar-server/src/main/webapp/WEB-INF/db/migrate/089_set_default_project_roles.rb
sonar-server/src/main/webapp/WEB-INF/db/migrate/320_move_default_roles.rb [new file with mode: 0644]

index 602181cdd449d3032f71ee1d4d63480ff76430e9..67cbc72d58bfe51a92b116e38f476193ae5b2d08 100644 (file)
@@ -34,6 +34,8 @@ import org.sonar.core.review.ReviewDao;
 import org.sonar.core.rule.RuleDao;
 import org.sonar.core.template.LoadedTemplateDao;
 import org.sonar.core.user.AuthorDao;
+import org.sonar.core.user.RoleDao;
+import org.sonar.core.user.UserDao;
 
 import java.util.List;
 
@@ -45,19 +47,21 @@ public final class DaoUtils {
   @SuppressWarnings("unchecked")
   public static List<Class<?>> getDaoClasses() {
     return ImmutableList.of(
-        ActiveDashboardDao.class,
-        AuthorDao.class,
-        FilterDao.class,
-        DashboardDao.class,
-        DuplicationDao.class,
-        LoadedTemplateDao.class,
-        PropertiesDao.class,
-        PurgeDao.class,
-        ResourceIndexerDao.class,
-        ResourceDao.class,
-        ResourceKeyUpdaterDao.class,
-        ReviewCommentDao.class,
-        ReviewDao.class,
-        RuleDao.class);
+      ActiveDashboardDao.class,
+      AuthorDao.class,
+      FilterDao.class,
+      DashboardDao.class,
+      DuplicationDao.class,
+      LoadedTemplateDao.class,
+      PropertiesDao.class,
+      PurgeDao.class,
+      ResourceIndexerDao.class,
+      ResourceDao.class,
+      ResourceKeyUpdaterDao.class,
+      ReviewCommentDao.class,
+      ReviewDao.class,
+      RoleDao.class,
+      RuleDao.class,
+      UserDao.class);
   }
 }
index 0014a466638fc86a9043b823265bafff7748f0ea..dfe7480a6190eaa0053692ae2af256584723c4ad 100644 (file)
@@ -35,7 +35,7 @@ import java.util.List;
  */
 public class DatabaseVersion implements BatchComponent, ServerComponent {
 
-  public static final int LAST_VERSION = 306;
+  public static final int LAST_VERSION = 320;
 
   public static enum Status {
     UP_TO_DATE, REQUIRES_UPGRADE, REQUIRES_DOWNGRADE, FRESH_INSTALL
index dd7d58cb20ae10a8792838f16d0beefafdb23690..d051fe6942269bb40588a2d6949007f591386d6c 100644 (file)
@@ -24,46 +24,25 @@ import org.apache.commons.lang.StringUtils;
 import org.apache.ibatis.builder.xml.XMLMapperBuilder;
 import org.apache.ibatis.logging.LogFactory;
 import org.apache.ibatis.mapping.Environment;
-import org.apache.ibatis.session.Configuration;
-import org.apache.ibatis.session.ExecutorType;
-import org.apache.ibatis.session.SqlSession;
-import org.apache.ibatis.session.SqlSessionFactory;
-import org.apache.ibatis.session.SqlSessionFactoryBuilder;
+import org.apache.ibatis.session.*;
 import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.BatchComponent;
 import org.sonar.api.ServerComponent;
-import org.sonar.core.dashboard.ActiveDashboardDto;
-import org.sonar.core.dashboard.ActiveDashboardMapper;
-import org.sonar.core.dashboard.DashboardDto;
-import org.sonar.core.dashboard.DashboardMapper;
-import org.sonar.core.dashboard.WidgetDto;
-import org.sonar.core.dashboard.WidgetMapper;
-import org.sonar.core.dashboard.WidgetPropertyDto;
-import org.sonar.core.dashboard.WidgetPropertyMapper;
+import org.sonar.core.dashboard.*;
 import org.sonar.core.dependency.DependencyDto;
 import org.sonar.core.dependency.DependencyMapper;
 import org.sonar.core.dependency.ResourceSnapshotDto;
 import org.sonar.core.dependency.ResourceSnapshotMapper;
 import org.sonar.core.duplication.DuplicationMapper;
 import org.sonar.core.duplication.DuplicationUnitDto;
-import org.sonar.core.filter.CriterionDto;
-import org.sonar.core.filter.CriterionMapper;
-import org.sonar.core.filter.FilterColumnDto;
-import org.sonar.core.filter.FilterColumnMapper;
-import org.sonar.core.filter.FilterDto;
-import org.sonar.core.filter.FilterMapper;
+import org.sonar.core.filter.*;
 import org.sonar.core.properties.PropertiesMapper;
 import org.sonar.core.properties.PropertyDto;
 import org.sonar.core.purge.PurgeMapper;
 import org.sonar.core.purge.PurgeVendorMapper;
 import org.sonar.core.purge.PurgeableSnapshotDto;
-import org.sonar.core.resource.ResourceDto;
-import org.sonar.core.resource.ResourceIndexDto;
-import org.sonar.core.resource.ResourceIndexerMapper;
-import org.sonar.core.resource.ResourceKeyUpdaterMapper;
-import org.sonar.core.resource.ResourceMapper;
-import org.sonar.core.resource.SnapshotDto;
+import org.sonar.core.resource.*;
 import org.sonar.core.review.ReviewCommentDto;
 import org.sonar.core.review.ReviewCommentMapper;
 import org.sonar.core.review.ReviewDto;
@@ -72,8 +51,7 @@ import org.sonar.core.rule.RuleDto;
 import org.sonar.core.rule.RuleMapper;
 import org.sonar.core.template.LoadedTemplateDto;
 import org.sonar.core.template.LoadedTemplateMapper;
-import org.sonar.core.user.AuthorDto;
-import org.sonar.core.user.AuthorMapper;
+import org.sonar.core.user.*;
 
 import java.io.InputStream;
 
@@ -102,18 +80,22 @@ public class MyBatis implements BatchComponent, ServerComponent {
     loadAlias(conf, "FilterColumn", FilterColumnDto.class);
     loadAlias(conf, "Dashboard", DashboardDto.class);
     loadAlias(conf, "Dependency", DependencyDto.class);
-    loadAlias(conf, "ResourceSnapshot", ResourceSnapshotDto.class);
     loadAlias(conf, "DuplicationUnit", DuplicationUnitDto.class);
+    loadAlias(conf, "Group", GroupDto.class);
+    loadAlias(conf, "GroupRole", GroupRoleDto.class);
     loadAlias(conf, "LoadedTemplate", LoadedTemplateDto.class);
     loadAlias(conf, "Property", PropertyDto.class);
     loadAlias(conf, "PurgeableSnapshot", PurgeableSnapshotDto.class);
-    loadAlias(conf, "Review", ReviewDto.class);
-    loadAlias(conf, "ReviewComment", ReviewCommentDto.class);
     loadAlias(conf, "Resource", ResourceDto.class);
     loadAlias(conf, "ResourceIndex", ResourceIndexDto.class);
+    loadAlias(conf, "ResourceSnapshot", ResourceSnapshotDto.class);
+    loadAlias(conf, "Review", ReviewDto.class);
+    loadAlias(conf, "ReviewComment", ReviewCommentDto.class);
     loadAlias(conf, "Rule", RuleDto.class);
     loadAlias(conf, "Snapshot", SnapshotDto.class);
     loadAlias(conf, "SchemaMigration", SchemaMigrationDto.class);
+    loadAlias(conf, "User", UserDto.class);
+    loadAlias(conf, "UserRole", UserRoleDto.class);
     loadAlias(conf, "Widget", WidgetDto.class);
     loadAlias(conf, "WidgetProperty", WidgetPropertyDto.class);
 
@@ -124,19 +106,21 @@ public class MyBatis implements BatchComponent, ServerComponent {
     loadMapper(conf, FilterColumnMapper.class);
     loadMapper(conf, DashboardMapper.class);
     loadMapper(conf, DependencyMapper.class);
-    loadMapper(conf, ResourceSnapshotMapper.class);
     loadMapper(conf, DuplicationMapper.class);
     loadMapper(conf, LoadedTemplateMapper.class);
     loadMapper(conf, PropertiesMapper.class);
     loadMapper(conf, PurgeMapper.class);
     loadMapper(conf, PurgeVendorMapper.class);
-    loadMapper(conf, ResourceMapper.class);
     loadMapper(conf, ResourceKeyUpdaterMapper.class);
+    loadMapper(conf, ResourceIndexerMapper.class);
+    loadMapper(conf, ResourceMapper.class);
+    loadMapper(conf, ResourceSnapshotMapper.class);
     loadMapper(conf, ReviewCommentMapper.class);
     loadMapper(conf, ReviewMapper.class);
-    loadMapper(conf, ResourceIndexerMapper.class);
+    loadMapper(conf, RoleMapper.class);
     loadMapper(conf, RuleMapper.class);
     loadMapper(conf, SchemaMigrationMapper.class);
+    loadMapper(conf, UserMapper.class);
     loadMapper(conf, WidgetMapper.class);
     loadMapper(conf, WidgetPropertyMapper.class);
 
@@ -183,7 +167,7 @@ public class MyBatis implements BatchComponent, ServerComponent {
 
   private InputStream getPathToMapper(Class mapperClass) {
     InputStream input = getClass().getResourceAsStream(
-        "/" + StringUtils.replace(mapperClass.getName(), ".", "/") + "-" + database.getDialect().getId() + ".xml");
+      "/" + StringUtils.replace(mapperClass.getName(), ".", "/") + "-" + database.getDialect().getId() + ".xml");
     if (input == null) {
       input = getClass().getResourceAsStream("/" + StringUtils.replace(mapperClass.getName(), ".", "/") + ".xml");
     }
diff --git a/sonar-core/src/main/java/org/sonar/core/user/GroupDto.java b/sonar-core/src/main/java/org/sonar/core/user/GroupDto.java
new file mode 100644 (file)
index 0000000..796ea6f
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.core.user;
+
+import javax.annotation.Nullable;
+import java.util.Date;
+
+/**
+ * @since 3.2
+ */
+public class GroupDto {
+  private Long id;
+  private String name;
+  private String description;
+  private Date createdAt;
+  private Date updatedAt;
+
+  public Long getId() {
+    return id;
+  }
+
+  public GroupDto setId(Long id) {
+    this.id = id;
+    return this;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public GroupDto setName(String name) {
+    this.name = name;
+    return this;
+  }
+
+  public String getDescription() {
+    return description;
+  }
+
+  public GroupDto setDescription(@Nullable String description) {
+    this.description = description;
+    return this;
+  }
+
+  public Date getCreatedAt() {
+    return createdAt;
+  }
+
+  public GroupDto setCreatedAt(Date createdAt) {
+    this.createdAt = createdAt;
+    return this;
+  }
+
+  public Date getUpdatedAt() {
+    return updatedAt;
+  }
+
+  public GroupDto setUpdatedAt(Date updatedAt) {
+    this.updatedAt = updatedAt;
+    return this;
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/user/GroupRoleDto.java b/sonar-core/src/main/java/org/sonar/core/user/GroupRoleDto.java
new file mode 100644 (file)
index 0000000..84f1b6e
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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.core.user;
+
+import javax.annotation.Nullable;
+
+/**
+ * @since 3.2
+ */
+public class GroupRoleDto {
+  private Long id;
+  private Long groupId;
+  private Long resourceId;
+  private String role;
+
+  public Long getId() {
+    return id;
+  }
+
+  public GroupRoleDto setId(Long id) {
+    this.id = id;
+    return this;
+  }
+
+  public Long getGroupId() {
+    return groupId;
+  }
+
+  /**
+   * Null when Anyone
+   */
+  public GroupRoleDto setGroupId(@Nullable Long groupId) {
+    this.groupId = groupId;
+    return this;
+  }
+
+  public Long getResourceId() {
+    return resourceId;
+  }
+
+  public GroupRoleDto setResourceId(Long resourceId) {
+    this.resourceId = resourceId;
+    return this;
+  }
+
+  public String getRole() {
+    return role;
+  }
+
+  public GroupRoleDto setRole(String role) {
+    this.role = role;
+    return this;
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/user/RoleDao.java b/sonar-core/src/main/java/org/sonar/core/user/RoleDao.java
new file mode 100644 (file)
index 0000000..164a72e
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * 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.core.user;
+
+import org.apache.ibatis.session.SqlSession;
+import org.sonar.core.persistence.MyBatis;
+
+import java.util.Collection;
+
+/**
+ * @since 3.2
+ */
+public class RoleDao {
+  private final MyBatis mybatis;
+
+  public RoleDao(MyBatis mybatis) {
+    this.mybatis = mybatis;
+  }
+
+  public RoleDao insertGroupRoles(Collection<GroupRoleDto> groupRoles) {
+    SqlSession session = mybatis.openBatchSession();
+    try {
+      RoleMapper mapper = session.getMapper(RoleMapper.class);
+      for (GroupRoleDto groupRole : groupRoles) {
+        mapper.insertGroupRole(groupRole);
+      }
+      session.commit();
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+    return this;
+  }
+
+  public RoleDao insertUserRoles(Collection<UserRoleDto> userRoles) {
+    SqlSession session = mybatis.openBatchSession();
+    try {
+      RoleMapper mapper = session.getMapper(RoleMapper.class);
+      for (UserRoleDto userRole : userRoles) {
+        mapper.insertUserRole(userRole);
+      }
+      session.commit();
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+    return this;
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/user/RoleMapper.java b/sonar-core/src/main/java/org/sonar/core/user/RoleMapper.java
new file mode 100644 (file)
index 0000000..bd2b45f
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.core.user;
+
+/**
+ * @since 3.2
+ */
+public interface RoleMapper {
+
+  void insertGroupRole(GroupRoleDto groupRole);
+
+  void insertUserRole(UserRoleDto userRole);
+
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/user/UserDao.java b/sonar-core/src/main/java/org/sonar/core/user/UserDao.java
new file mode 100644 (file)
index 0000000..1cf1e0c
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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.core.user;
+
+import org.apache.ibatis.session.SqlSession;
+import org.sonar.core.persistence.MyBatis;
+
+/**
+ * @since 3.2
+ */
+public class UserDao {
+  private final MyBatis mybatis;
+
+  public UserDao(MyBatis mybatis) {
+    this.mybatis = mybatis;
+  }
+
+  /**
+   * Search for user by login. Disabled users are ignored.
+   *
+   * @return the user, null if user not found
+   */
+
+  public UserDto selectUserByLogin(String login) {
+    SqlSession session = mybatis.openSession();
+    try {
+      UserMapper mapper = session.getMapper(UserMapper.class);
+      return mapper.selectUserByLogin(login);
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+  }
+
+  /**
+   * Search for group by name.
+   *
+   * @return the group, null if group not found
+   */
+  public GroupDto selectGroupByName(String name) {
+    SqlSession session = mybatis.openSession();
+    try {
+      UserMapper mapper = session.getMapper(UserMapper.class);
+      return mapper.selectGroupByName(name);
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/user/UserDto.java b/sonar-core/src/main/java/org/sonar/core/user/UserDto.java
new file mode 100644 (file)
index 0000000..15b108f
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * 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.core.user;
+
+import javax.annotation.Nullable;
+import java.util.Date;
+
+/**
+ * @since 3.2
+ */
+public class UserDto {
+  private Long id;
+  private String login;
+  private String name;
+  private String email;
+  private Date createdAt;
+  private Date updatedAt;
+  private boolean enabled = true;
+
+  public Long getId() {
+    return id;
+  }
+
+  public UserDto setId(Long id) {
+    this.id = id;
+    return this;
+  }
+
+  public String getLogin() {
+    return login;
+  }
+
+  public UserDto setLogin(String login) {
+    this.login = login;
+    return this;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public UserDto setName(String name) {
+    this.name = name;
+    return this;
+  }
+
+  public String getEmail() {
+    return email;
+  }
+
+  public UserDto setEmail(@Nullable String email) {
+    this.email = email;
+    return this;
+  }
+
+  public Date getCreatedAt() {
+    return createdAt;
+  }
+
+  public UserDto setCreatedAt(Date createdAt) {
+    this.createdAt = createdAt;
+    return this;
+  }
+
+  public Date getUpdatedAt() {
+    return updatedAt;
+  }
+
+  public UserDto setUpdatedAt(Date updatedAt) {
+    this.updatedAt = updatedAt;
+    return this;
+  }
+
+  public boolean isEnabled() {
+    return enabled;
+  }
+
+  public UserDto setEnabled(boolean enabled) {
+    this.enabled = enabled;
+    return this;
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/user/UserMapper.java b/sonar-core/src/main/java/org/sonar/core/user/UserMapper.java
new file mode 100644 (file)
index 0000000..d8d4e20
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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.core.user;
+
+/**
+ * @since 3.2
+ */
+public interface UserMapper {
+
+  /**
+   * Select user by login. Note that disabled users are ignored.
+   */
+  UserDto selectUserByLogin(String login);
+  GroupDto selectGroupByName(String name);
+
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/user/UserRoleDto.java b/sonar-core/src/main/java/org/sonar/core/user/UserRoleDto.java
new file mode 100644 (file)
index 0000000..1b53216
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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.core.user;
+
+import javax.annotation.Nullable;
+
+/**
+ * @since 3.2
+ */
+public class UserRoleDto {
+  private Long id;
+  private Long userId;
+  private Long resourceId;
+  private String role;
+
+  public Long getId() {
+    return id;
+  }
+
+  public UserRoleDto setId(Long id) {
+    this.id = id;
+    return this;
+  }
+
+  public Long getUserId() {
+    return userId;
+  }
+
+  public UserRoleDto setUserId(Long userId) {
+    this.userId = userId;
+    return this;
+  }
+
+  public Long getResourceId() {
+    return resourceId;
+  }
+
+  public UserRoleDto setResourceId(Long resourceId) {
+    this.resourceId = resourceId;
+    return this;
+  }
+
+  public String getRole() {
+    return role;
+  }
+
+  public UserRoleDto setRole(String role) {
+    this.role = role;
+    return this;
+  }
+}
index 681838d3d8b014b32bfa9f508db6ba040b4e846d..2493292440f3abefeb31804213134b175e5e3a33 100644 (file)
@@ -1,17 +1,17 @@
 -- All the rows inserted during Rails migrations. Rows inserted during server startup tasks (Java) are excluded : rules, profiles, metrics, ...
 
-INSERT INTO GROUP_ROLES(ID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (1, 1, null, 'admin');
-INSERT INTO GROUP_ROLES(ID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (2, 1, null, 'default-admin');
-INSERT INTO GROUP_ROLES(ID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (3, 2, null, 'default-user');
-INSERT INTO GROUP_ROLES(ID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (4, null, null, 'default-user');
-INSERT INTO GROUP_ROLES(ID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (5, 2, null, 'default-codeviewer');
-INSERT INTO GROUP_ROLES(ID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (6, null, null, 'default-codeviewer');
-ALTER TABLE GROUP_ROLES ALTER COLUMN ID RESTART WITH 7;
-
 INSERT INTO GROUPS(ID, NAME, DESCRIPTION, CREATED_AT, UPDATED_AT) VALUES (1, 'sonar-administrators', 'System administrators', '2011-09-26 22:27:51.0', '2011-09-26 22:27:51.0');
 INSERT INTO GROUPS(ID, NAME, DESCRIPTION, CREATED_AT, UPDATED_AT) VALUES (2, 'sonar-users', 'Any new users created will automatically join this group', '2011-09-26 22:27:51.0', '2011-09-26 22:27:51.0');
 ALTER TABLE GROUPS ALTER COLUMN ID RESTART WITH 3;
 
+INSERT INTO GROUP_ROLES(ID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (1, 1, null, 'admin');
+ALTER TABLE GROUP_ROLES ALTER COLUMN ID RESTART WITH 2;
+
+INSERT INTO PROPERTIES(ID, PROP_KEY, RESOURCE_ID, TEXT_VALUE, USER_ID) VALUES (1, 'sonar.role.admin.project.defaultGroups', null, 'sonar-administrators', null);
+INSERT INTO PROPERTIES(ID, PROP_KEY, RESOURCE_ID, TEXT_VALUE, USER_ID) VALUES (2, 'sonar.role.user.project.defaultGroups', null, 'sonar-users,Anyone', null);
+INSERT INTO PROPERTIES(ID, PROP_KEY, RESOURCE_ID, TEXT_VALUE, USER_ID) VALUES (3, 'sonar.role.codeviewer.project.defaultGroups', null, 'sonar-users,Anyone', null);
+ALTER TABLE PROPERTIES ALTER COLUMN ID RESTART WITH 4;
+
 INSERT INTO GROUPS_USERS(USER_ID, GROUP_ID) VALUES (1, 1);
 INSERT INTO GROUPS_USERS(USER_ID, GROUP_ID) VALUES (1, 2);
 
@@ -162,6 +162,7 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('303');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('304');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('305');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('306');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('320');
 
 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;
diff --git a/sonar-core/src/main/resources/org/sonar/core/user/RoleMapper.xml b/sonar-core/src/main/resources/org/sonar/core/user/RoleMapper.xml
new file mode 100644 (file)
index 0000000..753f13e
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="org.sonar.core.user.RoleMapper">
+
+  <insert id="insertGroupRole" parameterType="GroupRole" useGeneratedKeys="true" keyProperty="id">
+    INSERT INTO group_roles (group_id, resource_id, role)
+    VALUES (#{groupId, jdbcType=INTEGER}, #{resourceId, jdbcType=INTEGER}, #{role, jdbcType=VARCHAR})
+  </insert>
+
+  <insert id="insertUserRole" parameterType="UserRole" useGeneratedKeys="true" keyProperty="id">
+    INSERT INTO user_roles (user_id, resource_id, role)
+    VALUES (#{userId, jdbcType=INTEGER}, #{resourceId, jdbcType=INTEGER}, #{role, jdbcType=VARCHAR})
+  </insert>
+</mapper>
diff --git a/sonar-core/src/main/resources/org/sonar/core/user/UserMapper.xml b/sonar-core/src/main/resources/org/sonar/core/user/UserMapper.xml
new file mode 100644 (file)
index 0000000..36154c7
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="org.sonar.core.user.UserMapper">
+
+  <select id="selectUserByLogin" parameterType="string" resultType="User">
+    select id, login, name, email, created_at AS "createdAt", updated_at AS "updatedAt", active as "enabled"
+    from users where login=#{id} and active=${_true}
+  </select>
+
+  <select id="selectGroupByName" parameterType="string" resultType="Group">
+    select id, name, description, created_at AS "createdAt", updated_at AS "updatedAt"
+    from groups where name=#{id}
+  </select>
+
+
+</mapper>
diff --git a/sonar-core/src/test/java/org/sonar/core/user/RoleDaoTest.java b/sonar-core/src/test/java/org/sonar/core/user/RoleDaoTest.java
new file mode 100644 (file)
index 0000000..939046d
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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.core.user;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.core.persistence.DaoTestCase;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+
+public class RoleDaoTest extends DaoTestCase {
+
+  private RoleDao dao;
+
+  @Before
+  public void setUp() {
+    dao = new RoleDao(getMyBatis());
+  }
+
+  @Test
+  public void insertGroupRoles() {
+    setupData("insertGroupRoles");
+
+    Collection<GroupRoleDto> groupRoles = Arrays.asList(
+      new GroupRoleDto().setGroupId(100L).setResourceId(200L).setRole("admin"),
+
+      // no group id => Anyone
+      new GroupRoleDto().setResourceId(200L).setRole("user")
+    );
+    dao.insertGroupRoles(groupRoles);
+
+    checkTables("insertGroupRoles", "group_roles");
+  }
+
+  @Test
+  public void insertUserRoles() {
+    setupData("insertUserRoles");
+
+    Collection<UserRoleDto> userRoles = Arrays.asList(
+      new UserRoleDto().setUserId(100L).setResourceId(200L).setRole("admin"),
+      new UserRoleDto().setUserId(101L).setResourceId(200L).setRole("user")
+    );
+    dao.insertUserRoles(userRoles);
+
+    checkTables("insertUserRoles", "user_roles");
+  }
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/user/UserDaoTest.java b/sonar-core/src/test/java/org/sonar/core/user/UserDaoTest.java
new file mode 100644 (file)
index 0000000..6015f5e
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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.core.user;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.core.persistence.DaoTestCase;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+
+public class UserDaoTest extends DaoTestCase {
+
+  private UserDao dao;
+
+  @Before
+  public void setUp() {
+    dao = new UserDao(getMyBatis());
+  }
+
+  @Test
+  public void selectUserByLogin_ignore_same_disabled_login() {
+    setupData("selectUserByLogin");
+
+    UserDto user = dao.selectUserByLogin("marius");
+    assertThat(user).isNotNull();
+    assertThat(user.getId()).isEqualTo(101L);
+    assertThat(user.getLogin()).isEqualTo("marius");
+    assertThat(user.getName()).isEqualTo("Marius");
+    assertThat(user.getEmail()).isEqualTo("marius@lesbronzes.fr");
+    assertThat(user.getCreatedAt()).isNotNull();
+    assertThat(user.getUpdatedAt()).isNotNull();
+    assertThat(user.isEnabled()).isTrue();
+  }
+
+  @Test
+  public void selectUserByLogin_ignore_disabled() {
+    setupData("selectUserByLogin");
+
+    UserDto user = dao.selectUserByLogin("disabled");
+    assertThat(user).isNull();
+  }
+
+  @Test
+  public void selectUserByLogin_not_found() {
+    setupData("selectUserByLogin");
+
+    UserDto user = dao.selectUserByLogin("not_found");
+    assertThat(user).isNull();
+  }
+
+  @Test
+  public void selectGroupByName() {
+    setupData("selectGroupByName");
+
+    GroupDto group = dao.selectGroupByName("sonar-users");
+    assertThat(group).isNotNull();
+    assertThat(group.getId()).isEqualTo(1L);
+    assertThat(group.getName()).isEqualTo("sonar-users");
+    assertThat(group.getDescription()).isEqualTo("Sonar Users");
+    assertThat(group.getCreatedAt()).isNotNull();
+    assertThat(group.getUpdatedAt()).isNotNull();
+  }
+
+  @Test
+  public void selectGroupByName_not_found() {
+    setupData("selectGroupByName");
+
+    GroupDto group = dao.selectGroupByName("not-found");
+    assertThat(group).isNull();
+  }
+}
diff --git a/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/insertGroupRoles-result.xml b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/insertGroupRoles-result.xml
new file mode 100644 (file)
index 0000000..72fd8e4
--- /dev/null
@@ -0,0 +1,4 @@
+<dataset>
+  <group_roles id="1" group_id="100" resource_id="200" role="admin"/>
+  <group_roles id="2" group_id="[null]" resource_id="200" role="user"/>
+</dataset>
\ No newline at end of file
diff --git a/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/insertGroupRoles.xml b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/insertGroupRoles.xml
new file mode 100644 (file)
index 0000000..a3306c7
--- /dev/null
@@ -0,0 +1,2 @@
+<dataset>
+</dataset>
\ No newline at end of file
diff --git a/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/insertUserRoles-result.xml b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/insertUserRoles-result.xml
new file mode 100644 (file)
index 0000000..253a46b
--- /dev/null
@@ -0,0 +1,4 @@
+<dataset>
+  <user_roles id="1" user_id="100" resource_id="200" role="admin"/>
+  <user_roles id="2" user_id="101" resource_id="200" role="user"/>
+</dataset>
\ No newline at end of file
diff --git a/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/insertUserRoles.xml b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/insertUserRoles.xml
new file mode 100644 (file)
index 0000000..a3306c7
--- /dev/null
@@ -0,0 +1,2 @@
+<dataset>
+</dataset>
\ No newline at end of file
diff --git a/sonar-core/src/test/resources/org/sonar/core/user/UserDaoTest/selectGroupByName.xml b/sonar-core/src/test/resources/org/sonar/core/user/UserDaoTest/selectGroupByName.xml
new file mode 100644 (file)
index 0000000..9434d78
--- /dev/null
@@ -0,0 +1,4 @@
+<dataset>
+  <groups id="1" name="sonar-users" description="Sonar Users" created_at="2011-05-18" updated_at="2012-07-21"/>
+  <groups id="2" name="sonar-administrators" description="Sonar Administrators" created_at="2011-05-18" updated_at="2012-07-21"/>
+</dataset>
\ No newline at end of file
diff --git a/sonar-core/src/test/resources/org/sonar/core/user/UserDaoTest/selectUserByLogin.xml b/sonar-core/src/test/resources/org/sonar/core/user/UserDaoTest/selectUserByLogin.xml
new file mode 100644 (file)
index 0000000..1c7bbfb
--- /dev/null
@@ -0,0 +1,12 @@
+<dataset>
+  <!-- disabled -->
+  <users id="50" login="disabled" name="Disabled" email="disabled@lesbronzes.fr" created_at="2011-05-18" updated_at="2012-07-21" active="[false]"/>
+  <users id="100" login="marius" name="Marius" email="marius@lesbronzes.fr" created_at="2011-05-18" updated_at="2012-07-21" active="[false]"/>
+
+  <!-- enabled -->
+  <users id="101" login="marius" name="Marius" email="marius@lesbronzes.fr" created_at="2011-05-18" updated_at="2012-07-21" active="[true]"/>
+
+  <users id="102" login="jcdus" name="Jean-Claude Dus" email="jcdus@lesbronzes.fr" created_at="2011-05-18" updated_at="2012-07-21" active="[true]"/>
+
+
+</dataset>
index 4729927bb905fc7d7f0e915f4e722ad16eea8c67..4dbc9ec57a48685f43b6f9f4dd2142e9302e6855 100644 (file)
 # sonar 2.0
 class SetDefaultProjectRoles < ActiveRecord::Migration
 
-  # Do not use faux models
-
   def self.up
-    administrators=Group.find_by_name('sonar-administrators')
-    users=Group.find_by_name('sonar-users')
-
-    # default project roles
-    GroupRole.create(:resource_id => nil, :role => 'default-admin', :group_id => administrators.id)
-    GroupRole.create(:resource_id => nil, :role => 'default-user', :group_id => users.id)
-    GroupRole.create(:resource_id => nil, :role => 'default-user', :group_id => nil)
-    GroupRole.create(:resource_id => nil, :role => 'default-codeviewer', :group_id => users.id)
-    GroupRole.create(:resource_id => nil, :role => 'default-codeviewer', :group_id => nil)
   end
 
 end
diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/320_move_default_roles.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/320_move_default_roles.rb
new file mode 100644 (file)
index 0000000..a699221
--- /dev/null
@@ -0,0 +1,102 @@
+#
+# 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
+#
+
+#
+# Sonar 3.2
+#
+class MoveDefaultRoles < ActiveRecord::Migration
+
+  class Group < ActiveRecord::Base
+  end
+
+  class GroupRole < ActiveRecord::Base
+  end
+
+  class User < ActiveRecord::Base
+  end
+  class UserRole < ActiveRecord::Base
+  end
+
+  class Property < ActiveRecord::Base
+    set_table_name 'properties'
+  end
+
+  def self.up
+    if GroupRole.count==0
+      # fresh install
+      Property.delete_all(['prop_key like ?', 'sonar.role.%'])
+      Property.create(:prop_key => 'sonar.role.admin.project.defaultGroups', :text_value => 'sonar-administrators')
+      Property.create(:prop_key => 'sonar.role.user.project.defaultGroups', :text_value => 'sonar-users,Anyone')
+      Property.create(:prop_key => 'sonar.role.codeviewer.project.defaultGroups', :text_value => 'sonar-users,Anyone')
+    else
+      # upgrade from version < 3.2.
+      move_groups
+      move_users
+    end
+  end
+
+  private
+
+  def self.move_groups
+    groups_per_role={}
+    group_roles = GroupRole.find(:all, :conditions => ['resource_id is null and role like ?', 'default-%'])
+
+    group_roles.each do |group_role|
+      role = group_role.role[8..-1]
+      group_name = nil
+      if group_role.group_id
+        group = Group.find(group_role.group_id)
+        group_name = group.name if group
+      else
+        group_name = 'Anyone'
+      end
+      if group_name
+        groups_per_role[role]||=[]
+        groups_per_role[role]<<group_name
+      end
+    end
+
+    groups_per_role.each_pair do |role, groups|
+      Property.create(:prop_key => "sonar.role.#{role}.project.defaultGroups", :text_value => groups.join(','))
+    end
+
+    #GroupRole.delete_all ['role like ?', 'default-%']
+  end
+
+  def self.move_users
+    users_per_role={}
+    user_roles = UserRole.find(:all, :conditions => ['user_id is not null and resource_id is null and role like ?', 'default-%'])
+
+    user_roles.each do |user_role|
+      role = user_role.role[8..-1]
+      user = User.find(user_role.user_id)
+      if user
+        users_per_role[role]||=[]
+        users_per_role[role]<<user.login
+      end
+    end
+
+    users_per_role.each_pair do |role, users|
+      Property.create(:prop_key => "sonar.role.#{role}.project.defaultUsers", :text_value => users.join(','))
+    end
+
+    #UserRole.delete_all ['role like ?', 'default-%']
+  end
+end