/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.cms.web.portal.services; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import javax.annotation.PostConstruct; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.enonic.cms.core.structure.SiteKey; import com.enonic.cms.core.structure.SiteProperties; import com.enonic.cms.core.structure.SitePropertiesListener; import com.enonic.cms.core.structure.SitePropertiesService; import com.enonic.cms.core.structure.SitePropertyNames; import com.enonic.cms.core.structure.SiteService; @Component public class UserServicesAccessManagerImpl implements UserServicesAccessManager, SitePropertiesListener { private static enum AccessPermission { ALLOW, DENY, } private static final String ACCESS_RULE_ALL = "*"; private static final AccessPermission DEFAULT_ACCESS_RULE = AccessPermission.DENY; private SitePropertiesService sitePropertiesService; private SiteService siteService; private ConcurrentMap<SiteKey, ConcurrentMap<String, AccessPermission>> sitesAccessRules; public UserServicesAccessManagerImpl() { sitesAccessRules = new ConcurrentHashMap<SiteKey, ConcurrentMap<String, AccessPermission>>(); } @PostConstruct public void postConstruct() { sitePropertiesService.registerSitePropertiesListener( this ); } @Override public boolean isOperationAllowed( SiteKey site, String service, String operation ) { siteService.checkSiteExist( site ); ConcurrentMap<String, AccessPermission> siteRules = getRulesForSite( site ); AccessPermission access = applyAccessRules( service, operation, siteRules ); return access == AccessPermission.ALLOW; } private AccessPermission applyAccessRules( String service, String operation, ConcurrentMap<String, AccessPermission> siteRules ) { // search for specific rule: "service.operation" AccessPermission accessServiceOperation = siteRules.get( service + "." + operation ); if ( accessServiceOperation != null ) { return accessServiceOperation; } // search for generic rule: "service.*" AccessPermission accessService = siteRules.get( service + ".*" ); if ( accessService != null ) { siteRules.putIfAbsent( service + "." + operation, accessService ); return accessService; } // no rule found -> return default and cache value AccessPermission defaultAccess = siteRules.get( ACCESS_RULE_ALL ); siteRules.putIfAbsent( service + "." + operation, defaultAccess ); return defaultAccess; } private ConcurrentMap<String, AccessPermission> getRulesForSite( SiteKey site ) { ConcurrentMap<String, AccessPermission> rules = sitesAccessRules.get( site ); if ( rules == null ) { initSiteRules( site ); rules = sitesAccessRules.get( site ); } return rules; } @Override public void sitePropertiesLoaded( final SiteProperties siteProperties ) { // nothing } @Override public void sitePropertiesReloaded( final SiteProperties siteProperties ) { sitesAccessRules.remove( siteProperties.getSiteKey() ); initSiteRules( siteProperties.getSiteKey() ); } private void initSiteRules( SiteKey site ) { ConcurrentMap<String, AccessPermission> siteRules = new ConcurrentHashMap<String, AccessPermission>(); String allowRules = sitePropertiesService.getSiteProperty( site, SitePropertyNames.HTTP_SERVICES_ALLOW_PROPERTY ); String denyRules = sitePropertiesService.getSiteProperty( site, SitePropertyNames.HTTP_SERVICES_DENY_PROPERTY ); parseAndAddRules( allowRules, AccessPermission.ALLOW, siteRules, site ); parseAndAddRules( denyRules, AccessPermission.DENY, siteRules, site ); siteRules.putIfAbsent( ACCESS_RULE_ALL, DEFAULT_ACCESS_RULE ); sitesAccessRules.putIfAbsent( site, siteRules ); } private void parseAndAddRules( String accessRules, AccessPermission accessPermission, ConcurrentMap<String, AccessPermission> siteRules, SiteKey site ) { accessRules = StringUtils.trimToEmpty( accessRules ); String[] ruleItems = accessRules.split( "," ); for ( String ruleItem : ruleItems ) { ruleItem = ruleItem.trim(); if ( ruleItem.isEmpty() ) { continue; } if ( siteRules.containsKey( ruleItem ) ) { throw new IllegalArgumentException( "Duplicated value for http service access rule '" + ruleItem + "' on site " + site ); } siteRules.put( ruleItem, accessPermission ); } } @Autowired public void setSitePropertiesService( SitePropertiesService sitePropertiesService ) { this.sitePropertiesService = sitePropertiesService; } @Autowired public void setSiteService( SiteService siteService ) { this.siteService = siteService; } }