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=**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=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=**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_**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/**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.

