From 2fdc1d3a7ec176663cf7bb138f3628856fa34e67 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Fri, 26 Nov 2010 17:33:07 +0100 Subject: [PATCH] improve permission system --- .../java/sonia/scm/repository/Permission.java | 128 +++--------------- .../sonia/scm/repository/PermissionType.java | 72 ++++++++++ .../sonia/scm/repository/PermissionUtil.java | 61 ++++++--- .../scm/repository/PermissionUtilTest.java | 63 +++++++-- .../scm/web/filter/PermissionFilter.java | 5 +- 5 files changed, 190 insertions(+), 139 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/repository/PermissionType.java 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 d3f0dd5a49..939b01d995 100644 --- a/scm-core/src/main/java/sonia/scm/repository/Permission.java +++ b/scm-core/src/main/java/sonia/scm/repository/Permission.java @@ -70,13 +70,10 @@ public class Permission implements Serializable * * * @param name - * @param writeable */ - public Permission(String name, boolean writeable) + public Permission(String name) { this.name = name; - this.writeable = writeable; - this.groupPermission = false; } /** @@ -84,67 +81,12 @@ public class Permission implements Serializable * * * @param name - * @param writeable - * @param groupPermission + * @param type */ - public Permission(String name, boolean writeable, boolean groupPermission) + public Permission(String name, PermissionType type) { this.name = name; - this.writeable = writeable; - this.groupPermission = groupPermission; - } - - /** - * Constructs ... - * - * - * @param name - * @param writeable - * @param groupPermission - * @param path - */ - public Permission(String name, boolean writeable, boolean groupPermission, - String path) - { - this.name = name; - this.writeable = writeable; - this.groupPermission = groupPermission; - this.path = path; - } - - //~--- methods -------------------------------------------------------------- - - /** - * Method description - * - * - * @return - */ - @Override - public String toString() - { - StringBuilder buffer = new StringBuilder(); - - buffer.append(name); - - if (groupPermission) - { - buffer.append(" (Group)"); - } - - buffer.append(" - r"); - - if (writeable) - { - buffer.append("w"); - } - - if (Util.isNotEmpty(path)) - { - buffer.append(" ").append(path); - } - - return buffer.toString(); + this.type = type; } //~--- get methods ---------------------------------------------------------- @@ -166,42 +108,9 @@ public class Permission implements Serializable * * @return */ - public String getPath() + public PermissionType getType() { - return path; - } - - /** - * Method description - * - * - * @return - */ - public boolean isGroupPermission() - { - return groupPermission; - } - - /** - * Method description - * - * - * @return - */ - public boolean isRootPermission() - { - return Util.isEmpty(path); - } - - /** - * Method description - * - * - * @return - */ - public boolean isWriteable() - { - return writeable; + return type; } //~--- set methods ---------------------------------------------------------- @@ -210,24 +119,29 @@ public class Permission implements Serializable * Method description * * - * @param path + * @param name */ - public void setPath(String path) + public void setName(String name) { - this.path = path; + this.name = name; + } + + /** + * Method description + * + * + * @param type + */ + public void setType(PermissionType type) + { + this.type = type; } //~--- fields --------------------------------------------------------------- - /** Field description */ - private boolean groupPermission; - /** Field description */ private String name; /** Field description */ - private String path = ""; - - /** Field description */ - private boolean writeable; + private PermissionType type = PermissionType.READ; } diff --git a/scm-core/src/main/java/sonia/scm/repository/PermissionType.java b/scm-core/src/main/java/sonia/scm/repository/PermissionType.java new file mode 100644 index 0000000000..901a256b81 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/PermissionType.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.repository; + +/** + * + * @author Sebastian Sdorra + */ +public enum PermissionType +{ + READ(0), WRITE(10), OWNER(100); + + /** + * Constructs ... + * + * + * @param value + */ + private PermissionType(int value) + { + this.value = value; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public int getValue() + { + return value; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private int value; +} 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 54aef232fe..c87ff00d68 100644 --- a/scm-core/src/main/java/sonia/scm/repository/PermissionUtil.java +++ b/scm-core/src/main/java/sonia/scm/repository/PermissionUtil.java @@ -55,12 +55,12 @@ public class PermissionUtil * * @param repository * @param user - * @param write + * @param pt */ public static void assertPermission(Repository repository, User user, - boolean write) + PermissionType pt) { - if (!hasPermission(repository, user, write)) + if (!hasPermission(repository, user, pt)) { throw new IllegalStateException("action denied"); } @@ -74,36 +74,61 @@ public class PermissionUtil * * @param repository * @param user - * @param write + * @param pt * * @return */ public static boolean hasPermission(Repository repository, User user, - boolean write) + PermissionType pt) { String username = user.getName(); AssertUtil.assertIsNotEmpty(username); boolean result = false; - List permissions = repository.getPermissions(); - if (permissions != null) + if (user.isAdmin()) { - for (Permission p : permissions) + result = true; + } + else + { + List permissions = repository.getPermissions(); + + if (permissions != null) { - if (!p.isGroupPermission()) - { - String name = p.getName(); + result = hasPermission(permissions, username, pt); + } + } - if ((name != null) && name.equalsIgnoreCase(username) - && (!write || p.isWriteable())) - { - result = true; + return result; + } - break; - } - } + /** + * Method description + * + * + * @param permissions + * @param username + * @param pt + * + * @return + */ + private static boolean hasPermission(List permissions, + String username, PermissionType pt) + { + boolean result = false; + + for (Permission p : permissions) + { + String name = p.getName(); + + if ((name != null) && name.equalsIgnoreCase(username) + && (p.getType().getValue() >= pt.getValue())) + { + result = true; + + break; } } 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 21d8a05262..964408cd51 100644 --- a/scm-core/src/test/java/sonia/scm/repository/PermissionUtilTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/PermissionUtilTest.java @@ -59,9 +59,14 @@ public class PermissionUtilTest public PermissionUtilTest() { repository = new Repository(); + admams.setAdmin(true); - Permission[] permissions = new Permission[] { new Permission("dent", false), - new Permission("perfect", true) }; + Permission[] permissions = new Permission[] { + new Permission("dent", PermissionType.READ), + new Permission("perfect", + PermissionType.WRITE), + new Permission("marvin", + PermissionType.OWNER) }; repository.setPermissions(Arrays.asList(permissions)); } @@ -75,7 +80,7 @@ public class PermissionUtilTest @Test(expected = IllegalStateException.class) public void assertFailedPermissionTest() { - PermissionUtil.assertPermission(repository, dent, true); + PermissionUtil.assertPermission(repository, dent, PermissionType.WRITE); } /** @@ -85,9 +90,15 @@ public class PermissionUtilTest @Test public void assertPermissionTest() { - PermissionUtil.hasPermission(repository, dent, false); - PermissionUtil.hasPermission(repository, perfect, false); - PermissionUtil.hasPermission(repository, perfect, true); + PermissionUtil.assertPermission(repository, dent, PermissionType.READ); + PermissionUtil.assertPermission(repository, perfect, PermissionType.READ); + PermissionUtil.assertPermission(repository, perfect, PermissionType.WRITE); + PermissionUtil.assertPermission(repository, marvin, PermissionType.READ); + PermissionUtil.assertPermission(repository, marvin, PermissionType.WRITE); + PermissionUtil.assertPermission(repository, marvin, PermissionType.OWNER); + PermissionUtil.assertPermission(repository, admams, PermissionType.READ); + PermissionUtil.assertPermission(repository, admams, PermissionType.WRITE); + PermissionUtil.assertPermission(repository, admams, PermissionType.OWNER); } //~--- get methods ---------------------------------------------------------- @@ -99,12 +110,30 @@ public class PermissionUtilTest @Test public void hasPermissionTest() { - assertTrue(PermissionUtil.hasPermission(repository, dent, false)); - assertTrue(PermissionUtil.hasPermission(repository, perfect, false)); - assertTrue(PermissionUtil.hasPermission(repository, perfect, true)); - assertFalse(PermissionUtil.hasPermission(repository, dent, true)); - assertFalse(PermissionUtil.hasPermission(repository, slarti, true)); - assertFalse(PermissionUtil.hasPermission(repository, slarti, false)); + assertTrue(PermissionUtil.hasPermission(repository, dent, + PermissionType.READ)); + assertTrue(PermissionUtil.hasPermission(repository, perfect, + PermissionType.READ)); + assertTrue(PermissionUtil.hasPermission(repository, perfect, + PermissionType.WRITE)); + assertFalse(PermissionUtil.hasPermission(repository, dent, + PermissionType.WRITE)); + assertFalse(PermissionUtil.hasPermission(repository, slarti, + PermissionType.WRITE)); + assertFalse(PermissionUtil.hasPermission(repository, slarti, + PermissionType.READ)); + assertTrue(PermissionUtil.hasPermission(repository, marvin, + PermissionType.READ)); + assertTrue(PermissionUtil.hasPermission(repository, marvin, + PermissionType.WRITE)); + assertTrue(PermissionUtil.hasPermission(repository, marvin, + PermissionType.OWNER)); + assertTrue(PermissionUtil.hasPermission(repository, admams, + PermissionType.READ)); + assertTrue(PermissionUtil.hasPermission(repository, admams, + PermissionType.WRITE)); + assertTrue(PermissionUtil.hasPermission(repository, admams, + PermissionType.OWNER)); } //~--- fields --------------------------------------------------------------- @@ -122,5 +151,13 @@ public class PermissionUtilTest /** Field description */ private User slarti = new User("slarti", "Slartibartfaß", - "Slartibartfass@hitchhiker.com"); + "slartibartfass@hitchhiker.com"); + + /** Field description */ + private User marvin = new User("marvin", "Marvin", + "paranoid.android@hitchhiker.com"); + + /** Field description */ + private User admams = new User("adams", "Douglas Adams", + "douglas.adams@hitchhiker.com"); } diff --git a/scm-web-api/src/main/java/sonia/scm/web/filter/PermissionFilter.java b/scm-web-api/src/main/java/sonia/scm/web/filter/PermissionFilter.java index aa39a88ad9..489fcc1577 100644 --- a/scm-web-api/src/main/java/sonia/scm/web/filter/PermissionFilter.java +++ b/scm-web-api/src/main/java/sonia/scm/web/filter/PermissionFilter.java @@ -40,6 +40,7 @@ import com.google.inject.Provider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import sonia.scm.repository.PermissionType; import sonia.scm.repository.PermissionUtil; import sonia.scm.repository.Repository; import sonia.scm.user.User; @@ -134,7 +135,9 @@ public abstract class PermissionFilter extends HttpFilter boolean writeRequest = isWriteRequest(request); if (PermissionUtil.hasPermission(repository, securityContext.getUser(), - writeRequest)) + writeRequest + ? PermissionType.WRITE + : PermissionType.READ)) { chain.doFilter(request, response); }