From adf7fae4461861063708ab9e9b9beab7149f18d0 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Fri, 7 Jan 2011 18:15:11 +0100 Subject: [PATCH] changes for issue '#2 Support applying permissions to groups as well as users' --- .../src/main/java/sonia/scm/group/Group.java | 13 +++++ .../java/sonia/scm/group/GroupManager.java | 19 ++++++- .../java/sonia/scm/repository/Permission.java | 40 +++++++++++++ .../sonia/scm/repository/PermissionUtil.java | 18 ++++-- .../scm/web/security/WebSecurityContext.java | 10 ++++ .../scm/repository/PermissionUtilTest.java | 47 +++++++++++++++ .../web/security/DummyWebSecurityContext.java | 18 ++++++ .../sonia/scm/group/xml/XmlGroupManager.java | 25 ++++++++ .../web/security/BasicSecurityContext.java | 57 +++++++++++++++++++ 9 files changed, 239 insertions(+), 8 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/group/Group.java b/scm-core/src/main/java/sonia/scm/group/Group.java index c1bc83f4f5..9235ecb006 100644 --- a/scm-core/src/main/java/sonia/scm/group/Group.java +++ b/scm-core/src/main/java/sonia/scm/group/Group.java @@ -377,6 +377,19 @@ public class Group return type; } + /** + * Method description + * + * + * @param member + * + * @return + */ + public boolean isMember(String member) + { + return (members != null) && members.contains(member); + } + /** * Method description * diff --git a/scm-core/src/main/java/sonia/scm/group/GroupManager.java b/scm-core/src/main/java/sonia/scm/group/GroupManager.java index aa2c86b548..93c2795a33 100644 --- a/scm-core/src/main/java/sonia/scm/group/GroupManager.java +++ b/scm-core/src/main/java/sonia/scm/group/GroupManager.java @@ -38,10 +38,25 @@ package sonia.scm.group; import sonia.scm.ListenerSupport; import sonia.scm.Manager; +//~--- JDK imports ------------------------------------------------------------ + +import java.util.Collection; + /** * * @author Sebastian Sdorra */ public interface GroupManager - extends Manager, - ListenerSupport {} + extends Manager, ListenerSupport +{ + + /** + * Method description + * + * + * @param member + * + * @return + */ + public Collection getGroupsForMember(String member); +} diff --git a/scm-core/src/main/java/sonia/scm/repository/Permission.java b/scm-core/src/main/java/sonia/scm/repository/Permission.java index 856ce8096b..50305239d1 100644 --- a/scm-core/src/main/java/sonia/scm/repository/Permission.java +++ b/scm-core/src/main/java/sonia/scm/repository/Permission.java @@ -85,6 +85,21 @@ public class Permission implements Serializable this.type = type; } + /** + * Constructs ... + * + * + * @param name + * @param groupPermission + * @param type + */ + public Permission(String name, boolean groupPermission, PermissionType type) + { + this.name = name; + this.groupPermission = groupPermission; + this.type = type; + } + //~--- get methods ---------------------------------------------------------- /** @@ -109,8 +124,30 @@ public class Permission implements Serializable return type; } + /** + * Method description + * + * + * @return + */ + public boolean isGroupPermission() + { + return groupPermission; + } + //~--- set methods ---------------------------------------------------------- + /** + * Method description + * + * + * @param groupPermission + */ + public void setGroupPermission(boolean groupPermission) + { + this.groupPermission = groupPermission; + } + /** * Method description * @@ -135,6 +172,9 @@ public class Permission implements Serializable //~--- fields --------------------------------------------------------------- + /** Field description */ + private boolean groupPermission = false; + /** Field description */ private String name; diff --git a/scm-core/src/main/java/sonia/scm/repository/PermissionUtil.java b/scm-core/src/main/java/sonia/scm/repository/PermissionUtil.java index 85526cdf3b..595cb5d836 100644 --- a/scm-core/src/main/java/sonia/scm/repository/PermissionUtil.java +++ b/scm-core/src/main/java/sonia/scm/repository/PermissionUtil.java @@ -43,6 +43,7 @@ import sonia.scm.web.security.WebSecurityContext; //~--- JDK imports ------------------------------------------------------------ +import java.util.Collection; import java.util.List; /** @@ -134,7 +135,8 @@ public class PermissionUtil if (permissions != null) { - result = hasPermission(permissions, username, pt); + result = hasPermission(permissions, username, + securityContext.getGroups(), pt); } } @@ -147,12 +149,13 @@ public class PermissionUtil * * @param permissions * @param username + * @param groups * @param pt * * @return */ private static boolean hasPermission(List permissions, - String username, PermissionType pt) + String username, Collection groups, PermissionType pt) { boolean result = false; @@ -160,12 +163,15 @@ public class PermissionUtil { String name = p.getName(); - if ((name != null) && name.equalsIgnoreCase(username) - && (p.getType().getValue() >= pt.getValue())) + if ((name != null) && (p.getType().getValue() >= pt.getValue())) { - result = true; + if (name.equals(username) + || (p.isGroupPermission() && groups.contains(p.getName()))) + { + result = true; - break; + break; + } } } diff --git a/scm-core/src/main/java/sonia/scm/web/security/WebSecurityContext.java b/scm-core/src/main/java/sonia/scm/web/security/WebSecurityContext.java index d113ae672b..1b9ccec280 100644 --- a/scm-core/src/main/java/sonia/scm/web/security/WebSecurityContext.java +++ b/scm-core/src/main/java/sonia/scm/web/security/WebSecurityContext.java @@ -40,6 +40,8 @@ import sonia.scm.user.User; //~--- JDK imports ------------------------------------------------------------ +import java.util.Collection; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -76,6 +78,14 @@ public interface WebSecurityContext extends SecurityContext //~--- get methods ---------------------------------------------------------- + /** + * Method description + * + * + * @return + */ + public Collection getGroups(); + /** * Method description * diff --git a/scm-core/src/test/java/sonia/scm/repository/PermissionUtilTest.java b/scm-core/src/test/java/sonia/scm/repository/PermissionUtilTest.java index 676920ff20..5b56d42f62 100644 --- a/scm-core/src/test/java/sonia/scm/repository/PermissionUtilTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/PermissionUtilTest.java @@ -50,7 +50,10 @@ import static org.mockito.Mockito.*; //~--- JDK imports ------------------------------------------------------------ +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; /** * @@ -108,6 +111,30 @@ public class PermissionUtilTest PermissionUtil.assertPermission(repository, admams, PermissionType.OWNER); } + /** + * Method description + * + */ + @Test + public void testGroupPermissions() + { + WebSecurityContext context = mockGroupCtx(new User("dent", "Arthur Dent", + "arthur.dent@hitchhiker.com")); + Repository r = new Repository(); + + r.setPermissions( + new ArrayList( + Arrays.asList( + new Permission("dent"), + new Permission("devel", true, PermissionType.READ), + new Permission("qa", true, PermissionType.WRITE)))); + assertTrue(PermissionUtil.hasPermission(r, context, PermissionType.READ)); + assertTrue(PermissionUtil.hasPermission(r, context, PermissionType.WRITE)); + assertFalse(PermissionUtil.hasPermission(r, context, PermissionType.OWNER)); + r.getPermissions().add(new Permission("dent", PermissionType.OWNER)); + assertTrue(PermissionUtil.hasPermission(r, context, PermissionType.OWNER)); + } + //~--- get methods ---------------------------------------------------------- /** @@ -162,6 +189,26 @@ public class PermissionUtilTest return context; } + /** + * Method description + * + * + * @param user + * + * @return + */ + private WebSecurityContext mockGroupCtx(User user) + { + WebSecurityContext context = mockCtx(user); + Set groups = new HashSet(); + + groups.add("devel"); + groups.add("qa"); + when(context.getGroups()).thenReturn(groups); + + return context; + } + //~--- fields --------------------------------------------------------------- /** Field description */ diff --git a/scm-test/src/main/java/sonia/scm/web/security/DummyWebSecurityContext.java b/scm-test/src/main/java/sonia/scm/web/security/DummyWebSecurityContext.java index 9ec7ab1409..467a6dbe3a 100644 --- a/scm-test/src/main/java/sonia/scm/web/security/DummyWebSecurityContext.java +++ b/scm-test/src/main/java/sonia/scm/web/security/DummyWebSecurityContext.java @@ -39,6 +39,9 @@ import sonia.scm.user.User; //~--- JDK imports ------------------------------------------------------------ +import java.util.HashSet; +import java.util.Set; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -97,6 +100,18 @@ public class DummyWebSecurityContext implements WebSecurityContext //~--- get methods ---------------------------------------------------------- + /** + * Method description + * + * + * @return + */ + @Override + public Set getGroups() + { + return groups; + } + /** * Method description * @@ -123,6 +138,9 @@ public class DummyWebSecurityContext implements WebSecurityContext //~--- fields --------------------------------------------------------------- + /** Field description */ + private Set groups = new HashSet(); + /** Field description */ private User user; } diff --git a/scm-webapp/src/main/java/sonia/scm/group/xml/XmlGroupManager.java b/scm-webapp/src/main/java/sonia/scm/group/xml/XmlGroupManager.java index cad532084f..9a6a747e12 100644 --- a/scm-webapp/src/main/java/sonia/scm/group/xml/XmlGroupManager.java +++ b/scm-webapp/src/main/java/sonia/scm/group/xml/XmlGroupManager.java @@ -60,6 +60,7 @@ import java.io.IOException; import java.util.Collection; import java.util.LinkedList; +import java.util.Set; /** * @@ -323,6 +324,30 @@ public class XmlGroupManager extends AbstractGroupManager return groups; } + /** + * Method description + * + * + * @param member + * + * @return + */ + @Override + public Collection getGroupsForMember(String member) + { + LinkedList groups = new LinkedList(); + + for (Group group : groupDB.values()) + { + if (group.isMember(member)) + { + groups.add(group.clone()); + } + } + + return groups; + } + //~--- methods -------------------------------------------------------------- /** diff --git a/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java b/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java index b8c7ba5336..91f4cf4743 100644 --- a/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java +++ b/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java @@ -42,11 +42,17 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.config.ScmConfiguration; +import sonia.scm.group.Group; +import sonia.scm.group.GroupManager; import sonia.scm.user.User; import sonia.scm.user.UserManager; //~--- JDK imports ------------------------------------------------------------ +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -74,15 +80,18 @@ public class BasicSecurityContext implements WebSecurityContext * * @param configuration * @param authenticator + * @param groupManager * @param userManager */ @Inject public BasicSecurityContext(ScmConfiguration configuration, AuthenticationManager authenticator, + GroupManager groupManager, UserManager userManager) { this.configuration = configuration; this.authenticator = authenticator; + this.groupManager = groupManager; this.userManager = userManager; } @@ -128,6 +137,8 @@ public class BasicSecurityContext implements WebSecurityContext { userManager.create(user); } + + loadGroups(); } catch (Exception ex) { @@ -150,10 +161,28 @@ public class BasicSecurityContext implements WebSecurityContext public void logout(HttpServletRequest request, HttpServletResponse response) { user = null; + groups = null; } //~--- get methods ---------------------------------------------------------- + /** + * Method description + * + * + * @return + */ + @Override + public Collection getGroups() + { + if (groups == null) + { + groups = new HashSet(); + } + + return groups; + } + /** * Method description * @@ -183,6 +212,28 @@ public class BasicSecurityContext implements WebSecurityContext return getUser() != null; } + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + */ + private void loadGroups() + { + groups = new HashSet(); + + Collection groupCollection = + groupManager.getGroupsForMember(user.getName()); + + if (groupCollection != null) + { + for (Group group : groupCollection) + { + groups.add(group.getName()); + } + } + } + //~--- fields --------------------------------------------------------------- /** Field description */ @@ -191,6 +242,12 @@ public class BasicSecurityContext implements WebSecurityContext /** Field description */ private ScmConfiguration configuration; + /** Field description */ + private GroupManager groupManager; + + /** Field description */ + private Set groups = new HashSet(); + /** Field description */ private User user;