Package org.sonatype.security.realms.tools

Source Code of org.sonatype.security.realms.tools.ResourceMergingConfigurationManager

/*
* Sonatype Nexus (TM) Open Source Version
* Copyright (c) 2007-2014 Sonatype, Inc.
* All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
*
* This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
* which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
*
* Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
* of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
* Eclipse Foundation. All other trademarks are the property of their respective owners.
*/
package org.sonatype.security.realms.tools;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.enterprise.inject.Typed;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;

import org.sonatype.configuration.validation.InvalidConfigurationException;
import org.sonatype.security.authorization.NoSuchPrivilegeException;
import org.sonatype.security.authorization.NoSuchRoleException;
import org.sonatype.security.model.CPrivilege;
import org.sonatype.security.model.CRole;
import org.sonatype.security.model.CUser;
import org.sonatype.security.model.CUserRoleMapping;
import org.sonatype.security.model.Configuration;
import org.sonatype.security.realms.privileges.PrivilegeDescriptor;
import org.sonatype.security.realms.validator.SecurityValidationContext;
import org.sonatype.security.usermanagement.UserNotFoundException;
import org.sonatype.security.usermanagement.xml.SecurityXmlUserManager;
import org.sonatype.sisu.goodies.eventbus.EventBus;

import org.codehaus.plexus.util.StringUtils;

