Pablo,

In the attached file, I insert a send cookie action on login and a remove 
cookie action on logout. The steps mirror the xml changes.

Ray

On Sun, 2018-01-14 at 09:01 -0800, Pablo Vidaurri wrote:
I created a class that extends AbstractCasWebflowConfigurer to modify the 
webflow instead of modifying xml directly. I can define a new action-state with 
transitions but I can't seem to modify an already existing one.

For realSubmit action-state within login webflow:


<action-state id="realSubmit">
   <transition on="warn" to="warn"/>
   <transition on="success" to="sendTicketGrantingTicket"/>
   .
   .
   .
</action-state>

For "success", how can I programatically change the transition from 
"sendTicketGrantingTicket" to "doMyCustomAction"?
Would I have to define the entire action state or can I just update the single 
transition?

I have the org.springframework.webflow.engine.Flow Object but I don't see an 
appropriate method to update the transition.

Thanks.
-psv

--
Ray Bon
Programmer analyst
Development Services, University Systems
2507218831 | CLE 019 | [email protected]

-- 
- Website: https://apereo.github.io/cas
- Gitter Chatroom: https://gitter.im/apereo/cas
- List Guidelines: https://goo.gl/1VRrw7
- Contributions: https://goo.gl/mh7qDG
--- 
You received this message because you are subscribed to the Google Groups "CAS 
Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/a/apereo.org/d/msgid/cas-user/1516039864.1815.7.camel%40uvic.ca.
package org.apereo.cas.web.flow;

import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.web.flow.configurer.AbstractCasWebflowConfigurer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.webflow.definition.TransitionDefinition;
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
import org.springframework.webflow.engine.*;
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
import org.springframework.webflow.execution.Action;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
 * This is {@UvicSsoCookieWebflowConfigurer}.
 *
 * @author Ray Bon
 * @since 5.1.5
 */
public class UvicSsoCookieWebflowConfigurer extends AbstractCasWebflowConfigurer {

	private static final Logger LOGGER = LoggerFactory.getLogger(UvicSsoCookieWebflowConfigurer.class);

	@Autowired
	private SendUvicSsoCookieAction sendUvicSsoCookieAction;

	@Autowired
	private RemoveUvicSsoCookieAction removeUvicSsoCookieAction;

	public UvicSsoCookieWebflowConfigurer(final FlowBuilderServices flowBuilderServices,
										  final FlowDefinitionRegistry loginFlowDefinitionRegistry,
										  final ApplicationContext applicationContext,
										  final CasConfigurationProperties casProperties,
										  FlowDefinitionRegistry logoutFlowDefinitionRegistry) {
		super(flowBuilderServices, loginFlowDefinitionRegistry, applicationContext, casProperties);
		super.setLogoutFlowDefinitionRegistry(logoutFlowDefinitionRegistry);
	}

	@Override
	protected void doInitialize() {
		final Flow loginFlow = getLoginFlow();

		if (null != loginFlow) {
			LOGGER.debug("send uvic sso cookie do initialize");
			//LOGGER.debug("login flow before: " + loginFlow);
			insertSendUvicSsoCookie(loginFlow);
			//LOGGER.debug("login flow after:  " + getLoginFlow());
		}

		final Flow logoutFlow = getLogoutFlow();

		if ((null != logoutFlow) && (null != loginFlow)){
			LOGGER.debug("remove uvic sso cookie do initialize");
			//LOGGER.debug("logout flow before: " + logoutFlow);
			insertRemoveUvicSsoCookie(loginFlow, logoutFlow);
			//LOGGER.debug("login flow after:  " + getLoginFlow());
			//LOGGER.debug("logout flow after:  " + logoutFlow);
		}
	}

