Hi Rick,
Good speaking with you the other day. Here are some other things I've noticed while working on this USM implementation to support a SQL backend.
call to EndsWith from authenticate -
IF !EMPTY(this.cPasswordEncryptionKey) AND !EndsWith(this.oUser.Password,"~~")
In the method, it makes this comparison to see if the right-most 2 characters match the double tilde that is used as the indicator of the end of hash string.
IF RIGHT(lcSourceString,LEN(lcCompare)) == lcCompare
However, lcSourceString is not getting trimmed and if it has whitespace on the end then this will never return true. It's easy enough for me to handle in my OnAuthenticateUser sub-class but I wanted to raise it with you.
Next, there's some logic to see if an account has expired and it has dependencies on VFP's peculiar EMPTY function and date/datetime values.
IF .NOT. EMPTY(THIS.ouser.expireson) .AND. THIS.ouser.expireson<DATE()
As SQL has no concept of an empty date, only nulls, the default 1/1/1900 will result in all accounts appearing as expired. Again, I am handling this in my implementation.

This is based on using varchar
fields in FoxPro and SQL which is what the tooling creates for the table. varchar
fields when returned to FoxPro don't use fill white space at the end of the string to fill the field size.
The only time you should run into a problem with this is if you don't use varchar
fields in the database - otherwise the data will be trimmed. If you have existing data not in varchar you switch to varchar
for the fields, and then explicitly trim the data to remove the extra blank characters from the fields.
+++ Rick ---