/**
* ConfigurationManager that aggregates {@link StaticSecurityResource}s and {@link DynamicSecurityResource}s with
* default ConfigurationManager.
*
* @author Brian Demers
*/
@Singleton
@Typed(ConfigurationManager.class)
@Named("resourceMerging")
public class ResourceMergingConfigurationManager
    extends AbstractConfigurationManager
{
  // This will handle all normal security.xml file loading/storing
  private final ConfigurationManager manager;

  private final List<StaticSecurityResource> staticResources;

  private final List<DynamicSecurityResource> dynamicResources;

  @Inject
  public ResourceMergingConfigurationManager(EventBus eventBus,
                                             List<DynamicSecurityResource> dynamicResources,
                                             @Named("legacydefault") ConfigurationManager manager,
                                             List<StaticSecurityResource> staticResources)
  {
    super(eventBus);
    this.dynamicResources = dynamicResources;
    this.manager = manager;
    this.staticResources = staticResources;
  }

  public void runRead(ConfigurationManagerAction action)
      throws Exception
  {
    //No support for this
    throw new UnsupportedOperationException(
        "Concurrent access not supported. ConcurrentConfigurationManager should be used instead");
  }

  public void runWrite(ConfigurationManagerAction action)
      throws Exception
  {
    //No support for this
    throw new UnsupportedOperationException(
        "Concurrent access not supported. ConcurrentConfigurationManager should be used instead");
  }

  public void clearCache() {
    super.clearCache();
    manager.clearCache();
  }

  public void createPrivilege(CPrivilege privilege)
      throws InvalidConfigurationException
  {
    manager.createPrivilege(privilege, initializeContext());
  }

  public void createPrivilege(CPrivilege privilege, SecurityValidationContext context)
      throws InvalidConfigurationException
  {
    if (context == null) {
      context = initializeContext();
    }

    // The static config can't be updated, so delegate to xml file
    manager.createPrivilege(privilege, context);
  }

  public void createRole(CRole role)
      throws InvalidConfigurationException
  {
    manager.createRole(role, initializeContext());
  }

  public void createRole(CRole role, SecurityValidationContext context)
      throws InvalidConfigurationException
  {
    if (context == null) {
      context = initializeContext();
    }

    // The static config can't be updated, so delegate to xml file
    manager.createRole(role, context);
  }

  public void createUser(CUser user, Set<String> roles)
      throws InvalidConfigurationException
  {
    manager.createUser(user, roles, initializeContext());
  }

  public void createUser(CUser user, String password, Set<String> roles)
      throws InvalidConfigurationException
  {
    manager.createUser(user, password, roles, initializeContext());
  }

  public void createUser(CUser user, Set<String> roles, SecurityValidationContext context)
      throws InvalidConfigurationException
  {
    createUser(user, null, roles, context);
  }

  public void createUser(CUser user, String password, Set<String> roles, SecurityValidationContext context)
      throws InvalidConfigurationException
  {
    if (context == null) {
      context = initializeContext();
    }

    // The static config can't be updated, so delegate to xml file
    manager.createUser(user, password, roles, context);
  }

  public void deletePrivilege(String id)
      throws NoSuchPrivilegeException
  {
    // The static config can't be updated, so delegate to xml file
    manager.deletePrivilege(id);
  }

  public void deleteRole(String id)
      throws NoSuchRoleException
  {
    // The static config can't be updated, so delegate to xml file
    manager.deleteRole(id);
  }

  public void deleteUser(String id)
      throws UserNotFoundException
  {
    // The static config can't be updated, so delegate to xml file
    manager.deleteUser(id);
  }

  public String getPrivilegeProperty(CPrivilege privilege, String key) {
    return manager.getPrivilegeProperty(privilege, key);
  }

  public String getPrivilegeProperty(String id, String key)
      throws NoSuchPrivilegeException
  {
    return manager.getPrivilegeProperty(id, key);
  }

  public SecurityValidationContext initializeContext() {
    SecurityValidationContext context = new SecurityValidationContext();

    context.addExistingUserIds();
    context.addExistingRoleIds();
    context.addExistingPrivilegeIds();

    List<CUser> users = new ArrayList<CUser>(listUsers());
    for (CUser user : users) {
      context.getExistingUserIds().add(user.getId());

      context.getExistingEmailMap().put(user.getId(), user.getEmail());
    }

    List<CRole> roles = new ArrayList<CRole>(listRoles());
    for (CRole role : roles) {
      context.getExistingRoleIds().add(role.getId());

      ArrayList<String> containedRoles = new ArrayList<String>();

      containedRoles.addAll(role.getRoles());

      context.getRoleContainmentMap().put(role.getId(), containedRoles);

      context.getExistingRoleNameMap().put(role.getId(), role.getName());
    }

    List<CPrivilege> privs = new ArrayList<CPrivilege>(listPrivileges());
    for (CPrivilege priv : privs) {
      context.getExistingPrivilegeIds().add(priv.getId());
    }

    return context;
  }

  public List<CPrivilege> listPrivileges() {
    List<CPrivilege> list = new ArrayList<CPrivilege>(manager.listPrivileges());

    for (CPrivilege item : (List<CPrivilege>) getConfiguration().getPrivileges()) {
      // ALL privileges that come from StaticSecurityResources are NOT editable
      // only roles defined in the security.xml can be updated.
      item.setReadOnly(true);
      list.add(item);
    }

    return list;
  }

  public List<CRole> listRoles() {
    List<CRole> list = new ArrayList<CRole>(manager.listRoles());

    for (CRole item : (List<CRole>) getConfiguration().getRoles()) {
      CRole role = item;
      // ALL roles that come from StaticSecurityResources are NOT editable
      // only roles defined in the security.xml can be updated.
      item.setReadOnly(true);
      list.add(role);
    }

    return list;
  }

  private CRole mergeRolesContents(CRole roleA, CRole roleB) {
    // ROLES
    Set<String> roles = new HashSet<String>();
    // make sure they are not empty
    if (roleA.getRoles() != null) {
      roles.addAll(roleA.getRoles());
    }
    if (roleB.getRoles() != null) {
      roles.addAll(roleB.getRoles());
    }

    // PRIVS
    Set<String> privs = new HashSet<String>();
    // make sure they are not empty
    if (roleA.getPrivileges() != null) {
      privs.addAll(roleA.getPrivileges());
    }
    if (roleB.getPrivileges() != null) {
      privs.addAll(roleB.getPrivileges());
    }

    CRole newRole = new CRole();
    newRole.setId(roleA.getId());
    newRole.setRoles(new ArrayList<String>(roles));
    newRole.setPrivileges(new ArrayList<String>(privs));

    // now for the name and description
    if (StringUtils.isNotEmpty(roleA.getName())) {
      newRole.setName(roleA.getName());
    }
    else {
      newRole.setName(roleB.getName());
    }

    if (StringUtils.isNotEmpty(roleA.getDescription())) {
      newRole.setDescription(roleA.getDescription());
    }
    else {
      newRole.setDescription(roleB.getDescription());
    }

    // and session timeout (which we don't use)
    if (roleA.getSessionTimeout() > roleB.getSessionTimeout()) {
      newRole.setSessionTimeout(roleA.getSessionTimeout());
    }
    else {
      newRole.setSessionTimeout(roleB.getSessionTimeout());
    }

    return newRole;
  }

  public List<CUser> listUsers() {
    return manager.listUsers();
  }

  public CPrivilege readPrivilege(String id)
      throws NoSuchPrivilegeException
  {
    final CPrivilege privilege = getConfiguration().getPrivilegeById(id);

    if (privilege != null) {
      privilege.setReadOnly(true);

      return privilege;
    }
    else {
      return manager.readPrivilege(id);
    }
  }

  public CRole readRole(String id)
      throws NoSuchRoleException
  {
    final CRole role = getConfiguration().getRoleById(id);

    if (role != null) {
      role.setReadOnly(true);

      return role;
    }
    else {
      // nothing found in static, try the original source, will throw if nothing is found
      return manager.readRole(id);
    }
  }

  public CUser readUser(String id)
      throws UserNotFoundException
  {
    // users can only come from the security.xml
    return manager.readUser(id);
  }

  public void createUserRoleMapping(CUserRoleMapping userRoleMapping, SecurityValidationContext context)
      throws InvalidConfigurationException
  {
    if (context == null) {
      context = this.initializeContext();
    }

    manager.createUserRoleMapping(userRoleMapping, context);
  }

  public void createUserRoleMapping(CUserRoleMapping userRoleMapping)
      throws InvalidConfigurationException
  {
    manager.createUserRoleMapping(userRoleMapping, initializeContext());
  }

  public void deleteUserRoleMapping(String userId, String source)
      throws NoSuchRoleMappingException
  {
    manager.deleteUserRoleMapping(userId, source);
  }

  public List<CUserRoleMapping> listUserRoleMappings() {
    return manager.listUserRoleMappings();
  }

  public CUserRoleMapping readUserRoleMapping(String userId, String source)
      throws NoSuchRoleMappingException
  {
    return manager.readUserRoleMapping(userId, source);
  }

  public void updateUserRoleMapping(CUserRoleMapping userRoleMapping, SecurityValidationContext context)
      throws InvalidConfigurationException, NoSuchRoleMappingException
  {
    if (context == null) {
      context = this.initializeContext();
    }

    manager.updateUserRoleMapping(userRoleMapping, context);
  }

  public void updateUserRoleMapping(CUserRoleMapping userRoleMapping)
      throws InvalidConfigurationException, NoSuchRoleMappingException
  {
    updateUserRoleMapping(userRoleMapping, initializeContext());
  }

  public void updatePrivilege(CPrivilege privilege)
      throws InvalidConfigurationException, NoSuchPrivilegeException
  {
    manager.updatePrivilege(privilege, initializeContext());
  }

  public void updatePrivilege(CPrivilege privilege, SecurityValidationContext context)
      throws InvalidConfigurationException, NoSuchPrivilegeException
  {
    if (context == null) {
      context = initializeContext();
    }

    // The static config can't be updated, so delegate to xml file
    manager.updatePrivilege(privilege, context);
  }

  public void updateRole(CRole role)
      throws InvalidConfigurationException, NoSuchRoleException
  {
    manager.updateRole(role, initializeContext());
  }

  public void updateRole(CRole role, SecurityValidationContext context)
      throws InvalidConfigurationException, NoSuchRoleException
  {
    if (context == null) {
      context = initializeContext();
    }

    // The static config can't be updated, so delegate to xml file
    manager.updateRole(role, context);
  }

  public void updateUser(CUser user)
      throws InvalidConfigurationException, UserNotFoundException
  {
    Set<String> roles = new HashSet<String>();
    try {
      CUserRoleMapping userRoleMapping = this.readUserRoleMapping(user.getId(), SecurityXmlUserManager.SOURCE);
      roles.addAll(userRoleMapping.getRoles());
    }
    catch (NoSuchRoleMappingException e) {
      this.log.debug("User: {} has no roles", user.getId());
    }
    this.updateUser(user, new HashSet<String>(roles));
  }

  public void updateUser(CUser user, Set<String> roles)
      throws InvalidConfigurationException, UserNotFoundException
  {
    manager.updateUser(user, roles, initializeContext());
  }

  public void updateUser(CUser user, Set<String> roles, SecurityValidationContext context)
      throws InvalidConfigurationException, UserNotFoundException
  {
    if (context == null) {
      context = initializeContext();
    }

    // The static config can't be updated, so delegate to xml file
    manager.updateUser(user, roles, context);
  }

  public List<PrivilegeDescriptor> listPrivilegeDescriptors() {
    return manager.listPrivilegeDescriptors();
  }

  public void cleanRemovedPrivilege(String privilegeId) {
    manager.cleanRemovedPrivilege(privilegeId);
  }

  public void cleanRemovedRole(String roleId) {
    manager.cleanRemovedRole(roleId);
  }

  // ==

  public void save() {
    // The static config can't be updated, so delegate to xml file
    manager.save();
  }

  // ==

  @Override
  protected boolean shouldRebuildConfiguration() {
    for (DynamicSecurityResource resource : dynamicResources) {
      if (resource.isDirty()) {
        return true;
      }
    }
    return false;
  }

  protected Configuration doGetConfiguration() {
    final Configuration configuration = new Configuration();

    for (StaticSecurityResource resource : staticResources) {
      Configuration resConfig = resource.getConfiguration();

      if (resConfig != null) {
        appendConfig(configuration, resConfig);
      }
    }

    for (DynamicSecurityResource resource : dynamicResources) {
      Configuration resConfig = resource.getConfiguration();

      if (resConfig != null) {
        appendConfig(configuration, resConfig);
      }
    }

    return configuration;
  }

  private Configuration appendConfig(final Configuration configuration, final Configuration config) {
    for (CPrivilege privilege : (List<CPrivilege>) config.getPrivileges()) {
      configuration.addPrivilege(privilege);
    }

    // number of roles can be significant (>15K), so need to speedup lookup roles by roleId
    final Map<String, CRole> roles = new HashMap<String, CRole>();
    for (CRole role : configuration.getRoles()) {
      roles.put(role.getId(), role);
    }

    for (Iterator<CRole> iterator = config.getRoles().iterator(); iterator.hasNext(); ) {
      CRole role = iterator.next();

      // need to check if we need to merge the static config
      CRole eachRole = roles.get(role.getId());
      if (eachRole != null) {
        role = this.mergeRolesContents(role, eachRole);
        configuration.removeRole(eachRole);
      }

      configuration.addRole(role);
      roles.put(role.getId(), role); // deduplicate config roles
    }

    for (CUser user : (List<CUser>) config.getUsers()) {
      configuration.addUser(user);
    }

    return configuration;
  }
}
TOP

Related Classes of org.sonatype.security.realms.tools.ResourceMergingConfigurationManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.