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=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.

