Przeglądaj źródła

remove SMSFIRST, EMAILFIRST and BOTH token send methods

Jason Rivard 7 lat temu
rodzic
commit
f193d53b29

+ 27 - 11
server/src/main/java/password/pwm/config/Configuration.java

@@ -109,6 +109,15 @@ public class Configuration implements SettingReader {
         this.storedConfiguration = storedConfiguration;
     }
 
+    public static void deprecatedSettingException(final PwmSetting pwmSetting, final String profile, final MessageSendMethod value)
+    {
+        if (value != null && value.isDeprecated()) {
+            final String msg = pwmSetting.toMenuLocationDebug(profile, PwmConstants.DEFAULT_LOCALE)
+                    + " setting is using a no longer functional setting value: " + value;
+            throw new IllegalStateException(msg);
+        }
+    }
+
     public String toDebugString() {
         final StringBuilder outputText = new StringBuilder();
         outputText.append("  ");
@@ -162,7 +171,12 @@ public class Configuration implements SettingReader {
 
     public <E extends Enum<E>> E readSettingAsEnum(final PwmSetting setting, final Class<E> enumClass) {
         final StoredValue value = readStoredValue(setting);
-        return JavaTypeConverter.valueToEnum(setting, value, enumClass);
+        final E returnValue =  JavaTypeConverter.valueToEnum(setting, value, enumClass);
+        if (MessageSendMethod.class.equals(enumClass)) {
+            deprecatedSettingException(setting, null, (MessageSendMethod) returnValue);
+        }
+
+        return returnValue;
     }
 
     public <E extends Enum<E>> Set<E> readSettingAsOptionList(final PwmSetting setting, final Class<E> enumClass) {
@@ -371,15 +385,17 @@ public class Configuration implements SettingReader {
                 throw new IllegalArgumentException("may not read SELECT enum value for setting: " + setting.toString());
             }
 
-            final String strValue = (String)value.toNativeObject();
-            try {
-                return (E)enumClass.getMethod("valueOf", String.class).invoke(null, strValue);
-            } catch (InvocationTargetException e1) {
-                if (e1.getCause() instanceof IllegalArgumentException) {
-                    LOGGER.error("illegal setting value for option '" + strValue + "' for setting key '" + setting.getKey() + "' is not recognized, will use default");
+            if (value != null) {
+                final String strValue = (String) value.toNativeObject();
+                try {
+                    return (E) enumClass.getMethod("valueOf", String.class).invoke(null, strValue);
+                } catch (InvocationTargetException e1) {
+                    if (e1.getCause() instanceof IllegalArgumentException) {
+                        LOGGER.error("illegal setting value for option '" + strValue + "' for setting key '" + setting.getKey() + "' is not recognized, will use default");
+                    }
+                } catch (Exception e1) {
+                    LOGGER.error("unexpected error", e1);
                 }
-            } catch (Exception e1) {
-                LOGGER.error("unexpected error", e1);
             }
 
             return null;
@@ -907,7 +923,7 @@ public class Configuration implements SettingReader {
             case ForgottenPassword:
                 newProfile = ForgottenPasswordProfile.makeFromStoredConfiguration(storedConfiguration, profileID);
                 break;
-            
+
             case NewUser:
                 newProfile = NewUserProfile.makeFromStoredConfiguration(storedConfiguration, profileID);
                 break;
@@ -937,7 +953,7 @@ public class Configuration implements SettingReader {
     }
 
     public String configurationHash()
-            throws PwmUnrecoverableException 
+            throws PwmUnrecoverableException
     {
         if (this.cashedConfigurationHash == null) {
             this.cashedConfigurationHash = storedConfiguration.settingChecksum();

+ 26 - 7
server/src/main/java/password/pwm/config/option/MessageSendMethod.java

@@ -23,11 +23,30 @@
 package password.pwm.config.option;
 
 public enum MessageSendMethod implements ConfigurationOption {
-    NONE,
-    EMAILONLY,
-    BOTH,
-    EMAILFIRST,
-    SMSFIRST,
-    SMSONLY,
-    CHOICE_SMS_EMAIL,
+    NONE(false),
+
+    EMAILONLY(false),
+    SMSONLY(false),
+    CHOICE_SMS_EMAIL(false),
+
+    @Deprecated
+    BOTH(true),         //deprecated oct 2017
+
+    @Deprecated
+    EMAILFIRST(true),   //deprecated oct 2017
+
+    @Deprecated
+    SMSFIRST(true),     //deprecated oct 2017
+
+    ;
+
+    private final boolean deprecated;
+
+    MessageSendMethod(final boolean deprecated) {
+        this.deprecated = deprecated;
+    }
+
+    public boolean isDeprecated() {
+        return deprecated;
+    }
 }

+ 15 - 8
server/src/main/java/password/pwm/config/profile/AbstractProfile.java

@@ -22,18 +22,19 @@
 
 package password.pwm.config.profile;
 
-import password.pwm.config.value.data.ActionConfiguration;
 import password.pwm.config.Configuration;
-import password.pwm.config.value.data.FormConfiguration;
 import password.pwm.config.PwmSetting;
 import password.pwm.config.PwmSettingCategory;
 import password.pwm.config.PwmSettingSyntax;
 import password.pwm.config.SettingReader;
 import password.pwm.config.StoredValue;
-import password.pwm.config.value.data.UserPermission;
 import password.pwm.config.option.IdentityVerificationMethod;
+import password.pwm.config.option.MessageSendMethod;
 import password.pwm.config.stored.StoredConfiguration;
 import password.pwm.config.value.VerificationMethodValue;
+import password.pwm.config.value.data.ActionConfiguration;
+import password.pwm.config.value.data.FormConfiguration;
+import password.pwm.config.value.data.UserPermission;
 import password.pwm.util.PasswordData;
 
 import java.security.cert.X509Certificate;
@@ -49,10 +50,10 @@ import java.util.Set;
 
 public abstract class AbstractProfile implements Profile, SettingReader {
 
-    protected final String identifier;
-    protected final Map<PwmSetting,StoredValue> storedValueMap;
+    private final String identifier;
+    final Map<PwmSetting,StoredValue> storedValueMap;
 
-    protected AbstractProfile(final String identifier, final Map<PwmSetting, StoredValue> storedValueMap) {
+    AbstractProfile(final String identifier, final Map<PwmSetting, StoredValue> storedValueMap) {
         this.identifier = identifier;
         this.storedValueMap = storedValueMap;
     }
@@ -88,7 +89,13 @@ public abstract class AbstractProfile implements Profile, SettingReader {
 
     @Override
     public <E extends Enum<E>> E readSettingAsEnum(final PwmSetting setting, final Class<E> enumClass) {
-        return Configuration.JavaTypeConverter.valueToEnum(setting, storedValueMap.get(setting), enumClass);
+        final StoredValue value = storedValueMap.get(setting);
+        final E returnValue =  Configuration.JavaTypeConverter.valueToEnum(setting, value, enumClass);
+        if (MessageSendMethod.class.equals(enumClass)) {
+            Configuration.deprecatedSettingException(setting, this.getIdentifier(), (MessageSendMethod) returnValue);
+        }
+
+        return returnValue;
     }
 
     public List<ActionConfiguration> readSettingAsAction(final PwmSetting setting) {
@@ -150,7 +157,7 @@ public abstract class AbstractProfile implements Profile, SettingReader {
         return valueMap;
     }
 
-    public Set<IdentityVerificationMethod> readVerificationMethods(final PwmSetting pwmSetting, final VerificationMethodValue.EnabledState enabledState) {
+    Set<IdentityVerificationMethod> readVerificationMethods(final PwmSetting pwmSetting, final VerificationMethodValue.EnabledState enabledState) {
         final Set<IdentityVerificationMethod> result = new LinkedHashSet<>();
         final StoredValue configValue = storedValueMap.get(pwmSetting);
         final VerificationMethodValue.VerificationMethodSettings verificationMethodSettings = (VerificationMethodValue.VerificationMethodSettings)configValue.toNativeObject();

+ 1 - 1
server/src/main/java/password/pwm/config/profile/LdapProfile.java

@@ -96,7 +96,7 @@ public class LdapProfile extends AbstractProfile implements Profile {
     @Override
     public String getDisplayName(final Locale locale) {
         final String displayName = readSettingAsLocalizedString(PwmSetting.LDAP_PROFILE_DISPLAY_NAME,locale);
-        return displayName == null || displayName.length() < 1 ? identifier : displayName;
+        return displayName == null || displayName.length() < 1 ? getIdentifier() : displayName;
     }
 
     public String getUsernameAttribute() {

+ 75 - 1
server/src/main/java/password/pwm/health/ConfigurationChecker.java

@@ -31,6 +31,9 @@ import password.pwm.config.Configuration;
 import password.pwm.config.PwmSetting;
 import password.pwm.config.PwmSettingSyntax;
 import password.pwm.config.option.DataStorageMethod;
+import password.pwm.config.option.MessageSendMethod;
+import password.pwm.config.profile.ForgottenPasswordProfile;
+import password.pwm.config.profile.HelpdeskProfile;
 import password.pwm.config.profile.LdapProfile;
 import password.pwm.config.profile.NewUserProfile;
 import password.pwm.config.profile.PwmPasswordPolicy;
@@ -49,6 +52,8 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 public class ConfigurationChecker implements HealthChecker {
     private static final PwmLogger LOGGER = PwmLogger.forClass(ConfigurationChecker.class);
@@ -224,7 +229,8 @@ public class ConfigurationChecker implements HealthChecker {
     private static final List<Class<? extends ConfigHealthCheck>> ALL_CHECKS = Collections.unmodifiableList(Arrays.asList(
             VerifyPasswordPolicyConfigs.class,
             VerifyResponseLdapAttribute.class,
-            VerifyDbConfiguredIfNeeded.class
+            VerifyDbConfiguredIfNeeded.class,
+            VerifyIfDeprecatedSendMethodValuesUsed.class
     ));
 
     static class VerifyResponseLdapAttribute implements ConfigHealthCheck {
@@ -294,6 +300,74 @@ public class ConfigurationChecker implements HealthChecker {
         }
     }
 
+    static class VerifyIfDeprecatedSendMethodValuesUsed implements ConfigHealthCheck {
+        @Override
+        public List<HealthRecord> healthCheck(final Configuration config, final Locale locale) {
+            final Set<MessageSendMethod> deprecatedMethods = Arrays
+                    .stream(MessageSendMethod.values())
+                    .filter(MessageSendMethod::isDeprecated)
+                    .collect(Collectors.toSet());
+
+            final List<HealthRecord> records = new ArrayList<>();
+
+            {
+                final MessageSendMethod method = config.readSettingAsEnum(PwmSetting.ACTIVATE_TOKEN_SEND_METHOD, MessageSendMethod.class);
+                if (deprecatedMethods.contains(method)) {
+                    records.add(HealthRecord.forMessage(HealthMessage.Config_InvalidSendMethod,
+                            method.toString(),
+                            PwmSetting.ACTIVATE_TOKEN_SEND_METHOD.toMenuLocationDebug(null, locale)
+                    ));
+                }
+            }
+
+            {
+                final MessageSendMethod method = config.readSettingAsEnum(PwmSetting.FORGOTTEN_USERNAME_SEND_USERNAME_METHOD, MessageSendMethod.class);
+                if (deprecatedMethods.contains(method)) {
+                    records.add(HealthRecord.forMessage(HealthMessage.Config_InvalidSendMethod,
+                            method.toString(),
+                            PwmSetting.FORGOTTEN_USERNAME_SEND_USERNAME_METHOD.toMenuLocationDebug(null, locale)
+                    ));
+                }
+            }
+
+            for (final HelpdeskProfile helpdeskProfile : config.getHelpdeskProfiles().values()) {
+                final MessageSendMethod method = helpdeskProfile.readSettingAsEnum(PwmSetting.HELPDESK_TOKEN_SEND_METHOD, MessageSendMethod.class);
+
+                if (deprecatedMethods.contains(method)) {
+                    records.add(HealthRecord.forMessage(HealthMessage.Config_InvalidSendMethod,
+                            method.toString(),
+                            PwmSetting.HELPDESK_TOKEN_SEND_METHOD.toMenuLocationDebug(helpdeskProfile.getIdentifier(), locale)
+                    ));
+                }
+            }
+
+            for (final ForgottenPasswordProfile forgottenPasswordProfile : config.getForgottenPasswordProfiles().values()) {
+                {
+                    final MessageSendMethod method = forgottenPasswordProfile.readSettingAsEnum(PwmSetting.RECOVERY_SENDNEWPW_METHOD, MessageSendMethod.class);
+
+                    if (deprecatedMethods.contains(method)) {
+                        records.add(HealthRecord.forMessage(HealthMessage.Config_InvalidSendMethod,
+                                method.toString(),
+                                PwmSetting.RECOVERY_SENDNEWPW_METHOD.toMenuLocationDebug(forgottenPasswordProfile.getIdentifier(), locale)
+                        ));
+                    }
+                }
+                {
+                    final MessageSendMethod method = forgottenPasswordProfile.readSettingAsEnum(PwmSetting.RECOVERY_TOKEN_SEND_METHOD, MessageSendMethod.class);
+
+                    if (deprecatedMethods.contains(method)) {
+                        records.add(HealthRecord.forMessage(HealthMessage.Config_InvalidSendMethod,
+                                method.toString(),
+                                PwmSetting.RECOVERY_TOKEN_SEND_METHOD.toMenuLocationDebug(forgottenPasswordProfile.getIdentifier(), locale)
+                        ));
+                    }
+                }
+            }
+
+            return records;
+        }
+    }
+
     interface ConfigHealthCheck {
         List<HealthRecord> healthCheck(
                  Configuration configuration,

+ 1 - 0
server/src/main/java/password/pwm/health/HealthMessage.java

@@ -67,6 +67,7 @@ public enum HealthMessage {
     Config_DNValueValidity                  (HealthStatus.CONFIG,   HealthTopic.Configuration),
     Config_NoRecoveryEnabled                (HealthStatus.CAUTION,  HealthTopic.Configuration),
     Config_Certificate                      (HealthStatus.WARN,     HealthTopic.Configuration),
+    Config_InvalidSendMethod                (HealthStatus.CAUTION,  HealthTopic.Configuration),
     LDAP_VendorsNotSame                     (HealthStatus.CONFIG,   HealthTopic.LDAP),
     LDAP_OK                                 (HealthStatus.GOOD,     HealthTopic.LDAP),
     LDAP_RecentlyUnreachable                (HealthStatus.CAUTION,  HealthTopic.LDAP),

+ 7 - 163
server/src/main/java/password/pwm/http/bean/ForgottenPasswordBean.java

@@ -24,6 +24,9 @@ package password.pwm.http.bean;
 
 import com.google.gson.annotations.SerializedName;
 import com.novell.ldapchai.cr.ChallengeSet;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.Value;
 import password.pwm.VerificationMethodSystem;
 import password.pwm.bean.UserIdentity;
 import password.pwm.config.value.data.FormConfiguration;
@@ -41,6 +44,7 @@ import java.util.Set;
 /**
  * @author Jason D. Rivard
  */
+@Data
 public class ForgottenPasswordBean extends PwmSessionBean {
 
     @SerializedName("u")
@@ -64,65 +68,7 @@ public class ForgottenPasswordBean extends PwmSessionBean {
     @SerializedName("fp")
     private String forgottenPasswordProfileID;
 
-
-    public UserIdentity getUserIdentity() {
-        return userIdentity;
-    }
-
-    public void setUserIdentity(final UserIdentity userIdentity) {
-        this.userIdentity = userIdentity;
-    }
-
-    public Locale getUserLocale()
-    {
-        return userLocale;
-    }
-
-    public void setUserLocale(final Locale userLocale)
-    {
-        this.userLocale = userLocale;
-    }
-
-    public Progress getProgress()
-    {
-        return progress;
-    }
-
-    public ChallengeSet getPresentableChallengeSet()
-    {
-        return presentableChallengeSet;
-    }
-
-    public void setPresentableChallengeSet(final ChallengeSet presentableChallengeSet)
-    {
-        this.presentableChallengeSet = presentableChallengeSet;
-    }
-
-    public List<FormConfiguration> getAttributeForm()
-    {
-        return attributeForm;
-    }
-
-    public void setAttributeForm(final List<FormConfiguration> attributeForm)
-    {
-        this.attributeForm = attributeForm;
-    }
-
-    public void setProgress(final Progress progress)
-    {
-        this.progress = progress;
-    }
-
-    public RecoveryFlags getRecoveryFlags()
-    {
-        return recoveryFlags;
-    }
-
-    public void setRecoveryFlags(final RecoveryFlags recoveryFlags)
-    {
-        this.recoveryFlags = recoveryFlags;
-    }
-
+    @Data
     public static class Progress implements Serializable {
         @SerializedName("s")
         private boolean tokenSent;
@@ -144,66 +90,6 @@ public class ForgottenPasswordBean extends PwmSessionBean {
 
         private transient VerificationMethodSystem remoteRecoveryMethod;
 
-        public Set<IdentityVerificationMethod> getSatisfiedMethods() {
-            return satisfiedMethods;
-        }
-
-        public boolean isTokenSent()
-        {
-            return tokenSent;
-        }
-
-        public void setTokenSent(final boolean tokenSent)
-        {
-            this.tokenSent = tokenSent;
-        }
-
-        public boolean isAllPassed()
-        {
-            return allPassed;
-        }
-
-        public void setAllPassed(final boolean allPassed)
-        {
-            this.allPassed = allPassed;
-        }
-
-        public MessageSendMethod getTokenSendChoice()
-        {
-            return tokenSendChoice;
-        }
-
-        public void setTokenSendChoice(final MessageSendMethod tokenSendChoice)
-        {
-            this.tokenSendChoice = tokenSendChoice;
-        }
-
-        public String getTokenSentAddress()
-        {
-            return tokenSentAddress;
-        }
-
-        public void setTokenSentAddress(final String tokenSentAddress)
-        {
-            this.tokenSentAddress = tokenSentAddress;
-        }
-
-        public IdentityVerificationMethod getInProgressVerificationMethod() {
-            return inProgressVerificationMethod;
-        }
-
-        public void setInProgressVerificationMethod(final IdentityVerificationMethod inProgressVerificationMethod) {
-            this.inProgressVerificationMethod = inProgressVerificationMethod;
-        }
-
-        public VerificationMethodSystem getRemoteRecoveryMethod() {
-            return remoteRecoveryMethod;
-        }
-
-        public void setRemoteRecoveryMethod(final VerificationMethodSystem remoteRecoveryMethod) {
-            this.remoteRecoveryMethod = remoteRecoveryMethod;
-        }
-
         public void clearTokenSentStatus() {
             this.setTokenSent(false);
             this.setTokenSentAddress(null);
@@ -211,6 +97,8 @@ public class ForgottenPasswordBean extends PwmSessionBean {
         }
     }
 
+    @Value
+    @AllArgsConstructor
     public static class RecoveryFlags implements Serializable {
         @SerializedName("a")
         private final boolean allowWhenLdapIntruderLocked;
@@ -235,50 +123,6 @@ public class ForgottenPasswordBean extends PwmSessionBean {
             this.minimumOptionalAuthMethods = 0;
             this.tokenSendMethod = MessageSendMethod.NONE;
         }
-
-        public RecoveryFlags(
-                final Set<IdentityVerificationMethod> requiredAuthMethods,
-                final Set<IdentityVerificationMethod> optionalAuthMethods,
-                final int minimumOptionalAuthMethods,
-                final boolean allowWhenLdapIntruderLocked,
-                final MessageSendMethod tokenSendMethod
-        )
-        {
-            this.requiredAuthMethods = Collections.unmodifiableSet(requiredAuthMethods);
-            this.optionalAuthMethods = Collections.unmodifiableSet(optionalAuthMethods);
-            this.minimumOptionalAuthMethods = minimumOptionalAuthMethods;
-            this.allowWhenLdapIntruderLocked = allowWhenLdapIntruderLocked;
-            this.tokenSendMethod = tokenSendMethod;
-        }
-
-        public Set<IdentityVerificationMethod> getRequiredAuthMethods() {
-            return requiredAuthMethods;
-        }
-
-        public boolean isAllowWhenLdapIntruderLocked()
-        {
-            return allowWhenLdapIntruderLocked;
-        }
-
-        public MessageSendMethod getTokenSendMethod() {
-            return tokenSendMethod;
-        }
-
-        public Set<IdentityVerificationMethod> getOptionalAuthMethods() {
-            return optionalAuthMethods;
-        }
-
-        public int getMinimumOptionalAuthMethods() {
-            return minimumOptionalAuthMethods;
-        }
-    }
-
-    public String getForgottenPasswordProfileID() {
-        return forgottenPasswordProfileID;
-    }
-
-    public void setForgottenPasswordProfileID(final String forgottenPasswordProfileID) {
-        this.forgottenPasswordProfileID = forgottenPasswordProfileID;
     }
 
     public Type getType() {

+ 1 - 14
server/src/main/java/password/pwm/http/servlet/ActivateUserServlet.java

@@ -512,22 +512,9 @@ public class ActivateUserServlet extends AbstractPwmServlet {
         final Configuration config = pwmApplication.getConfig();
         final UserInfo userInfo = pwmSession.getUserInfo();
         final MessageSendMethod pref = MessageSendMethod.valueOf(config.readSettingAsString(PwmSetting.ACTIVATE_TOKEN_SEND_METHOD));
+
         final boolean success;
         switch (pref) {
-            case BOTH:
-                // Send both email and SMS, success if one of both succeeds
-                final boolean suc1 = sendPostActivationEmail(pwmRequest);
-                final boolean suc2 = sendPostActivationSms(pwmRequest);
-                success = suc1 || suc2;
-                break;
-            case EMAILFIRST:
-                // Send email first, try SMS if email is not available
-                success = sendPostActivationEmail(pwmRequest) || sendPostActivationSms(pwmRequest);
-                break;
-            case SMSFIRST:
-                // Send SMS first, try email if SMS is not available
-                success = sendPostActivationSms(pwmRequest) || sendPostActivationEmail(pwmRequest);
-                break;
             case SMSONLY:
                 // Only try SMS
                 success = sendPostActivationSms(pwmRequest);

+ 0 - 24
server/src/main/java/password/pwm/http/servlet/ForgottenUsernameServlet.java

@@ -276,30 +276,6 @@ public class ForgottenUsernameServlet extends AbstractPwmServlet {
             case NONE:
                 break;
 
-            case BOTH:
-                // Send both email and SMS, success if one of both succeeds
-                final ErrorInformation err1 = sendEmailViaMethod(pwmApplication, sessionLabel, userInfo, emailItemBean);
-                final ErrorInformation err2 = sendSmsViaMethod(pwmApplication, sessionLabel, userInfo, smsMessage);
-                if (err1 != null) {
-                    error = err1;
-                } else if (err2 != null) {
-                    error = err2;
-                }
-                break;
-            case EMAILFIRST:
-                // Send email first, try SMS if email is not available
-                error = sendEmailViaMethod(pwmApplication, sessionLabel, userInfo, emailItemBean);
-                if (error != null) {
-                    error = sendSmsViaMethod(pwmApplication, sessionLabel, userInfo, smsMessage);
-                }
-                break;
-            case SMSFIRST:
-                // Send SMS first, try email if SMS is not available
-                error = sendSmsViaMethod(pwmApplication, sessionLabel, userInfo, smsMessage);
-                if (error != null) {
-                    error = sendEmailViaMethod(pwmApplication, sessionLabel, userInfo, emailItemBean);
-                }
-                break;
             case SMSONLY:
                 // Only try SMS
                 error = sendSmsViaMethod(pwmApplication, sessionLabel, userInfo, smsMessage);

+ 1 - 1
server/src/main/java/password/pwm/http/servlet/forgottenpw/ForgottenPasswordServlet.java

@@ -1295,10 +1295,10 @@ public class ForgottenPasswordServlet extends ControlledPwmServlet {
         final boolean allowWhenLdapIntruderLocked = forgottenPasswordProfile.readSettingAsBoolean(PwmSetting.RECOVERY_ALLOW_WHEN_LOCKED);
 
         return new ForgottenPasswordBean.RecoveryFlags(
+                allowWhenLdapIntruderLocked,
                 requiredRecoveryVerificationMethods,
                 optionalRecoveryVerificationMethods,
                 minimumOptionalRecoveryAuthMethods,
-                allowWhenLdapIntruderLocked,
                 tokenSendMethod
         );
     }

+ 2 - 2
server/src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskServlet.java

@@ -714,12 +714,12 @@ public class HelpdeskServlet extends ControlledPwmServlet {
         final String destEmailAddress = macroMachine.expandMacros(emailItemBean.getTo());
         final StringBuilder destDisplayString = new StringBuilder();
         if (destEmailAddress != null && !destEmailAddress.isEmpty()) {
-            if (tokenSendMethod == MessageSendMethod.BOTH || tokenSendMethod == MessageSendMethod.EMAILFIRST || tokenSendMethod == MessageSendMethod.EMAILONLY) {
+            if (tokenSendMethod == MessageSendMethod.EMAILONLY) {
                 destDisplayString.append(destEmailAddress);
             }
         }
         if (userInfo.getUserSmsNumber() != null && !userInfo.getUserSmsNumber().isEmpty()) {
-            if (tokenSendMethod == MessageSendMethod.BOTH || tokenSendMethod == MessageSendMethod.SMSFIRST || tokenSendMethod == MessageSendMethod.SMSONLY) {
+            if (tokenSendMethod == MessageSendMethod.SMSONLY) {
                 if (destDisplayString.length() > 0) {
                     destDisplayString.append(", ");
                 }

+ 6 - 39
server/src/main/java/password/pwm/svc/token/TokenService.java

@@ -445,9 +445,12 @@ public class TokenService implements PwmService {
             return true;
         }
 
-        if (configuration.readSettingAsBoolean(PwmSetting.ACTIVATE_USER_ENABLE) &&
-                MessageSendMethod.NONE != configuration.readSettingAsTokenSendMethod(PwmSetting.ACTIVATE_TOKEN_SEND_METHOD)) {
-            return true;
+
+        if (configuration.readSettingAsBoolean(PwmSetting.ACTIVATE_USER_ENABLE)) {
+            final MessageSendMethod activateMethod = configuration.readSettingAsEnum(PwmSetting.ACTIVATE_TOKEN_SEND_METHOD, MessageSendMethod.class);
+            if (MessageSendMethod.NONE != activateMethod) {
+                return true;
+            }
         }
 
         if (configuration.readSettingAsBoolean(PwmSetting.CHALLENGE_ENABLE)) {
@@ -634,42 +637,6 @@ public class TokenService implements PwmService {
                         // should never read here
                         LOGGER.error("attempt to send token to destination type 'NONE'");
                         throw new PwmUnrecoverableException(PwmError.ERROR_UNKNOWN);
-                    case BOTH:
-                        // Send both email and SMS, success if one of both succeeds
-                        final boolean suc1 = sendEmailToken(pwmApplication, userInfo, macroMachine, configuredEmailSetting, emailAddress, tokenKey);
-                        if (suc1) {
-                            sentTypes.add(TokenDestinationItem.Type.email);
-                        }
-                        final boolean suc2 = sendSmsToken(pwmApplication, userInfo, macroMachine, smsNumber, smsMessage, tokenKey);
-                        if (suc2) {
-                            sentTypes.add(TokenDestinationItem.Type.sms);
-                        }
-                        success = suc1 || suc2;
-                        break;
-                    case EMAILFIRST:
-                        // Send email first, try SMS if email is not available
-                        final boolean emailSuccess = sendEmailToken(pwmApplication, userInfo, macroMachine, configuredEmailSetting, emailAddress, tokenKey);
-                        if (emailSuccess) {
-                            success = true;
-                            sentTypes.add(TokenDestinationItem.Type.email);
-                        } else {
-                            success = sendSmsToken(pwmApplication, userInfo, macroMachine, smsNumber, smsMessage, tokenKey);
-                            if (success) {
-                                sentTypes.add(TokenDestinationItem.Type.sms);
-                            }
-                        }
-                        break;
-                    case SMSFIRST:
-                        // Send SMS first, try email if SMS is not available
-                        final boolean smsSuccess = sendSmsToken(pwmApplication, userInfo, macroMachine, smsNumber, smsMessage, tokenKey);
-                        if (smsSuccess) {
-                            success = true;
-                            sentTypes.add(TokenDestinationItem.Type.sms);
-                        } else {
-                            success = sendEmailToken(pwmApplication, userInfo, macroMachine, configuredEmailSetting, emailAddress, tokenKey);
-                            sentTypes.add(TokenDestinationItem.Type.email);
-                        }
-                        break;
                     case SMSONLY:
                         // Only try SMS
                         success = sendSmsToken(pwmApplication, userInfo, macroMachine, smsNumber, smsMessage, tokenKey);

+ 1 - 29
server/src/main/java/password/pwm/util/operations/PasswordUtility.java

@@ -120,36 +120,8 @@ public class PasswordUtility {
         final String smsNumber = userInfo.getUserSmsNumber();
         String returnToAddress = emailAddress;
 
-        ErrorInformation error = null;
+        final ErrorInformation error;
         switch (messageSendMethod) {
-            case BOTH:
-                // Send both email and SMS, success if one of both succeeds
-                final ErrorInformation err1 = sendNewPasswordEmail(userInfo, pwmApplication, macroMachine, newPassword, emailAddress, userLocale);
-                final ErrorInformation err2 = sendNewPasswordSms(userInfo, pwmApplication, macroMachine, newPassword, smsNumber, userLocale);
-                if (err1 != null) {
-                    error = err1;
-                    returnToAddress = smsNumber;
-                } else if (err2 != null) {
-                    error = err2;
-                }
-                break;
-            case EMAILFIRST:
-                // Send email first, try SMS if email is not available
-                error = sendNewPasswordEmail(userInfo, pwmApplication, macroMachine, newPassword, emailAddress, userLocale);
-                if (error != null) {
-                    error = sendNewPasswordSms(userInfo, pwmApplication, macroMachine, newPassword, smsNumber, userLocale);
-                    returnToAddress = smsNumber;
-                }
-                break;
-            case SMSFIRST:
-                // Send SMS first, try email if SMS is not available
-                error = sendNewPasswordSms(userInfo, pwmApplication, macroMachine, newPassword, smsNumber, userLocale);
-                if (error != null) {
-                    error = sendNewPasswordEmail(userInfo, pwmApplication, macroMachine, newPassword, emailAddress, userLocale);
-                } else {
-                    returnToAddress = smsNumber;
-                }
-                break;
             case SMSONLY:
                 // Only try SMS
                 error = sendNewPasswordSms(userInfo, pwmApplication, macroMachine, newPassword, smsNumber, userLocale);

+ 10 - 22
server/src/main/resources/password/pwm/config/PwmSetting.xml

@@ -2453,11 +2453,8 @@
             <value><![CDATA[EMAILONLY]]></value>
         </default>
         <options>
-            <option value="EMAILONLY">Email Only - Send to email address</option>
-            <option value="SMSONLY">SMS Only - Send via SMS</option>
-            <option value="BOTH">Both - Send token to both email and SMS</option>
-            <option value="EMAILFIRST">Email First - Try to send token via email; if no email address is available, send via SMS</option>
-            <option value="SMSFIRST">SMS First - Try to send token via SMS; if no SMS number is available, send via email</option>
+            <option value="EMAILONLY">Email - Send to email address</option>
+            <option value="SMSONLY">SMS - Send via SMS</option>
             <option value="CHOICE_SMS_EMAIL">User Choice - If both SMS and email address is available, user decides</option>
         </options>
     </setting>
@@ -2476,11 +2473,8 @@
             <value><![CDATA[EMAILONLY]]></value>
         </default>
         <options>
-            <option value="EMAILONLY">Email Only - Send to email address</option>
-            <option value="SMSONLY">SMS Only - Send via SMS</option>
-            <option value="BOTH">Both - Send token to both email and SMS</option>
-            <option value="EMAILFIRST">Email First - Try to send token via email; if no email address is available, send via SMS</option>
-            <option value="SMSFIRST">SMS First - Try to send token via SMS; if no SMS number is available, send via email</option>
+            <option value="EMAILONLY">Email - Send to email address</option>
+            <option value="SMSONLY">SMS - Send via SMS</option>
         </options>
     </setting>
     <setting hidden="false" key="recovery.postActions" level="2">
@@ -2547,11 +2541,8 @@
         </default>
         <options>
             <option value="NONE">None - Do not send email</option>
-            <option value="EMAILONLY">Email Only - Send to email address</option>
-            <option value="SMSONLY">SMS Only - Send via SMS</option>
-            <option value="BOTH">Both - Send token to both email and SMS</option>
-            <option value="EMAILFIRST">Email First - Try to send token via email; if no email address is available, send via SMS</option>
-            <option value="SMSFIRST">SMS First - Try to send token via SMS; if no SMS number is available, send via email</option>
+            <option value="EMAILONLY">Email - Send to email address</option>
+            <option value="SMSONLY">SMS - Send via SMS</option>
         </options>
     </setting>
     <setting hidden="false" key="newUser.enable" level="1" required="true">
@@ -2858,11 +2849,8 @@
         </default>
         <options>
             <option value="NONE">None - Token verification will not be performed</option>
-            <option value="EMAILONLY">Email Only - Send to email address</option>
-            <option value="SMSONLY">SMS Only - Send via SMS</option>
-            <option value="BOTH">Both - Send token to both email and SMS</option>
-            <option value="EMAILFIRST">Email First - Try to send token via email; if no email address is available, send via SMS</option>
-            <option value="SMSFIRST">SMS First - Try to send token via SMS; if no SMS number is available, send via email</option>
+            <option value="EMAILONLY">Email - Send to email address</option>
+            <option value="SMSONLY">SMS - Send via SMS</option>
         </options>
     </setting>
     <setting hidden="false" key="updateAttributes.enable" level="1" required="true">
@@ -3481,8 +3469,8 @@
         </default>
         <options>
             <option value="NONE">None - Token verification will not be available</option>
-            <option value="EMAILONLY">Email Only - Send to email address</option>
-            <option value="SMSONLY">SMS Only - Send via SMS</option>
+            <option value="EMAILONLY">Email - Send to email address</option>
+            <option value="SMSONLY">SMS - Send via SMS</option>
             <option value="CHOICE_SMS_EMAIL">Operator Choice - If both SMS and email address is available, helpdesk operator decides</option>
         </options>
     </setting>

+ 1 - 0
server/src/main/resources/password/pwm/i18n/Health.properties

@@ -57,6 +57,7 @@ HealthMessage_Config_PasswordPolicyProblem=Password policy '%1%' configuration a
 HealthMessage_Config_UserPermissionValidity=User Permission configuration for setting %1% issue: %2%.  This may cause unexpected issues.
 HealthMessage_Config_DNValueValidity=LDAP DN configuration setting %1% issue: %2%.  This may cause unexpected issues.
 HealthMessage_Config_Certificate=Certificate for setting %1% issue: %2%
+HealthMessage_Config_InvalidSendMethod=The send method '%1%' is no longer available for setting %2%.  Please modify the configuration to use an alternate value.
 HealthMessage_LDAP_VendorsNotSame=LDAP directories of different vendor types are in use.  This configuration may cause undesirable side effects and is not supported.  %1%
 HealthMessage_LDAP_Ad_History_Asn_Missing=%1% is enabled, but the server at %2% does not support this feature.  Check to be sure it is upgraded to Windows Server 2008 R2 SP1 or greater.  Password changes against this server may fail until this is resolved.
 HealthMessage_LDAP_RecentlyUnreachable=LDAP profile %1% was recently unavailable (%2% ago at %3%): %4%