i agree On Thursday, 22 August 2013 11:16:20 UTC-5, Richard wrote: > > Hello, > > I just push these change in production, then face some exception... Some > of our users have email as username some don't... So the fix I found is not > the proper solution... I think we will have to improve ldap_auth logic to > get out of the mud with this... I will look throught this a bit more see > what I can come up with. What ldap_auth should do is to check user > credentials, if the user log with email but he already have a user with the > same username and password it should use this user instead of creating a > new user with email as username and missing first_name and many other field > empty... > > Richard > > > On Wed, Aug 21, 2013 at 9:34 AM, Richard Vézina > <[email protected]<javascript:> > > wrote: > >> No problem, thank for the follow... >> >> Richard >> >> >> On Wed, Aug 21, 2013 at 4:51 AM, Massimo Di Pierro >> <[email protected]<javascript:> >> > 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] <javascript:>. >>> 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.

