No problem!

As long as there is a solution in the next version I will be happy...
Curious to know what is bugging you though, adding a new validator? Maybe
the IS_MAIL() could be hack in order that it usage could be reversed,
something like this : IS_MAIL(..., complement=True), then it will return
true if the string is not a email... So don't need a new validator.

Richard




On Tue, Aug 13, 2013 at 10:04 AM, Massimo Di Pierro <
[email protected]> wrote:

> I need to review this. I understand the problem but I am not convinced by
> the solution. I will need one week.
>
>
> On Monday, 12 August 2013 08:46:31 UTC-5, Richard wrote:
>
>> UP!
>>
>>
>>
>> On Fri, Aug 9, 2013 at 10:59 AM, Richard Vézina <[email protected]>wrote:
>>
>>> Here the patch!!
>>>
>>> I have not been able to use the IS_NOT_EMAIL() validator from
>>> validators.py didn't understand how validators are import in tools.py...
>>>
>>> NOTE :
>>> About my precedent mail... the "auth_table.username.requires =
>>> IS_NOT_IN_DB(db, auth_table.username" from the book is not require if the
>>> user use the "auth.define_tables(username=**True)" and the recommended
>>> auth_tables customization mechanism. So, I think the book should be revised
>>> this way :
>>>
>>> "In case you use old style customizing auth_tables. Make sure your
>>> username field definition looks like that :
>>>  Field('username', 'string',
>>>           notnull=True,
>>>           required=True,
>>>            requires=[IS_NOT_EMPTY(error_**message=T(auth.messages.is_**
>>> empty)),
>>>                     IS_NOT_IN_DB(db, 'auth_user.username'),
>>> IS_NOT_EMAIL()]
>>>           ),
>>>
>>> Where you make sure you use these validators in order to make sure email
>>> is not used as username and there is no duplicated username in your
>>> auth_user table."
>>>
>>> :)
>>>
>>> Richard
>>>
>>>
>>>
>>>
>>> On Wed, Aug 7, 2013 at 1:48 PM, Richard Vézina <[email protected]>wrote:
>>>
>>>> I would also add this :
>>>>
>>>> tmpvalidator = [IS_NOT_EMPTY(error_message=se**lf.messages.is_empty), 
>>>> IS_NOT_IN_DB(db,
>>>> 'auth_user.username'), IS_NOT_EMAIL()]
>>>>
>>>> Since this line in the book :
>>>>
>>>> auth_table.username.requires = IS_NOT_IN_DB(db, auth_table.username)
>>>>
>>>>
>>>> Doesn't seem to works and could be erase since who want a duplicated
>>>> username in his auth_user??
>>>>
>>>>
>>>> Richard
>>>>
>>>>
>>>>
>>>>
>>>> On Wed, Aug 7, 2013 at 1:35 PM, Richard Vézina 
>>>> <[email protected]>wrote:
>>>>
>>>>> Better then that I think :
>>>>>
>>>>> In gluon/tools.py in Auth login() near line 2006 :
>>>>>
>>>>> Replace :
>>>>> tmpvalidator = IS_NOT_EMPTY(error_message=**self.messages.is_empty)
>>>>>
>>>>> With :
>>>>>         if 'username' in table_user.fields or \
>>>>>                 not self.settings.login_email_**validate:
>>>>>             tmpvalidator = 
>>>>> [IS_NOT_EMPTY(error_message=**self.messages.is_empty),
>>>>> IS_NOT_EMAIL()]
>>>>>
>>>>> Will require to add this new validator though :
>>>>>
>>>>> class IS_NOT_EMAIL:
>>>>>     def __init__(self, error_message='You can\'t use email as
>>>>> username'):
>>>>>         self.e = error_message
>>>>>     def __call__(self, value):
>>>>>         if not IS_EMAIL()(value)[1]:
>>>>>             return (value, self.e)
>>>>>         return (value, None)
>>>>>
>>>>> What you think about that??
>>>>>
>>>>> Richard
>>>>>
>>>>>
>>>>> On Wed, Aug 7, 2013 at 1:23 PM, Richard Vézina 
>>>>> <[email protected]>wrote:
>>>>>
>>>>>> from gluon.validators import IS_EMAIL
>>>>>>
>>>>>>             if ldap_mode == 'ad':
>>>>>>                 # Microsoft Active Directory
>>>>>>                 if IS_EMAIL()(username)[1] is not None:
>>>>>>                 #if '@' not in username:
>>>>>>                     domain = []
>>>>>>                     for x in ldap_basedn.split(','):
>>>>>>                         if "DC=" in x.upper():
>>>>>>                             domain.append(x.split('=')[-1]**)
>>>>>>                     username = "%s@%s" % (username, '.'.join(domain))
>>>>>>                 else:
>>>>>>                     return False
>>>>>>                 username_bare = username.split("@")[0]
>>>>>>
>>>>>>
>>>>>> This prevent login to occure and new user to be inserted when email
>>>>>> is used as username... however it not returning any advise to the 
>>>>>> user... I
>>>>>> will try to figure out how to implement validation from ldap_auth and get
>>>>>> back with a patch.
>>>>>>
>>>>>> Richard
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Wed, Aug 7, 2013 at 10:56 AM, Richard Vézina <
>>>>>> [email protected]> wrote:
>>>>>>
>>>>>>> Ok!
>>>>>>>
>>>>>>> :)
>>>>>>>
>>>>>>> Richard
>>>>>>>
>>>>>>>
>>>>>>> On Wed, Aug 7, 2013 at 10:10 AM, Massimo Di Pierro <
>>>>>>> [email protected]> wrote:
>>>>>>>
>>>>>>>> Please send me a patch when you test it. ;-)
>>>>>>>>
>>>>>>>> On Wednesday, 7 August 2013 07:51:58 UTC-5, Richard wrote:
>>>>>>>>
>>>>>>>>> No change... Auth seems to delegate entirely the validation on
>>>>>>>>> username input field in case ldap_auth is used as authentication 
>>>>>>>>> method.
>>>>>>>>>
>>>>>>>>> I guess this simple refactor (not tested) could do the tricks at
>>>>>>>>> least for Active directory :
>>>>>>>>>
>>>>>>>>>                 if not IS_EMAIL()(username)[1]:
>>>>>>>>>                     domain = []
>>>>>>>>>                     for x in ldap_basedn.split(','):
>>>>>>>>>                         if "DC=" in x.upper():
>>>>>>>>>                             domain.append(x.split('=')[-1]****)
>>>>>>>>>                     identifier = "%s@%s" % (username,
>>>>>>>>> '.'.join(domain))
>>>>>>>>>                 else: return ERROR...
>>>>>>>>>                 username_bare = username.split("@")[0]
>>>>>>>>>
>>>>>>>>> Richard
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Wed, Aug 7, 2013 at 8:42 AM, Richard Vézina <
>>>>>>>>> [email protected]> wrote:
>>>>>>>>>
>>>>>>>>>> Hello,
>>>>>>>>>>
>>>>>>>>>> I was about to post this (I think I answer your question) :
>>>>>>>>>>
>>>>>>>>>> Hello,
>>>>>>>>>>
>>>>>>>>>> I think I found a flaw in the interaction between Auth and LDAP
>>>>>>>>>> contrib (web2py 2.4.7).
>>>>>>>>>>
>>>>>>>>>> If I set LDAP as unique authentification method
>>>>>>>>>> (auth.settings.login_methods = LDAP) as written in the book, web2py 
>>>>>>>>>> should
>>>>>>>>>> leaves LDAP to create user... The things is web2py Auth seems to 
>>>>>>>>>> create
>>>>>>>>>> user even if it LDAP that is responsible of doing it. I mean, I 
>>>>>>>>>> carefully
>>>>>>>>>> read the code of LDAP and the only way it could create a new user is 
>>>>>>>>>> if
>>>>>>>>>> manage_groups=True by calling do_manage_groups() since the other 
>>>>>>>>>> place
>>>>>>>>>> where LDAP is instert new user it set email, first_name and 
>>>>>>>>>> last_name. In
>>>>>>>>>> my case, if user use email instead of username (that should not be 
>>>>>>>>>> email,
>>>>>>>>>> but I can't enforce this with the custom IS_NOT_EMAIL() validator I 
>>>>>>>>>> wrote)
>>>>>>>>>> for login a new user get inserted like this : first_name = email (or 
>>>>>>>>>> the
>>>>>>>>>> content of username input that is an email), username = email and
>>>>>>>>>> registration_id = email. As far as I can see the only way LDAP could
>>>>>>>>>> produce this result is if the do_manage_groups method is called, but 
>>>>>>>>>> it
>>>>>>>>>> can't be call if manage_groups is set to False. So, the only 
>>>>>>>>>> remaining
>>>>>>>>>> possibility is that Auth is creating the new user because it recieve 
>>>>>>>>>> a bad
>>>>>>>>>> signal from LDAP.
>>>>>>>>>>
>>>>>>>>>> I make a couples tests and found that the insert new user base on
>>>>>>>>>> the credentials of already existing user that log with it email 
>>>>>>>>>> instead of
>>>>>>>>>> it username occure at line 2147-2148. So I guess Auth recieve a True 
>>>>>>>>>> flag
>>>>>>>>>> from LDAP mean the user exist in directory, since web2py can't match 
>>>>>>>>>> a
>>>>>>>>>> existing user base on the wrong username (email) it insert a new 
>>>>>>>>>> user with
>>>>>>>>>> wrong setting.
>>>>>>>>>>
>>>>>>>>>> The origin of this is multifold. First, I think it could be
>>>>>>>>>> prevent if there was a IS_NOT_EMAIL() validator on the username 
>>>>>>>>>> field, for
>>>>>>>>>> some reason I can't get it to work properly with LDAP because of the 
>>>>>>>>>> way
>>>>>>>>>> LDAP is working the validator seems to be skipped, and the username 
>>>>>>>>>> is
>>>>>>>>>> first check against directory. Maybe using IS_NOT_EMAIL() inside 
>>>>>>>>>> ldap_auth
>>>>>>>>>> contrib could solve this issue. Other possible origin is the way 
>>>>>>>>>> ldap_auth
>>>>>>>>>> is written. I mean it seems that for saving a variable "username" is
>>>>>>>>>> re-used... I think that the issue is coming from line 8 of code 
>>>>>>>>>> extract
>>>>>>>>>> below :
>>>>>>>>>>
>>>>>>>>>>             if ldap_mode == 'ad':
>>>>>>>>>>                 # Microsoft Active Directory
>>>>>>>>>>                 if '@' not in username:
>>>>>>>>>>                     domain = []
>>>>>>>>>>                     for x in ldap_basedn.split(','):
>>>>>>>>>>                         if "DC=" in x.upper():
>>>>>>>>>>                             domain.append(x.split('=')[-1]****)
>>>>>>>>>>                      username = "%s@%s" % (username,
>>>>>>>>>> '.'.join(domain))
>>>>>>>>>>                 username_bare = username.split("@")[0]
>>>>>>>>>>                 con.set_option(ldap.OPT_**PROTOC**OL_VERSION, 3)
>>>>>>>>>>                 # In cases where ForestDnsZones and
>>>>>>>>>> DomainDnsZones are found,
>>>>>>>>>>                 # result will look like the following:
>>>>>>>>>>                 # ['ldap://ForestDnsZones.**domain**
>>>>>>>>>> .com/DC=ForestDnsZones<http://ForestDnsZones.domain.com/DC=ForestDnsZones>
>>>>>>>>>> ,
>>>>>>>>>>                 #    DC=domain,DC=com']
>>>>>>>>>>                 if ldap_binddn:
>>>>>>>>>>                     # need to search directory with an admin
>>>>>>>>>> account 1st
>>>>>>>>>>                     con.simple_bind_s(ldap_binddn, ldap_bindpw)
>>>>>>>>>>                 else:
>>>>>>>>>>                     # credentials should be in the form of
>>>>>>>>>> [email protected]
>>>>>>>>>>                     con.simple_bind_s(username, password)
>>>>>>>>>>                 # this will throw an index error if the account
>>>>>>>>>> is not found
>>>>>>>>>>                 # in the ldap_basedn
>>>>>>>>>>                 requested_attrs = ['sAMAccountName']
>>>>>>>>>>                 if manage_user:
>>>>>>>>>>                     requested_attrs.extend([user_**f**
>>>>>>>>>> irstname_attrib,
>>>>>>>>>>                                            user_lastname_attrib,
>>>>>>>>>>                                            user_mail_attrib])
>>>>>>>>>>                 result = con.search_ext_s(
>>>>>>>>>>                     ldap_basedn, ldap.SCOPE_SUBTREE,
>>>>>>>>>>                     "(&(sAMAccountName=%s)(%s))" % (
>>>>>>>>>>                                 ldap.filter.escape_filter_**char*
>>>>>>>>>> *s(username_bare),
>>>>>>>>>>                                 filterstr),
>>>>>>>>>>                     requested_attrs)[0][1]
>>>>>>>>>>                 if not isinstance(result, dict):
>>>>>>>>>>                     # result should be a dict in the form
>>>>>>>>>>                     # {'sAMAccountName': [username_bare]}
>>>>>>>>>>                     logger.warning('User [%s] not found!' %
>>>>>>>>>> username)
>>>>>>>>>>                     return False
>>>>>>>>>>                 if ldap_binddn:
>>>>>>>>>>                     # We know the user exists & is in the correct
>>>>>>>>>> OU
>>>>>>>>>>                     # so now we just check the password
>>>>>>>>>>                     con.simple_bind_s(username, password)
>>>>>>>>>>                 username = username_bare
>>>>>>>>>>
>>>>>>>>>> This peace of code is pretty unreliable : It start by re-creating
>>>>>>>>>> a email and store it in username vars if username it recieves from 
>>>>>>>>>> web2py
>>>>>>>>>> is not a email before derive a username_bare from the altered 
>>>>>>>>>> username var
>>>>>>>>>> and at the end it finally set username = username_bare... Why all 
>>>>>>>>>> this just
>>>>>>>>>> to avoid create a var?!
>>>>>>>>>>
>>>>>>>>>> I propose to refator this using creating a new ID or identifier
>>>>>>>>>> var to store connection "identifier" var instead reusing the 
>>>>>>>>>> username for
>>>>>>>>>> that. Then it will require to determine if the IS_NOT_EMAIL() should 
>>>>>>>>>> go at
>>>>>>>>>> Auth level or ldap_auth. I don't know so much LDAP in general and 
>>>>>>>>>> even less
>>>>>>>>>> the different implementation, so I don't know if some implementation 
>>>>>>>>>> use
>>>>>>>>>> email as an identifier or not. Since, the Auth class as mechanism to 
>>>>>>>>>> create
>>>>>>>>>> missing user I don't no if it intentional to allow the creation of 
>>>>>>>>>> user
>>>>>>>>>> with email as username or not... So, maybe it a option in to use
>>>>>>>>>> IS_NOT_EMAIL() on username field in this case it will require that
>>>>>>>>>> IS_NOT_EMAIL be at level of Auth. Maybe, I didn't be able to make 
>>>>>>>>>> work my
>>>>>>>>>> custom validator because of the order of validator (I had set 
>>>>>>>>>> multiple
>>>>>>>>>> validator on username), I will try to set only IS_NOT_EMAIL and 
>>>>>>>>>> report here
>>>>>>>>>> if it solve the problem I have with LDAP authentication.
>>>>>>>>>>
>>>>>>>>>> Thanks
>>>>>>>>>>
>>>>>>>>>> Richard
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Wed, Aug 7, 2013 at 7:22 AM, Massimo Di Pierro <
>>>>>>>>>> [email protected]> wrote:
>>>>>>>>>>
>>>>>>>>>>> How would you change this?
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On Monday, 5 August 2013 15:42:39 UTC-5, Richard wrote:
>>>>>>>>>>>
>>>>>>>>>>>> Hello,
>>>>>>>>>>>>
>>>>>>>>>>>> Is there a way to prevent user to log with there email? I set
>>>>>>>>>>>> LDAP authentication, I create a username field on custom auth_user 
>>>>>>>>>>>> model
>>>>>>>>>>>> and set auth.define_tables(username=**Tr****ue)
>>>>>>>>>>>>
>>>>>>>>>>>> But I notice that I can still login with [email protected]. In
>>>>>>>>>>>> this case, ldap_auth create a new user with first_name and 
>>>>>>>>>>>> username =
>>>>>>>>>>>> [email protected]
>>>>>>>>>>>>
>>>>>>>>>>>> So, I think there is a flaw here in ldap_auth :
>>>>>>>>>>>>
>>>>>>>>>>>> if ldap_mode == 'ad':
>>>>>>>>>>>>                 # Microsoft Active Directory
>>>>>>>>>>>>                 if '@' not in username:
>>>>>>>>>>>>                     domain = []
>>>>>>>>>>>>                     for x in ldap_basedn.split(','):
>>>>>>>>>>>>                         if "DC=" in x.upper():
>>>>>>>>>>>>                             domain.append(x.split('=')[-1]*****
>>>>>>>>>>>> *)
>>>>>>>>>>>>                     username = "%s@%s" % (username,
>>>>>>>>>>>> '.'.join(domain))
>>>>>>>>>>>>                 username_bare = username.split("@")[0]
>>>>>>>>>>>>
>>>>>>>>>>>> Since it seems to recreate email as username...
>>>>>>>>>>>>
>>>>>>>>>>>> Thanks
>>>>>>>>>>>>
>>>>>>>>>>>> Richard
>>>>>>>>>>>>
>>>>>>>>>>>  --
>>>>>>>>>>>
>>>>>>>>>>> ---
>>>>>>>>>>> You received this message because you are subscribed to the
>>>>>>>>>>> Google Groups "web2py-users" group.
>>>>>>>>>>> To unsubscribe from this group and stop receiving emails from
>>>>>>>>>>> it, send an email to web2py+un...@**googlegroups.com.
>>>>>>>>>>>
>>>>>>>>>>> For more options, visit https://groups.google.com/**grou**
>>>>>>>>>>> ps/opt_out <https://groups.google.com/groups/opt_out>.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>  --
>>>>>>>>
>>>>>>>> ---
>>>>>>>> You received this message because you are subscribed to the Google
>>>>>>>> Groups "web2py-users" group.
>>>>>>>> To unsubscribe from this group and stop receiving emails from it,
>>>>>>>> send an email to web2py+un...@**googlegroups.com.
>>>>>>>> For more options, visit 
>>>>>>>> https://groups.google.com/**groups/opt_out<https://groups.google.com/groups/opt_out>
>>>>>>>> .
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>  --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "web2py-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
>

-- 

--- 
You received this message because you are subscribed to the Google Groups 
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to