Commit 1a8699a0 authored by michael.simon's avatar michael.simon
Browse files

add first idea of an user update hook, configurable per home org

parent 11a2ce08
package edu.kit.scc.webreg.hook;
import java.util.List;
import java.util.Map;
import edu.kit.scc.webreg.entity.ServiceEntity;
import edu.kit.scc.webreg.entity.UserEntity;
public interface UserUpdateHook {
void preUpdateUser(UserEntity user, Map<String, String> genericStore, Map<String, List<Object>> attributeMap, String executor,
ServiceEntity service, StringBuffer debugLog) throws UserUpdateHookException;
void postUpdateUser(UserEntity user, Map<String, String> genericStore, Map<String, List<Object>> attributeMap, String executor,
ServiceEntity service, StringBuffer debugLog) throws UserUpdateHookException;
}
package edu.kit.scc.webreg.hook;
public class UserUpdateHookException extends Exception {
private static final long serialVersionUID = 1L;
public UserUpdateHookException() {
super();
}
public UserUpdateHookException(String message, Throwable cause) {
super(message, cause);
}
public UserUpdateHookException(String message) {
super(message);
}
public UserUpdateHookException(Throwable cause) {
super(cause);
}
}
package edu.kit.scc.webreg.hook;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import edu.kit.scc.webreg.entity.ServiceEntity;
import edu.kit.scc.webreg.entity.UserEntity;
public class UserUpdateNullHook implements UserUpdateHook {
private static final Logger logger = LoggerFactory.getLogger(UserUpdateNullHook.class);
@Override
public void preUpdateUser(UserEntity user, Map<String, String> genericStore, Map<String, List<Object>> attributeMap, String executor,
ServiceEntity service, StringBuffer debugLog) {
logger.info("UserUpdateNullHook preUpdateUser called");
}
@Override
public void postUpdateUser(UserEntity user, Map<String, String> genericStore, Map<String, List<Object>> attributeMap, String executor,
ServiceEntity service, StringBuffer debugLog) {
logger.info("UserUpdateNullHook postUpdateUser called");
}
}
package edu.kit.scc.webreg.hook;
import java.util.List;
import java.util.Map;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import edu.kit.scc.webreg.entity.ScriptEntity;
import edu.kit.scc.webreg.entity.ServiceEntity;
import edu.kit.scc.webreg.entity.UserEntity;
import edu.kit.scc.webreg.script.ScriptingEnv;
import edu.kit.scc.webreg.service.reg.ScriptingWorkflow;
public class UserUpdateScriptHook implements UserUpdateHook, ScriptingWorkflow {
private static final Logger logger = LoggerFactory.getLogger(UserUpdateScriptHook.class);
protected ScriptingEnv scriptingEnv;
@Override
public void preUpdateUser(UserEntity user, Map<String, String> genericStore, Map<String, List<Object>> attributeMap, String executor,
ServiceEntity service, StringBuffer debugLog) throws UserUpdateHookException {
logger.debug("UserUpdateScriptHook preUpdateUser called");
Invocable invocable = resolveScript(genericStore);
try {
invocable.invokeFunction("preUpdateUser", scriptingEnv, user, genericStore, attributeMap, service, logger, debugLog);
} catch (NoSuchMethodException e) {
logger.info("No preUpdateUser Method. Skipping execution.");
} catch (ScriptException e) {
throw new UserUpdateHookException(e);
}
}
@Override
public void postUpdateUser(UserEntity user, Map<String, String> genericStore, Map<String, List<Object>> attributeMap, String executor,
ServiceEntity service, StringBuffer debugLog) throws UserUpdateHookException {
logger.debug("UserUpdateScriptHook postUpdateUser called");
Invocable invocable = resolveScript(genericStore);
try {
invocable.invokeFunction("preUpdateUser", scriptingEnv, user, genericStore, attributeMap, service, logger, debugLog);
} catch (NoSuchMethodException e) {
logger.info("No preUpdateUser Method. Skipping execution.");
} catch (ScriptException e) {
throw new UserUpdateHookException(e);
}
}
@Override
public void setScriptingEnv(ScriptingEnv env) {
this.scriptingEnv = env;
}
protected Invocable resolveScript(Map<String, String> genericStore) throws UserUpdateHookException {
if (genericStore.containsKey("user_update_hook_script")) {
String scriptName = genericStore.get("user_update_hook_script");
try {
ScriptEntity scriptEntity = scriptingEnv.getScriptDao().findByName(scriptName);
if (scriptEntity == null)
throw new UserUpdateHookException("user update hook not configured properly. script is missing.");
if (scriptEntity.getScriptType().equalsIgnoreCase("javascript")) {
ScriptEngine engine = (new ScriptEngineManager()).getEngineByName(scriptEntity.getScriptEngine());
if (engine == null)
throw new UserUpdateHookException("user update hook not configured properly. engine not found: " + scriptEntity.getScriptEngine());
engine.eval(scriptEntity.getScript());
Invocable invocable = (Invocable) engine;
return invocable;
}
else {
throw new UserUpdateHookException("unkown script type: " + scriptEntity.getScriptType());
}
} catch (ScriptException e) {
throw new UserUpdateHookException(e);
}
}
else {
throw new UserUpdateHookException("user_update_hook_script not configured");
}
}
}
......@@ -61,13 +61,17 @@ import edu.kit.scc.webreg.exc.EventSubmitException;
import edu.kit.scc.webreg.exc.MetadataException;
import edu.kit.scc.webreg.exc.RegisterException;
import edu.kit.scc.webreg.exc.UserUpdateException;
import edu.kit.scc.webreg.hook.UserUpdateHook;
import edu.kit.scc.webreg.hook.UserUpdateHookException;
import edu.kit.scc.webreg.logging.LogHelper;
import edu.kit.scc.webreg.script.ScriptingEnv;
import edu.kit.scc.webreg.service.SerialService;
import edu.kit.scc.webreg.service.ServiceService;
import edu.kit.scc.webreg.service.UserServiceHook;
import edu.kit.scc.webreg.service.group.HomeOrgGroupUpdater;
import edu.kit.scc.webreg.service.identity.IdentityUpdater;
import edu.kit.scc.webreg.service.reg.AttributeSourceQueryService;
import edu.kit.scc.webreg.service.reg.ScriptingWorkflow;
import edu.kit.scc.webreg.service.reg.impl.Registrator;
import edu.kit.scc.webreg.service.saml.AttributeQueryHelper;
import edu.kit.scc.webreg.service.saml.Saml2AssertionService;
......@@ -150,6 +154,9 @@ public class UserUpdater implements Serializable {
@Inject
private LogHelper logHelper;
@Inject
private ScriptingEnv scriptingEnv;
public SamlUserEntity updateUser(SamlUserEntity user, Map<String, List<Object>> attributeMap, String executor, StringBuffer debugLog)
throws UserUpdateException {
return updateUser(user, attributeMap, executor, null, debugLog);
......@@ -159,7 +166,7 @@ public class UserUpdater implements Serializable {
ServiceEntity service, StringBuffer debugLog)
throws UserUpdateException {
MDC.put("userId", "" + user.getId());
logger.debug("Updating user {}", user.getEppn());
logger.debug("Updating SAML user {}", user.getEppn());
user = userDao.merge(user);
......@@ -169,7 +176,30 @@ public class UserUpdater implements Serializable {
auditor.startAuditTrail(executor);
auditor.setName(getClass().getName() + "-UserUpdate-Audit");
auditor.setDetail("Update user " + user.getEppn());
UserUpdateHook updateHook = null;
if (user.getIdp().getGenericStore().containsKey("user_update_hook")) {
String hookClass = user.getIdp().getGenericStore().get("user_update_hook");
try {
updateHook = (UserUpdateHook) Class.forName(hookClass).getDeclaredConstructor().newInstance();
if (updateHook instanceof ScriptingWorkflow)
((ScriptingWorkflow) updateHook).setScriptingEnv(scriptingEnv);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException | SecurityException
| ClassNotFoundException e) {
logger.warn("Cannot instantiate updateHook class. This is probably a misconfiguration.");
}
}
if (updateHook != null) {
try {
updateHook.preUpdateUser(user, user.getGenericStore(), attributeMap, executor, service, debugLog);
} catch (UserUpdateHookException e) {
logger.warn("An exception happened while calling UserUpdateHook!", e);
}
}
// List to store parent services, that are not registered. Need to be registered
// later, when attribute map is populated
List<ServiceEntity> delayedRegisterList = new ArrayList<ServiceEntity>();
......@@ -285,7 +315,15 @@ public class UserUpdater implements Serializable {
logger.warn("Parent registration didn't work out like it should", e);
}
}
if (updateHook != null) {
try {
updateHook.postUpdateUser(user, user.getGenericStore(), attributeMap, executor, service, debugLog);
} catch (UserUpdateHookException e) {
logger.warn("An exception happened while calling UserUpdateHook!", e);
}
}
user.setLastUpdate(new Date());
user.setLastFailedUpdate(null);
user.setScheduledUpdate(getNextScheduledUpdate());
......
......@@ -232,7 +232,7 @@ public class OidcUserUpdater implements Serializable {
ServiceEntity service)
throws UserUpdateException {
MDC.put("userId", "" + user.getId());
logger.debug("Updating user {}", user.getEppn());
logger.debug("Updating OIDC user {}", user.getEppn());
user = userDao.merge(user);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment