dmccallum/person-directory — pull request #2 by dmccallum (2013-10-08 22:58:46+00:00)
Title: SSP-1669 Optionally wildcard LDAP and JDBC search terms

This issue is also tracked as PERSONDIR-77

This addresses a disconnect between the way uPortal wildcards searches
against its local attribute store and the way wildcarding is handled
in OOTB PD JDBC and LDAP DAOs.

By default a 4.1.x uP wraps all non-username search terms in wildcards.
I.e. a search for "Dan" via the "Simple" user search feature becomes
"where like '%Dan%". But in the PD JDBC DAO, the
wildcarding treatment was limited to replacing end user-specified "*"'s
with "%"'s. So "Dan" becomes "where = 'Dan'" and "D*n"
becomes "where like 'D%n'". The LDAP DAO was basically
the same. And neither DAO gave special treatment to username
attributes.

There's nothing wrong with these JDBC and LDAP PD wildcarding
behaviors, but when deployed into uPortal you get unexpected results
because sometimes the uPortal search scope ends up being more broad
that the PD scope (when there are no end-user specified wildcards)
and sometimes more narrow (when there is an end-user specified
wildcard, which gets treated literally). And again, uP disallows
wildcarding for usernames period, whereas username is just another
attribute in the PD impls.

So this commit provides config options which allow you to approximate
uPortal wildcarding behavior in PD JDBC and LDAP DAOs. The defaults
preserve legacy behavior:

allowUsernameWildcards - Set to false for uP-style behavior;
wildcard placeholders will be treated literally on username
searches.

wildcardDataAttributes - Set to true for uP-style wildcard
wrapping of all non-username searches.

wildcardedDataAttributeExclusions - If wildcardDataAttributes
is true, use this to list out *data* attributes which should
never be automatically wrapped in wildcards. End-user specified
wildcards are still supported, if present.

Because query building in all these DAOs occurs after logical,
app-layer query attribute names have been converted to physical,
data-layer query attribute names, detecting a username search
requires additional config: usernameDataAttribute. We cannot use
the usernameAttributeProvider for this purpose because it
functions elsewhere as the strategy for determining the *app-layer*
username attribute name. An alternative would have been to attempt
a reverse mapping based on the value returned from
usernameAttributeProvider. But because there are no limits on the
cardinality of mappings in either direction, we elected to require
explicit specification of the data-layer username attribute name
if it is not identical to the app-layer attribute name.

As noted in Javadoc, the boilerplate code supporting the above
config is intentionally duplicated between DAOs because factoring
it into the shared parent class (AbstractQueryPersonAttributeDao)
would have resulted in config code in that class that didn't
actually impact behavior in that class. Addressing this duplication
could be a target for future refactoring, but would require
abstracting more data-layer attribute handling into that class.

Finally, note that SSP runs with a uP patch that implements some
of this wildcarding harmonization in reverse. Specifically, it
supports preference of user-specified wildcards over automatically
wrapping search terms in wildcards. See
https://github.com/Jasig/uPortal/commit/c14576953acdefba8157aa5d44d611743cf47f90