mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-02-05 06:09:12 +01:00
merge with branch apache-shiro
This commit is contained in:
@@ -44,33 +44,75 @@ public enum HandlerEvent
|
||||
/**
|
||||
* After a new object is stored by a handler.
|
||||
*/
|
||||
CREATE,
|
||||
CREATE(true),
|
||||
|
||||
/**
|
||||
* After a object is modified by a handler.
|
||||
*/
|
||||
MODIFY,
|
||||
MODIFY(true),
|
||||
|
||||
/**
|
||||
* After a object is removed by a handler.
|
||||
*/
|
||||
DELETE,
|
||||
DELETE(true),
|
||||
|
||||
/**
|
||||
* Before a new object is stored by a handler.
|
||||
* @since 1.16
|
||||
*/
|
||||
BEFORE_CREATE,
|
||||
BEFORE_CREATE(false),
|
||||
|
||||
/**
|
||||
* Before a object is modified by a handler.
|
||||
* @since 1.16
|
||||
*/
|
||||
BEFORE_MODIFY,
|
||||
BEFORE_MODIFY(false),
|
||||
|
||||
/**
|
||||
* Before a object is removed by a handler.
|
||||
* @since 1.16
|
||||
*/
|
||||
BEFORE_DELETE
|
||||
BEFORE_DELETE(false);
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param post
|
||||
*/
|
||||
private HandlerEvent(boolean post)
|
||||
{
|
||||
this.post = post;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns true if the event is fired after the action is occurred.
|
||||
*
|
||||
*
|
||||
* @return true if the event is fired after the action is occurred
|
||||
* @since 1.21
|
||||
*/
|
||||
public boolean isPost()
|
||||
{
|
||||
return post;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the event is fired before the action is occurred.
|
||||
*
|
||||
*
|
||||
* @return true if the event is fired before the action is occurred
|
||||
* @since 1.21
|
||||
*/
|
||||
public boolean isPre()
|
||||
{
|
||||
return !post;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private boolean post;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ package sonia.scm;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.util.ServiceUtil;
|
||||
|
||||
/**
|
||||
@@ -52,6 +53,14 @@ public class SCMContext
|
||||
/** Name of the anonymous user */
|
||||
public static final String USER_ANONYMOUS = "anonymous";
|
||||
|
||||
/**
|
||||
* the anonymous user
|
||||
* @since 1.21
|
||||
*/
|
||||
public static final User ANONYMOUS = new User(USER_ANONYMOUS,
|
||||
"SCM Anonymous",
|
||||
"scm-anonymous@scm-manager.com");
|
||||
|
||||
/** Singleton instance of {@link SCMContextProvider} */
|
||||
private static volatile SCMContextProvider provider;
|
||||
|
||||
|
||||
@@ -73,10 +73,10 @@ public class ScmState
|
||||
* @param repositoryTypes - available repository types
|
||||
* @param clientConfig - client configuration
|
||||
*/
|
||||
@Deprecated
|
||||
public ScmState(SCMContextProvider provider,
|
||||
WebSecurityContext securityContext,
|
||||
Collection<Type> repositoryTypes,
|
||||
ScmClientConfig clientConfig)
|
||||
WebSecurityContext securityContext, Collection<Type> repositoryTypes,
|
||||
ScmClientConfig clientConfig)
|
||||
{
|
||||
this(provider, securityContext, repositoryTypes, null, clientConfig);
|
||||
}
|
||||
@@ -93,10 +93,10 @@ public class ScmState
|
||||
*
|
||||
* @since 1.14
|
||||
*/
|
||||
@Deprecated
|
||||
public ScmState(SCMContextProvider provider,
|
||||
WebSecurityContext securityContext,
|
||||
Collection<Type> repositoryTypes, String defaultUserType,
|
||||
ScmClientConfig clientConfig)
|
||||
WebSecurityContext securityContext, Collection<Type> repositoryTypes,
|
||||
String defaultUserType, ScmClientConfig clientConfig)
|
||||
{
|
||||
this.version = provider.getVersion();
|
||||
this.user = securityContext.getUser();
|
||||
@@ -106,6 +106,31 @@ public class ScmState
|
||||
this.defaultUserType = defaultUserType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs {@link ScmState} object.
|
||||
*
|
||||
*
|
||||
* @param provider context provider
|
||||
* @param user current user
|
||||
* @param groups groups of the current user
|
||||
* @param repositoryTypes available repository types
|
||||
* @param defaultUserType default user type
|
||||
* @param clientConfig client configuration
|
||||
*
|
||||
* @since 1.21
|
||||
*/
|
||||
public ScmState(SCMContextProvider provider, User user,
|
||||
Collection<String> groups, Collection<Type> repositoryTypes,
|
||||
String defaultUserType, ScmClientConfig clientConfig)
|
||||
{
|
||||
this.version = provider.getVersion();
|
||||
this.user = user;
|
||||
this.groups = groups;
|
||||
this.repositoryTypes = repositoryTypes;
|
||||
this.clientConfig = clientConfig;
|
||||
this.defaultUserType = defaultUserType;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
||||
137
scm-core/src/main/java/sonia/scm/group/GroupNames.java
Normal file
137
scm-core/src/main/java/sonia/scm/group/GroupNames.java
Normal file
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* 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.group;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* This class represents all associated groups for a user.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.21
|
||||
*/
|
||||
public final class GroupNames implements Serializable, Iterable<String>
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
private static final long serialVersionUID = 8615685985213897947L;
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*/
|
||||
public GroupNames()
|
||||
{
|
||||
this.collection = Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param collection
|
||||
*/
|
||||
public GroupNames(Collection<String> collection)
|
||||
{
|
||||
this.collection = Collections.unmodifiableCollection(collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param groupName
|
||||
* @param groupNames
|
||||
*/
|
||||
public GroupNames(String groupName, String... groupNames)
|
||||
{
|
||||
this.collection = Lists.asList(groupName, groupNames);
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param groupName
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean contains(String groupName)
|
||||
{
|
||||
return collection.contains(groupName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Iterator<String> iterator()
|
||||
{
|
||||
return collection.iterator();
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Collection<String> getCollection()
|
||||
{
|
||||
return collection;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private Collection<String> collection;
|
||||
}
|
||||
@@ -37,18 +37,21 @@ package sonia.scm.repository;
|
||||
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.group.GroupNames;
|
||||
import sonia.scm.security.Role;
|
||||
import sonia.scm.security.ScmSecurityException;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.util.AssertUtil;
|
||||
import sonia.scm.web.security.WebSecurityContext;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -73,14 +76,13 @@ public class PermissionUtil
|
||||
* @param repository
|
||||
* @param securityContext
|
||||
* @param pt
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public static void assertPermission(Repository repository,
|
||||
WebSecurityContext securityContext, PermissionType pt)
|
||||
WebSecurityContext securityContext, PermissionType pt)
|
||||
{
|
||||
if (!hasPermission(repository, securityContext, pt))
|
||||
{
|
||||
throw new ScmSecurityException("action denied");
|
||||
}
|
||||
assertPermission(repository, pt);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,13 +93,32 @@ public class PermissionUtil
|
||||
* @param securityContextProvider
|
||||
* @param pt
|
||||
*/
|
||||
@Deprecated
|
||||
public static void assertPermission(Repository repository,
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
PermissionType pt)
|
||||
Provider<WebSecurityContext> securityContextProvider, PermissionType pt)
|
||||
{
|
||||
assertPermission(repository, securityContextProvider.get(), pt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
* @param securityContextProvider
|
||||
* @param pt
|
||||
*
|
||||
* @since 1.21
|
||||
*/
|
||||
@Deprecated
|
||||
public static void assertPermission(Repository repository, PermissionType pt)
|
||||
{
|
||||
if (!hasPermission(null, repository, pt))
|
||||
{
|
||||
throw new ScmSecurityException("action denied");
|
||||
}
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -109,12 +130,13 @@ public class PermissionUtil
|
||||
* @param pt
|
||||
*
|
||||
* @return
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean hasPermission(Repository repository,
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
PermissionType pt)
|
||||
Provider<WebSecurityContext> securityContextProvider, PermissionType pt)
|
||||
{
|
||||
return hasPermission(repository, securityContextProvider.get(), pt);
|
||||
return hasPermission(null, repository, pt);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,39 +148,67 @@ public class PermissionUtil
|
||||
* @param pt
|
||||
*
|
||||
* @return
|
||||
* @deprecated use {@link #hasPermission(Repository,PermissionType)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean hasPermission(Repository repository,
|
||||
WebSecurityContext securityContext, PermissionType pt)
|
||||
WebSecurityContext securityContext, PermissionType pt)
|
||||
{
|
||||
return hasPermission(null, repository, pt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param configuration
|
||||
* @param repository
|
||||
* @param pt
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @since 1.21
|
||||
*/
|
||||
public static boolean hasPermission(ScmConfiguration configuration,
|
||||
Repository repository, PermissionType pt)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (securityContext != null)
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
|
||||
if (subject.isAuthenticated())
|
||||
{
|
||||
User user = securityContext.getUser();
|
||||
String username = subject.getPrincipal().toString();
|
||||
|
||||
if (user != null)
|
||||
AssertUtil.assertIsNotEmpty(username);
|
||||
|
||||
if (subject.hasRole(Role.ADMIN)
|
||||
|| ((pt == PermissionType.READ) && repository.isPublicReadable()))
|
||||
{
|
||||
String username = user.getName();
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
List<Permission> permissions = repository.getPermissions();
|
||||
|
||||
AssertUtil.assertIsNotEmpty(username);
|
||||
|
||||
if (user.isAdmin()
|
||||
|| ((pt == PermissionType.READ) && repository.isPublicReadable()))
|
||||
if (permissions != null)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
List<Permission> permissions = repository.getPermissions();
|
||||
GroupNames groupNames =
|
||||
subject.getPrincipals().oneByType(GroupNames.class);
|
||||
|
||||
result = hasPermission(permissions, username, groupNames, pt);
|
||||
|
||||
if (permissions != null)
|
||||
{
|
||||
result = hasPermission(permissions, username,
|
||||
securityContext.getGroups(), pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// check anonymous access
|
||||
result = (configuration != null)
|
||||
&& configuration.isAnonymousAccessEnabled()
|
||||
&& repository.isPublicReadable() && (pt == PermissionType.READ);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -173,10 +223,28 @@ public class PermissionUtil
|
||||
*
|
||||
* @return true if the repository is writable
|
||||
* @since 1.14
|
||||
* @deprecated use {@link #isWritable(ScmConfiguration, Repository)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean isWritable(ScmConfiguration configuration,
|
||||
Repository repository, WebSecurityContext securityContext)
|
||||
{
|
||||
return isWritable(configuration, repository);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the repository is writable.
|
||||
*
|
||||
*
|
||||
* @param configuration SCM-Manager main configuration
|
||||
* @param repository repository to check
|
||||
* @param securityContext current user security context
|
||||
*
|
||||
* @return true if the repository is writable
|
||||
* @since 1.21
|
||||
*/
|
||||
public static boolean isWritable(ScmConfiguration configuration,
|
||||
Repository repository,
|
||||
WebSecurityContext securityContext)
|
||||
Repository repository)
|
||||
{
|
||||
boolean permitted = false;
|
||||
|
||||
@@ -185,13 +253,13 @@ public class PermissionUtil
|
||||
if (logger.isWarnEnabled())
|
||||
{
|
||||
logger.warn("{} is archived and is not writeable",
|
||||
repository.getName());
|
||||
repository.getName());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
permitted = PermissionUtil.hasPermission(repository, securityContext,
|
||||
PermissionType.WRITE);
|
||||
permitted = PermissionUtil.hasPermission(configuration, repository,
|
||||
PermissionType.WRITE);
|
||||
}
|
||||
|
||||
return permitted;
|
||||
@@ -209,7 +277,7 @@ public class PermissionUtil
|
||||
* @return
|
||||
*/
|
||||
private static boolean hasPermission(List<Permission> permissions,
|
||||
String username, Collection<String> groups, PermissionType pt)
|
||||
String username, GroupNames groups, PermissionType pt)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
@@ -218,8 +286,8 @@ public class PermissionUtil
|
||||
String name = p.getName();
|
||||
|
||||
if (((name != null) && (p.getType().getValue() >= pt.getValue()))
|
||||
&& (name.equals(username)
|
||||
|| (p.isGroupPermission() && groups.contains(p.getName()))))
|
||||
&& (name.equals(username)
|
||||
|| (p.isGroupPermission() && groups.contains(p.getName()))))
|
||||
{
|
||||
result = true;
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ package sonia.scm.repository.api;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -47,6 +46,7 @@ import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.HandlerEvent;
|
||||
import sonia.scm.cache.Cache;
|
||||
import sonia.scm.cache.CacheManager;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.repository.BlameResult;
|
||||
import sonia.scm.repository.Branches;
|
||||
import sonia.scm.repository.BrowserResult;
|
||||
@@ -65,7 +65,6 @@ import sonia.scm.repository.Tags;
|
||||
import sonia.scm.repository.spi.RepositoryServiceProvider;
|
||||
import sonia.scm.repository.spi.RepositoryServiceResolver;
|
||||
import sonia.scm.security.ScmSecurityException;
|
||||
import sonia.scm.web.security.WebSecurityContext;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
@@ -134,16 +133,40 @@ public final class RepositoryServiceFactory
|
||||
* @param securityContextProvider provider for the current security context
|
||||
* @param resolvers a set of {@link RepositoryServiceResolver}
|
||||
* @param preProcessorUtil helper object for pre processor handling
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
@Inject
|
||||
@Deprecated
|
||||
public RepositoryServiceFactory(CacheManager cacheManager,
|
||||
RepositoryManager repositoryManager,
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
Set<RepositoryServiceResolver> resolvers, PreProcessorUtil preProcessorUtil)
|
||||
{
|
||||
this(null, cacheManager, repositoryManager, resolvers, preProcessorUtil);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link RepositoryServiceFactory}. This constructor
|
||||
* should not be called manually, it should only be used by the injection
|
||||
* container.
|
||||
*
|
||||
*
|
||||
* @param configuration configuration
|
||||
* @param cacheManager cache manager
|
||||
* @param repositoryManager manager for repositories
|
||||
* @param securityContextProvider provider for the current security context
|
||||
* @param resolvers a set of {@link RepositoryServiceResolver}
|
||||
* @param preProcessorUtil helper object for pre processor handling
|
||||
*
|
||||
* @since 1.21
|
||||
*/
|
||||
@Inject
|
||||
public RepositoryServiceFactory(ScmConfiguration configuration,
|
||||
CacheManager cacheManager, RepositoryManager repositoryManager,
|
||||
Set<RepositoryServiceResolver> resolvers, PreProcessorUtil preProcessorUtil)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
this.cacheManager = cacheManager;
|
||||
this.repositoryManager = repositoryManager;
|
||||
this.securityContextProvider = securityContextProvider;
|
||||
this.resolvers = resolvers;
|
||||
this.preProcessorUtil = preProcessorUtil;
|
||||
|
||||
@@ -250,8 +273,11 @@ public final class RepositoryServiceFactory
|
||||
Preconditions.checkNotNull(repository, "repository is required");
|
||||
|
||||
// check for read permissions of current user
|
||||
PermissionUtil.assertPermission(repository, securityContextProvider,
|
||||
PermissionType.READ);
|
||||
if (!PermissionUtil.hasPermission(configuration, repository,
|
||||
PermissionType.READ))
|
||||
{
|
||||
throw new ScmSecurityException("read permission are required");
|
||||
}
|
||||
|
||||
RepositoryService service = null;
|
||||
|
||||
@@ -404,6 +430,9 @@ public final class RepositoryServiceFactory
|
||||
/** Field description */
|
||||
private CacheManager cacheManager;
|
||||
|
||||
/** scm-manager configuration */
|
||||
private ScmConfiguration configuration;
|
||||
|
||||
/** Field description */
|
||||
private PreProcessorUtil preProcessorUtil;
|
||||
|
||||
@@ -412,7 +441,4 @@ public final class RepositoryServiceFactory
|
||||
|
||||
/** Field description */
|
||||
private Set<RepositoryServiceResolver> resolvers;
|
||||
|
||||
/** Field description */
|
||||
private Provider<WebSecurityContext> securityContextProvider;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import org.apache.shiro.authz.Permission;
|
||||
|
||||
import sonia.scm.repository.PermissionType;
|
||||
import sonia.scm.repository.Repository;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* This class represents the permission to a repository of a user.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.21
|
||||
*/
|
||||
public final class RepositoryPermission implements Permission, Serializable
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String WILDCARD = "*";
|
||||
|
||||
/** Field description */
|
||||
private static final long serialVersionUID = 3832804235417228043L;
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
* @param permissionType
|
||||
*/
|
||||
public RepositoryPermission(Repository repository,
|
||||
PermissionType permissionType)
|
||||
{
|
||||
this(repository.getId(), permissionType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param repositoryId
|
||||
* @param permissionType
|
||||
*/
|
||||
public RepositoryPermission(String repositoryId,
|
||||
PermissionType permissionType)
|
||||
{
|
||||
this.repositoryId = repositoryId;
|
||||
this.permissionType = permissionType;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param obj
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getClass() != obj.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
final RepositoryPermission other = (RepositoryPermission) obj;
|
||||
|
||||
return Objects.equal(repositoryId, other.repositoryId)
|
||||
&& Objects.equal(permissionType, other.permissionType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hashCode(repositoryId, permissionType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param p
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean implies(Permission p)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (p instanceof RepositoryPermission)
|
||||
{
|
||||
RepositoryPermission rp = (RepositoryPermission) p;
|
||||
|
||||
//J-
|
||||
result = (repositoryId.equals(WILDCARD) || repositoryId.equals(rp.repositoryId))
|
||||
&& (permissionType.getValue() >= rp.permissionType.getValue());
|
||||
//J+
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
//J-
|
||||
return Objects.toStringHelper(this)
|
||||
.add("repositoryId", repositoryId)
|
||||
.add("permissionType", permissionType)
|
||||
.toString();
|
||||
//J+
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public PermissionType getPermissionType()
|
||||
{
|
||||
return permissionType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getRepositoryId()
|
||||
{
|
||||
return repositoryId;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private PermissionType permissionType;
|
||||
|
||||
/** Field description */
|
||||
private String repositoryId;
|
||||
}
|
||||
48
scm-core/src/main/java/sonia/scm/security/Role.java
Normal file
48
scm-core/src/main/java/sonia/scm/security/Role.java
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.21
|
||||
*/
|
||||
public final class Role
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String ADMIN = "admin";
|
||||
|
||||
/** Field description */
|
||||
public static final String USER = "user";
|
||||
}
|
||||
@@ -40,7 +40,9 @@ import sonia.scm.user.User;
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @deprecated use {@link SecurityUtils#getSecurityManager()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface SecurityContext
|
||||
{
|
||||
|
||||
|
||||
70
scm-core/src/main/java/sonia/scm/security/Tokens.java
Normal file
70
scm-core/src/main/java/sonia/scm/security/Tokens.java
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Create tokens for security reasons.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.21
|
||||
*/
|
||||
public final class Tokens
|
||||
{
|
||||
|
||||
/**
|
||||
* Build an {@link AuthenticationToken} for use with
|
||||
* {@link Subject#login(org.apache.shiro.authc.AuthenticationToken)}.
|
||||
*
|
||||
*
|
||||
* @param request servlet request
|
||||
* @param username username of the user to authenticate
|
||||
* @param password password of the user to authenticate
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static AuthenticationToken createAuthenticationToken(
|
||||
HttpServletRequest request, String username, String password)
|
||||
{
|
||||
return new UsernamePasswordToken(username, password,
|
||||
request.getRemoteAddr());
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra All rights reserved.
|
||||
* 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 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.
|
||||
* 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.template;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
@@ -37,7 +37,11 @@ package sonia.scm.util;
|
||||
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
|
||||
import sonia.scm.SCMContext;
|
||||
import sonia.scm.security.Role;
|
||||
import sonia.scm.security.ScmSecurityException;
|
||||
import sonia.scm.security.SecurityContext;
|
||||
import sonia.scm.user.User;
|
||||
@@ -54,36 +58,51 @@ public class SecurityUtil
|
||||
*
|
||||
*
|
||||
* @param contextProvider
|
||||
* @deprecated use {@link Subject#checkRole(java.lang.String)} with {
|
||||
* @link Role#ADMIN} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void assertIsAdmin(
|
||||
Provider<? extends SecurityContext> contextProvider)
|
||||
Provider<? extends SecurityContext> contextProvider)
|
||||
{
|
||||
assertIsAdmin(contextProvider.get());
|
||||
assertIsAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
* This method is only present for compatibility reasons.
|
||||
* Use {@link Subject#checkRole(java.lang.String)} with {
|
||||
* @link Role#ADMIN} instead.
|
||||
*
|
||||
*
|
||||
* @param context
|
||||
* @since 1.21
|
||||
*/
|
||||
public static void assertIsAdmin(SecurityContext context)
|
||||
public static void assertIsAdmin()
|
||||
{
|
||||
AssertUtil.assertIsNotNull(context);
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
|
||||
User user = context.getUser();
|
||||
|
||||
if (user == null)
|
||||
if (!subject.isAuthenticated())
|
||||
{
|
||||
throw new ScmSecurityException("user is not authenticated");
|
||||
}
|
||||
|
||||
if (!user.isAdmin())
|
||||
else if (!subject.hasRole(Role.ADMIN))
|
||||
{
|
||||
throw new ScmSecurityException("admin account is required");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param context
|
||||
* @deprecated use {@link Subject#checkRole(java.lang.String)} with {
|
||||
* @link Role#ADMIN} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void assertIsAdmin(SecurityContext context)
|
||||
{
|
||||
assertIsAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -91,7 +110,7 @@ public class SecurityUtil
|
||||
* @param contextProvider
|
||||
*/
|
||||
public static void assertIsNotAnonymous(
|
||||
Provider<? extends SecurityContext> contextProvider)
|
||||
Provider<? extends SecurityContext> contextProvider)
|
||||
{
|
||||
if (isAnonymous(contextProvider))
|
||||
{
|
||||
@@ -124,7 +143,7 @@ public class SecurityUtil
|
||||
* @return
|
||||
*/
|
||||
public static User getCurrentUser(
|
||||
Provider<? extends SecurityContext> contextProvider)
|
||||
Provider<? extends SecurityContext> contextProvider)
|
||||
{
|
||||
AssertUtil.assertIsNotNull(contextProvider);
|
||||
|
||||
@@ -151,7 +170,7 @@ public class SecurityUtil
|
||||
* @return
|
||||
*/
|
||||
public static boolean isAdmin(
|
||||
Provider<? extends SecurityContext> contextProvider)
|
||||
Provider<? extends SecurityContext> contextProvider)
|
||||
{
|
||||
return isAdmin(contextProvider.get());
|
||||
}
|
||||
@@ -169,7 +188,7 @@ public class SecurityUtil
|
||||
AssertUtil.assertIsNotNull(contextProvider);
|
||||
|
||||
return (contextProvider.getUser() != null)
|
||||
&& contextProvider.getUser().isAdmin();
|
||||
&& contextProvider.getUser().isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,7 +200,7 @@ public class SecurityUtil
|
||||
* @return
|
||||
*/
|
||||
public static boolean isAnonymous(
|
||||
Provider<? extends SecurityContext> contextProvider)
|
||||
Provider<? extends SecurityContext> contextProvider)
|
||||
{
|
||||
return isAnonymous(contextProvider.get());
|
||||
}
|
||||
|
||||
@@ -39,11 +39,17 @@ import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.SCMContext;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.util.AssertUtil;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
import sonia.scm.util.Util;
|
||||
import sonia.scm.web.security.WebSecurityContext;
|
||||
@@ -87,12 +93,23 @@ public class BasicAuthenticationFilter extends HttpFilter
|
||||
*
|
||||
*
|
||||
* @param securityContextProvider
|
||||
* @deprecated use the constructor with out arguments instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public BasicAuthenticationFilter(
|
||||
Provider<WebSecurityContext> securityContextProvider) {}
|
||||
|
||||
/**
|
||||
* Constructs a new basic authenticaton filter
|
||||
*
|
||||
* @param configuration scm-manager global configuration
|
||||
*
|
||||
* @since 1.21
|
||||
*/
|
||||
@Inject
|
||||
public BasicAuthenticationFilter(
|
||||
Provider<WebSecurityContext> securityContextProvider)
|
||||
public BasicAuthenticationFilter(ScmConfiguration configuration)
|
||||
{
|
||||
this.securityContextProvider = securityContextProvider;
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
@@ -110,12 +127,10 @@ public class BasicAuthenticationFilter extends HttpFilter
|
||||
*/
|
||||
@Override
|
||||
protected void doFilter(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException
|
||||
HttpServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
WebSecurityContext securityContext = securityContextProvider.get();
|
||||
|
||||
AssertUtil.assertIsNotNull(securityContext);
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
|
||||
User user = null;
|
||||
String authentication = request.getHeader(HEADER_AUTHORIZATION);
|
||||
@@ -127,7 +142,7 @@ public class BasicAuthenticationFilter extends HttpFilter
|
||||
logger.trace("found basic authorization header, start authentication");
|
||||
}
|
||||
|
||||
user = authenticate(request, response, securityContext, authentication);
|
||||
user = authenticate(request, response, subject, authentication);
|
||||
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
@@ -141,14 +156,20 @@ public class BasicAuthenticationFilter extends HttpFilter
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (securityContext.isAuthenticated())
|
||||
else if (subject.isAuthenticated())
|
||||
{
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("user is allready authenticated");
|
||||
}
|
||||
|
||||
user = securityContext.getUser();
|
||||
user = subject.getPrincipals().oneByType(User.class);
|
||||
}
|
||||
else if ((configuration != null)
|
||||
&& configuration.isAnonymousAccessEnabled())
|
||||
{
|
||||
user = SCMContext.ANONYMOUS;
|
||||
|
||||
}
|
||||
|
||||
if (user == null)
|
||||
@@ -158,12 +179,12 @@ public class BasicAuthenticationFilter extends HttpFilter
|
||||
logger.trace("could not find user send unauthorized");
|
||||
}
|
||||
|
||||
HttpUtil.sendUnauthorized(request, response);
|
||||
handleUnauthorized(request, response, chain);
|
||||
}
|
||||
else
|
||||
{
|
||||
chain.doFilter(new SecurityHttpServletRequestWrapper(request, user),
|
||||
response);
|
||||
response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,9 +202,8 @@ public class BasicAuthenticationFilter extends HttpFilter
|
||||
* @since 1.8
|
||||
*/
|
||||
protected void handleUnauthorized(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain chain)
|
||||
throws IOException, ServletException
|
||||
HttpServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
HttpUtil.sendUnauthorized(request, response);
|
||||
}
|
||||
@@ -195,14 +215,13 @@ public class BasicAuthenticationFilter extends HttpFilter
|
||||
* @param request
|
||||
* @param response
|
||||
* @param securityContext
|
||||
* @param subject
|
||||
* @param authentication
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private User authenticate(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
WebSecurityContext securityContext,
|
||||
String authentication)
|
||||
HttpServletResponse response, Subject subject, String authentication)
|
||||
{
|
||||
String token = authentication.substring(6);
|
||||
|
||||
@@ -223,8 +242,25 @@ public class BasicAuthenticationFilter extends HttpFilter
|
||||
logger.trace("try to authenticate user {}", username);
|
||||
}
|
||||
|
||||
user = securityContext.authenticate(request, response, username,
|
||||
password);
|
||||
try
|
||||
{
|
||||
|
||||
subject.login(new UsernamePasswordToken(username, password,
|
||||
request.getRemoteAddr()));
|
||||
user = subject.getPrincipals().oneByType(User.class);
|
||||
}
|
||||
catch (AuthenticationException ex)
|
||||
{
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("authentication failed for user ".concat(username),
|
||||
ex);
|
||||
}
|
||||
else if (logger.isWarnEnabled())
|
||||
{
|
||||
logger.warn("authentication failed for user {}", username);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (logger.isWarnEnabled())
|
||||
{
|
||||
@@ -242,5 +278,5 @@ public class BasicAuthenticationFilter extends HttpFilter
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private Provider<WebSecurityContext> securityContextProvider;
|
||||
private ScmConfiguration configuration;
|
||||
}
|
||||
|
||||
@@ -38,18 +38,18 @@ package sonia.scm.web.filter;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.ArgumentIsInvalidException;
|
||||
import sonia.scm.SCMContext;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.repository.PermissionType;
|
||||
import sonia.scm.repository.PermissionUtil;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.security.ScmSecurityException;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.util.AssertUtil;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
import sonia.scm.util.Util;
|
||||
import sonia.scm.web.security.WebSecurityContext;
|
||||
@@ -78,6 +78,18 @@ public abstract class PermissionFilter extends HttpFilter
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs a new permission filter
|
||||
*
|
||||
* @param configuration global scm-manager configuration
|
||||
*
|
||||
* @since 1.21
|
||||
*/
|
||||
public PermissionFilter(ScmConfiguration configuration)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
@@ -85,12 +97,13 @@ public abstract class PermissionFilter extends HttpFilter
|
||||
*
|
||||
* @param configuration
|
||||
* @param securityContextProvider
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public PermissionFilter(ScmConfiguration configuration,
|
||||
Provider<WebSecurityContext> securityContextProvider)
|
||||
Provider<WebSecurityContext> securityContextProvider)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
this.securityContextProvider = securityContextProvider;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
@@ -130,97 +143,81 @@ public abstract class PermissionFilter extends HttpFilter
|
||||
*/
|
||||
@Override
|
||||
protected void doFilter(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException
|
||||
HttpServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
WebSecurityContext securityContext = securityContextProvider.get();
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
|
||||
AssertUtil.assertIsNotNull(securityContext);
|
||||
|
||||
User user = securityContext.getUser();
|
||||
|
||||
if (user != null)
|
||||
try
|
||||
{
|
||||
try
|
||||
Repository repository = getRepository(request);
|
||||
|
||||
if (repository != null)
|
||||
{
|
||||
Repository repository = getRepository(request);
|
||||
boolean writeRequest = isWriteRequest(request);
|
||||
|
||||
if (repository != null)
|
||||
if (hasPermission(repository, writeRequest))
|
||||
{
|
||||
boolean writeRequest = isWriteRequest(request);
|
||||
|
||||
if (hasPermission(repository, securityContext, writeRequest))
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("{} access to repository {} for user {} granted",
|
||||
new Object[] { writeRequest
|
||||
? "write"
|
||||
: "read", repository.getName(),
|
||||
user.getName() });
|
||||
}
|
||||
|
||||
chain.doFilter(request, response);
|
||||
logger.trace("{} access to repository {} for user {} granted",
|
||||
new Object[] { writeRequest
|
||||
? "write"
|
||||
: "read", repository.getName(), subject.getPrincipal() });
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.info("{} access to repository {} for user {} denied",
|
||||
new Object[] { writeRequest
|
||||
? "write"
|
||||
: "read", repository.getName(),
|
||||
user.getName() });
|
||||
}
|
||||
|
||||
sendAccessDenied(response, user);
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.debug("repository not found");
|
||||
logger.info("{} access to repository {} for user {} denied",
|
||||
new Object[] { writeRequest
|
||||
? "write"
|
||||
: "read", repository.getName(), subject.getPrincipal() });
|
||||
}
|
||||
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
sendAccessDenied(response, subject);
|
||||
}
|
||||
}
|
||||
catch (ArgumentIsInvalidException ex)
|
||||
else
|
||||
{
|
||||
if (logger.isTraceEnabled())
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.trace(
|
||||
"wrong request at ".concat(request.getRequestURI()).concat(
|
||||
" send redirect"), ex);
|
||||
}
|
||||
else if (logger.isWarnEnabled())
|
||||
{
|
||||
logger.warn("wrong request at {} send redirect",
|
||||
request.getRequestURI());
|
||||
logger.debug("repository not found");
|
||||
}
|
||||
|
||||
response.sendRedirect(getRepositoryRootHelpUrl(request));
|
||||
}
|
||||
catch (ScmSecurityException ex)
|
||||
{
|
||||
if (logger.isWarnEnabled())
|
||||
{
|
||||
logger.warn("user {} has not enough permissions", user.getName());
|
||||
}
|
||||
|
||||
sendAccessDenied(response, user);
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (ArgumentIsInvalidException ex)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.debug("user in not authenticated");
|
||||
logger.trace(
|
||||
"wrong request at ".concat(request.getRequestURI()).concat(
|
||||
" send redirect"), ex);
|
||||
}
|
||||
else if (logger.isWarnEnabled())
|
||||
{
|
||||
logger.warn("wrong request at {} send redirect",
|
||||
request.getRequestURI());
|
||||
}
|
||||
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN);
|
||||
response.sendRedirect(getRepositoryRootHelpUrl(request));
|
||||
}
|
||||
catch (ScmSecurityException ex)
|
||||
{
|
||||
if (logger.isWarnEnabled())
|
||||
{
|
||||
logger.warn("user {} has not enough permissions",
|
||||
subject.getPrincipal());
|
||||
}
|
||||
|
||||
sendAccessDenied(response, subject);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,8 +231,8 @@ public abstract class PermissionFilter extends HttpFilter
|
||||
private String extractType(HttpServletRequest request)
|
||||
{
|
||||
Iterator<String> it = Splitter.on(
|
||||
HttpUtil.SEPARATOR_PATH).omitEmptyStrings().split(
|
||||
request.getRequestURI()).iterator();
|
||||
HttpUtil.SEPARATOR_PATH).omitEmptyStrings().split(
|
||||
request.getRequestURI()).iterator();
|
||||
String type = it.next();
|
||||
|
||||
if (Util.isNotEmpty(request.getContextPath()))
|
||||
@@ -252,19 +249,20 @@ public abstract class PermissionFilter extends HttpFilter
|
||||
*
|
||||
* @param response
|
||||
* @param user
|
||||
* @param subject
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private void sendAccessDenied(HttpServletResponse response, User user)
|
||||
throws IOException
|
||||
private void sendAccessDenied(HttpServletResponse response, Subject subject)
|
||||
throws IOException
|
||||
{
|
||||
if (SCMContext.USER_ANONYMOUS.equals(user.getName()))
|
||||
if (subject.isAuthenticated())
|
||||
{
|
||||
HttpUtil.sendUnauthorized(response);
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN);
|
||||
HttpUtil.sendUnauthorized(response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,21 +297,18 @@ public abstract class PermissionFilter extends HttpFilter
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private boolean hasPermission(Repository repository,
|
||||
WebSecurityContext securityContext,
|
||||
boolean writeRequest)
|
||||
private boolean hasPermission(Repository repository, boolean writeRequest)
|
||||
{
|
||||
boolean permitted = false;
|
||||
|
||||
if (writeRequest)
|
||||
{
|
||||
permitted = PermissionUtil.isWritable(configuration, repository,
|
||||
securityContext);
|
||||
permitted = PermissionUtil.isWritable(configuration, repository);
|
||||
}
|
||||
else
|
||||
{
|
||||
permitted = PermissionUtil.hasPermission(repository, securityContext,
|
||||
PermissionType.READ);
|
||||
permitted = PermissionUtil.hasPermission(configuration, repository,
|
||||
PermissionType.READ);
|
||||
}
|
||||
|
||||
return permitted;
|
||||
@@ -321,9 +316,6 @@ public abstract class PermissionFilter extends HttpFilter
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
protected Provider<WebSecurityContext> securityContextProvider;
|
||||
|
||||
/** Field description */
|
||||
private ScmConfiguration configuration;
|
||||
}
|
||||
|
||||
@@ -67,6 +67,21 @@ public abstract class ProviderPermissionFilter extends PermissionFilter
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param configuration
|
||||
* @param repositoryProvider
|
||||
* @since 1.21
|
||||
*/
|
||||
public ProviderPermissionFilter(ScmConfiguration configuration,
|
||||
RepositoryProvider repositoryProvider)
|
||||
{
|
||||
super(configuration);
|
||||
this.repositoryProvider = repositoryProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
@@ -75,14 +90,14 @@ public abstract class ProviderPermissionFilter extends PermissionFilter
|
||||
* @param configuration
|
||||
* @param securityContextProvider
|
||||
* @param repositoryProvider
|
||||
* @deprecated
|
||||
*/
|
||||
public ProviderPermissionFilter(
|
||||
ScmConfiguration configuration,
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
RepositoryProvider repositoryProvider)
|
||||
@Deprecated
|
||||
public ProviderPermissionFilter(ScmConfiguration configuration,
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
RepositoryProvider repositoryProvider)
|
||||
{
|
||||
super(configuration, securityContextProvider);
|
||||
this.repositoryProvider = repositoryProvider;
|
||||
this(configuration, repositoryProvider);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
@@ -107,7 +122,7 @@ public abstract class ProviderPermissionFilter extends PermissionFilter
|
||||
catch (ProvisionException ex)
|
||||
{
|
||||
Throwables.propagateIfInstanceOf(ex.getCause(),
|
||||
IllegalStateException.class);
|
||||
IllegalStateException.class);
|
||||
|
||||
if (logger.isErrorEnabled())
|
||||
{
|
||||
|
||||
@@ -71,15 +71,31 @@ public abstract class RegexPermissionFilter extends PermissionFilter
|
||||
* @param securityContextProvider
|
||||
* @param repositoryManager
|
||||
*/
|
||||
public RegexPermissionFilter(
|
||||
ScmConfiguration configuration,
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
RepositoryManager repositoryManager)
|
||||
public RegexPermissionFilter(ScmConfiguration configuration,
|
||||
RepositoryManager repositoryManager)
|
||||
{
|
||||
super(configuration, securityContextProvider);
|
||||
super(configuration);
|
||||
this.repositoryManager = repositoryManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param configuration
|
||||
* @param securityContextProvider
|
||||
* @param repositoryManager
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public RegexPermissionFilter(ScmConfiguration configuration,
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
RepositoryManager repositoryManager)
|
||||
{
|
||||
this(configuration, repositoryManager);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,11 +44,14 @@ import java.util.Collection;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @deprecated use {@link SecurityUtils#getSecurityManager()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface WebSecurityContext extends SecurityContext
|
||||
{
|
||||
|
||||
|
||||
Reference in New Issue
Block a user