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 | r...@uvic.ca

-- 
- 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 cas-user+unsubscr...@apereo.org.
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