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=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.
5236.patch
Description: Binary data

