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]>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_**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].
>>>> 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