Package org.sonatype.security.rest

Source Code of org.sonatype.security.rest.AbstractSecurityPlexusResource

/*
* 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.rest;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;

import org.sonatype.configuration.validation.InvalidConfigurationException;
import org.sonatype.configuration.validation.ValidationMessage;
import org.sonatype.configuration.validation.ValidationResponse;
import org.sonatype.nexus.rest.model.AliasingListConverter;
import org.sonatype.nexus.rest.model.HtmlUnescapeStringConverter;
import org.sonatype.plexus.rest.ReferenceFactory;
import org.sonatype.plexus.rest.resource.AbstractPlexusResource;
import org.sonatype.plexus.rest.resource.PlexusResourceException;
import org.sonatype.plexus.rest.resource.error.ErrorMessage;
import org.sonatype.plexus.rest.resource.error.ErrorResponse;
import org.sonatype.security.SecuritySystem;
import org.sonatype.security.authorization.AuthorizationManager;
import org.sonatype.security.authorization.NoSuchAuthorizationManagerException;
import org.sonatype.security.authorization.NoSuchRoleException;
import org.sonatype.security.authorization.Role;
import org.sonatype.security.rest.model.PlexusRoleResource;
import org.sonatype.security.rest.model.PlexusUserResource;
import org.sonatype.security.rest.model.RoleAndPrivilegeListFilterResource;
import org.sonatype.security.rest.model.RoleAndPrivilegeListResource;
import org.sonatype.security.rest.model.RoleResource;
import org.sonatype.security.rest.model.UserChangePasswordResource;
import org.sonatype.security.rest.model.UserResource;
import org.sonatype.security.usermanagement.DefaultUser;
import org.sonatype.security.usermanagement.RoleIdentifier;
import org.sonatype.security.usermanagement.User;
import org.sonatype.security.usermanagement.UserStatus;

import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import org.apache.commons.lang.StringEscapeUtils;
import org.restlet.data.Reference;
import org.restlet.data.Request;
import org.restlet.data.Status;

/**
* Base class of SecurityPlexusResources. Contains error handling util methods and conversion between DTO and
* persistence model.
*
* @author bdemers
*/
@Produces({"application/xml", "application/json"})
@Consumes({"application/xml", "application/json"})
public abstract class AbstractSecurityPlexusResource
    extends AbstractPlexusResource
{

  @Inject
  private SecuritySystem securitySystem;

  protected static final String DEFAULT_SOURCE = "default";

  @Inject
  protected ReferenceFactory referenceFactory;

  protected SecuritySystem getSecuritySystem() {
    return securitySystem;
  }

  protected ErrorResponse getErrorResponse(String id, String msg) {
    ErrorResponse ner = new ErrorResponse();
    ErrorMessage ne = new ErrorMessage();
    ne.setId(id);
    ne.setMsg(msg);
    ner.addError(ne);
    return ner;
  }

  protected void handleInvalidConfigurationException(InvalidConfigurationException e)
      throws PlexusResourceException
  {
    getLogger().debug("Configuration error!", e);

    ErrorResponse errorResponse;

    ValidationResponse vr = e.getValidationResponse();

    if (vr != null && vr.getValidationErrors().size() > 0) {
      ValidationMessage vm = vr.getValidationErrors().get(0);
      errorResponse = getErrorResponse(vm.getKey(), vm.getShortMessage());
    }
    else {
      errorResponse = getErrorResponse("*", e.getMessage());
    }

    throw new PlexusResourceException(Status.CLIENT_ERROR_BAD_REQUEST, "Configuration error.", errorResponse);
  }

  protected UserResource securityToRestModel(User user, Request request, boolean appendResourceId) {
    UserResource resource = new UserResource();
    resource.setEmail(user.getEmailAddress());
    resource.setFirstName(user.getFirstName());
    resource.setLastName(user.getLastName());
    resource.setStatus(user.getStatus().name());
    resource.setUserId(user.getUserId());

    String resourceId = "";
    if (appendResourceId) {
      resourceId = resource.getUserId();
    }
    resource.setResourceURI(this.createChildReference(request, resourceId).toString());

    for (RoleIdentifier role : user.getRoles()) {
      resource.addRole(role.getRoleId());
    }

    return resource;
  }

  protected User restToSecurityModel(User user, UserResource resource)
      throws InvalidConfigurationException
  {
    if (user == null) {
      user = new DefaultUser();
    }

    // validate users Status, converting to an ENUM throws an exception, so we need to explicitly check it
    this.checkUsersStatus(resource.getStatus());

    user.setEmailAddress(resource.getEmail());
    user.setFirstName(resource.getFirstName());
    user.setLastName(resource.getLastName());
    user.setStatus(UserStatus.valueOf(resource.getStatus()));
    user.setUserId(resource.getUserId());

    // set the users source
    user.setSource(DEFAULT_SOURCE);

    Set<RoleIdentifier> roles = new HashSet<RoleIdentifier>();
    for (String roleId : resource.getRoles()) {
      roles.add(new RoleIdentifier(DEFAULT_SOURCE, roleId));
    }

    user.setRoles(roles);

    return user;
  }

  protected PlexusUserResource securityToRestModel(User user) {
    PlexusUserResource resource = new PlexusUserResource();

    resource.setUserId(user.getUserId());
    resource.setSource(user.getSource());
    resource.setFirstName(user.getFirstName());
    resource.setLastName(user.getLastName());
    resource.setEmail(user.getEmailAddress());
    resource.setStatus(user.getStatus().name());

    for (RoleIdentifier role : user.getRoles()) {
      resource.addRole(this.securityToRestModel(role));
    }

    return resource;
  }

  protected PlexusRoleResource securityToRestModel(Role role) {
    if (role == null) {
      return null;
    }

    PlexusRoleResource roleResource = new PlexusRoleResource();
    roleResource.setRoleId(role.getRoleId());
    roleResource.setName(role.getName());
    roleResource.setSource(role.getSource());

    return roleResource;
  }

  protected List<PlexusUserResource> securityToRestModel(Set<User> users) {
    List<PlexusUserResource> restUsersList = new ArrayList<PlexusUserResource>();

    for (User user : users) {
      restUsersList.add(securityToRestModel(user));
    }
    return restUsersList;
  }

  // TODO: come back to this, we need to change the PlexusRoleResource
  protected PlexusRoleResource securityToRestModel(RoleIdentifier role) {
    // TODO: We shouldn't be looking up the role name here anyway... this should get pushed up to the
    // SecuritySystem.
    String roleName = role.getRoleId();

    SecuritySystem securitySystem = this.getSecuritySystem();

    try {
      AuthorizationManager authzManager = securitySystem.getAuthorizationManager(DEFAULT_SOURCE);
      roleName = authzManager.getRole(role.getRoleId()).getName();
    }
    catch (NoSuchAuthorizationManagerException e) {
      this.getLogger().warn("Failed to lookup the users Role: " + role.getRoleId() + " source: "
          + role.getSource() + " but the user has this role.", e);
    }
    catch (NoSuchRoleException e) {
      // this is a Warning if the role's source is default, if its not, then we most of the time it would not be
      // found anyway.
      if (DEFAULT_SOURCE.equals(role.getSource())) {
        this.getLogger().warn("Failed to lookup the users Role: " + role.getRoleId() + " source: "
            + role.getSource() + " but the user has this role.", e);
      }
      else {
        this.getLogger().debug("Failed to lookup the users Role: " + role.getRoleId() + " source: "
            + role.getSource() + " falling back to the roleId for the role's name.");
      }
    }

    PlexusRoleResource roleResource = new PlexusRoleResource();
    roleResource.setRoleId(role.getRoleId());
    roleResource.setName(roleName);
    roleResource.setSource(role.getSource());

    return roleResource;
  }

  protected Reference createChildReference(Request request, String childPath) {
    return this.referenceFactory.createChildReference(request, childPath);
  }

  protected void checkUsersStatus(String status)
      throws InvalidConfigurationException
  {
    boolean found = false;
    for (UserStatus userStatus : UserStatus.values()) {
      if (userStatus.name().equals(status)) {
        found = true;
      }
    }

    if (!found) {
      ValidationResponse response = new ValidationResponse();
      response.addValidationError(new ValidationMessage("status", "Users status is not valid."));
      throw new InvalidConfigurationException(response);
    }
  }

  protected String getRequestAttribute(final Request request, final String key) {
    return getRequestAttribute(request, key, true);
  }

  protected String getRequestAttribute(final Request request, final String key, final boolean decode) {
    final String value = request.getAttributes().get(key).toString();

    if (decode) {
      try {
        return URLDecoder.decode(value, "UTF-8");
      }
      catch (UnsupportedEncodingException e) {
        getLogger().warn("Failed to decode URL attribute.", e);
      }
    }

    return value;
  }

  @Override
  public void configureXStream(final XStream xstream) {
    super.configureXStream(xstream);
    xstream.registerLocalConverter(UserChangePasswordResource.class, "oldPassword",
        new HtmlUnescapeStringConverter(true));
    xstream
        .registerLocalConverter(UserChangePasswordResource.class, "newPassword", new HtmlUnescapeStringConverter(true));
    xstream.registerLocalConverter(RoleResource.class, "id", new HtmlUnescapeStringConverter(true));
    xstream.registerLocalConverter(UserResource.class, "userId", new HtmlUnescapeStringConverter(true));
    xstream.registerLocalConverter(UserResource.class, "password", new HtmlUnescapeStringConverter(true));
    xstream.registerLocalConverter(RoleAndPrivilegeListResource.class, "id", new HtmlUnescapeStringConverter(true));

    xstream.registerLocalConverter(UserResource.class, "roles", new HtmlUnescapeStringCollectionConverter("role"));
    xstream.registerLocalConverter(RoleResource.class, "roles", new HtmlUnescapeStringCollectionConverter("role"));
    xstream.registerLocalConverter(RoleResource.class, "privileges",
        new HtmlUnescapeStringCollectionConverter("privilege"));
    xstream.registerLocalConverter(RoleAndPrivilegeListFilterResource.class, "selectedRoleIds",
        new HtmlUnescapeStringCollectionConverter("selectedRoleId"));
    xstream.registerLocalConverter(RoleAndPrivilegeListFilterResource.class, "selectedPrivilegeIds",
        new HtmlUnescapeStringCollectionConverter("selectedPrivilegeId"));
    xstream.registerLocalConverter(RoleAndPrivilegeListFilterResource.class, "hiddenRoleIds",
        new HtmlUnescapeStringCollectionConverter("hiddenRoleId"));
    xstream.registerLocalConverter(RoleAndPrivilegeListFilterResource.class, "hiddenPrivilegeIds",
        new HtmlUnescapeStringCollectionConverter("hiddenPrivilegeId"));
  }

  private static class HtmlUnescapeStringCollectionConverter
      extends AliasingListConverter
  {

    public HtmlUnescapeStringCollectionConverter(String alias) {
      super(String.class, alias);
    }

    @Override
    public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
      final List<Object> unmarshal = (List<Object>) super.unmarshal(reader, context);

      // return value needs to be a "real" List
      return Lists.newArrayList(Collections2.transform(unmarshal, new Function()
      {
        @Nullable
        @Override
        public Object apply(@Nullable final Object input) {
          if (input instanceof String) {
            return StringEscapeUtils.unescapeHtml((String) input);
          }

          return input;
        }
      }));
    }
  }
}
TOP

Related Classes of org.sonatype.security.rest.AbstractSecurityPlexusResource

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.