Given the following code snippet in a controller (default or any other): 

auth.settings.allow_basic_login = True
def howdy():
    auth.settings.allow_basic_login = True
    response.view = 'generic.json'
    if auth.user:
        this_user = auth.user.id
    else:
        this_user = "unset"
    return dict(user=this_user)
if the controller action is called as such:
% curl --user 't...@somewhere.com:supersecretpassword' 
http://127.0.0.1:8000/myapp/controller/howdy                      

this response you'll get it this: 
{"user": "unset"} 

The same goes for using auth.is_logged_in(): 

The result is different, however, when you use one of the 'requires' 
decorators:                                                             

auth.settings.allow_basic_login = True

def howdy():
    auth.settings.allow_basic_login = True
    @auth.requires_login()
    def proforma():
        pass #empty function just to invoke auth.requires
    proforma() #call empty function
    response.view = 'generic.json'
    if auth.user:
        this_user = auth.user.id
    else:
        this_user = "unset"
    return dict(user=this_user)
this results in:
% curl --user 't...@somewhere.com:supersecretpassword' 
http://127.0.0.1:8000/myapp/controller/howdy                      
{"user": 1}  

After some digging I discovered that in tools.py auth.requires_* ends up 
calling login_bare which is why the second one works. I realize that 
according to the book (
http://web2py.com/books/default/chapter/29/9?search=login_bare) 
 login_bare() can be called to login the user "manually". Unfortunately the 
examples for auth.settings.allow_basic_login in the manual/book 
(http://web2py.com/books/default/chapter/29/9#Access-Control-and-Basic-Authentication
 
, http://web2py.com/books/default/chapter/29/9#Settings-and-messages , & 
http://web2py.com/books/default/chapter/29/10#Access-Control) don't address 
the fact that no login is actually executed without the decorators. With 
the last example if someone wanted to use that as a guide they might think 
that changing: 

@auth.requires_login()
@request.restful()
def api():
   def GET(s):
       return 'access granted, you said %s' % s
   return locals()

to: 


@request.restful()
def api():
   def GET(s):

       if auth.is_logged_in():
           return 'access granted, you said %s' % s

       else:

           return 'access denied'
   return locals()


Should work, but they would be mistaken (and likely to spend much time 
trying to figure out why one worked and the other did not). I don't know 
whether it was the intention that using basic auth prevent a call to log 
the user in by default. It seems that either the code should be fixed or we 
should update the documentation to clarify that login_bare() should be 
called explicitly (directly or indirectly) to actually execute the login 
process. 

Reply via email to