No problem, thank for the follow... Richard
On Wed, Aug 21, 2013 at 4:51 AM, Massimo Di Pierro < [email protected]> wrote: > 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]>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]> 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=**T**rue)" 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_**m** >>>>>> essage=T(auth.messages.is_**empt**y)), >>>>>> 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=**sel** >>>>>>>> f.messages.is_empty) >>>>>>>> >>>>>>>> With : >>>>>>>> if 'username' in table_user.fields or \ >>>>>>>> not self.settings.login_email_**vali**date: >>>>>>>> tmpvalidator = >>>>>>>> [IS_NOT_EMPTY(error_message=**se**lf.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/**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]. > 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.

