Package org.geomajas.internal.security

Source Code of org.geomajas.internal.security.SecurityContextImpl$AuthorizationGetter

/*
* This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
*
* Copyright 2008-2011 Geosparc nv, http://www.geosparc.com/, Belgium.
*
* The program is available in open source according to the GNU Affero
* General Public License. All contributions in this program are covered
* by the Geomajas Contributors License Agreement. For full licensing
* details, see LICENSE.txt in the project root.
*/

package org.geomajas.internal.security;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.geomajas.configuration.LayerInfo;
import org.geomajas.layer.Layer;
import org.geomajas.layer.VectorLayer;
import org.geomajas.layer.feature.InternalFeature;
import org.geomajas.security.AreaAuthorization;
import org.geomajas.security.AttributeAuthorization;
import org.geomajas.security.Authentication;
import org.geomajas.security.AuthorizationNeedsWiring;
import org.geomajas.security.BaseAuthorization;
import org.geomajas.security.FeatureAuthorization;
import org.geomajas.security.SavedAuthentication;
import org.geomajas.security.SavedAuthorization;
import org.geomajas.security.SecurityContext;
import org.geomajas.security.VectorLayerSelectFilterAuthorization;
import org.geomajas.service.ConfigurationService;
import org.geomajas.service.DtoConverterService;
import org.geomajas.service.FilterService;
import org.geomajas.service.GeoService;
import org.opengis.filter.Filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;

import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.PrecisionModel;

