]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-4453 Apply permission template to a list of resources in the internal permissio...
authorJean-Baptiste Vilain <jean-baptiste.vilain@sonarsource.com>
Thu, 11 Jul 2013 10:40:40 +0000 (12:40 +0200)
committerJean-Baptiste Vilain <jean-baptiste.vilain@sonarsource.com>
Thu, 11 Jul 2013 10:40:40 +0000 (12:40 +0200)
18 files changed:
plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties
sonar-core/src/main/java/org/sonar/core/permission/ComponentPermissionFacade.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/permission/package-info.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/resource/DefaultResourcePermissions.java
sonar-core/src/test/java/org/sonar/core/permission/ComponentPermissionFacadeTest.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/resource/DefaultResourcePermissionsTest.java
sonar-server/src/main/java/org/sonar/server/permission/ApplyPermissionTemplateQuery.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/permission/InternalPermissionService.java
sonar-server/src/main/java/org/sonar/server/permission/InternalPermissionTemplateService.java
sonar-server/src/main/java/org/sonar/server/util/RubyUtils.java
sonar-server/src/main/webapp/WEB-INF/app/controllers/permission_templates_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/controllers/roles_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/views/permission_templates/index.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/roles/projects.html.erb
sonar-server/src/main/webapp/WEB-INF/db/migrate/418_migrate_default_permissions.rb
sonar-server/src/test/java/org/sonar/server/permission/ApplyPermissionTemplateQueryTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/permission/InternalPermissionServiceTest.java
sonar-server/src/test/java/org/sonar/server/util/RubyUtilsTest.java

index 0fdefad95842c858b744fa840688c592816742bb..e125aa371c58d8646b6b854d30991fdbbc01d152 100644 (file)
@@ -2248,6 +2248,7 @@ projects_role.user=Role: Users
 projects_role.user.desc=Ability to browse the measures and to create/edit issues on the project.
 projects_role.codeviewer=Role: Code Viewers
 projects_role.codeviewer.desc=Ability to view the source code of the project.
+projects_role.apply_template=Apply permission template
 
 
 #------------------------------------------------------------------------------
