Looking at your code again: @auth.requires_login() def call(token): row = db(db.subscription.token == token).select().first() my_number = row.my_calls if my_number > 0 & my_token == token: db(db.subscription.token == my_token).update(my_calls=db.subscription.my_calls-1) return service() else: raise Exception()
I see two problems: 1) you have both @auth.requires_login() which only works if you enable auth.allow_basic_login = True and you have token authentication. Are you sure you want two authentications one on top of the other? 2) call is a method and cannot take arguments. If your intention is passing the token as request.args(0) simply do: def call(): token = request.args(0) # grab the token row = db(db.subscription.token == token).select().first() my_number = row.my_calls if my_number > 0 & my_token == token: db(db.subscription.token == my_token).update(my_calls=db.subscription.my_calls-1) del request.args[0] # make sure you remove the token else you may mess-up some services. return service() else: raise Exception() On Sep 15, 2:46 pm, Eric <hu5...@gmail.com> wrote: > OK, here's where my background as a non-CS/humanities major starts to > hurt. I'm trying to implement a token authentication for a web > service using RPC. I've also developed a sign-up/payment website for > the web service that uses web2py with auth. I had the service working > fine using basic authentication, but then I realized that my target > audience may not always use a client with basic authentication > enabled, plus a token authentication system offers me other advantages > that I would like. > > Anyway, I need advice on where exactly is best to check for the > token. Intuitively, it seems reasonable to check for the token in the > call function that I've exposed, but what is confusing me is the fact > that all the arguments passed by the call go to the decorated RPC > function that is called. Indeed, when I check the token in the > exposed call action and use curl to make the call using a valid token, > I get a "invalid function (api/call)" error. > > So how would I should I pass a token to the exposed call action in > addition to passing other arguments to the various linked actions? > > Or do I need to check for the token inside each of my remote > procedures? Also, is there a good way to cache the token, or will I > need to check it on every call? > > Finally, I had a counter working well with basic authentication to > limit calls to a certain number per month. I guess if I have to check > for the token inside each of my remote procedures, then that's also > where I´ll need to put the counter. This would seem to make for messy > and repetitive code, but I'm not sure what else to do. > > Would anyone like to jump in or point me to a pertinent resource? I'd > be very grateful. Django has a token API plugin > at:https://github.com/jpulgarin/django-tokenapi/tree/master/tokenapi but > I'm not able to extrapolate from their plugin to my app. > > ####### > #model## > ################## > db.define_table('subscription', > Field('id','id'), > Field('token', > label=T('User Token')), > Field('my_calls', type='integer', default=100, > label=T('User Calls'),writable=False,readable=False), > Field('subscription_method', 'reference method', required=True, > label=T('Subscription Method')), > Field('is_active','boolean',default=False, > label=T('Active'),writable=False,readable=False), > Field('created_on','datetime',default=request.now, > label=T('Created On'),writable=False,readable=False), > Field('modified_on','datetime',default=request.now, > label=T('Modified On'),writable=False,readable=False, > update=request.now), > Field('created_by',db.auth_user,default=auth.user_id, > label=T('Created By'),writable=False,readable=False), > Field('modified_by',db.auth_user,default=auth.user_id, > label=T('Modified By'),writable=False,readable=False, > update=auth.user_id), > format='%(plan)s', > migrate=settings.migrate) > > ############ > ##controller#### > # coding: utf8 > from gluon.tools import Service > service = Service(globals()) > > @service.run > def my_function1(foo,bar): > ... > return response.body.getvalue() > > @service.run > def my_function2(foo,bar): > ... > return response.body.getvalue() > > @auth.requires_login() > def call(token): > row = db(db.subscription.token == token).select().first() > my_number = row.my_calls > if my_number > 0 & my_token == token: > db(db.subscription.token == > my_token).update(my_calls=db.subscription.my_calls-1) > return service() > else: > raise Exception()