implement permission collector

This commit is contained in:
Sebastian Sdorra
2013-05-26 12:26:25 +02:00
parent f7dece4696
commit d2097bda05
4 changed files with 276 additions and 140 deletions

View File

@@ -42,6 +42,8 @@ import com.google.inject.servlet.RequestScoped;
import com.google.inject.servlet.ServletModule;
import com.google.inject.throwingproviders.ThrowingProviderBinder;
import org.apache.shiro.authz.permission.PermissionResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -90,6 +92,7 @@ import sonia.scm.security.DefaultSecuritySystem;
import sonia.scm.security.EncryptionHandler;
import sonia.scm.security.KeyGenerator;
import sonia.scm.security.MessageDigestEncryptionHandler;
import sonia.scm.security.RepositoryPermissionResolver;
import sonia.scm.security.SecurityContext;
import sonia.scm.security.SecuritySystem;
import sonia.scm.store.BlobStoreFactory;
@@ -273,6 +276,7 @@ public class ScmServletModule extends ServletModule
pluginLoader.processExtensions(binder());
// bind security stuff
bind(PermissionResolver.class, RepositoryPermissionResolver.class);
bind(AuthenticationManager.class, ChainAuthenticatonManager.class);
bind(SecurityContext.class).to(BasicSecurityContext.class);
bind(WebSecurityContext.class).to(BasicSecurityContext.class);

View File

