I have not forgotten. I opened issue 1645.

On Tuesday, 13 August 2013 15:13:30 UTC-5, Richard wrote:
>
> Massimo,
>
> If you are concern about possible backward compatibility issue that this 
> change could raise... Maybe we could find a way to let the ldap_auth return 
> validator error to form (to user)... I could live with that too... I just 
> didn't find a easy way to make it works from ldap_auth (mean a lot of 
> refactoring could be required and I don't want to screw up ldap_auth for 
> others, I am not equiped to test it properly over different ldap 
> implementation). I just have to change a single line in tools.py + add a 
> IS_NOT_EMAIL() validator, that was the easiest...
>
> :)
>
> Richard
>
>
> On Tue, Aug 13, 2013 at 10:19 AM, Richard Vézina 
> <[email protected]<javascript:>
> > wrote:
>
>> 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] <javascript:>> 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] <javascript:>.
>>> 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