All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.imunity.scim.user.mapping.evaluation.MVELEvaluator Maven / Gradle / Ivy

There is a newer version: 4.0.1
Show newest version
/*
 * Copyright (c) 2021 Bixbit - Krzysztof Benedyczak. All rights reserved.
 * See LICENCE.txt file for licensing information.
 */

package io.imunity.scim.user.mapping.evaluation;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.logging.log4j.Logger;
import org.mvel2.MVEL;
import org.springframework.stereotype.Component;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

import pl.edu.icm.unity.base.utils.Log;
import pl.edu.icm.unity.engine.api.AttributeValueConverter;
import pl.edu.icm.unity.engine.api.mvel.MVELGroup;
import pl.edu.icm.unity.exceptions.IllegalAttributeValueException;
import pl.edu.icm.unity.types.basic.Attribute;
import pl.edu.icm.unity.types.basic.AttributeExt;
import pl.edu.icm.unity.types.basic.Identity;

@Component
class MVELEvaluator
{
	private static final Logger log = Log.getLogger(Log.U_SERVER_SCIM, MVELEvaluator.class);
	
	public final int COMPILED_MVEL_CACHE_TTL_IN_HOURS = 1;

	private final AttributeValueConverter attrValueConverter;
	private final Cache compiledMvelCache;

	MVELEvaluator(AttributeValueConverter attrValueConverter)
	{
		this.attrValueConverter = attrValueConverter;
		this.compiledMvelCache = CacheBuilder.newBuilder()
				.expireAfterAccess(COMPILED_MVEL_CACHE_TTL_IN_HOURS, TimeUnit.HOURS).build();
	}

	Object evalMVEL(String mvel, EvaluatorContext context) throws IllegalAttributeValueException
	{
		if (mvel == null)
			return null;

		Serializable expressionCompiled = getCompiledMvel(mvel);
		return MVEL.executeExpression(expressionCompiled, createContext(context), new HashMap<>());
	}

	private Serializable getCompiledMvel(String mvel)
	{
		Serializable cached = compiledMvelCache.getIfPresent(mvel);
		if (cached != null)
			return cached;
		Serializable actual = MVEL.compileExpression(mvel);
		compiledMvelCache.put(mvel, actual);
		return actual;
	}

	Object createContext(EvaluatorContext context) throws IllegalAttributeValueException
	{
		Map ret = new HashMap<>();
		ret.put(SCIMMvelContextKey.idsByType.toString(), createIdentityContextElement(context));
		addAttributesToContext(SCIMMvelContextKey.attr.name(),
				SCIMMvelContextKey.attrObj.name(), SCIMMvelContextKey.attrs.name(), ret,
				context.user.attributes, attrValueConverter);

		List groups = new ArrayList<>();
		Map groupsObj = new HashMap<>();

		context.user.groups.forEach(g ->
		{
			groups.add(g.getPathEncoded());
			groupsObj.put(g.getName(), context.groupProvider.get(g.getPathEncoded()));
		});

		ret.put(SCIMMvelContextKey.groups.toString(), groups);
		ret.put(SCIMMvelContextKey.groupsObj.name(), groupsObj);

		if (context.arrayObj != null)
		{
			ret.put(SCIMMvelContextKey.arrayObj.toString(), context.arrayObj);
		}

		log.info("MVEL evaluation context: {}", ret);
		return ret;
	}

	private void addAttributesToContext(String attrKey, String attrObjKey, String attrsKey, Map ret,
			List attributes, AttributeValueConverter attrConverter) throws IllegalAttributeValueException
	{
		Map attr = new HashMap<>();
		Map attrObj = new HashMap<>();
		Map> attrs = new HashMap<>();

		for (Attribute ra : attributes)
		{
			List values = attrConverter.internalValuesToExternal(ra.getName(), ra.getValues());
			String v = values.isEmpty() ? "" : values.get(0);
			attr.put(ra.getName(), v);
			attrs.put(ra.getName(), values);
			attrObj.put(ra.getName(),
					values.isEmpty() ? "" : attrConverter.internalValuesToObjectValues(ra.getName(), ra.getValues()));
		}
		ret.put(attrKey, attr);
		ret.put(attrObjKey, attrObj);
		ret.put(attrsKey, attrs);
	}

	private Map> createIdentityContextElement(EvaluatorContext context)
	{
		Map> idsByType = new HashMap<>();
		for (Identity id : context.user.identities)
		{
			List vals = idsByType.get(id.getTypeId());
			if (vals == null)
			{
				vals = new ArrayList<>();
				idsByType.put(id.getTypeId(), vals);
			}
			vals.add(id.getValue());
		}
		return idsByType;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy