Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
pl.edu.icm.unity.engine.translation.out.OutputTranslationProfile Maven / Gradle / Ivy
/*
* Copyright (c) 2014 ICM Uniwersytet Warszawski All rights reserved.
* See LICENCE.txt file for licensing information.
*/
package pl.edu.icm.unity.engine.translation.out;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.log4j.NDC;
import org.apache.logging.log4j.Logger;
import eu.unicore.util.configuration.ConfigurationException;
import pl.edu.icm.unity.base.attribute.Attribute;
import pl.edu.icm.unity.base.attribute.IllegalAttributeValueException;
import pl.edu.icm.unity.base.exceptions.EngineException;
import pl.edu.icm.unity.base.exceptions.InternalException;
import pl.edu.icm.unity.base.group.Group;
import pl.edu.icm.unity.base.identity.Identity;
import pl.edu.icm.unity.base.translation.TranslationProfile;
import pl.edu.icm.unity.base.utils.Log;
import pl.edu.icm.unity.engine.api.AttributeValueConverter;
import pl.edu.icm.unity.engine.api.GroupsManagement;
import pl.edu.icm.unity.engine.api.attributes.DynamicAttribute;
import pl.edu.icm.unity.engine.api.authn.RemoteAuthnMetadata;
import pl.edu.icm.unity.engine.api.authn.InvocationContext;
import pl.edu.icm.unity.engine.api.authn.LoginSession;
import pl.edu.icm.unity.engine.api.exceptions.RuntimeEngineException;
import pl.edu.icm.unity.engine.api.group.GroupsChain;
import pl.edu.icm.unity.engine.api.mvel.MVELGroup;
import pl.edu.icm.unity.engine.api.translation.TranslationActionInstance;
import pl.edu.icm.unity.engine.api.translation.TranslationCondition;
import pl.edu.icm.unity.engine.api.translation.out.OutputTranslationAction;
import pl.edu.icm.unity.engine.api.translation.out.OutputTranslationActionsRegistry;
import pl.edu.icm.unity.engine.api.translation.out.OutputTranslationMVELContextKey;
import pl.edu.icm.unity.engine.api.translation.out.TranslationInput;
import pl.edu.icm.unity.engine.api.translation.out.TranslationResult;
import pl.edu.icm.unity.engine.translation.ExecutionBreakException;
import pl.edu.icm.unity.engine.translation.TranslationProfileInstance;
import pl.edu.icm.unity.engine.translation.TranslationRuleInvocationContext;
/**
* Entry point: output translation profile, a list of translation rules
* annotated with a name and description.
*
* @author K. Benedyczak
*/
public class OutputTranslationProfile
extends TranslationProfileInstance
{
private static final Logger log = Log.getLogger(Log.U_SERVER_TRANSLATION, OutputTranslationProfile.class);
private OutputTranslationActionsRegistry registry;
private OutputTranslationProfileRepository profileRepo;
private GroupsManagement groupMan;
private AttributeValueConverter attrConverter;
public OutputTranslationProfile(TranslationProfile profile, OutputTranslationProfileRepository profileRepo,
OutputTranslationActionsRegistry registry, AttributeValueConverter attrConverter,
GroupsManagement groupProvider)
{
super(profile, registry);
this.registry = registry;
this.profileRepo = profileRepo;
this.attrConverter = attrConverter;
this.groupMan = groupProvider;
}
public TranslationResult translate(TranslationInput input) throws EngineException
{
return translate(input, null);
}
private TranslationResult translate(TranslationInput input, TranslationResult partialState) throws EngineException
{
NDC.push("[TrProfile " + profile.getName() + "]");
if (log.isDebugEnabled())
log.debug("Unprocessed data from local database:\n" + input.getTextDump());
Object mvelCtx = createMvelContext(input, attrConverter, g -> getGroupChain(g));
try
{
int i = 1;
TranslationResult translationState = null;
if (partialState == null)
translationState = initiateTranslationResult(input);
else
translationState = partialState;
for (OutputTranslationRule rule : ruleInstances)
{
NDC.push("[r: " + (i++) + " " + rule.getAction().getName() + "]");
try
{
TranslationRuleInvocationContext context = rule.invoke(
input, mvelCtx, profile.getName(),
translationState);
if (context.getIncludedProfile() != null)
{
invokeOutputTranslationProfile(
context.getIncludedProfile(), input,
translationState);
}
} catch (ExecutionBreakException e)
{
break;
} finally
{
NDC.pop();
}
}
return translationState;
} finally
{
NDC.pop();
}
}
public static TranslationResult initiateTranslationResult(TranslationInput input)
{
TranslationResult ret = new TranslationResult();
Collection attrs = input.getAttributes().stream()
.map(attr -> new DynamicAttribute(attr))
.collect(Collectors.toList());
ret.getAttributes().addAll(attrs);
for (Identity id : input.getEntity().getIdentities())
ret.getIdentities().add(id);
return ret;
}
static Map createMvelContext(TranslationInput input,
AttributeValueConverter attrConverter, Function groupProvider) throws IllegalAttributeValueException
{
Map ret = new HashMap<>();
ret.put(OutputTranslationMVELContextKey.protocol.name(), input.getProtocol());
ret.put(OutputTranslationMVELContextKey.protocolSubtype.name(), input.getProtocolSubType());
ret.put(OutputTranslationMVELContextKey.requester.name(), input.getRequester());
addAttributesToContext(OutputTranslationMVELContextKey.attr.name(),
OutputTranslationMVELContextKey.attrObj.name(), OutputTranslationMVELContextKey.attrs.name(), ret,
input.getAttributes(), attrConverter);
addAttributesToContext(OutputTranslationMVELContextKey.requesterAttr.name(),
OutputTranslationMVELContextKey.requesterAttrObj.name(),
OutputTranslationMVELContextKey.requesterAttrs.name(), ret, input.getRequesterAttributes(),
attrConverter);
Map> idsByType = new HashMap<>();
for (Identity id : input.getEntity().getIdentities())
{
List vals = idsByType.get(id.getTypeId());
if (vals == null)
{
vals = new ArrayList<>();
idsByType.put(id.getTypeId(), vals);
}
vals.add(id.getValue());
}
ret.put(OutputTranslationMVELContextKey.idsByType.name(), idsByType);
ret.put(OutputTranslationMVELContextKey.importStatus.name(), input.getImportStatus().entrySet().stream()
.collect(Collectors.toMap(Entry::getKey, e -> String.valueOf(e.getValue()))));
List groupNames = input.getGroups().stream()
.map(group -> group.getName())
.collect(Collectors.toList());
ret.put(OutputTranslationMVELContextKey.groups.name(), groupNames);
ret.put(OutputTranslationMVELContextKey.usedGroup.name(), input.getChosenGroup());
Group main = new Group(input.getChosenGroup());
List subgroups = new ArrayList();
for (String group : groupNames)
{
Group g = new Group(group);
if (g.isChild(main))
subgroups.add(group);
}
ret.put(OutputTranslationMVELContextKey.subGroups.name(), subgroups);
Map groupsObj = input.getGroups().stream()
.collect(Collectors.toMap(group -> group.getName(),
group -> new MVELGroup(groupProvider.apply(group.getPathEncoded()))));
ret.put(OutputTranslationMVELContextKey.groupsObj.name(), groupsObj);
if (InvocationContext.hasCurrent() && InvocationContext.getCurrent().getLoginSession() != null)
{
LoginSession loginSession = InvocationContext.getCurrent().getLoginSession();
Set authenticatedIdentities = loginSession.getAuthenticatedIdentities();
ret.put(OutputTranslationMVELContextKey.authenticatedWith.name(),
new ArrayList(authenticatedIdentities));
ret.put(OutputTranslationMVELContextKey.idp.name(),
loginSession.getRemoteIdP() == null ? "_LOCAL" : loginSession.getRemoteIdP());
List usedAuthenticators = new ArrayList<>();
if (loginSession.getLogin1stFactor().optionId != null)
usedAuthenticators.add(loginSession.getLogin1stFactor().optionId.getAuthenticatorKey());
if (loginSession.getLogin2ndFactor().optionId != null)
usedAuthenticators.add(loginSession.getLogin2ndFactor().optionId.getAuthenticatorKey());
ret.put(OutputTranslationMVELContextKey.authentications.name(), usedAuthenticators);
ret.put(OutputTranslationMVELContextKey.mfa.name(), usedAuthenticators.size() > 1);
ret.putAll(getAuthnContextMvelVariables(loginSession.getFirstFactorRemoteIdPAuthnContext()));
} else
{
ret.put(OutputTranslationMVELContextKey.authenticatedWith.name(), new ArrayList());
ret.put(OutputTranslationMVELContextKey.idp.name(), null);
}
return ret;
}
private static Map getAuthnContextMvelVariables(RemoteAuthnMetadata authnContext)
{
Map ret = new HashMap<>();
List acrs = new ArrayList<>();
String upstreamProtocol = OutputTranslationMVELContextKey.DEFAULT_UPSTREAM_PROTOCOL;
String upstreamIdP = null;
if (authnContext != null)
{
acrs.addAll(authnContext.classReferences());
upstreamIdP = authnContext.remoteIdPId();
upstreamProtocol = authnContext.protocol().name();
}
ret.put(OutputTranslationMVELContextKey.upstreamACRs.name(), acrs);
ret.put(OutputTranslationMVELContextKey.upstreamProtocol.name(), upstreamProtocol);
ret.put(OutputTranslationMVELContextKey.upstreamIdP.name(), upstreamIdP);
return ret;
}
private static void addAttributesToContext(String attrKey, String attrObjKey, String attrsKey, Map ret,
Collection 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);
}
@Override
protected OutputTranslationRule createRule(TranslationActionInstance action,
TranslationCondition condition)
{
if (!(action instanceof OutputTranslationAction))
{
throw new InternalException(
"The translation action of the input translation "
+ "profile is not compatible with it, it is "
+ action.getClass());
}
return new OutputTranslationRule((OutputTranslationAction) action, condition);
}
private TranslationResult invokeOutputTranslationProfile(String profile,
TranslationInput input, TranslationResult translationState)
throws EngineException
{
TranslationProfile translationProfile = profileRepo.listAllProfiles()
.get(profile);
if (translationProfile == null)
throw new ConfigurationException("The output translation profile '"
+ profile + "' included in another profile does not exist");
OutputTranslationProfile profileInstance = new OutputTranslationProfile(
translationProfile, profileRepo, registry, attrConverter, groupMan);
TranslationResult result = profileInstance.translate(input, translationState);
return result;
}
private GroupsChain getGroupChain(String g)
{
try
{
return groupMan.getGroupsChain(g);
} catch (EngineException e)
{
log.error("Can not get group", e);
throw new RuntimeEngineException(e);
}
}
}