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]<javascript:>
> > 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]<javascript:>
>> > wrote:
>>
>>> I would also add this :
>>>
>>> tmpvalidator = [IS_NOT_EMPTY(error_message=self.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]<javascript:>
>>> > 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]<javascript:>
>>>> > 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]<javascript:>
>>>>> > wrote:
>>>>>
>>>>>> Ok!
>>>>>>
>>>>>> :)
>>>>>>
>>>>>> Richard
>>>>>>
>>>>>>
>>>>>> On Wed, Aug 7, 2013 at 10:10 AM, Massimo Di Pierro <
>>>>>> [email protected] <javascript:>> 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_**PROTOCOL_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_**
>>>>>>>>> firstname_attrib,
>>>>>>>>>                                            user_lastname_attrib,
>>>>>>>>>                                            user_mail_attrib])
>>>>>>>>>                 result = con.search_ext_s(
>>>>>>>>>                     ldap_basedn, ldap.SCOPE_SUBTREE,
>>>>>>>>>                     "(&(sAMAccountName=%s)(%s))" % (
>>>>>>>>>                                 ldap.filter.escape_filter_**
>>>>>>>>> chars(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/**
>>>>>>>>>> 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