/**
* 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.securityexpr;
import org.seedstack.seed.SeedException;
import org.seedstack.seed.el.ELContextBuilder;
import org.seedstack.seed.el.ELService;
import org.seedstack.seed.security.internal.SecurityErrorCode;
import javax.el.ELContext;
import javax.inject.Inject;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* The Security Expression Interpreter has the responsibility to interpret any form of security expression.
*/
public class SecurityExpressionInterpreter {
@Inject
private ELService elService;
@Inject
private ELContextBuilder elContextBuilder;
/**
* This methods will interpret any security expression. It will handle it
* accordingly in function of its type.
* <p>
* For now, Boolean will be interpreted as Boolean and String will be
* interpreted by the {@link ELService} as an Expression Language from the JSR 341.
*
* @param securityExpression the security expression.
* @return True if the security expression interpretation is secured.
*/
public Boolean interpret(Object securityExpression) {
Boolean interpretation = Boolean.FALSE;
if (securityExpression instanceof Boolean) {
interpretation = Boolean.class.cast(securityExpression);
} else if (securityExpression instanceof String) {
interpretation = expression((String) securityExpression);
}
return interpretation;
}
private Boolean expression(String expression) {
ELContextBuilder.ELPropertyProvider elContextProvider = elContextBuilder.defaultContext();
for (Map.Entry<String, Method> entry : getMethods().entrySet()) {
elContextProvider.withFunction("", entry.getKey(), entry.getValue());
}
ELContext elContext = elContextProvider.build();
return (Boolean) elService.withExpression(expression, Boolean.class).withContext(elContext).asValueExpression().eval();
}
private Map<String, Method> getMethods() {
Map<String, Method> availableMethods = new HashMap<>();
try {
availableMethods.put("hasRole", SecurityExpressionUtils.class.getDeclaredMethod("hasRole", String.class));
availableMethods.put("hasRoleOn", SecurityExpressionUtils.class.getDeclaredMethod("hasRoleOn", String.class, String.class));
availableMethods.put("hasPermission", SecurityExpressionUtils.class.getDeclaredMethod("hasPermission", String.class));
availableMethods.put("hasPermissionOn", SecurityExpressionUtils.class.getDeclaredMethod("hasPermissionOn", String.class, String.class));
} catch (NoSuchMethodException e) {
throw SeedException.wrap(e, SecurityErrorCode.UNEXPECTED_ERROR);
}
return availableMethods;
}
}