瀏覽代碼

Merge remote-tracking branch 'origin/master' into hf-changes

James Albright 9 年之前
父節點
當前提交
a1956598ff

+ 11 - 11
src/main/java/password/pwm/util/macro/InternalMacros.java

@@ -27,23 +27,23 @@ import password.pwm.bean.UserInfoBean;
 import password.pwm.config.PwmSetting;
 import password.pwm.config.PwmSetting;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.logging.PwmLogger;
 
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Collections;
-import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.regex.Pattern;
 import java.util.regex.Pattern;
 
 
 public abstract class InternalMacros {
 public abstract class InternalMacros {
 
 
     private static final PwmLogger LOGGER = PwmLogger.forClass(InternalMacros.class);
     private static final PwmLogger LOGGER = PwmLogger.forClass(InternalMacros.class);
 
 
-    public static final List<Class<? extends MacroImplementation>> INTERNAL_MACROS;
+    public static final Map<Class<? extends MacroImplementation>,MacroImplementation.Scope> INTERNAL_MACROS;
     static {
     static {
-        final List<Class<? extends MacroImplementation>> defaultMacros = new ArrayList<>();
-        defaultMacros.add(OtpSetupTimeMacro.class);
-        defaultMacros.add(ResponseSetupTimeMacro.class);
-        defaultMacros.add(PwmSettingReference.class);
-        defaultMacros.add(PwmAppName.class);
-        INTERNAL_MACROS = Collections.unmodifiableList(defaultMacros);
+        final Map<Class<? extends MacroImplementation>,MacroImplementation.Scope>  defaultMacros = new HashMap<>();
+        defaultMacros.put(OtpSetupTimeMacro.class, MacroImplementation.Scope.Static);
+        defaultMacros.put(ResponseSetupTimeMacro.class, MacroImplementation.Scope.Static);
+        defaultMacros.put(PwmSettingReference.class, MacroImplementation.Scope.Static);
+        defaultMacros.put(PwmAppName.class, MacroImplementation.Scope.Static);
+        INTERNAL_MACROS = Collections.unmodifiableMap(defaultMacros);
     }
     }
 
 
     static abstract class InternalAbstractMacro extends AbstractMacro {
     static abstract class InternalAbstractMacro extends AbstractMacro {
@@ -66,7 +66,7 @@ public abstract class InternalMacros {
             if (userInfoBean != null && userInfoBean.getOtpUserRecord() != null && userInfoBean.getOtpUserRecord().getTimestamp() != null) {
             if (userInfoBean != null && userInfoBean.getOtpUserRecord() != null && userInfoBean.getOtpUserRecord().getTimestamp() != null) {
                 return PwmConstants.DEFAULT_DATETIME_FORMAT.format(userInfoBean.getOtpUserRecord().getTimestamp());
                 return PwmConstants.DEFAULT_DATETIME_FORMAT.format(userInfoBean.getOtpUserRecord().getTimestamp());
             }
             }
-            return null;
+            return "";
         }
         }
     }
     }
 
 
@@ -83,7 +83,7 @@ public abstract class InternalMacros {
             if (userInfoBean != null && userInfoBean.getResponseInfoBean() != null && userInfoBean.getResponseInfoBean().getTimestamp() != null) {
             if (userInfoBean != null && userInfoBean.getResponseInfoBean() != null && userInfoBean.getResponseInfoBean().getTimestamp() != null) {
                 return PwmConstants.DEFAULT_DATETIME_FORMAT.format(userInfoBean.getResponseInfoBean().getTimestamp());
                 return PwmConstants.DEFAULT_DATETIME_FORMAT.format(userInfoBean.getResponseInfoBean().getTimestamp());
             }
             }
-            return null;
+            return "";
         }
         }
     }
     }
 
 

+ 8 - 2
src/main/java/password/pwm/util/macro/MacroImplementation.java

@@ -23,15 +23,21 @@
 package password.pwm.util.macro;
 package password.pwm.util.macro;
 
 
 import password.pwm.PwmApplication;
 import password.pwm.PwmApplication;
-import password.pwm.bean.UserInfoBean;
 import password.pwm.bean.LoginInfoBean;
 import password.pwm.bean.LoginInfoBean;