diff --git a/sonar-core/src/main/java/org/sonar/core/permission/ComponentPermissionFacade.java b/sonar-core/src/main/java/org/sonar/core/permission/ComponentPermissionFacade.java
new file mode 100644 (file)
index 0000000..7d73036
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.
+ */
+
+package org.sonar.core.permission;
+
+import org.apache.ibatis.session.SqlSession;
+import org.sonar.api.ServerExtension;
+import org.sonar.api.security.DefaultGroups;
+import org.sonar.api.task.TaskExtension;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.user.*;
+
+import java.util.List;
+
+/**
+ * Internal use only
+ * @since 3.7
+ *
+ * This facade wraps all the db operations related to component-based permissions
+ */
+public class ComponentPermissionFacade implements TaskExtension, ServerExtension {
+
+  private final MyBatis myBatis;
+  private final RoleDao roleDao;
+  private final UserDao userDao;
+  private final PermissionDao permissionDao;
+
+  public ComponentPermissionFacade(MyBatis myBatis, RoleDao roleDao, UserDao userDao, PermissionDao permissionDao) {
+    this.myBatis = myBatis;
+    this.roleDao = roleDao;
+    this.userDao = userDao;
+    this.permissionDao = permissionDao;
+  }
+
+  public void setUserPermission(Long resourceId, String userLogin, String permission) {
+    SqlSession session = myBatis.openSession();
+    try {
+      UserDto user = session.getMapper(UserMapper.class).selectUserByLogin(userLogin);
+      if (user != null) {
+        UserRoleDto userRole = new UserRoleDto()
+          .setRole(permission)
+          .setUserId(user.getId())
+          .setResourceId(Long.valueOf(resourceId));
+        roleDao.deleteUserRole(userRole, session);
+        roleDao.insertUserRole(userRole, session);
+        session.commit();
+      }
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+  }
+
+  public void setGroupPermission(Long resourceId, String groupName, String permission) {
+    SqlSession session = myBatis.openSession();
+    try {
+      GroupRoleDto groupRole = new GroupRoleDto()
+        .setRole(permission)
+        .setResourceId(Long.valueOf(resourceId));
+      if (DefaultGroups.isAnyone(groupName)) {
+        roleDao.deleteGroupRole(groupRole, session);
+        roleDao.insertGroupRole(groupRole, session);
+        session.commit();
+      } else {
+        GroupDto group = userDao.selectGroupByName(groupName, session);
+        if (group != null) {
+          groupRole.setGroupId(group.getId());
+          roleDao.deleteGroupRole(groupRole, session);
+          roleDao.insertGroupRole(groupRole, session);
+          session.commit();
+        }
+      }
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+  }
+
+  public int countPermissions(Long resourceId) {
+    return roleDao.countGroupRoles(resourceId) + roleDao.countUserRoles(resourceId);
+  }
+
+  public void removeAllPermissions(Long resourceId, SqlSession session) {
+    roleDao.deleteGroupRolesByResourceId(resourceId, session);
+    roleDao.deleteUserRolesByResourceId(resourceId, session);
+  }
+
+  public void addUserPermission(Long resourceId, String userLogin, String permission, SqlSession session) {
+    UserDto user = userDao.selectActiveUserByLogin(userLogin, session);
+    if (user != null) {
+      UserRoleDto userRoleDto = new UserRoleDto().setRole(permission).setUserId(user.getId()).setResourceId(resourceId);
+      roleDao.insertUserRole(userRoleDto, session);
+    }
+  }
+
+  public void addGroupPermission(Long resourceId, String groupName, String permission, SqlSession session) {
+    GroupRoleDto groupRole = new GroupRoleDto().setRole(permission).setResourceId(resourceId);
+    if (DefaultGroups.isAnyone(groupName)) {
+      roleDao.insertGroupRole(groupRole, session);
+    } else {
+      GroupDto group = userDao.selectGroupByName(groupName, session);
+      if (group != null) {
+        roleDao.insertGroupRole(groupRole.setGroupId(group.getId()), session);
+      }
+    }
+  }
+
+  public PermissionTemplateDto getPermissionTemplate(Long templateId) {
+    PermissionTemplateDto permissionTemplateDto = permissionDao.selectTemplateById(templateId);
+    if(permissionTemplateDto == null) {
+      throw new IllegalArgumentException("Could not retrieve permission template with id " + templateId);
+    }
+    PermissionTemplateDto templateWithPermissions = permissionDao.selectPermissionTemplate(permissionTemplateDto.getName());
+    if(templateWithPermissions == null) {
+      throw new IllegalArgumentException("Could not retrieve permissions for template with id " + templateId);
+    }
+    return templateWithPermissions;
+  }
+
+  public void applyPermissionTemplate(Long templateId, Long resourceId) {
+    SqlSession session = myBatis.openSession();
+    try {
+      PermissionTemplateDto permissionTemplate = getPermissionTemplate(templateId);
+      List<PermissionTemplateUserDto> usersPermissions = permissionTemplate.getUsersPermissions();
+      if(usersPermissions != null) {
+        for (PermissionTemplateUserDto userPermission : usersPermissions) {
+          addUserPermission(resourceId, userPermission.getUserLogin(), userPermission.getPermission(), session);
+
+        }
+      }
+      List<PermissionTemplateGroupDto> groupsPermissions = permissionTemplate.getGroupsPermissions();
+      if(groupsPermissions != null) {
+        for (PermissionTemplateGroupDto groupPermission : groupsPermissions) {
+          addGroupPermission(resourceId, groupPermission.getGroupName(), groupPermission.getPermission(), session);
+        }
+      }
+      session.commit();
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/permission/package-info.java b/sonar-core/src/main/java/org/sonar/core/permission/package-info.java
new file mode 100644 (file)
index 0000000..78344ab
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.
+ */
+
+@ParametersAreNonnullByDefault
+package org.sonar.core.permission;
+
+import javax.annotation.ParametersAreNonnullByDefault;
\ No newline at end of file
index eb8febb0fc5cfa2bc64572bb2a7a47b2595a060f..cdaf5b445fb8f308f5f0f3c653c3d50efd155845 100644 (file)
@@ -28,8 +28,11 @@ import org.sonar.api.security.DefaultGroups;
 import org.sonar.api.security.ResourcePermissions;
 import org.sonar.api.task.TaskExtension;
 import org.sonar.api.web.UserRole;
+import org.sonar.core.permission.ComponentPermissionFacade;
 import org.sonar.core.persistence.MyBatis;
-import org.sonar.core.user.*;
+import org.sonar.core.user.PermissionTemplateDto;
+import org.sonar.core.user.PermissionTemplateGroupDto;
+import org.sonar.core.user.PermissionTemplateUserDto;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -41,69 +44,31 @@ public class DefaultResourcePermissions implements ResourcePermissions, TaskExte
 
   private final Settings settings;
   private final MyBatis myBatis;
-  private final RoleDao roleDao;
-  private final UserDao userDao;
-  private final PermissionDao permissionDao;
+  private final ComponentPermissionFacade permissionFacade;
 
-  public DefaultResourcePermissions(Settings settings, MyBatis myBatis, RoleDao roleDao, UserDao userDao, PermissionDao permissionDao) {
+  public DefaultResourcePermissions(Settings settings, MyBatis myBatis, ComponentPermissionFacade permissionFacade) {
     this.settings = settings;
     this.myBatis = myBatis;
-    this.roleDao = roleDao;
-    this.userDao = userDao;
-    this.permissionDao = permissionDao;
+    this.permissionFacade = permissionFacade;
   }
 
   public boolean hasRoles(Resource resource) {
     if (resource.getId() != null) {
       Long resourceId = Long.valueOf(resource.getId());
-      return roleDao.countGroupRoles(resourceId) + roleDao.countUserRoles(resourceId) > 0;
+      return permissionFacade.countPermissions(resourceId) > 0;
     }
     return false;
   }
 
   public void grantUserRole(Resource resource, String login, String role) {
     if (resource.getId() != null) {
-      SqlSession session = myBatis.openSession();
-      try {
-        UserDto user = session.getMapper(UserMapper.class).selectUserByLogin(login);
-        if (user != null) {
-          UserRoleDto userRole = new UserRoleDto()
-              .setRole(role)
-              .setUserId(user.getId())
-              .setResourceId(Long.valueOf(resource.getId()));
-          roleDao.deleteUserRole(userRole, session);
-          roleDao.insertUserRole(userRole, session);
-          session.commit();
-        }
-      } finally {
-        MyBatis.closeQuietly(session);
-      }
+      permissionFacade.setUserPermission(Long.valueOf(resource.getId()), login, role);
     }
   }
 
   public void grantGroupRole(Resource resource, String groupName, String role) {
     if (resource.getId() != null) {
-      SqlSession session = myBatis.openSession();
-      try {
-        GroupRoleDto groupRole = new GroupRoleDto()
-            .setRole(role)
-            .setResourceId(Long.valueOf(resource.getId()));
-        if (DefaultGroups.isAnyone(groupName)) {
-          roleDao.deleteGroupRole(groupRole, session);
-          roleDao.insertGroupRole(groupRole, session);
-          session.commit();
-        } else {
-          GroupDto group = userDao.selectGroupByName(groupName, session);
-          if (group != null) {
-            groupRole.setGroupId(group.getId());
-            roleDao.deleteGroupRole(groupRole, session);
-            roleDao.insertGroupRole(groupRole, session);
-            session.commit();
-          }
-        }
-      } finally {
-        MyBatis.closeQuietly(session);
-      }
+      permissionFacade.setGroupPermission(Long.valueOf(resource.getId()), groupName, role);
     }
   }
 
@@ -124,8 +89,7 @@ public class DefaultResourcePermissions implements ResourcePermissions, TaskExte
 
   private void removeRoles(Resource resource, SqlSession session) {
     Long resourceId = Long.valueOf(resource.getId());
-    roleDao.deleteGroupRolesByResourceId(resourceId, session);
-    roleDao.deleteUserRolesByResourceId(resourceId, session);
+    permissionFacade.removeAllPermissions(resourceId, session);
   }
 
   private void grantDefaultRoles(Resource resource, String role, SqlSession session) {
@@ -133,24 +97,14 @@ public class DefaultResourcePermissions implements ResourcePermissions, TaskExte
 
     List<String> groupNames = getEligibleGroups(role, applicablePermissionTemplate);
     for (String groupName : groupNames) {
-      GroupRoleDto groupRole = new GroupRoleDto().setRole(role).setResourceId(Long.valueOf(resource.getId()));
-      if (DefaultGroups.isAnyone(groupName)) {
-        roleDao.insertGroupRole(groupRole, session);
-      } else {
-        GroupDto group = userDao.selectGroupByName(groupName, session);
-        if (group != null) {
-          roleDao.insertGroupRole(groupRole.setGroupId(group.getId()), session);
-        }
-      }
+      Long resourceId = Long.valueOf(resource.getId());
+      permissionFacade.addGroupPermission(resourceId, groupName, role, session);
     }
 
     List<String> logins = getEligibleUsers(role, applicablePermissionTemplate);
     for (String login : logins) {
-      UserDto user = userDao.selectActiveUserByLogin(login, session);
-      if (user != null) {
-        UserRoleDto userRoleDto = new UserRoleDto().setRole(role).setUserId(user.getId()).setResourceId(Long.valueOf(resource.getId()));
-        roleDao.insertUserRole(userRoleDto, session);
-      }
+      Long resourceId = Long.valueOf(resource.getId());
+      permissionFacade.addUserPermission(resourceId, login, role, session);
     }
   }
 
@@ -184,25 +138,15 @@ public class DefaultResourcePermissions implements ResourcePermissions, TaskExte
   private PermissionTemplateDto getPermissionTemplate(String qualifier) {
     String qualifierTemplateId = settings.getString("sonar.permission.template." + qualifier + ".default");
     if(!StringUtils.isBlank(qualifierTemplateId)) {
-      return getTemplateWithPermissions(qualifierTemplateId);
+      Long templateId = Long.parseLong(qualifierTemplateId);
+      return permissionFacade.getPermissionTemplate(templateId);
     }
 
     String defaultTemplateId = settings.getString("sonar.permission.template.default");
     if(StringUtils.isBlank(defaultTemplateId)) {
       throw new IllegalStateException("At least one default permission template should be defined");
     }
-    return getTemplateWithPermissions(defaultTemplateId);
-  }
-
-  private PermissionTemplateDto getTemplateWithPermissions(String templateId) {
-    PermissionTemplateDto permissionTemplateDto = permissionDao.selectTemplateById(Long.parseLong(templateId));
-    if(permissionTemplateDto == null) {
-      throw new IllegalArgumentException("Could not retrieve permission template with id " + templateId);
-    }
-    PermissionTemplateDto templateWithPermissions = permissionDao.selectPermissionTemplate(permissionTemplateDto.getName());
-    if(templateWithPermissions == null) {
-      throw new IllegalArgumentException("Could not retrieve permissions for template with id " + templateId);
-    }
-    return templateWithPermissions;
+    Long templateId = Long.parseLong(defaultTemplateId);
+    return permissionFacade.getPermissionTemplate(templateId);
   }
 }
diff --git a/sonar-core/src/test/java/org/sonar/core/permission/ComponentPermissionFacadeTest.java b/sonar-core/src/test/java/org/sonar/core/permission/ComponentPermissionFacadeTest.java
new file mode 100644 (file)
index 0000000..88fca00
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.
+ */
+
+package org.sonar.core.permission;
+
+public class ComponentPermissionFacadeTest {
+}
index d3442d462836004e621696205a52ffa2181955ad..5a6fc165002f616b50e446606d0e14070ecfad2a 100644 (file)
@@ -27,6 +27,7 @@ import org.sonar.api.config.Settings;
 import org.sonar.api.resources.Project;
 import org.sonar.api.resources.Resource;
 import org.sonar.api.security.DefaultGroups;
+import org.sonar.core.permission.ComponentPermissionFacade;
 import org.sonar.core.persistence.AbstractDaoTestCase;
 import org.sonar.core.user.PermissionDao;
 import org.sonar.core.user.RoleDao;
@@ -46,8 +47,9 @@ public class DefaultResourcePermissionsTest extends AbstractDaoTestCase {
   @Before
   public void initResourcePermissions() {
     settings = new Settings();
-    permissions = new DefaultResourcePermissions(settings, getMyBatis(),
+    ComponentPermissionFacade permissionFacade = new ComponentPermissionFacade(getMyBatis(),
       new RoleDao(getMyBatis()), new UserDao(getMyBatis()), new PermissionDao(getMyBatis()));
+    permissions = new DefaultResourcePermissions(settings, getMyBatis(), permissionFacade);
   }
 
   @Test
diff --git a/sonar-server/src/main/java/org/sonar/server/permission/ApplyPermissionTemplateQuery.java b/sonar-server/src/main/java/org/sonar/server/permission/ApplyPermissionTemplateQuery.java
new file mode 100644 (file)
index 0000000..dd6eea9
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.
+ */
+
+package org.sonar.server.permission;
+
+import org.picocontainer.annotations.Nullable;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.util.RubyUtils;
+
+import java.util.List;
+import java.util.Map;
+
+public class ApplyPermissionTemplateQuery {
+
+  private static final String TEMPLATE_ID = "template_id";
+  private static final String COMPONENTS_KEY = "components";
+
+  private final Long templateId;
+  private List<String> selectedComponents;
+
+  private ApplyPermissionTemplateQuery(@Nullable Long templateId) {
+    this.templateId= templateId;
+  }
+
+  public static ApplyPermissionTemplateQuery buildFromParams(Map<String, Object> params) {
+    ApplyPermissionTemplateQuery query = new ApplyPermissionTemplateQuery(RubyUtils.toLong(params.get(TEMPLATE_ID)));
+    query.setSelectedComponents(RubyUtils.toStrings(params.get(COMPONENTS_KEY)));
+    return query;
+  }
+
+  public Long getTemplateId() {
+    return templateId;
+  }
+
+  public List<String> getSelectedComponents() {
+    return selectedComponents;
+  }
+
+  public void validate() {
+    if(templateId == null) {
+      throw new BadRequestException("Permission template is mandatory");
+    }
+    if(selectedComponents == null || selectedComponents.isEmpty()) {
+      throw new BadRequestException("Please provide at least one entry to which the permission template should be applied");
+    }
+  }
+
+  private void setSelectedComponents(List<String> selectedComponents) {
+    this.selectedComponents = selectedComponents;
+  }
+}
index 25be7f704ba2cadbbbad67ee3f8e561a8790e725..825e4d66cd4af83499f7b924c8dddcb65a4316f8 100644 (file)
@@ -24,6 +24,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.ServerComponent;
 import org.sonar.api.security.DefaultGroups;
+import org.sonar.core.permission.ComponentPermissionFacade;
 import org.sonar.core.user.*;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.user.UserSession;
@@ -43,10 +44,12 @@ public class InternalPermissionService implements ServerComponent {
 
   private final RoleDao roleDao;
   private final UserDao userDao;
+  private final ComponentPermissionFacade permissionFacade;
 
-  public InternalPermissionService(RoleDao roleDao, UserDao userDao) {
+  public InternalPermissionService(RoleDao roleDao, UserDao userDao, ComponentPermissionFacade permissionFacade) {
     this.roleDao = roleDao;
     this.userDao = userDao;
+    this.permissionFacade = permissionFacade;
   }
 
   public void addPermission(final Map<String, Object> params) {
@@ -57,6 +60,20 @@ public class InternalPermissionService implements ServerComponent {
     changePermission(REMOVE, params);
   }
 
+  public void applyPermissionTemplate(Map<String, Object> params) {
+    UserSession.get().checkLoggedIn();
+    UserSession.get().checkGlobalPermission(Permission.SYSTEM_ADMIN);
+    ApplyPermissionTemplateQuery query = ApplyPermissionTemplateQuery.buildFromParams(params);
+    query.validate();
+    for (String component : query.getSelectedComponents()) {
+      applyPermissionTemplate(query.getTemplateId(), component);
+    }
+  }
+
+  private void applyPermissionTemplate(Long templateId, String componentId) {
+    permissionFacade.applyPermissionTemplate(templateId, Long.parseLong(componentId));
+  }
+
   private void changePermission(String permissionChange, Map<String, Object> params) {
     UserSession.get().checkLoggedIn();
     UserSession.get().checkGlobalPermission(Permission.SYSTEM_ADMIN);
index 306771b55ee94342ae4c337b418c270e5491bf7f..6f19069ca9099179d2c62d53cc57159be34c7bb9 100644 (file)
@@ -34,6 +34,7 @@ import org.sonar.server.exceptions.ServerErrorException;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Used by ruby code <pre>Internal.permission_templates</pre>
@@ -134,6 +135,12 @@ public class InternalPermissionTemplateService implements ServerComponent {
       }
     };
     updater.executeUpdate();
+  }
+
+  public void applyPermissionTemplate(String templateName, Map<String, Object> params) {
+
+
+
   }
 
   private void validateTemplateName(Long templateId, String templateName) {
index 8ac178283d0546259d21c549ed58ba25d768e132..78c17bb800e7ccbd332f7c2aa2dd50ab842cf5f1 100644 (file)
@@ -132,4 +132,24 @@ public class RubyUtils {
     }
     throw new IllegalArgumentException("Unsupported type for boolean: " + o.getClass());
   }
+
+  @CheckForNull
+  public static Long toLong(@Nullable Object o) {
+    if (o == null) {
+      return null;
+    }
+    if (o instanceof Integer) {
+      return ((Integer)o).longValue();
+    }
+    if (o instanceof Long) {
+      return ((Long) o);
+    }
+    if (o instanceof String) {
+      if (StringUtils.isBlank((String)o)) {
+        return null;
+      }
+      return Long.parseLong((String) o);
+    }
+    throw new IllegalArgumentException("Unsupported type for long: " + o.getClass());
+  }
 }
index 164a7ea91bb96dac1323ea93faa38aea2c91f354..e1bb8d7229131cb31eddabbda3d294b4bf5621c5 100644 (file)
@@ -43,7 +43,7 @@ class PermissionTemplatesController < ApplicationController
     templates_names.each do |template_name|
       permission_template = Internal.permission_templates.selectPermissionTemplate(template_name)
       @permission_templates << permission_template
-      @permission_templates_options << [permission_template.name, permission_template.id]
+      @permission_templates_options << [permission_template.name, permission_template.id.to_s]
     end
     @root_qualifiers = get_root_qualifiers
 
index 4899124412f6caaded9cba7b49a85b40846f88f2..9d6832a8aba0043cf2ab0b9e6db2d029f76f8c3f 100644 (file)
@@ -86,7 +86,9 @@ class RolesController < ApplicationController
     bad_request('Missing qualifier') if params[:qualifier].blank?
   end
 
+  def bulk_apply_form
 
+  end
 
   # POST REQUESTS
 
@@ -118,8 +120,18 @@ class RolesController < ApplicationController
     redirect
   end
 
+  def bulk_apply_template
+    verify_post_request
+    require_parameters :name
+    Internal.permissions.applyPermissionTemplate(params)
+
+    redirect_to :action => 'projects'
+  end
+
   private
+
   def redirect
     redirect_to(:action => params['redirect'] || 'global', :q => params[:q], :qualifier => params[:qualifier], :page => params[:page])
   end
+
 end
index 53b168883631d68aa5d4d31e7753dc3a534ed132..9638d93f275f18a19ed357d16a07da8374a8be23 100644 (file)
@@ -11,6 +11,7 @@
     <% @root_qualifiers.each do |qualifier| %>
       <%= label_tag("default_template_#{qualifier}", "Default permission template for #{message('qualifier.' + qualifier)}:") %>
       <%= select_tag("default_template_#{qualifier}", options_for_select(@permission_templates_options, @default_templates[qualifier])) %>
+      <br/>
     <% end %>
     <br/>
     <br/>
index 564ae0fdbc95373d16d8d176ddf2155f5e052139..7b32d9edfb0c96b36b7bfdf35f5947ca2c651f6b 100644 (file)
@@ -1,4 +1,4 @@
-<h1 class="marginbottom10"><%= message('roles.page') -%></h1>
+<h1><%= message('roles.page') -%></h1>
 
 <% if @qualifiers.size>1 %>
   <ul class="tabs" id="qualifier-tabs">
   <div class="tabs-panel">
 <% end %>
 
-<table class="data width100" id="default-project-roles">
-  <thead>
-  <tr>
-    <th><%= message('projects_role.role') -%> <%= message("qualifiers.#{@qualifier}") -%></th>
-    <th width="35%"><%= message('projects_role.users') -%></th>
-    <th width="35%"><%= message('projects_role.groups') -%></th>
-  </tr>
-  </thead>
-  <tbody>
-
-  <tr class="even">
-    <td valign="top"><b><%= message('projects_role.admin') -%></b><br/><span class="small gray"><%= message('projects_role.admin.desc') -%></span>
-    </td>
-    <td valign="top" style="word-break:break-all;width:35%;">
-      <div style="vertical-align:top">
-        <span id="u-admin"><%= default_project_users('admin', @qualifier).map{|u| h u.name}.join(', ') -%></span>
-        (<%= link_to "select", {:action => 'edit_default_project_users', :role => 'admin', :redirect => 'projects', :qualifier => @qualifier}, :class => 'link-action', :id => 'selectu-admin' -%>)
-      </div>
-    </td>
-    <td valign="top" style="word-break:break-all;width:35%;">
-      <span id="g-admin"><%= default_project_group_names('admin', @qualifier).join(', ') -%></span>
-      (<%= link_to "select", {:action => 'edit_default_project_groups', :role => 'admin', :redirect => 'projects', :qualifier => @qualifier}, :class => 'link-action', :id => 'selectg-admin' -%>)
-    </td>
-  </tr>
-  <tr class="odd">
-    <td valign="top"><b><%= message('projects_role.user') -%></b><br/><span class="small gray"><%= message('projects_role.user.desc') -%></span>
-    </td>
-    <td valign="top" style="word-break:break-all;width:35%;">
-      <span id="u-user"><%= default_project_users('user', @qualifier).map{|u| h u.name}.join(', ') -%></span>
-      (<%= link_to "select", {:action => 'edit_default_project_users', :role => 'user', :redirect => 'projects', :qualifier => @qualifier}, :class => 'link-action', :id => 'selectu-user' -%>)
-    </td>
-    <td valign="top" style="word-break:break-all;width:35%;">
-      <span id="g-user"><%= default_project_group_names('user', @qualifier).join(', ') -%></span>
-      (<%= link_to "select", {:action => 'edit_default_project_groups', :role => 'user', :redirect => 'projects', :qualifier => @qualifier}, :class => 'link-action', :id => 'selectg-user' -%>)
-    </td>
-  </tr>
-  <tr class="even">
-    <td valign="top">
-      <b><%= message('projects_role.codeviewer') -%></b><br/><span class="small gray"><%= message('projects_role.codeviewer.desc') -%></span></td>
-    <td valign="top" style="word-break:break-all;width:35%;">
-      <span id="u-codeviewer"><%= default_project_users('codeviewer', @qualifier).map{|u| h u.name}.join(', ') -%></span>
-      (<%= link_to "select", {:action => 'edit_default_project_users', :role => 'codeviewer', :redirect => 'projects', :qualifier => @qualifier}, :class => 'link-action', :id => 'selectu-codeviewer' -%>)
-    </td>
-    <td valign="top" style="word-break:break-all;width:35%;">
-      <span id="g-codeviewer"><%= default_project_group_names('codeviewer', @qualifier).join(', ') -%></span>
-      (<%= link_to "select", {:action => 'edit_default_project_groups', :role => 'codeviewer', :redirect => 'projects', :qualifier => @qualifier}, :class => 'link-action', :id => 'selectg-codeviewer' -%>)
-    </td>
-  </tr>
-  </tbody>
-</table>
-
-
-<br/><br/>
+<div id="project-roles-operations" style="float: right;">
+  <ul class="operations">
+    <li class="last">
+      <a id="bulk-update" href="<%= url_for params.merge({:action => 'bulk_apply_form'}) -%>"
+         class="link-action open-modal"><%= message('projects_role.apply_template') -%></a>
+    </li>
+  </ul>
+</div>
 
-<table class="data width100" id="projects">
-  <thead>
-  <tr>
-    <th>
-      <form action="<%= url_for :action => 'projects', :qualifier => @qualifier -%>" method="GET">
-        <input type="hidden" name="qualifier" value="<%= @qualifier -%>"/>
-        <input type="text" name="q" value="<%= params[:q] -%>" id="search_text"/>
-        <input type="submit" value="<%= message('search_verb') -%>" id="search_submit"/>
-      </form>
-    </th>
-    <th><%= message('projects_role.admin') -%></th>
-    <th><%= message('projects_role.user') -%></th>
-    <th><%= message('projects_role.codeviewer') -%></th>
-  </tr>
-  </thead>
+  <table class="data width100" id="projects">
+    <thead>
+    <tr>
+      <th>
+        <form action="<%= url_for :action => 'projects', :qualifier => @qualifier -%>" method="GET">
+          <input type="hidden" name="qualifier" value="<%= @qualifier -%>"/>
+          <input type="text" name="q" value="<%= params[:q] -%>" id="search_text"/>
+          <input type="submit" value="<%= message('search_verb') -%>" id="search_submit"/>
+        </form>
+      </th>
+      <th><%= message('projects_role.admin') -%></th>
+      <th><%= message('projects_role.user') -%></th>
+      <th><%= message('projects_role.codeviewer') -%></th>
+    </tr>
+    </thead>
 
-  <%= table_pagination(@pagination, :colspan => 4) { |label, page_id| link_to(label, params.merge({:page => page_id}))} -%>
+    <%= table_pagination(@pagination, :colspan => 4) { |label, page_id| link_to(label, params.merge({:page => page_id}))} -%>
 
-  <tbody>
-  <% if @projects.empty? %>
-    <tr class="even">
-      <td colspan="4" align="left"><%= message('no_results') %></td>
-    </tr>
-  <% end
+    <tbody>
+    <% if @projects.empty? %>
+      <tr class="even">
+        <td colspan="4" align="left"><%= message('no_results') %></td>
+      </tr>
+    <% end
 
-     @projects.each do |project|
-  %>
-    <tr class="<%= cycle('even', 'odd') -%>">
-      <td valign="top"><b><%= h project.name %></b><br/>
-        <span class="small gray"><%= h project.key -%></span>
-      </td>
-      <td valign="top">
-        <%
-           users=Api::Utils.insensitive_sort(project.user_roles.select { |ur| ur.role=='admin' }.map { |ur| ur.user.name })
-           groups=Api::Utils.insensitive_sort(project.group_roles.select { |gr| gr.role=='admin' }.map { |gr| group_name(gr.group) })
-        %>
-        <span id="u-admin-<%= u project.kee -%>"><%= users.join(', ') %></span>
-        (<a href="<%= ApplicationController.root_context -%>/roles/edit_users?redirect=projects&role=admin&resource=<%= project.id -%>&q=<%= u params[:q] -%>&qualifier=<%= @qualifier -%>&page=<%= params[:page] -%>" class="link-action" id="selectu-admin-<%= u project.kee -%>">select users</a>)<br/>
-        <span id="g-admin-<%= u project.kee -%>"><%= groups.join(', ') %></span>
-        (<a href="<%= ApplicationController.root_context -%>/roles/edit_groups?redirect=projects&role=admin&resource=<%= project.id -%>&q=<%= u params[:q] -%>&qualifier=<%= @qualifier -%>&page=<%= params[:page] -%>" class="link-action" id="selectg-admin-<%= u project.kee -%>">select groups</a>)
-      </td>
-      <td valign="top">
-        <%
-           users=Api::Utils.insensitive_sort(project.user_roles.select { |ur| ur.role=='user' }.map { |ur| ur.user.name })
-           groups=Api::Utils.insensitive_sort(project.group_roles.select { |gr| gr.role=='user' }.map { |gr| group_name(gr.group) })
-        %>
-        <span id="u-user-<%= u project.kee -%>"><%= users.join(', ') %></span>
-        (<a href="<%= ApplicationController.root_context -%>/roles/edit_users?redirect=projects&role=user&resource=<%= project.id -%>&q=<%= u params[:q] -%>&qualifier=<%= @qualifier -%>&page=<%= params[:page] -%>" class="link-action" id="selectu-user-<%= u project.kee -%>">select users</a>)<br/>
-        <span id="g-user-<%= u project.kee -%>"><%= groups.join(', ') %></span>
-        (<a href="<%= ApplicationController.root_context -%>/roles/edit_groups?redirect=projects&role=user&resource=<%= project.id -%>&q=<%= u params[:q] -%>&qualifier=<%= @qualifier -%>&page=<%= params[:page] -%>" class="link-action" id="selectg-user-<%= u project.kee -%>">select groups</a>)
-      </td>
-      <td valign="top">
-        <%
-           users=Api::Utils.insensitive_sort(project.user_roles.select { |ur| ur.role=='codeviewer' }.map { |ur| ur.user.name })
-           groups=Api::Utils.insensitive_sort(project.group_roles.select { |gr| gr.role=='codeviewer' }.map { |gr| group_name(gr.group) })
-        %>
-        <span id="u-codeviewer-<%= u project.kee -%>"><%= users.join(', ') %></span>
-        (<a href="<%= ApplicationController.root_context -%>/roles/edit_users?redirect=projects&role=codeviewer&resource=<%= project.id -%>&q=<%= u params[:q] -%>&qualifier=<%= @qualifier -%>&page=<%= params[:page] -%>" class="link-action" id="selectu-codeviewer-<%= u project.kee -%>">select users</a>)<br/>
-        <span id="g-codeviewer-<%= u project.kee -%>"><%= groups.join(', ') %></span>
-        (<a href="<%= ApplicationController.root_context -%>/roles/edit_groups?redirect=projects&role=codeviewer&resource=<%= project.id -%>&q=<%= u params[:q] -%>&qualifier=<%= @qualifier -%>&page=<%= params[:page] -%>" class="link-action" id="selectg-codeviewer-<%= u project.kee -%>">select groups</a>)
-      </td>
-    </tr>
-  <%
-     end %>
-  </tbody>
-</table>
+       @projects.each do |project|
+    %>
+      <tr class="<%= cycle('even', 'odd') -%>">
+        <td valign="top"><b><%= h project.name %></b><br/>
+          <span class="small gray"><%= h project.key -%></span>
+        </td>
+        <td valign="top">
+          <%
+             users=Api::Utils.insensitive_sort(project.user_roles.select { |ur| ur.role=='admin' }.map { |ur| ur.user.name })
+             groups=Api::Utils.insensitive_sort(project.group_roles.select { |gr| gr.role=='admin' }.map { |gr| group_name(gr.group) })
+          %>
+          <span id="u-admin-<%= u project.kee -%>"><%= users.join(', ') %></span>
+          (<a href="<%= ApplicationController.root_context -%>/roles/edit_users?redirect=projects&role=admin&resource=<%= project.id -%>&q=<%= u params[:q] -%>&qualifier=<%= @qualifier -%>&page=<%= params[:page] -%>" class="link-action" id="selectu-admin-<%= u project.kee -%>">select users</a>)<br/>
+          <span id="g-admin-<%= u project.kee -%>"><%= groups.join(', ') %></span>
+          (<a href="<%= ApplicationController.root_context -%>/roles/edit_groups?redirect=projects&role=admin&resource=<%= project.id -%>&q=<%= u params[:q] -%>&qualifier=<%= @qualifier -%>&page=<%= params[:page] -%>" class="link-action" id="selectg-admin-<%= u project.kee -%>">select groups</a>)
+        </td>
+        <td valign="top">
+          <%
+             users=Api::Utils.insensitive_sort(project.user_roles.select { |ur| ur.role=='user' }.map { |ur| ur.user.name })
+             groups=Api::Utils.insensitive_sort(project.group_roles.select { |gr| gr.role=='user' }.map { |gr| group_name(gr.group) })
+          %>
+          <span id="u-user-<%= u project.kee -%>"><%= users.join(', ') %></span>
+          (<a href="<%= ApplicationController.root_context -%>/roles/edit_users?redirect=projects&role=user&resource=<%= project.id -%>&q=<%= u params[:q] -%>&qualifier=<%= @qualifier -%>&page=<%= params[:page] -%>" class="link-action" id="selectu-user-<%= u project.kee -%>">select users</a>)<br/>
+          <span id="g-user-<%= u project.kee -%>"><%= groups.join(', ') %></span>
+          (<a href="<%= ApplicationController.root_context -%>/roles/edit_groups?redirect=projects&role=user&resource=<%= project.id -%>&q=<%= u params[:q] -%>&qualifier=<%= @qualifier -%>&page=<%= params[:page] -%>" class="link-action" id="selectg-user-<%= u project.kee -%>">select groups</a>)
+        </td>
+        <td valign="top">
+          <%
+             users=Api::Utils.insensitive_sort(project.user_roles.select { |ur| ur.role=='codeviewer' }.map { |ur| ur.user.name })
+             groups=Api::Utils.insensitive_sort(project.group_roles.select { |gr| gr.role=='codeviewer' }.map { |gr| group_name(gr.group) })
+          %>
+          <span id="u-codeviewer-<%= u project.kee -%>"><%= users.join(', ') %></span>
+          (<a href="<%= ApplicationController.root_context -%>/roles/edit_users?redirect=projects&role=codeviewer&resource=<%= project.id -%>&q=<%= u params[:q] -%>&qualifier=<%= @qualifier -%>&page=<%= params[:page] -%>" class="link-action" id="selectu-codeviewer-<%= u project.kee -%>">select users</a>)<br/>
+          <span id="g-codeviewer-<%= u project.kee -%>"><%= groups.join(', ') %></span>
+          (<a href="<%= ApplicationController.root_context -%>/roles/edit_groups?redirect=projects&role=codeviewer&resource=<%= project.id -%>&q=<%= u params[:q] -%>&qualifier=<%= @qualifier -%>&page=<%= params[:page] -%>" class="link-action" id="selectg-codeviewer-<%= u project.kee -%>">select groups</a>)
+        </td>
+      </tr>
+    <%
+       end %>
+    </tbody>
+  </table>
 
-<% if @qualifiers.size>1 %></div><% end %>
+<% if @qualifiers.size>1 %>
+  </div>
+<% end %>
 
 <script>
   $('search_text').focus();
index f4c10ac97f82a2800d8797f5429a4996c5c03749..469f9f4291f6930f3aaed7aa9f2eb57e175a1189 100644 (file)
@@ -75,7 +75,6 @@ class MigrateDefaultPermissions < ActiveRecord::Migration
     default_template = PermissionTemplate.create(
       :name => 'Default template',
       :description => 'This permission template will be used as default when no other permission configuration is available')
-    puts('default template created')
 
     sonar_admins_group = Group.find_by_name('sonar-administrators')
     sonar_users_group = Group.find_by_name('sonar-users')
@@ -83,14 +82,12 @@ class MigrateDefaultPermissions < ActiveRecord::Migration
     # sonar-administrators default permissions
     if sonar_admins_group
       PermissionTemplateGroup.create(:group_id => sonar_admins_group.id, :permission_reference => 'admin', :template_id => default_template.id)
-      puts('admin template group created')
     end
 
     # sonar-users default permissions
     if sonar_users_group
       PermissionTemplateGroup.create(:group_id => sonar_users_group.id, :permission_reference => 'user', :template_id => default_template.id)
       PermissionTemplateGroup.create(:group_id => sonar_users_group.id, :permission_reference => 'codeviewer', :template_id => default_template.id)
-      puts('users template group created')
     end
 
     # Anyone group default permissions
diff --git a/sonar-server/src/test/java/org/sonar/server/permission/ApplyPermissionTemplateQueryTest.java b/sonar-server/src/test/java/org/sonar/server/permission/ApplyPermissionTemplateQueryTest.java
new file mode 100644 (file)
index 0000000..363be4b
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.
+ */
+
+package org.sonar.server.permission;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.server.exceptions.BadRequestException;
+
+import java.util.Collections;
+import java.util.Map;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class ApplyPermissionTemplateQueryTest {
+
+  @Rule
+  public ExpectedException throwable = ExpectedException.none();
+
+  @Test
+  public void should_populate_with_params() throws Exception {
+
+    Map<String, Object> params = Maps.newHashMap();
+    params.put("template_id", "1");
+    params.put("components", Lists.newArrayList("1", "2", "3"));
+
+    ApplyPermissionTemplateQuery query = ApplyPermissionTemplateQuery.buildFromParams(params);
+
+    assertThat(query.getTemplateId()).isEqualTo(1L);
+    assertThat(query.getSelectedComponents()).containsOnly("1", "2", "3");
+  }
+
+  @Test
+  public void should_invalidate_query_with_empty_name() throws Exception {
+
+    throwable.expect(BadRequestException.class);
+    throwable.expectMessage("Permission template is mandatory");
+
+    Map<String, Object> params = Maps.newHashMap();
+    params.put("template_id", "");
+    params.put("components", Lists.newArrayList("1", "2", "3"));
+
+    ApplyPermissionTemplateQuery query = ApplyPermissionTemplateQuery.buildFromParams(params);
+    query.validate();
+  }
+
+  @Test
+  public void should_invalidate_query_with_no_components() throws Exception {
+
+    throwable.expect(BadRequestException.class);
+    throwable.expectMessage("Please provide at least one entry to which the permission template should be applied");
+
+    Map<String, Object> params = Maps.newHashMap();
+    params.put("template_id", "1");
+    params.put("components", Collections.EMPTY_LIST);
+
+    ApplyPermissionTemplateQuery query = ApplyPermissionTemplateQuery.buildFromParams(params);
+    query.validate();
+  }
+}
index 238d541ada5b1ada7ed308143668a6e6bd0f2495..5112fe239cdc778893e371788b7020204d0a48b2 100644 (file)
@@ -30,13 +30,8 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.security.DefaultGroups;
-import org.sonar.core.user.GroupDto;
-import org.sonar.core.user.GroupRoleDto;
-import org.sonar.core.user.Permission;
-import org.sonar.core.user.RoleDao;
-import org.sonar.core.user.UserDao;
-import org.sonar.core.user.UserDto;
-import org.sonar.core.user.UserRoleDto;
+import org.sonar.core.permission.ComponentPermissionFacade;
+import org.sonar.core.user.*;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.UnauthorizedException;
@@ -46,10 +41,7 @@ import java.util.Map;
 
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
 import static org.sonar.server.permission.InternalPermissionServiceTest.MatchesGroupRole.matchesRole;
 import static org.sonar.server.permission.InternalPermissionServiceTest.MatchesUserRole.matchesRole;
 
@@ -62,6 +54,7 @@ public class InternalPermissionServiceTest {
   private InternalPermissionService service;
   private RoleDao roleDao;
   private UserDao userDao;
+  private ComponentPermissionFacade permissionFacade;
 
   @Before
   public void setUpCommonStubbing() {
@@ -76,12 +69,14 @@ public class InternalPermissionServiceTest {
     when(userDao.selectActiveUserByLogin("user")).thenReturn(targetedUser);
     when(userDao.selectGroupByName("group")).thenReturn(targetedGroup);
 
-    service = new InternalPermissionService(roleDao, userDao);
+    permissionFacade = mock(ComponentPermissionFacade.class);
+
+    service = new InternalPermissionService(roleDao, userDao, permissionFacade);
   }
 
   @Test
   public void should_add_user_permission() throws Exception {
-    params = buildParams("user", null, Permission.DASHBOARD_SHARING);
+    params = buildPermissionChangeParams("user", null, Permission.DASHBOARD_SHARING);
     setUpUserPermissions("user", Permission.QUALITY_PROFILE_ADMIN.key());
     UserRoleDto roleToInsert = new UserRoleDto().setUserId(2L).setRole(Permission.DASHBOARD_SHARING.key());
 
@@ -92,7 +87,7 @@ public class InternalPermissionServiceTest {
 
   @Test
   public void should_remove_user_permission() throws Exception {
-    params = buildParams("user", null, Permission.QUALITY_PROFILE_ADMIN);
+    params = buildPermissionChangeParams("user", null, Permission.QUALITY_PROFILE_ADMIN);
     setUpUserPermissions("user", Permission.QUALITY_PROFILE_ADMIN.key());
     UserRoleDto roleToRemove = new UserRoleDto().setUserId(2L).setRole(Permission.QUALITY_PROFILE_ADMIN.key());
 
@@ -103,7 +98,7 @@ public class InternalPermissionServiceTest {
 
   @Test
   public void should_add_group_permission() throws Exception {
-    params = buildParams(null, "group", Permission.DASHBOARD_SHARING);
+    params = buildPermissionChangeParams(null, "group", Permission.DASHBOARD_SHARING);
     setUpGroupPermissions("group", Permission.QUALITY_PROFILE_ADMIN.key());
     GroupRoleDto roleToInsert = new GroupRoleDto().setGroupId(2L).setRole(Permission.DASHBOARD_SHARING.key());
 
@@ -114,7 +109,7 @@ public class InternalPermissionServiceTest {
 
   @Test
   public void should_remove_group_permission() throws Exception {
-    params = buildParams(null, "group", Permission.QUALITY_PROFILE_ADMIN);
+    params = buildPermissionChangeParams(null, "group", Permission.QUALITY_PROFILE_ADMIN);
     setUpGroupPermissions("group", Permission.QUALITY_PROFILE_ADMIN.key());
     GroupRoleDto roleToRemove = new GroupRoleDto().setGroupId(2L).setRole(Permission.QUALITY_PROFILE_ADMIN.key());
 
@@ -125,7 +120,7 @@ public class InternalPermissionServiceTest {
 
   @Test
   public void should_skip_redundant_permission_change() throws Exception {
-    params = buildParams("user", null, Permission.QUALITY_PROFILE_ADMIN);
+    params = buildPermissionChangeParams("user", null, Permission.QUALITY_PROFILE_ADMIN);
     setUpUserPermissions("user", Permission.QUALITY_PROFILE_ADMIN.key());
 
     service.addPermission(params);
@@ -136,7 +131,7 @@ public class InternalPermissionServiceTest {
   @Test
   public void should_fail_on_invalid_request() throws Exception {
     throwable.expect(BadRequestException.class);
-    params = buildParams("user", "group", Permission.QUALITY_PROFILE_ADMIN);
+    params = buildPermissionChangeParams("user", "group", Permission.QUALITY_PROFILE_ADMIN);
 
     service.addPermission(params);
   }
@@ -144,7 +139,7 @@ public class InternalPermissionServiceTest {
   @Test
   public void should_fail_on_insufficient_rights() throws Exception {
     throwable.expect(ForbiddenException.class);
-    params = buildParams("user", null, Permission.QUALITY_PROFILE_ADMIN);
+    params = buildPermissionChangeParams("user", null, Permission.QUALITY_PROFILE_ADMIN);
 
     MockUserSession.set().setLogin("unauthorized").setPermissions(Permission.QUALITY_PROFILE_ADMIN);
 
@@ -154,7 +149,7 @@ public class InternalPermissionServiceTest {
   @Test
   public void should_fail_on_anonymous_access() throws Exception {
     throwable.expect(UnauthorizedException.class);
-    params = buildParams("user", null, Permission.QUALITY_PROFILE_ADMIN);
+    params = buildPermissionChangeParams("user", null, Permission.QUALITY_PROFILE_ADMIN);
 
     MockUserSession.set();
 
@@ -163,7 +158,7 @@ public class InternalPermissionServiceTest {
 
   @Test
   public void should_add_permission_to_anyone_group() throws Exception {
-    params = buildParams(null, DefaultGroups.ANYONE, Permission.QUALITY_PROFILE_ADMIN);
+    params = buildPermissionChangeParams(null, DefaultGroups.ANYONE, Permission.QUALITY_PROFILE_ADMIN);
     GroupRoleDto roleToInsert = new GroupRoleDto().setRole(Permission.QUALITY_PROFILE_ADMIN.key());
 
     service.addPermission(params);
@@ -173,7 +168,7 @@ public class InternalPermissionServiceTest {
 
   @Test
   public void should_remove_permission_from_anyone_group() throws Exception {
-    params = buildParams(null, DefaultGroups.ANYONE, Permission.QUALITY_PROFILE_ADMIN);
+    params = buildPermissionChangeParams(null, DefaultGroups.ANYONE, Permission.QUALITY_PROFILE_ADMIN);
     setUpGroupPermissions(DefaultGroups.ANYONE, Permission.QUALITY_PROFILE_ADMIN.key());
     GroupRoleDto roleToDelete = new GroupRoleDto().setRole(Permission.QUALITY_PROFILE_ADMIN.key());
 
@@ -182,6 +177,19 @@ public class InternalPermissionServiceTest {
     verify(roleDao).deleteGroupRole(argThat(matchesRole(roleToDelete)));
   }
 
+  @Test
+  public void should_apply_permission_template() throws Exception {
+    params = Maps.newHashMap();
+    params.put("template_id", "1");
+    params.put("components", "1,2,3");
+
+    service.applyPermissionTemplate(params);
+
+    verify(permissionFacade).applyPermissionTemplate(1L, 1L);
+    verify(permissionFacade).applyPermissionTemplate(1L, 2L);
+    verify(permissionFacade).applyPermissionTemplate(1L, 3L);
+  }
+
   protected static class MatchesUserRole extends BaseMatcher<UserRoleDto> {
 
     private final UserRoleDto referenceDto;
@@ -238,7 +246,7 @@ public class InternalPermissionServiceTest {
     }
   }
 
-  private Map<String, Object> buildParams(String login, String group, Permission perm) {
+  private Map<String, Object> buildPermissionChangeParams(String login, String group, Permission perm) {
     Map<String, Object> params = Maps.newHashMap();
     params.put("user", login);
     params.put("group", group);
index ba49d0dc81ffd2d4897473597a3c8febd4d4a29d..3919ffa60cf15b4b6aa1770f6a1f1dc7ad02ac70 100644 (file)
  */
 package org.sonar.server.util;
 
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.SonarException;
 
 import static java.util.Arrays.asList;
 import static org.fest.assertions.Assertions.assertThat;
-import static org.fest.assertions.Fail.fail;
 
 public class RubyUtilsTest {
+
+  @Rule
+  public ExpectedException throwable = ExpectedException.none();
+
   @Test
   public void should_parse_list_of_strings() {
     assertThat(RubyUtils.toStrings(null)).isNull();
@@ -48,12 +54,9 @@ public class RubyUtilsTest {
 
   @Test
   public void toInteger_unexpected_class() throws Exception {
-    try {
-      RubyUtils.toInteger(1.2);
-      fail();
-    } catch (IllegalArgumentException e) {
-      // ok
-    }
+    throwable.expect(IllegalArgumentException.class);
+
+    RubyUtils.toInteger(1.2);
   }
 
   @Test
@@ -70,12 +73,9 @@ public class RubyUtilsTest {
 
   @Test
   public void toDouble_unexpected_class() throws Exception {
-    try {
-      RubyUtils.toDouble(true);
-      fail();
-    } catch (IllegalArgumentException e) {
-      // ok
-    }
+    throwable.expect(IllegalArgumentException.class);
+
+    RubyUtils.toDouble(true);
   }
 
   @Test
@@ -91,12 +91,9 @@ public class RubyUtilsTest {
 
   @Test
   public void toBoolean_unexpected_class() throws Exception {
-    try {
-      RubyUtils.toBoolean(333);
-      fail();
-    } catch (IllegalArgumentException e) {
-      // ok
-    }
+    throwable.expect(IllegalArgumentException.class);
+
+    RubyUtils.toBoolean(333);
   }
 
   @Test
@@ -112,21 +109,30 @@ public class RubyUtilsTest {
 
   @Test
   public void toDate_bad_format() throws Exception {
-    try {
-      RubyUtils.toDate("01/02/2013");
-      fail();
-    } catch (Exception e) {
-      // ok
-    }
+    throwable.expect(SonarException.class);
+
+    RubyUtils.toDate("01/02/2013");
   }
 
   @Test
   public void toDate_unexpected_class() throws Exception {
-    try {
-      RubyUtils.toDate(333);
-      fail();
-    } catch (IllegalArgumentException e) {
-      // ok
-    }
+    throwable.expect(IllegalArgumentException.class);
+
+    RubyUtils.toDate(333);
+  }
+
+  @Test
+  public void toLong() throws Exception {
+    assertThat(RubyUtils.toLong(null)).isNull();
+    assertThat(RubyUtils.toLong(2)).isEqualTo(2L);
+    assertThat(RubyUtils.toLong(3L)).isEqualTo(3L);
+    assertThat(RubyUtils.toLong("4")).isEqualTo(4L);
+  }
+
+  @Test
+  public void toLong_unexpected_class() throws Exception {
+    throwable.expect(IllegalArgumentException.class);
+
+    RubyUtils.toLong(false);
   }
 }