diff --git a/pom.xml b/pom.xml index 652e4ef2c0..e0a388a48b 100644 --- a/pom.xml +++ b/pom.xml @@ -82,6 +82,15 @@ scm-manager release repository http://maven.scm-manager.org/nexus/content/groups/public + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + true + daily + + @@ -493,6 +502,7 @@ 9.2.10.v20150310 + 1.0.0-SNAPSHOT 1.2.3 diff --git a/scm-core/pom.xml b/scm-core/pom.xml index 2bbb656ea0..7045c52051 100644 --- a/scm-core/pom.xml +++ b/scm-core/pom.xml @@ -114,6 +114,19 @@ provided + + com.github.sdorra + ssp-lib + ${ssp.version} + + + + com.github.sdorra + ssp-processor + ${ssp.version} + true + + 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 f25f0c0124..8bffc22260 100644 --- a/scm-core/src/main/java/sonia/scm/group/Group.java +++ b/scm-core/src/main/java/sonia/scm/group/Group.java @@ -35,6 +35,8 @@ package sonia.scm.group; //~--- non-JDK imports -------------------------------------------------------- +import com.github.sdorra.ssp.PermissionObject; +import com.github.sdorra.ssp.StaticPermissions; import com.google.common.base.Objects; import com.google.common.collect.Lists; @@ -60,10 +62,11 @@ import javax.xml.bind.annotation.XmlRootElement; * * @author Sebastian Sdorra */ +@StaticPermissions("group") @XmlRootElement(name = "groups") @XmlAccessorType(XmlAccessType.FIELD) public class Group extends BasicPropertiesAware - implements ModelObject, Iterable + implements ModelObject, Iterable, PermissionObject { /** Field description */ diff --git a/scm-core/src/main/java/sonia/scm/repository/Repository.java b/scm-core/src/main/java/sonia/scm/repository/Repository.java index fb4dde3256..b0a976db55 100644 --- a/scm-core/src/main/java/sonia/scm/repository/Repository.java +++ b/scm-core/src/main/java/sonia/scm/repository/Repository.java @@ -35,6 +35,8 @@ package sonia.scm.repository; //~--- non-JDK imports -------------------------------------------------------- +import com.github.sdorra.ssp.PermissionObject; +import com.github.sdorra.ssp.StaticPermissions; import com.google.common.base.Objects; import com.google.common.collect.Lists; @@ -61,9 +63,13 @@ import javax.xml.bind.annotation.XmlRootElement; * * @author Sebastian Sdorra */ +@StaticPermissions( + value = "repository", + permissions = {"read", "write", "modify", "delete", "healthCheck"} +) @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "repositories") -public class Repository extends BasicPropertiesAware implements ModelObject +public class Repository extends BasicPropertiesAware implements ModelObject, PermissionObject { /** Field description */ diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryPermissions.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryPermissions.java deleted file mode 100644 index a0cf08cdc1..0000000000 --- a/scm-core/src/main/java/sonia/scm/repository/RepositoryPermissions.java +++ /dev/null @@ -1,272 +0,0 @@ -/** - * Copyright (c) 2014, 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; - -//~--- non-JDK imports -------------------------------------------------------- - -import sonia.scm.security.PermissionActionCheck; -import sonia.scm.security.PermissionCheck; - -/** - * Permission checks for repository related permissions. - * - * @author Sebastian Sdorra - * @since 2.0.0 - */ -public final class RepositoryPermissions -{ - - /** create permission */ - public static final String ACTION_CREATE = "create"; - - /** delete permission */ - public static final String ACTION_DELETE = "delete"; - - /** modify permission */ - public static final String ACTION_MODIFY = "modify"; - - /** health check permission implies modify permission */ - public static final String ACTION_HC = "hc,".concat(ACTION_MODIFY); - - /** read permission */ - public static final String ACTION_READ = "read"; - - /** write permission */ - public static final String ACTION_WRITE = "write"; - - /** permission separator */ - public static final String SEPARATOR = ":"; - - /** permission action separator */ - public static final String SEPERATOR_ACTION = ","; - - /** permission main type */ - public static final String TYPE = "repository"; - - //~--- constructors --------------------------------------------------------- - - private RepositoryPermissions() {} - - //~--- methods -------------------------------------------------------------- - - /** - * Returns permission check for create action. - * - * @return permission check for create action - */ - public static PermissionCheck create() - { - return check(ACTION_CREATE); - } - - /** - * Returns permission check for delete action. - * - * @param r repository for permission check - * - * @return permission check for delete action - */ - public static PermissionCheck delete(Repository r) - { - return delete(r.getId()); - } - - /** - * Returns permission check for delete action. - * - * @param id id of repository for permission check - * - * @return permission check for delete action - */ - public static PermissionCheck delete(String id) - { - return check(ACTION_DELETE.concat(SEPARATOR).concat(id)); - } - - /** - * Returns permission action check for delete action. - * - * @return permission action check for delete action - */ - public static PermissionActionCheck delete() - { - return actionCheck(ACTION_DELETE); - } - - /** - * Returns permission check for health check action. - * - * @param id id of repository for permission check - * - * @return permission check for health check action - */ - public static PermissionCheck healthCheck(String id) - { - return check(ACTION_HC.concat(SEPARATOR).concat(id)); - } - - /** - * Returns permission action check for health check action. - * - * @return permission action check for health check action. - */ - public static PermissionActionCheck healthCheck() - { - return new PermissionActionCheck<>( - TYPE.concat(SEPARATOR).concat(ACTION_HC)); - } - - /** - * Returns permission check for health check action. - * - * @param r repository for permission check - * - * @return permission check for health check action - */ - public static PermissionCheck healthCheck(Repository r) - { - return healthCheck(r.getId()); - } - - /** - * Returns permission action check for modify action. - * - * @param r repository for permission check - * - * @return permission action check for modify action - */ - public static PermissionCheck modify(Repository r) - { - return modify(r.getId()); - } - - /** - * Returns permission action check for modify action. - * - * - * @param id id of repository for permission check - * - * @return permission action check for modify action - */ - public static PermissionCheck modify(String id) - { - return check(ACTION_MODIFY.concat(SEPARATOR).concat(id)); - } - - /** - * Returns permission action check for modify action. - * - * @return permission action check for modify action - */ - public static PermissionActionCheck modify() - { - return actionCheck(ACTION_MODIFY); - } - - /** - * Returns permission check for read action. - * - * @param id id of repository for permission check - * - * @return permission check for read action - */ - public static PermissionCheck read(String id) - { - return check(ACTION_READ.concat(SEPARATOR).concat(id)); - } - - /** - * Returns permission check for read action. - * - * @param r repository for permission check - * - * @return permission check for read action - */ - public static PermissionCheck read(Repository r) - { - return read(r.getId()); - } - - /** - * Returns permission action check for read action. - * - * @return permission action check for read action - */ - public static PermissionActionCheck read() - { - return actionCheck(ACTION_READ); - } - - /** - * Returns permission check for write action. - * - * @param id id of repository for permission check - * - * @return permission check for write action - */ - public static PermissionCheck write(String id) - { - return check(ACTION_WRITE.concat(SEPARATOR).concat(id)); - } - - /** - * Returns permission check for write action. - * - * @param r repository for permission check - * - * @return permission check for write action - */ - public static PermissionCheck write(Repository r) - { - return write(r.getId()); - } - - /** - * Return permission action check for write action. - * - * @return permission action check for write action - */ - public static PermissionActionCheck write() - { - return actionCheck(ACTION_WRITE); - } - - private static PermissionActionCheck actionCheck(String action) - { - return new PermissionActionCheck<>(TYPE.concat(SEPARATOR).concat(action)); - } - - private static PermissionCheck check(String permission) - { - return new PermissionCheck(TYPE.concat(SEPARATOR).concat(permission)); - } -} diff --git a/scm-core/src/main/java/sonia/scm/security/PermissionActionCheck.java b/scm-core/src/main/java/sonia/scm/security/PermissionActionCheck.java deleted file mode 100644 index 0e8815d2fe..0000000000 --- a/scm-core/src/main/java/sonia/scm/security/PermissionActionCheck.java +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Copyright (c) 2014, 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.security; - -//~--- non-JDK imports -------------------------------------------------------- - -import org.apache.shiro.SecurityUtils; -import org.apache.shiro.subject.Subject; - -import sonia.scm.ModelObject; - -/** - * - * @author Sebastian Sdorra - * @param - * - * @since 2.0.0 - */ -public final class PermissionActionCheck -{ - - /** - * Constructs ... - * - * @param typedAction - */ - public PermissionActionCheck(String typedAction) - { - this.prefix = typedAction.concat(":"); - this.subject = SecurityUtils.getSubject(); - } - - //~--- methods -------------------------------------------------------------- - - /** - * Method description - * - * - * @param id - */ - public void check(String id) - { - subject.checkPermission(prefix.concat(id)); - } - - /** - * Method description - * - * - * @param item - */ - public void check(T item) - { - subject.checkPermission(prefix.concat(item.getId())); - } - - //~--- get methods ---------------------------------------------------------- - - /** - * Method description - * - * - * @param id - * - * @return - */ - public boolean isPermitted(String id) - { - return subject.isPermitted(prefix.concat(id)); - } - - /** - * Method description - * - * - * @param item - * - * @return - */ - public boolean isPermitted(T item) - { - return subject.isPermitted(prefix.concat(item.getId())); - } - - //~--- fields --------------------------------------------------------------- - - /** Field description */ - private final String prefix; - - /** Field description */ - private final Subject subject; -} diff --git a/scm-core/src/main/java/sonia/scm/security/PermissionCheck.java b/scm-core/src/main/java/sonia/scm/security/PermissionCheck.java deleted file mode 100644 index 0f8c0beb3a..0000000000 --- a/scm-core/src/main/java/sonia/scm/security/PermissionCheck.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright (c) 2014, 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.security; - -//~--- non-JDK imports -------------------------------------------------------- - -import org.apache.shiro.SecurityUtils; - -/** - * - * @author Sebastian Sdorra - * @since 2.0.0 - */ -public final class PermissionCheck -{ - - /** - * Constructs ... - * - * - * @param permission - */ - public PermissionCheck(String permission) - { - this.permission = permission; - } - - //~--- methods -------------------------------------------------------------- - - /** - * Method description - * - */ - public void check() - { - SecurityUtils.getSubject().checkPermission(permission); - } - - //~--- get methods ---------------------------------------------------------- - - /** - * Method description - * - * - * @return - */ - public boolean isPermitted() - { - return SecurityUtils.getSubject().isPermitted(permission); - } - - //~--- fields --------------------------------------------------------------- - - /** Field description */ - private final String permission; -} diff --git a/scm-core/src/main/java/sonia/scm/user/User.java b/scm-core/src/main/java/sonia/scm/user/User.java index 9ffec01c6f..69c5a5732f 100644 --- a/scm-core/src/main/java/sonia/scm/user/User.java +++ b/scm-core/src/main/java/sonia/scm/user/User.java @@ -35,6 +35,8 @@ package sonia.scm.user; //~--- non-JDK imports -------------------------------------------------------- +import com.github.sdorra.ssp.PermissionObject; +import com.github.sdorra.ssp.StaticPermissions; import com.google.common.base.Objects; import sonia.scm.BasicPropertiesAware; @@ -54,9 +56,10 @@ import javax.xml.bind.annotation.XmlRootElement; * * @author Sebastian Sdorra */ +@StaticPermissions("user") @XmlRootElement(name = "users") @XmlAccessorType(XmlAccessType.FIELD) -public class User extends BasicPropertiesAware implements Principal, ModelObject +public class User extends BasicPropertiesAware implements Principal, ModelObject, PermissionObject { /** Field description */ diff --git a/scm-core/src/test/java/sonia/scm/repository/RepositoryPermissionsTest.java b/scm-core/src/test/java/sonia/scm/repository/RepositoryPermissionsTest.java deleted file mode 100644 index 4457941c52..0000000000 --- a/scm-core/src/test/java/sonia/scm/repository/RepositoryPermissionsTest.java +++ /dev/null @@ -1,224 +0,0 @@ -/** - * Copyright (c) 2014, 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; - -import com.github.sdorra.shiro.ShiroRule; -import com.github.sdorra.shiro.SubjectAware; -import java.util.function.Supplier; -import org.apache.shiro.authz.UnauthorizedException; -import org.junit.Test; -import static org.junit.Assert.*; -import org.junit.Rule; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import static org.mockito.Mockito.*; -import org.mockito.runners.MockitoJUnitRunner; -import sonia.scm.security.PermissionActionCheck; -import sonia.scm.security.PermissionCheck; - -/** - * Unit tests for {@link RepositoryPermissions}. - * - * @author Sebastian Sdorra - */ -@RunWith(MockitoJUnitRunner.class) -@SubjectAware(configuration = "classpath:sonia/scm/repository/repository-permissions.ini") -public class RepositoryPermissionsTest { - - @Mock - private Repository repository; - - /** - * Shiro rule. - */ - @Rule - public ShiroRule shiro = new ShiroRule(); - - /** - * Test permission checks with id successful. - */ - @Test - @SubjectAware(username = "permitted", password = "secret") - public void testPermissionCheckWithId() { - assertPermissionCheckId(RepositoryPermissions::read); - assertPermissionCheckId(RepositoryPermissions::write); - assertPermissionCheckId(RepositoryPermissions::delete); - assertPermissionCheckId(RepositoryPermissions::modify); - assertPermissionCheckId(RepositoryPermissions::healthCheck); - } - - /** - * Test permission checks with id successful. - */ - @Test - @SubjectAware(username = "permitted", password = "secret") - public void testPermissionActionCheck() { - assertPermissionActionCheck(RepositoryPermissions::read); - assertPermissionActionCheck(RepositoryPermissions::write); - assertPermissionActionCheck(RepositoryPermissions::delete); - assertPermissionActionCheck(RepositoryPermissions::modify); - assertPermissionActionCheck(RepositoryPermissions::healthCheck); - } - - @Test - @SubjectAware(username = "notpermitted", password = "secret") - public void testPermissionActionCheckWithoutRequired() { - assertFailedPermissionActionCheck(RepositoryPermissions::read); - assertFailedPermissionActionCheck(RepositoryPermissions::write); - assertFailedPermissionActionCheck(RepositoryPermissions::delete); - assertFailedPermissionActionCheck(RepositoryPermissions::modify); - assertFailedPermissionActionCheck(RepositoryPermissions::healthCheck); - } - - /** - * Test permission checks with repository successful. - */ - @Test - @SubjectAware(username = "permitted", password = "secret") - public void testPermissionCheckWithRepository() { - assertPermissionCheckRepository(RepositoryPermissions::read); - assertPermissionCheckRepository(RepositoryPermissions::write); - assertPermissionCheckRepository(RepositoryPermissions::delete); - assertPermissionCheckRepository(RepositoryPermissions::modify); - assertPermissionCheckRepository(RepositoryPermissions::healthCheck); - } - - /** - * Test permission checks with id and without the required permissions. - */ - @Test - @SubjectAware(username = "notpermitted", password = "secret") - public void testPermissionCheckWithIdAndWithoutRequiredPermissions() { - assertFailedPermissionCheckId(RepositoryPermissions::read); - assertFailedPermissionCheckId(RepositoryPermissions::write); - assertFailedPermissionCheckId(RepositoryPermissions::delete); - assertFailedPermissionCheckId(RepositoryPermissions::modify); - assertFailedPermissionCheckId(RepositoryPermissions::healthCheck); - } - - /** - * Tests permission checks with repository and without the required permissions. - */ - @Test - @SubjectAware(username = "notpermitted", password = "secret") - public void testPermissionCheckWithRepositoryAndWithoutRequiredPermissions() { - assertFailedPermissionCheckRepository(RepositoryPermissions::read); - assertFailedPermissionCheckRepository(RepositoryPermissions::write); - assertFailedPermissionCheckRepository(RepositoryPermissions::delete); - assertFailedPermissionCheckRepository(RepositoryPermissions::modify); - assertFailedPermissionCheckRepository(RepositoryPermissions::healthCheck); - } - - private void assertFailedPermissionCheckRepository(RepositoryPermissionChecker checker) { - when(repository.getId()).thenReturn("abc"); - assertFailedPermissionCheck(checker.get(repository)); - } - - private void assertFailedPermissionCheckId(RepositoryPermissionChecker checker) { - assertFailedPermissionCheck(checker.get("abc")); - } - - private void assertFailedPermissionCheck(PermissionCheck check) { - assertNotNull(check); - assertFalse(check.isPermitted()); - boolean fail = false; - try { - check.check(); - } - catch (UnauthorizedException ex) { - fail = true; - } - assertTrue(fail); - } - - private void assertPermissionCheckRepository(RepositoryPermissionChecker checker) { - when(repository.getId()).thenReturn("abc"); - assertPermissionCheck(checker.get(repository)); - } - - private void assertPermissionCheckId(RepositoryPermissionChecker checker) { - assertPermissionCheck(checker.get("abc")); - } - - private void assertPermissionCheck(PermissionCheck check) { - assertNotNull(check); - assertTrue(check.isPermitted()); - check.check(); - } - - private void assertPermissionActionCheck(Supplier> supplier) { - assertPermissionActionCheck(supplier.get()); - } - - private void assertFailedPermissionActionCheck(Supplier> supplier) { - assertFailedPermissionActionCheck(supplier.get()); - } - - private void assertFailedPermissionActionCheck(PermissionActionCheck check) { - assertNotNull(check); - assertFalse(check.isPermitted("abc")); - boolean fail = false; - try { - check.check("abc"); - } - catch (UnauthorizedException ex) { - fail = true; - } - assertTrue(fail); - fail = false; - when(repository.getId()).thenReturn("abc"); - assertFalse(check.isPermitted(repository)); - try { - check.check(repository); - } - catch (UnauthorizedException ex) { - fail = true; - } - assertTrue(fail); - } - - private void assertPermissionActionCheck(PermissionActionCheck check) { - assertNotNull(check); - assertTrue(check.isPermitted("abc")); - check.check("abc"); - when(repository.getId()).thenReturn("abc"); - assertTrue(check.isPermitted(repository)); - check.check(repository); - } - - @FunctionalInterface - private static interface RepositoryPermissionChecker { - - public PermissionCheck get(T type); - - } - -} diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/MultiParentClassLoader.java b/scm-webapp/src/main/java/sonia/scm/plugin/MultiParentClassLoader.java index ebd8b6e24e..5881652ec4 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/MultiParentClassLoader.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/MultiParentClassLoader.java @@ -74,7 +74,7 @@ public class MultiParentClassLoader extends ClassLoader public MultiParentClassLoader(Collection parents) { super(null); - this.parents = new CopyOnWriteArrayList<>(parents); + this.parents = new CopyOnWriteArrayList(parents); } //~--- get methods ---------------------------------------------------------- diff --git a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java index 350052f5ac..daee5f42b3 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java @@ -35,6 +35,7 @@ package sonia.scm.repository; //~--- non-JDK imports -------------------------------------------------------- +import com.github.sdorra.ssp.PermissionActionCheck; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.util.concurrent.ThreadFactoryBuilder; @@ -53,7 +54,6 @@ import sonia.scm.SCMContextProvider; import sonia.scm.Type; import sonia.scm.config.ScmConfiguration; import sonia.scm.security.KeyGenerator; -import sonia.scm.security.PermissionActionCheck; import sonia.scm.util.AssertUtil; import sonia.scm.util.CollectionAppender; import sonia.scm.util.HttpUtil; diff --git a/scm-webapp/src/main/java/sonia/scm/repository/HealthChecker.java b/scm-webapp/src/main/java/sonia/scm/repository/HealthChecker.java index 302d92a79e..26f674a5b5 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/HealthChecker.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/HealthChecker.java @@ -33,6 +33,7 @@ package sonia.scm.repository; //~--- non-JDK imports -------------------------------------------------------- +import com.github.sdorra.ssp.PermissionActionCheck; import com.google.common.collect.ImmutableList; import com.google.inject.Inject; @@ -43,7 +44,6 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.Set; -import sonia.scm.security.PermissionActionCheck; /** * @@ -91,7 +91,7 @@ public final class HealthChecker public void check(String id) throws RepositoryNotFoundException, RepositoryException, IOException { - RepositoryPermissions.healthCheck(id); + RepositoryPermissions.healthCheck(id).check(); Repository repository = repositoryManager.get(id); @@ -116,7 +116,7 @@ public final class HealthChecker public void check(Repository repository) throws RepositoryException, IOException { - RepositoryPermissions.healthCheck(repository); + RepositoryPermissions.healthCheck(repository).check(); doCheck(repository); } diff --git a/scm-webapp/src/main/java/sonia/scm/user/DefaultUserManager.java b/scm-webapp/src/main/java/sonia/scm/user/DefaultUserManager.java index f1d6a67e90..48ea159c83 100644 --- a/scm-webapp/src/main/java/sonia/scm/user/DefaultUserManager.java +++ b/scm-webapp/src/main/java/sonia/scm/user/DefaultUserManager.java @@ -35,12 +35,10 @@ package sonia.scm.user; //~--- non-JDK imports -------------------------------------------------------- +import com.github.sdorra.ssp.PermissionActionCheck; import com.google.inject.Inject; import com.google.inject.Singleton; -import org.apache.shiro.SecurityUtils; -import org.apache.shiro.subject.Subject; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,12 +47,9 @@ import sonia.scm.SCMContextProvider; import sonia.scm.TransformFilter; import sonia.scm.search.SearchRequest; import sonia.scm.search.SearchUtil; -import sonia.scm.security.Role; -import sonia.scm.security.ScmSecurityException; import sonia.scm.util.AssertUtil; import sonia.scm.util.CollectionAppender; import sonia.scm.util.IOUtil; -import sonia.scm.util.SecurityUtil; import sonia.scm.util.Util; //~--- JDK imports ------------------------------------------------------------ @@ -99,10 +94,6 @@ public class DefaultUserManager extends AbstractUserManager /** * Constructs ... * -<<<<<<< mine -======= - * ->>>>>>> theirs * @param userDAO */ @Inject @@ -164,17 +155,7 @@ public class DefaultUserManager extends AbstractUserManager logger.info("create user {} of type {}", user.getName(), user.getType()); } - Subject subject = SecurityUtils.getSubject(); - - if (!subject.hasRole(Role.USER)) - { - throw new ScmSecurityException("user is not authenticated"); - } - - if (!subject.hasRole(Role.ADMIN)) - { - throw new ScmSecurityException("admin account is required"); - } + UserPermissions.create().check(); if (userDAO.contains(user.getName())) { @@ -205,9 +186,8 @@ public class DefaultUserManager extends AbstractUserManager logger.info("delete user {} of type {}", user.getName(), user.getType()); } - SecurityUtil.assertIsAdmin(); - String name = user.getName(); + UserPermissions.delete(name).check(); if (userDAO.contains(name)) { @@ -250,28 +230,13 @@ public class DefaultUserManager extends AbstractUserManager @Override public void modify(User user) throws UserException, IOException { + String name = user.getName(); if (logger.isInfoEnabled()) { logger.info("modify user {} of type {}", user.getName(), user.getType()); } - - Subject subject = SecurityUtils.getSubject(); - - if (!subject.isAuthenticated()) - { - throw new ScmSecurityException("user is not authenticated"); - } - - User currentUser = subject.getPrincipals().oneByType(User.class); - - if (!user.getName().equals(currentUser.getName()) - &&!subject.hasRole(Role.ADMIN)) - { - throw new ScmSecurityException("admin account is required"); - } - - String name = user.getName(); + UserPermissions.modify(user).check(); User oldUser = userDAO.get(name); if (oldUser != null) @@ -305,8 +270,7 @@ public class DefaultUserManager extends AbstractUserManager logger.info("refresh user {} of type {}", user.getName(), user.getType()); } - SecurityUtil.assertIsAdmin(); - + UserPermissions.read(user).check(); User fresh = userDAO.get(user.getName()); if (fresh == null) @@ -333,24 +297,23 @@ public class DefaultUserManager extends AbstractUserManager logger.debug("search user with query {}", searchRequest.getQuery()); } - return SearchUtil.search(searchRequest, userDAO.getAll(), - new TransformFilter() - { + final PermissionActionCheck check = UserPermissions.read(); + return SearchUtil.search(searchRequest, userDAO.getAll(), new TransformFilter() { @Override public User accept(User user) { User result = null; - - if (SearchUtil.matchesOne(searchRequest, user.getName(), - user.getDisplayName(), user.getMail())) - { + if (check.isPermitted(user) && matches(searchRequest, user)) { result = user.clone(); } - return result; } }); } + + private boolean matches(SearchRequest searchRequest, User user) { + return SearchUtil.matchesOne(searchRequest, user.getName(), user.getDisplayName(), user.getMail()); + } //~--- get methods ---------------------------------------------------------- @@ -365,8 +328,8 @@ public class DefaultUserManager extends AbstractUserManager @Override public User get(String id) { - - // SecurityUtil.assertIsAdmin(scurityContextProvider); + UserPermissions.read().check(id); + User user = userDAO.get(id); if (user != null) @@ -400,17 +363,16 @@ public class DefaultUserManager extends AbstractUserManager @Override public Collection getAll(Comparator comparator) { - SecurityUtil.assertIsAdmin(); + List users = new ArrayList<>(); - List users = new ArrayList(); - - for (User user : userDAO.getAll()) - { - users.add(user.clone()); + PermissionActionCheck check = UserPermissions.read(); + for (User user : userDAO.getAll()) { + if (check.isPermitted(user)) { + users.add(user.clone()); + } } - if (comparator != null) - { + if (comparator != null) { Collections.sort(users, comparator); } @@ -429,18 +391,17 @@ public class DefaultUserManager extends AbstractUserManager * @return */ @Override - public Collection getAll(Comparator comaparator, int start, - int limit) - { - SecurityUtil.assertIsAdmin(); - + public Collection getAll(Comparator comaparator, int start, int limit) { + final PermissionActionCheck check = UserPermissions.read(); return Util.createSubCollection(userDAO.getAll(), comaparator, new CollectionAppender() { @Override public void append(Collection collection, User item) { - collection.add(item.clone()); + if (check.isPermitted(item)) { + collection.add(item.clone()); + } } }, start, limit); }