@@ -0,0 +1,259 @@
/**
* 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.Predicate;
import com.google.common.collect.ImmutableList.Builder;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.permission.PermissionResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.group.GroupNames;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryDAO;
import sonia.scm.user.User;
import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------
import java.util.List;
/**
*
* @author Sebastian Sdorra
*/
@Singleton
public class PermissionCollector
{
/**
* the logger for PermissionCollector
*/
private static final Logger logger =
LoggerFactory.getLogger(PermissionCollector.class);
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param repositoryDAO
* @param securitySystem
* @param resolver
*/
@Inject
public PermissionCollector(RepositoryDAO repositoryDAO,
SecuritySystem securitySystem, PermissionResolver resolver)
{
this.repositoryDAO = repositoryDAO;
this.securitySystem = securitySystem;
this.resolver = resolver;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param user
* @param groups
*
* @return
*/
public List<Permission> collect(User user, GroupNames groups)
{
Builder<Permission> builder = new Builder<Permission>();
collectRepositoryPermissions(builder, user, groups);
collectGlobalPermissions(builder, user, groups);
return builder.build();
}
/**
* Method description
*
*
*
* @param builder
* @param user
* @param groups
*
* @return
*/
private void collectGlobalPermissions(Builder<Permission> builder,
final User user, final GroupNames groups)
{
if (logger.isTraceEnabled())
{
logger.trace("collect global permissions for user {}", user.getName());
}
List<StoredAssignedPermission> globalPermissions =
securitySystem.getPermissions(new Predicate<AssignedPermission>()
{
@Override
public boolean apply(AssignedPermission input)
{
return isUserPermission(user, groups, input);
}
});
for (StoredAssignedPermission gp : globalPermissions)
{
if (logger.isTraceEnabled())
{
logger.trace("add permission {} for user {}", gp.getPermission(),
user.getName());
}
Permission permission = resolver.resolvePermission(gp.getPermission());
if (permission != null)
{
builder.add(permission);
}
}
}
/**
* Method description
*
*
*
* @param builder
* @param user
* @param groups
*
* @return
*/
private void collectRepositoryPermissions(Builder<Permission> builder,
User user, GroupNames groups)
{
for (Repository repository : repositoryDAO.getAll())
{
if (logger.isTraceEnabled())
{
logger.trace("collect permissions for repository {} and user {}",
repository.getName(), user.getName());
}
collectRepositoryPermissions(builder, repository, user, groups);
}
}
/**
* Method description
*
*
* @param permissions
*
* @param builder
* @param repository
* @param user
* @param groups
*/
private void collectRepositoryPermissions(Builder<Permission> builder,
Repository repository, User user, GroupNames groups)
{
List<sonia.scm.repository.Permission> repositoryPermissions =
repository.getPermissions();
if (Util.isNotEmpty(repositoryPermissions))
{
for (sonia.scm.repository.Permission permission : repositoryPermissions)
{
if (isUserPermission(user, groups, permission))
{
RepositoryPermission rp = new RepositoryPermission(repository,
permission.getType());
if (logger.isTraceEnabled())
{
logger.trace("add repository permission {} for user {}", rp,
user.getName());
}
builder.add(rp);
}
}
}
else if (logger.isTraceEnabled())
{
logger.trace("repository {} has not permission entries",
repository.getName());
}
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param user
* @param groups
* @param perm
*
* @return
*/
private boolean isUserPermission(User user, GroupNames groups,
PermissionObject perm)
{
//J-
return (perm.isGroupPermission() && groups.contains(perm.getName()))
|| ((!perm.isGroupPermission()) && user.getName().equals(perm.getName()));
//J+
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private RepositoryDAO repositoryDAO;
/** Field description */
private PermissionResolver resolver;
/** Field description */
private SecuritySystem securitySystem;
}

View File

@@ -36,7 +36,6 @@ package sonia.scm.security;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.eventbus.Subscribe;
@@ -70,10 +69,7 @@ import sonia.scm.event.Subscriber;
import sonia.scm.group.Group;
import sonia.scm.group.GroupManager;
import sonia.scm.group.GroupNames;
import sonia.scm.repository.Permission;
import sonia.scm.repository.PermissionType;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryDAO;
import sonia.scm.repository.RepositoryEvent;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.user.User;
@@ -130,6 +126,7 @@ public class ScmRealm extends AuthorizingRealm
*
* @param configuration
* @param securitySystem
* @param collector
* @param cacheManager
* @param userManager
* @param groupManager
@@ -142,18 +139,16 @@ public class ScmRealm extends AuthorizingRealm
*/
@Inject
public ScmRealm(ScmConfiguration configuration,
SecuritySystem securitySystem, CacheManager cacheManager,
UserManager userManager, GroupManager groupManager,
RepositoryDAO repositoryDAO, UserDAO userDAO,
PermissionCollector collector, CacheManager cacheManager,
UserManager userManager, GroupManager groupManager, UserDAO userDAO,
AuthenticationManager authenticator, RepositoryManager manager,
Provider<HttpServletRequest> requestProvider,
Provider<HttpServletResponse> responseProvider)
{
this.configuration = configuration;
this.securitySystem = securitySystem;
this.collector = collector;
this.userManager = userManager;
this.groupManager = groupManager;
this.repositoryDAO = repositoryDAO;
this.userDAO = userDAO;
this.authenticator = authenticator;
this.requestProvider = requestProvider;
@@ -499,121 +494,6 @@ public class ScmRealm extends AuthorizingRealm
}
}
/**
* Method description
*
*
* @param user
* @param groups
*
* @return
*/
private List<String> collectGlobalPermissions(final User user,
final GroupNames groups)
{
if (logger.isTraceEnabled())
{
logger.trace("collect global permissions for user {}", user.getName());
}
List<String> permissions = Lists.newArrayList();
List<StoredAssignedPermission> globalPermissions =
securitySystem.getPermissions(new Predicate<AssignedPermission>()
{
@Override
public boolean apply(AssignedPermission input)
{
return isUserPermission(user, groups, input);
}
});
for (StoredAssignedPermission gp : globalPermissions)
{
if (logger.isTraceEnabled())
{
logger.trace("add permission {} for user {}", gp.getPermission(),
user.getName());
}
permissions.add(gp.getPermission());
}
return permissions;
}
/**
* Method description
*
*
* @param user
* @param groups
*
* @return
*/
private List<org.apache.shiro.authz.Permission> collectRepositoryPermissions(
User user, GroupNames groups)
{
List<org.apache.shiro.authz.Permission> permissions = Lists.newArrayList();
for (Repository repository : repositoryDAO.getAll())
{
if (logger.isTraceEnabled())
{
logger.trace("collect permissions for repository {} and user {}",
repository.getName(), user.getName());
}
collectRepositoryPermissions(permissions, repository, user, groups);
}
return permissions;
}
/**
* Method description
*
*
* @param permissions
* @param repository
* @param user
* @param groups
*/
private void collectRepositoryPermissions(
List<org.apache.shiro.authz.Permission> permissions, Repository repository,
User user, GroupNames groups)
{
List<Permission> repositoryPermissions = repository.getPermissions();
if (Util.isNotEmpty(repositoryPermissions))
{
for (Permission permission : repositoryPermissions)
{
if (isUserPermission(user, groups, permission))
{
RepositoryPermission rp = new RepositoryPermission(repository,
permission.getType());
if (logger.isTraceEnabled())
{
logger.trace("add repository permission {} for user {}", rp,
user.getName());
}
permissions.add(rp);
}
}
}
else if (logger.isTraceEnabled())
{
logger.trace("repository {} has not permission entries",
repository.getName());
}
}
/**
* Method description
*
@@ -674,19 +554,13 @@ public class ScmRealm extends AuthorizingRealm
}
else
{
permissions = collectRepositoryPermissions(user, groups);
globalPermissions = collectGlobalPermissions(user, groups);
permissions = collector.collect(user, groups);
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
info.addObjectPermissions(permissions);
if (globalPermissions != null)
{
info.addStringPermissions(globalPermissions);
}
return info;
}
@@ -830,24 +704,21 @@ public class ScmRealm extends AuthorizingRealm
/** Field description */
private Cache<String, AuthorizationInfo> cache;
/** Field description */
private PermissionCollector collector;
/** Field description */
private ScmConfiguration configuration;
/** Field description */
private GroupManager groupManager;
/** Field description */
private RepositoryDAO repositoryDAO;
/** Field description */
private Provider<HttpServletRequest> requestProvider;
/** Field description */
private Provider<HttpServletResponse> responseProvider;
/** Field description */
private SecuritySystem securitySystem;
/** Field description */
private UserDAO userDAO;