package org.apereo.cas.pm.web.flow; import org.apereo.cas.pm.PasswordChangeBean; import org.apereo.cas.web.flow.AbstractCasWebflowConfigurer; import org.apereo.cas.web.flow.CasWebflowConstants; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; import org.springframework.webflow.engine.ActionState; import org.springframework.webflow.engine.Flow; import org.springframework.webflow.engine.Transition; import org.springframework.webflow.engine.ViewState; import org.springframework.webflow.engine.builder.BinderConfiguration; import org.springframework.webflow.engine.builder.support.FlowBuilderServices; import org.springframework.webflow.execution.Action; import java.util.Arrays; /** * This is {@link PasswordManagementWebflowConfigurer}. * * @author Misagh Moayyed * @since 5.0.0 */ public class PasswordManagementWebflowConfigurer extends AbstractCasWebflowConfigurer { /** * Flow id for password reset. */ public static final String FLOW_ID_PASSWORD_RESET = "pswdreset"; /** * Flow id for password reset. */ public static final String FLOW_VAR_ID_PASSWORD = "password"; private static final String PASSWORD_CHANGE_ACTION = "passwordChangeAction"; private static final String SEND_PASSWORD_RESET_INSTRUCTIONS_ACTION = "sendInstructions"; @Autowired @Qualifier("initPasswordChangeAction") private Action passwordChangeAction; public PasswordManagementWebflowConfigurer(final FlowBuilderServices flowBuilderServices, final FlowDefinitionRegistry loginFlowDefinitionRegistry) { super(flowBuilderServices, loginFlowDefinitionRegistry); } @Override protected void doInitialize() throws Exception { final Flow flow = getLoginFlow(); if (flow != null) { createViewState(flow, CasWebflowConstants.VIEW_ID_AUTHENTICATION_BLOCKED, CasWebflowConstants.VIEW_ID_AUTHENTICATION_BLOCKED); createViewState(flow, CasWebflowConstants.VIEW_ID_INVALID_WORKSTATION, CasWebflowConstants.VIEW_ID_INVALID_WORKSTATION); createViewState(flow, CasWebflowConstants.VIEW_ID_INVALID_AUTHENTICATION_HOURS, CasWebflowConstants.VIEW_ID_INVALID_AUTHENTICATION_HOURS); createViewState(flow, CasWebflowConstants.VIEW_ID_ACCOUNT_LOCKED, CasWebflowConstants.VIEW_ID_ACCOUNT_LOCKED); createViewState(flow, CasWebflowConstants.VIEW_ID_ACCOUNT_DISABLED, CasWebflowConstants.VIEW_ID_ACCOUNT_DISABLED); createEndState(flow, CasWebflowConstants.VIEW_ID_PASSWORD_UPDATE_SUCCESS, CasWebflowConstants.VIEW_ID_PASSWORD_UPDATE_SUCCESS); if (casProperties.getAuthn().getPm().isEnabled()) { configure(flow, CasWebflowConstants.VIEW_ID_ACCOUNT_DISABLED); configure(flow, CasWebflowConstants.VIEW_ID_EXPIRED_PASSWORD); configurePasswordReset(); } else { createViewState(flow, CasWebflowConstants.VIEW_ID_ACCOUNT_DISABLED, CasWebflowConstants.VIEW_ID_ACCOUNT_DISABLED); createViewState(flow, CasWebflowConstants.VIEW_ID_EXPIRED_PASSWORD, CasWebflowConstants.VIEW_ID_EXPIRED_PASSWORD); } } } private void configurePasswordReset() { final Flow flow = getLoginFlow(); if (flow != null) { final ViewState state = (ViewState) flow.getState(CasWebflowConstants.STATE_ID_VIEW_LOGIN_FORM); createTransitionForState(state, CasWebflowConstants.TRANSITION_ID_RESET_PASSWORD, CasWebflowConstants.VIEW_ID_SEND_RESET_PASSWORD_ACCT_INFO); final ViewState accountInfo = createViewState(flow, CasWebflowConstants.VIEW_ID_SEND_RESET_PASSWORD_ACCT_INFO, CasWebflowConstants.VIEW_ID_SEND_RESET_PASSWORD_ACCT_INFO); createTransitionForState(accountInfo, "findAccount", SEND_PASSWORD_RESET_INSTRUCTIONS_ACTION); final ActionState sendInst = createActionState(flow, SEND_PASSWORD_RESET_INSTRUCTIONS_ACTION, createEvaluateAction("sendPasswordResetInstructionsAction")); createTransitionForState(sendInst, CasWebflowConstants.TRANSITION_ID_SUCCESS, CasWebflowConstants.VIEW_ID_SENT_RESET_PASSWORD_ACCT_INFO); createTransitionForState(sendInst, CasWebflowConstants.TRANSITION_ID_ERROR, accountInfo.getId()); createViewState(flow, CasWebflowConstants.VIEW_ID_SENT_RESET_PASSWORD_ACCT_INFO, CasWebflowConstants.VIEW_ID_SENT_RESET_PASSWORD_ACCT_INFO); final Flow pswdFlow = buildFlow("classpath:/webflow/pswdreset/pswdreset-webflow.xml", FLOW_ID_PASSWORD_RESET); createViewState(pswdFlow, "passwordResetErrorView", CasWebflowConstants.VIEW_ID_PASSORD_RESET_ERROR); createEndState(pswdFlow, CasWebflowConstants.STATE_ID_PASSWORD_UPDATE_SUCCESS, CasWebflowConstants.VIEW_ID_PASSWORD_UPDATE_SUCCESS); configure(pswdFlow, CasWebflowConstants.VIEW_ID_MUST_CHANGE_PASSWORD); loginFlowDefinitionRegistry.registerFlowDefinition(pswdFlow); } } private void configure(final Flow flow, final String id) { createFlowVariable(flow, FLOW_VAR_ID_PASSWORD, PasswordChangeBean.class); final BinderConfiguration binder = createStateBinderConfiguration(Arrays.asList(FLOW_VAR_ID_PASSWORD, "confirmedPassword")); final ViewState viewState = createViewState(flow, id, id, binder); createStateModelBinding(viewState, FLOW_VAR_ID_PASSWORD, PasswordChangeBean.class); viewState.getEntryActionList().add(this.passwordChangeAction); final Transition transition = createTransitionForState(viewState, CasWebflowConstants.TRANSITION_ID_SUBMIT, PASSWORD_CHANGE_ACTION); transition.getAttributes().put("bind", Boolean.TRUE); transition.getAttributes().put("validate", Boolean.TRUE); createStateDefaultTransition(viewState, id); final ActionState pswChangeAction = createActionState(flow, PASSWORD_CHANGE_ACTION, createEvaluateAction(PASSWORD_CHANGE_ACTION)); pswChangeAction.getTransitionSet().add( createTransition(PasswordChangeAction.PASSWORD_UPDATE_SUCCESS, CasWebflowConstants.STATE_ID_PASSWORD_UPDATE_SUCCESS)); pswChangeAction.getTransitionSet().add(createTransition(CasWebflowConstants.TRANSITION_ID_ERROR, id)); } }