/** * Copyright (c) 2013-2016, The SeedStack authors <http://seedstack.org> * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.seedstack.seed.security.internal; import com.google.inject.AbstractModule; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.PrivateModule; import com.google.inject.spi.ConstructorBinding; import com.google.inject.spi.Element; import com.google.inject.spi.Elements; import com.google.inject.spi.PrivateElements; import org.apache.shiro.mgt.SecurityManager; import org.seedstack.seed.SeedException; import org.seedstack.seed.security.Scope; import org.seedstack.seed.security.internal.securityexpr.SecurityExpressionModule; import java.util.Collection; import java.util.List; import java.util.Map; @SecurityConcern class SecurityModule extends AbstractModule { private static final Key<org.apache.shiro.mgt.SecurityManager> SECURITY_MANAGER_KEY = Key.get(SecurityManager.class); private final Map<String, Class<? extends Scope>> scopeClasses; private final SecurityConfigurer securityConfigurer; private final boolean elAvailable; private final Collection<SecurityProvider> securityProviders; SecurityModule(SecurityConfigurer securityConfigurer, Map<String, Class<? extends Scope>> scopeClasses, boolean elAvailable, Collection<SecurityProvider> securityProviders) { this.securityConfigurer = securityConfigurer; this.scopeClasses = scopeClasses; this.elAvailable = elAvailable; this.securityProviders = securityProviders; } @Override protected void configure() { install(new SecurityInternalModule(securityConfigurer, scopeClasses)); install(new SecurityAopModule()); if (elAvailable) { install(new SecurityExpressionModule()); } Module mainModuleToInstall = null; for (SecurityProvider securityProvider : securityProviders) { Module mainSecurityModule = securityProvider.provideMainSecurityModule(new SecurityGuiceConfigurer(securityConfigurer.getSecurityConfiguration())); if (mainSecurityModule != null) { if (mainModuleToInstall == null || mainModuleToInstall instanceof DefaultSecurityModule) { mainModuleToInstall = mainSecurityModule; } else if (!(mainSecurityModule instanceof DefaultSecurityModule)) { throw SeedException .createNew(SecurityErrorCode.MULTIPLE_MAIN_SECURITY_MODULES) .put("first", mainModuleToInstall.getClass().getCanonicalName()) .put("second", mainSecurityModule.getClass().getCanonicalName()); } } Module additionalSecurityModule = securityProvider.provideAdditionalSecurityModule(); if (additionalSecurityModule != null) { install(removeSecurityManager(additionalSecurityModule)); } } install(mainModuleToInstall); } private Module removeSecurityManager(Module module) { List<Element> elements = Elements.getElements(module); // ShiroModule is only a private module final PrivateElements privateElements = (PrivateElements) elements.iterator().next(); return new PrivateModule() { @Override protected void configure() { for (Element element : privateElements.getElements()) { if (!(element instanceof ConstructorBinding) || !((ConstructorBinding) element).getKey().equals(SECURITY_MANAGER_KEY)) { element.applyTo(binder()); } } for (Key<?> exposedKey : privateElements.getExposedKeys()) { if (!exposedKey.equals(SECURITY_MANAGER_KEY)) { expose(exposedKey); } } } }; } }