	/**
	 * Inserts a state into a transition for another state and sets the new state's matching transistion to
	 * the previous target (preserving the state flow). This method is currently hard coded to state success.
	 * @param insertAfterState this state will have its transition modified
	 * @param insertableState state to be inserted into the transition order
	 * @param insertAtTransisitonId id of the transition to be modifed
	 * @param insertableTransitionId transistion id of insertableState (is there a method to get this constant id?)
	 */
	private void insertStateIntoTransition(
			final TransitionableState insertAfterState,
			final TransitionableState insertableState,
			final String insertAtTransisitonId,
			final String insertableTransitionId) {
		TransitionDefinition td = insertAfterState.getTransition(insertAtTransisitonId);
		TransitionDefinition [] tds = insertAfterState.getTransitions();
		if (null == td) {
			LOGGER.warn("Transition, [{}], not found for [{}]. No insertion made.", insertAtTransisitonId, insertAfterState);
		} else {
			createTransitionForState(
					insertableState,
					CasWebflowConstants.STATE_ID_SUCCESS,
					td.getTargetStateId());
			createTransitionForState(
					insertAfterState,
					insertAtTransisitonId,
					insertableTransitionId,
					true);
		}
	}

	private void insertRemoveUvicSsoCookie(final Flow loginFlow, final Flow logoutFlow) {
		final ActionState terminateSessionLI = (ActionState) loginFlow.getState(
				CasWebflowConstants.STATE_ID_TERMINATE_SESSION);
		final ActionState terminateSessionLO = (ActionState) logoutFlow.getState(
				CasWebflowConstants.STATE_ID_TERMINATE_SESSION);
		final ActionState removeUvicSsoCookieActionStateLI = createActionState(
				loginFlow,
				RemoveUvicSsoCookieAction.STATE_ID_REMOVE_UVIC_SSO_COOKIE,
				removeUvicSsoCookieAction);
		final ActionState removeUvicSsoCookieActionStateLO = createActionState(
				logoutFlow,
				RemoveUvicSsoCookieAction.STATE_ID_REMOVE_UVIC_SSO_COOKIE,
				removeUvicSsoCookieAction);
		insertStateIntoTransition(terminateSessionLI, removeUvicSsoCookieActionStateLI, "*",
				RemoveUvicSsoCookieAction.STATE_ID_REMOVE_UVIC_SSO_COOKIE);
		insertStateIntoTransition(terminateSessionLO, removeUvicSsoCookieActionStateLO, "*",
				RemoveUvicSsoCookieAction.STATE_ID_REMOVE_UVIC_SSO_COOKIE);

		logAction(removeUvicSsoCookieActionStateLI);
		logAction(terminateSessionLI);
		logAction(removeUvicSsoCookieActionStateLO);
		logAction(terminateSessionLO);
	}

	private void insertSendUvicSsoCookie(final Flow loginFlow) {
		// TODO: perhaps this should be a subflow of send TGT see createSubflowState
		// then it would not need transition
		// otherwise uvic_sso transition should be the transisition of send TGT just in case its transistion was changed by another webflow element
		final ActionState sendUvicSsoCookieActionState = createActionState(
				loginFlow,
				SendUvicSsoCookieAction.STATE_ID_SEND_UVIC_SSO_COOKIE,
				sendUvicSsoCookieAction);
		final ActionState sendTGT = (ActionState) loginFlow.getState(
				CasWebflowConstants.STATE_ID_SEND_TICKET_GRANTING_TICKET);
		insertStateIntoTransition(sendTGT, sendUvicSsoCookieActionState, CasWebflowConstants.STATE_ID_SUCCESS,
				SendUvicSsoCookieAction.STATE_ID_SEND_UVIC_SSO_COOKIE);

		logAction(sendUvicSsoCookieActionState);
		logAction(sendTGT);
	}

	private void logAction(ActionState actionState) {
		LOGGER.debug("action state: " + actionState.getId());
		final TransitionDefinition [] tds = actionState.getTransitions();
		final List<Action> actions = StreamSupport.stream(actionState.getActionList().spliterator(), false)
				.collect(Collectors.toList());
		LOGGER.debug("\tnumber of transitions: " + tds.length);
		for (TransitionDefinition td : tds) {
			LOGGER.debug("\t\ttransition definition: " + td);
		}
		LOGGER.debug("\tnumber of actions: " + actions.size());
		actions.forEach(a -> LOGGER.debug("\t\taction: " + a));
	}
}

Reply via email to