/**
* {@link org.geomajas.security.SecurityContext} implementation.
* <p/>
* The security context is a thread scoped service which allows you to query the authorization details for the logged in
* user.
*
* @author Joachim Van der Auwera
*/
@Component
@Scope(value = "thread", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class SecurityContextImpl implements SecurityContext {

  private final Logger log = LoggerFactory.getLogger(SecurityContextImpl.class);

  private List<Authentication> authentications = new ArrayList<Authentication>();

  private String token;

  private String id; // SecurityContext id

  // user info
  private String userId;

  private String userName;

  private Locale userLocale;

  private String userOrganization;

  private String userDivision;

  @Autowired
  private FilterService filterService;

  @Autowired
  private ConfigurationService configurationService;

  @Autowired
  private DtoConverterService converterService;

  @Autowired
  private GeoService geoService;

  @Autowired
  private ApplicationContext applicationContext;

  public void setAuthentications(String token, List<Authentication> authentications) {
    this.token = token;
    this.authentications.clear();
    if (null != authentications) {
      for (Authentication auth : authentications) {
        for (BaseAuthorization ba : auth.getAuthorizations()) {
          if (ba instanceof AuthorizationNeedsWiring) {
            ((AuthorizationNeedsWiring) ba).wire(applicationContext);
          }
        }
        this.authentications.add(auth);
      }
    }
    userInfoInit();
  }

  /**
   * @inheritDoc
   */
  public List<Authentication> getSecurityServiceResults() {
    return authentications;
  }

  public String getToken() {
    return token;
  }

  /**
   * @inheritDoc
   */
  public String getUserId() {
    return userId;
  }

  /**
   * @inheritDoc
   */
  public String getUserName() {
    return userName;
  }

  /**
   * @inheritDoc
   */
  public Locale getUserLocale() {
    return userLocale;
  }

  /**
   * @inheritDoc
   */
  public String getUserOrganization() {
    return userOrganization;
  }

  /**
   * @inheritDoc
   */
  public String getUserDivision() {
    return userDivision;
  }

  /**
   * Calculate UserInfo strings.
   */
  private void userInfoInit() {
    boolean first = true;
    userId = null;
    userLocale = null;
    userName = null;
    userOrganization = null;
    userDivision = null;
    if (null != authentications) {
      for (Authentication auth : authentications) {
        userId = combine(userId, auth.getUserId());
        userName = combine(userName, auth.getUserName());
        if (first) {
          userLocale = auth.getUserLocale();
          first = false;
        } else {
          if (null != auth.getUserLocale()) {
            if (null == userLocale || !userLocale.equals(auth.getUserLocale())) {
              userLocale = null;
            }
          }
        }
        userOrganization = combine(userOrganization, auth.getUserOrganization());
        userDivision = combine(userDivision, auth.getUserDivision());
      }
    }

    // now calculate the "id" for this context, this should be independent of the data order, so sort
    Map<String, List<String>> idParts = new HashMap<String, List<String>>();
    if (null != authentications) {
      for (Authentication auth : authentications) {
        List<String> auths = new ArrayList<String>();
        for (BaseAuthorization ba : auth.getAuthorizations()) {
          auths.add(ba.getId());
        }
        Collections.sort(auths);
        idParts.put(auth.getSecurityServiceId(), auths);
      }
    }
    StringBuilder sb = new StringBuilder();
    List<String> sortedKeys = new ArrayList<String>(idParts.keySet());
    Collections.sort(sortedKeys);
    for (String key : sortedKeys) {
      if (sb.length() > 0) {
        sb.append('|');
      }
      List<String> auths = idParts.get(key);
      first = true;
      for (String ak : auths) {
        if (first) {
          first = false;
        } else {
          sb.append('|');
        }
        sb.append(ak);
      }
      sb.append('@');
      sb.append(key);
    }
    id = sb.toString();
  }

  /**
   * Combine user information strings.
   * <p/>
   * Extra information is appended (separated by a comma) if not yet present in the string.
   *
   * @param org
   *            base string to append to (avoiding duplication).
   * @param add
   *            string to add
   * @return org + ", " + add
   */
  private String combine(String org, String add) {
    if (null == org) {
      return add;
    }
    if (null == add || org.equals(add) || org.startsWith(add + ", ") || org.endsWith(", " + add)) {
      return org;
    }
    return org + ", " + add;
  }

  /**
   * @inheritDoc
   */
  public String getId() {
    return id;
  }

  /**
   * @inheritDoc
   */
  public boolean isToolAuthorized(String toolId) {
    for (Authentication authentication : authentications) {
      for (BaseAuthorization authorization : authentication.getAuthorizations()) {
        if (authorization.isToolAuthorized(toolId)) {
          return true;
        }
      }
    }
    return false;
  }

  /**
   * @inheritDoc
   */
  public boolean isCommandAuthorized(String commandName) {
    for (Authentication authentication : authentications) {
      for (BaseAuthorization authorization : authentication.getAuthorizations()) {
        if (authorization.isCommandAuthorized(commandName)) {
          return true;
        }
      }
    }
    return false;
  }

  /**
   * @inheritDoc
   */
  public boolean isLayerVisible(String layerId) {
    for (Authentication authentication : authentications) {
      for (BaseAuthorization authorization : authentication.getAuthorizations()) {
        if (authorization.isLayerVisible(layerId)) {
          return true;
        }
      }
    }
    return false;
  }

  /**
   * @inheritDoc
   */
  public boolean isLayerUpdateAuthorized(String layerId) {
    if (isLayerUpdateCapable(layerId)) {
      for (Authentication authentication : authentications) {
        for (BaseAuthorization authorization : authentication.getAuthorizations()) {
          if (authorization.isLayerUpdateAuthorized(layerId)) {
            return true;
          }
        }
      }
    }
    return false;
  }

  /**
   * @inheritDoc
   */
  public boolean isLayerCreateAuthorized(String layerId) {
    if (isLayerCreateCapable(layerId)) {
      for (Authentication authentication : authentications) {
        for (BaseAuthorization authorization : authentication.getAuthorizations()) {
          if (authorization.isLayerCreateAuthorized(layerId)) {
            return true;
          }
        }
      }
    }
    return false;
  }

  /**
   * @inheritDoc
   */
  public boolean isLayerDeleteAuthorized(String layerId) {
    if (isLayerUpdateCapable(layerId)) {
      for (Authentication authentication : authentications) {
        for (BaseAuthorization authorization : authentication.getAuthorizations()) {
          if (authorization.isLayerDeleteAuthorized(layerId)) {
            return true;
          }
        }
      }
    }
    return false;
  }

  /**
   * @inheritDoc
   */
  public Filter getFeatureFilter(String layerId) {
    Filter filter = null;
    for (Authentication authentication : authentications) {
      for (BaseAuthorization authorization : authentication.getAuthorizations()) {
        if (authorization instanceof VectorLayerSelectFilterAuthorization) {
          Filter part = ((VectorLayerSelectFilterAuthorization) authorization).getFeatureFilter(layerId);
          if (null != part) {
            filter = combineFilter(filter, part);
          }
        }
      }
    }
    return filter;
  }

  private Filter combineFilter(Filter base, Filter add) {
    if (null == base) {
      return add;
    }
    if (null == add) {
      return base;
    }
    return filterService.createAndFilter(base, add);
  }

  /**
   * @inheritDoc
   */
  public Geometry getVisibleArea(final String layerId) {
    return areaCombine(layerId, new AreaCombineGetter() {

      public Geometry get(AreaAuthorization auth) {
        return auth.getVisibleArea(layerId);
      }
    });
  }

  private Geometry areaCombine(String layerId, AreaCombineGetter areaGetter) {
    if (null == authentications || authentications.size() == 0) {
      // no authorizations, so nothing should be allowed
      return null;
    }

    Layer<?> layer = configurationService.getLayer(layerId);
    if (null == layer) {
      log.error("areaCombine on unknown layer " + layerId);
      return null;
    }
    LayerInfo layerInfo = layer.getLayerInfo();

    // base is the max bounds of the layer
    Envelope maxBounds = converterService.toInternal(layerInfo.getMaxExtent());
    PrecisionModel precisionModel = new PrecisionModel(PrecisionModel.FLOATING);
    int srid = geoService.getSridFromCrs(layer.getLayerInfo().getCrs());
    GeometryFactory geometryFactory = new GeometryFactory(precisionModel, srid);
    Geometry geometry = geometryFactory.toGeometry(maxBounds);

    // limit based on authorizations
    for (Authentication authentication : authentications) {
      for (BaseAuthorization authorization : authentication.getAuthorizations()) {
        if (authorization instanceof AreaAuthorization) {
          geometry = geometry.intersection(areaGetter.get((AreaAuthorization) authorization));
        }
      }
    }
    geometry.setSRID(srid); // force srid, even when not set correctly by security service
    return geometry;
  }

  /**
   * @inheritDoc
   */
  public boolean isPartlyVisibleSufficient(final String layerId) {
    return areaPartlySufficientCombine(new AuthorizationGetter<AreaAuthorization>() {

      public boolean get(AreaAuthorization auth) {
        return auth.isPartlyVisibleSufficient(layerId);
      }
    });
  }

  private boolean areaPartlySufficientCombine(AuthorizationGetter<AreaAuthorization> partlySufficientGetter) {
    boolean res = false;
    for (Authentication authentication : authentications) {
      for (BaseAuthorization authorization : authentication.getAuthorizations()) {
        if (authorization instanceof AreaAuthorization) {
          if (!partlySufficientGetter.get((AreaAuthorization) authorization)) {
            return false;
          }
          res = true;
        }
      }
    }
    return res;
  }

  /**
   * @inheritDoc
   */
  public Geometry getUpdateAuthorizedArea(final String layerId) {
    if (!isLayerUpdateCapable(layerId)) {
      return null;
    }
    return areaCombine(layerId, new AreaCombineGetter() {

      public Geometry get(AreaAuthorization auth) {
        return auth.getUpdateAuthorizedArea(layerId);
      }
    });
  }

  /**
   * @inheritDoc
   */
  public boolean isPartlyUpdateAuthorizedSufficient(final String layerId) {
    return areaPartlySufficientCombine(new AuthorizationGetter<AreaAuthorization>() {

      public boolean get(AreaAuthorization auth) {
        return auth.isPartlyUpdateAuthorizedSufficient(layerId);
      }
    });
  }

  /**
   * @inheritDoc
   */
  public Geometry getCreateAuthorizedArea(final String layerId) {
    if (!isLayerCreateCapable(layerId)) {
      return null;
    }
    return areaCombine(layerId, new AreaCombineGetter() {

      public Geometry get(AreaAuthorization auth) {
        return auth.getCreateAuthorizedArea(layerId);
      }
    });
  }

  /**
   * @inheritDoc
   */
  public boolean isPartlyCreateAuthorizedSufficient(final String layerId) {
    return areaPartlySufficientCombine(new AuthorizationGetter<AreaAuthorization>() {

      public boolean get(AreaAuthorization auth) {
        return auth.isPartlyCreateAuthorizedSufficient(layerId);
      }
    });
  }

  /**
   * @inheritDoc
   */
  public Geometry getDeleteAuthorizedArea(final String layerId) {
    if (!isLayerDeleteCapable(layerId)) {
      return null;
    }
    return areaCombine(layerId, new AreaCombineGetter() {

      public Geometry get(AreaAuthorization auth) {
        return auth.getDeleteAuthorizedArea(layerId);
      }
    });
  }

  /**
   * @inheritDoc
   */
  public boolean isPartlyDeleteAuthorizedSufficient(final String layerId) {
    return areaPartlySufficientCombine(new AuthorizationGetter<AreaAuthorization>() {

      public boolean get(AreaAuthorization auth) {
        return auth.isPartlyDeleteAuthorizedSufficient(layerId);
      }
    });
  }

  /**
   * @inheritDoc
   */
  public boolean isFeatureVisible(final String layerId, final InternalFeature feature) {
    return policyCombine(new AuthorizationGetter<BaseAuthorization>() {

      public boolean get(BaseAuthorization auth) {
        if (auth instanceof FeatureAuthorization) {
          return ((FeatureAuthorization) auth).isFeatureVisible(layerId, feature);
        } else {
          return auth.isLayerVisible(layerId);
        }
      }
    });
  }

  private boolean policyCombine(AuthorizationGetter<BaseAuthorization> auth) {
    for (Authentication authentication : authentications) {
      for (BaseAuthorization authorization : authentication.getAuthorizations()) {
        if (auth.get(authorization)) {
          return true;
        }
      }
    }
    return false;
  }

  /** @inheritDoc */
  public boolean isFeatureUpdateAuthorized(final String layerId, final InternalFeature feature) {
    return isLayerUpdateCapable(layerId) && policyCombine(new AuthorizationGetter<BaseAuthorization>() {
      public boolean get(BaseAuthorization auth) {
        if (auth instanceof FeatureAuthorization) {
          return ((FeatureAuthorization) auth).isFeatureUpdateAuthorized(layerId, feature);
        } else {
          return auth.isLayerUpdateAuthorized(layerId);
        }
      }
    });
  }

  /** @inheritDoc */
  public boolean isFeatureUpdateAuthorized(final String layerId, final InternalFeature orgFeature,
      final InternalFeature newFeature) {
    return isLayerUpdateCapable(layerId) && policyCombine(new AuthorizationGetter<BaseAuthorization>() {
      public boolean get(BaseAuthorization auth) {
        if (auth instanceof FeatureAuthorization) {
          return ((FeatureAuthorization) auth).isFeatureUpdateAuthorized(layerId, orgFeature, newFeature);
        } else {
          return auth.isLayerUpdateAuthorized(layerId);
        }
      }
    });
  }

  /** @inheritDoc */
  public boolean isFeatureDeleteAuthorized(final String layerId, final InternalFeature feature) {
    return isLayerDeleteCapable(layerId) && policyCombine(new AuthorizationGetter<BaseAuthorization>() {
      public boolean get(BaseAuthorization auth) {
        if (auth instanceof FeatureAuthorization) {
          return ((FeatureAuthorization) auth).isFeatureDeleteAuthorized(layerId, feature);
        } else {
          return auth.isLayerDeleteAuthorized(layerId);
        }
      }
    });
  }

  /** @inheritDoc */
  public boolean isFeatureCreateAuthorized(final String layerId, final InternalFeature feature) {
    return isLayerCreateCapable(layerId) && policyCombine(new AuthorizationGetter<BaseAuthorization>() {
      public boolean get(BaseAuthorization auth) {
        if (auth instanceof FeatureAuthorization) {
          return ((FeatureAuthorization) auth).isFeatureCreateAuthorized(layerId, feature);
        } else {
          return auth.isLayerCreateAuthorized(layerId);
        }
      }
    });
  }

  /**
   * @inheritDoc
   */
  public boolean isAttributeReadable(final String layerId, final InternalFeature feature,
      final String attributeName) {
    return policyCombine(new AuthorizationGetter<BaseAuthorization>() {

      public boolean get(BaseAuthorization auth) {
        if (auth instanceof AttributeAuthorization) {
          return ((AttributeAuthorization) auth).isAttributeReadable(layerId, feature, attributeName);
        } else if (auth instanceof FeatureAuthorization) {
          return ((FeatureAuthorization) auth).isFeatureVisible(layerId, feature);
        } else {
          return auth.isLayerVisible(layerId);
        }
      }
    });
  }

  /**
   * @inheritDoc
   */
  public boolean isAttributeWritable(final String layerId, final InternalFeature feature,
      final String attributeName) {
    return isLayerUpdateCapable(layerId) && policyCombine(new AuthorizationGetter<BaseAuthorization>() {
      public boolean get(BaseAuthorization auth) {
        if (auth instanceof AttributeAuthorization) {
          return ((AttributeAuthorization) auth).isAttributeWritable(layerId, feature, attributeName);
        } else if (auth instanceof FeatureAuthorization) {
          return ((FeatureAuthorization) auth).isFeatureUpdateAuthorized(layerId, feature);
        } else {
          return auth.isLayerUpdateAuthorized(layerId);
        }
      }
    });
  }

  private boolean isLayerUpdateCapable(String layerId) {
    if (null == configurationService) {
      return true; // for testing, when there is no spring context
    }
    VectorLayer layer = configurationService.getVectorLayer(layerId);
    return null != layer && layer.isUpdateCapable();
  }

  private boolean isLayerCreateCapable(String layerId) {
    if (null == configurationService) {
      return true; // for testing, when there is no spring context
    }
    VectorLayer layer = configurationService.getVectorLayer(layerId);
    return null != layer && layer.isCreateCapable();
  }

  private boolean isLayerDeleteCapable(String layerId) {
    if (null == configurationService) {
      return true; // for testing, when there is no spring context
    }
    VectorLayer layer = configurationService.getVectorLayer(layerId);
    return null != layer && layer.isDeleteCapable();
  }

  public SavedAuthorization getSavedAuthorization() {
    return new SavedAuthorizationImpl(this);
  }

  public void restoreSecurityContext(SavedAuthorization savedAuthorization) {
    List<Authentication> auths = new ArrayList<Authentication>();
    if (null != savedAuthorization) {
      for (SavedAuthentication sa : savedAuthorization.getAuthentications()) {
        Authentication auth = new Authentication();
        auth.setSecurityServiceId(sa.getSecurityServiceId());
        auth.setAuthorizations(sa.getAuthorizations());
        auths.add(auth);
      }
    }
    setAuthentications(null, auths);
    userInfoInit();
  }

  /**
   * Interface to unify/generalise the different areas.
   */
  private interface AreaCombineGetter {

    /**
     * Get the area which needs to be combined.
     *
     * @param auth
     *            authorization object to get data from
     * @return area to combine
     */
    Geometry get(AreaAuthorization auth);
  }

  /**
   * Interface to unify/generalise the different areas.
   */
  private interface AuthorizationGetter<AUTH extends BaseAuthorization> {

    /**
     * Get the "partly sufficient" status.
     *
     * @param auth
     *            authorization object to get data from
     * @return true when part in area is sufficient
     */
    boolean get(AUTH auth);
  }

}
TOP

Related Classes of org.geomajas.internal.security.SecurityContextImpl$AuthorizationGetter

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.