+import password.pwm.bean.UserInfoBean;
 import password.pwm.ldap.UserDataReader;
 import password.pwm.ldap.UserDataReader;
 
 
 import java.util.regex.Pattern;
 import java.util.regex.Pattern;
 
 
 public interface MacroImplementation {
 public interface MacroImplementation {
+    enum Scope {
+        Static,
+        System,
+        User,
+    }
+
     Pattern getRegExPattern();
     Pattern getRegExPattern();
-    
+
     String replaceValue(final String matchValue, final MacroRequestInfo macroRequestInfo)
     String replaceValue(final String matchValue, final MacroRequestInfo macroRequestInfo)
             throws MacroParseException;
             throws MacroParseException;
 
 

+ 49 - 11
src/main/java/password/pwm/util/macro/MacroMachine.java

@@ -23,14 +23,15 @@
 package password.pwm.util.macro;
 package password.pwm.util.macro;
 
 
 import password.pwm.PwmApplication;
 import password.pwm.PwmApplication;
+import password.pwm.PwmApplicationMode;
 import password.pwm.PwmConstants;
 import password.pwm.PwmConstants;
+import password.pwm.bean.LoginInfoBean;
 import password.pwm.bean.SessionLabel;
 import password.pwm.bean.SessionLabel;
 import password.pwm.bean.UserIdentity;
 import password.pwm.bean.UserIdentity;
 import password.pwm.bean.UserInfoBean;
 import password.pwm.bean.UserInfoBean;
 import password.pwm.config.PwmSetting;
 import password.pwm.config.PwmSetting;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.PwmRequest;
 import password.pwm.http.PwmRequest;
-import password.pwm.bean.LoginInfoBean;
 import password.pwm.ldap.LdapUserDataReader;
 import password.pwm.ldap.LdapUserDataReader;
 import password.pwm.ldap.UserDataReader;
 import password.pwm.ldap.UserDataReader;
 import password.pwm.ldap.UserStatusReader;
 import password.pwm.ldap.UserStatusReader;
@@ -50,7 +51,8 @@ public class MacroMachine {
     private final UserInfoBean userInfoBean;
     private final UserInfoBean userInfoBean;
     private final LoginInfoBean loginInfoBean;
     private final LoginInfoBean loginInfoBean;
     private final UserDataReader userDataReader;
     private final UserDataReader userDataReader;
-    private final Map<Pattern,MacroImplementation> macroImplementations;
+
+    private static final Map<MacroImplementation.Scope,Map<Pattern,MacroImplementation>> BUILTIN_MACROS = makeImplementations();
 
 
     public MacroMachine(
     public MacroMachine(
             final PwmApplication pwmApplication,
             final PwmApplication pwmApplication,
@@ -65,25 +67,33 @@ public class MacroMachine {
         this.userInfoBean = userInfoBean;
         this.userInfoBean = userInfoBean;
         this.loginInfoBean = loginInfoBean;
         this.loginInfoBean = loginInfoBean;
         this.userDataReader = userDataReader;
         this.userDataReader = userDataReader;
-        this.macroImplementations = makeImplementations();
     }
     }
 
 
-    private Map<Pattern,MacroImplementation> makeImplementations() {
-        final Set<Class<? extends MacroImplementation>> implementations = new HashSet<>();
-        implementations.addAll(StandardMacros.STANDARD_MACROS);
-        implementations.addAll(InternalMacros.INTERNAL_MACROS);
-        final LinkedHashMap<Pattern,MacroImplementation> map = new LinkedHashMap<>();
+    private static  Map<MacroImplementation.Scope,Map<Pattern,MacroImplementation>> makeImplementations() {
+        final Map<Class<? extends MacroImplementation>, MacroImplementation.Scope> implementations = new LinkedHashMap<>();
+        implementations.putAll(StandardMacros.STANDARD_MACROS);
+        implementations.putAll(InternalMacros.INTERNAL_MACROS);
+        final LinkedHashMap<MacroImplementation.Scope,Map<Pattern,MacroImplementation>> map = new LinkedHashMap<>();
 
 
-        for (Class macroClass : implementations) {
+        for (Class macroClass : implementations.keySet()) {
+            final MacroImplementation.Scope scope = implementations.get(macroClass);
             try {
             try {
                 final MacroImplementation macroImplementation = (MacroImplementation)macroClass.newInstance();
                 final MacroImplementation macroImplementation = (MacroImplementation)macroClass.newInstance();
                 final Pattern pattern = macroImplementation.getRegExPattern();
                 final Pattern pattern = macroImplementation.getRegExPattern();
-                map.put(pattern,macroImplementation);
+                if (!map.containsKey(scope)) {
+                    map.put(scope, new LinkedHashMap<Pattern, MacroImplementation>());
+                }
+                map.get(scope).put(pattern,macroImplementation);
             } catch (Exception e) {
             } catch (Exception e) {
-                LOGGER.error(sessionLabel, "unable to load macro class " + macroClass.getName() + ", error: " + e.getMessage());
+                LOGGER.error("unable to load macro class " + macroClass.getName() + ", error: " + e.getMessage());
             }
             }
         }
         }
 
 
+        return map;
+    }
+
+    private Map<Pattern,MacroImplementation> makeExternalImplementations(PwmApplication pwmApplication) {
+        final LinkedHashMap<Pattern,MacroImplementation> map = new LinkedHashMap<>();
         final List<String> externalMethods = pwmApplication == null
         final List<String> externalMethods = pwmApplication == null
                 ? Collections.<String>emptyList()
                 ? Collections.<String>emptyList()
                 : pwmApplication.getConfig().readSettingAsStringArray(PwmSetting.EXTERNAL_MACROS_REST_URLS);
                 : pwmApplication.getConfig().readSettingAsStringArray(PwmSetting.EXTERNAL_MACROS_REST_URLS);
@@ -146,8 +156,16 @@ public class MacroMachine {
             }
             }
         };
         };
 
 
+        final Map<Pattern,MacroImplementation> macroImplementations = new LinkedHashMap<>();
+        for (final MacroImplementation.Scope scope : effectiveScopes()) {
+            macroImplementations.putAll(BUILTIN_MACROS.get(scope));
+        }
+        if (effectiveScopes().contains(MacroImplementation.Scope.User)) {
+            macroImplementations.putAll(makeExternalImplementations(pwmApplication));
+        }
 
 
         String workingString = input;
         String workingString = input;
+        String previousString = workingString;
 
 
         for (final Pattern pattern : macroImplementations.keySet()) {
         for (final Pattern pattern : macroImplementations.keySet()) {
             final MacroImplementation pwmMacro = macroImplementations.get(pattern);
             final MacroImplementation pwmMacro = macroImplementations.get(pattern);
@@ -156,6 +174,11 @@ public class MacroMachine {
                 final Matcher matcher = pattern.matcher(workingString);
                 final Matcher matcher = pattern.matcher(workingString);
                 if (matcher.find()) {
                 if (matcher.find()) {
                     workingString = doReplace(workingString, pwmMacro, matcher, stringReplacer, macroRequestInfo);
                     workingString = doReplace(workingString, pwmMacro, matcher, stringReplacer, macroRequestInfo);
+                    if (workingString.equals(previousString)) {
+                        LOGGER.warn(sessionLabel, "macro replace was called but input string was not modified.  "
+                                + " macro=" + pwmMacro.getClass().getName() + ", pattern=" + pwmMacro.getRegExPattern().toString());
+                        break;
+                    }
                 } else {
                 } else {
                     matched = false;
                     matched = false;
                 }
                 }
@@ -165,6 +188,21 @@ public class MacroMachine {
         return workingString;
         return workingString;
     }
     }
 
 
+    private Set<MacroImplementation.Scope> effectiveScopes() {
+        final Set<MacroImplementation.Scope> scopes = new HashSet<>();
+        scopes.add(MacroImplementation.Scope.Static);
+        if (this.pwmApplication != null
+                && (pwmApplication.getApplicationMode() == PwmApplicationMode.RUNNING || pwmApplication.getApplicationMode() == PwmApplicationMode.CONFIGURATION)
+                ) {
+            scopes.add(MacroImplementation.Scope.System);
+            if (this.userInfoBean != null && this.userDataReader != null) {
+                scopes.add(MacroImplementation.Scope.User);
+            }
+        }
+        return Collections.unmodifiableSet(scopes);
+    }
+
+
     private String doReplace(
     private String doReplace(
             final String input,
             final String input,
             final MacroImplementation macroImplementation,
             final MacroImplementation macroImplementation,

+ 23 - 22
src/main/java/password/pwm/util/macro/StandardMacros.java

@@ -26,11 +26,11 @@ import com.novell.ldapchai.exception.ChaiException;
 import password.pwm.AppProperty;
 import password.pwm.AppProperty;
 import password.pwm.PwmApplication;
 import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
 import password.pwm.PwmConstants;
+import password.pwm.bean.LoginInfoBean;
 import password.pwm.bean.UserIdentity;
 import password.pwm.bean.UserIdentity;
 import password.pwm.bean.UserInfoBean;
 import password.pwm.bean.UserInfoBean;
 import password.pwm.config.PwmSetting;
 import password.pwm.config.PwmSetting;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.error.PwmUnrecoverableException;
-import password.pwm.bean.LoginInfoBean;
 import password.pwm.ldap.UserDataReader;
 import password.pwm.ldap.UserDataReader;
 import password.pwm.util.StringUtil;
 import password.pwm.util.StringUtil;
 import password.pwm.util.TimeDuration;
 import password.pwm.util.TimeDuration;
@@ -47,30 +47,31 @@ import java.util.regex.Pattern;
 public abstract class StandardMacros {
 public abstract class StandardMacros {
     private static final PwmLogger LOGGER = PwmLogger.forClass(StandardMacros.class);
     private static final PwmLogger LOGGER = PwmLogger.forClass(StandardMacros.class);
 
 
-    public static final List<Class<? extends MacroImplementation>> STANDARD_MACROS;
+    public static final Map<Class<? extends MacroImplementation>,MacroImplementation.Scope> STANDARD_MACROS;
     static {
     static {
-        final List<Class<? extends MacroImplementation>> defaultMacros = new ArrayList<>();
+        final Map<Class<? extends MacroImplementation>, MacroImplementation.Scope> defaultMacros = new LinkedHashMap<>();
 
 
         // wrapper macros
         // wrapper macros
-        defaultMacros.add(EncodingMacro.class);
-
-        defaultMacros.add(LdapMacro.class);
-        defaultMacros.add(UserPwExpirationTimeMacro.class);
-        defaultMacros.add(UserPwExpirationTimeDefaultMacro.class);
-        defaultMacros.add(UserDaysUntilPwExpireMacro.class);
-        defaultMacros.add(UserIDMacro.class);
-        defaultMacros.add(UserEmailMacro.class);
-        defaultMacros.add(UserPasswordMacro.class);
-        defaultMacros.add(InstanceIDMacro.class);
-        defaultMacros.add(CurrentTimeMacro.class);
-        defaultMacros.add(DefaultEmailFromAddressMacro.class);
-        defaultMacros.add(SiteURLMacro.class);
-        defaultMacros.add(SiteHostMacro.class);
-        defaultMacros.add(RandomCharMacro.class);
-        defaultMacros.add(RandomNumberMacro.class);
-        defaultMacros.add(UUIDMacro.class);
-        defaultMacros.add(UserLdapProfileMacro.class);
-        STANDARD_MACROS = Collections.unmodifiableList(defaultMacros);
+        defaultMacros.put(EncodingMacro.class, MacroImplementation.Scope.System);
+
+        defaultMacros.put(CurrentTimeMacro.class, MacroImplementation.Scope.System);
+        defaultMacros.put(InstanceIDMacro.class, MacroImplementation.Scope.System);
+        defaultMacros.put(DefaultEmailFromAddressMacro.class, MacroImplementation.Scope.System);
+        defaultMacros.put(SiteURLMacro.class, MacroImplementation.Scope.System);
+        defaultMacros.put(SiteHostMacro.class, MacroImplementation.Scope.System);
+        defaultMacros.put(RandomCharMacro.class, MacroImplementation.Scope.System);
+        defaultMacros.put(RandomNumberMacro.class, MacroImplementation.Scope.System);
+        defaultMacros.put(UUIDMacro.class, MacroImplementation.Scope.System);
+
+        defaultMacros.put(LdapMacro.class, MacroImplementation.Scope.User);
+        defaultMacros.put(UserPwExpirationTimeMacro.class, MacroImplementation.Scope.User);
+        defaultMacros.put(UserPwExpirationTimeDefaultMacro.class, MacroImplementation.Scope.User);
+        defaultMacros.put(UserDaysUntilPwExpireMacro.class, MacroImplementation.Scope.User);
+        defaultMacros.put(UserIDMacro.class, MacroImplementation.Scope.User);
+        defaultMacros.put(UserEmailMacro.class, MacroImplementation.Scope.User);
+        defaultMacros.put(UserPasswordMacro.class, MacroImplementation.Scope.User);
+        defaultMacros.put(UserLdapProfileMacro.class, MacroImplementation.Scope.User);
+        STANDARD_MACROS = Collections.unmodifiableMap(defaultMacros);
     }
     }
 
 
 
 

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

@@ -72,7 +72,7 @@ HealthMessage_LocalDBLogger_HighRecordCount=LocalDBLogger event log record count
 HealthMessage_LocalDBLogger_OldRecordPresent=Oldest LocalDBLogger event log record is %1%, configured maximum is %2%.  Excess records are being purged.
 HealthMessage_LocalDBLogger_OldRecordPresent=Oldest LocalDBLogger event log record is %1%, configured maximum is %2%.  Excess records are being purged.
 HealthMessage_ServiceClosed_LocalDBUnavail=unable to start %1% service, LocalDB is not available
 HealthMessage_ServiceClosed_LocalDBUnavail=unable to start %1% service, LocalDB is not available
 HealthMessage_ServiceClosed_AppReadOnly=unable to start %1% service, application is in read-only mode
 HealthMessage_ServiceClosed_AppReadOnly=unable to start %1% service, application is in read-only mode
-Message_SMS_SendFailure=Unable to send sms due to error: %1%
+HealthMessage_SMS_SendFailure=Unable to send sms due to error: %1%
 HealthStatus_WARN=WARN
 HealthStatus_WARN=WARN
 HealthStatus_CAUTION=CAUTION
 HealthStatus_CAUTION=CAUTION
 HealthStatus_CONFIG=CONFIGURATION
 HealthStatus_CONFIG=CONFIGURATION