Search code examples
pythongoogle-app-engine

Python admin only decorators


Alright This is What i have:

I'm playing around with authengine by scotch and can't figure out how to make a admin decorator. heres the code its rather simple:

class Jinja2Handler(webapp2.RequestHandler):
"""
    BaseHandler for all requests all other handlers will
    extend this handler

"""
@webapp2.cached_property
def jinja2(self):
    return jinja2.get_jinja2(app=self.app)

def get_messages(self, key='_messages'):
    try:
        return self.request.session.data.pop(key)
    except KeyError:
        return None

def render_template(self, template_name, template_values={}):
    messages = self.get_messages()
    if messages:
        template_values.update({'messages': messages})
    self.response.write(self.jinja2.render_template(
        template_name, **template_values))

def render_string(self, template_string, template_values={}):
    self.response.write(self.jinja2.environment.from_string(
        template_string).render(**template_values))

def json_response(self, json):
    self.response.headers.add_header('content-type', 'application/json', charset='utf-     8')
    self.response.out.write(json)

def UserArea(fuct):

    def Usercheck():
        return Usercheck


class PageHandler(Jinja2Handler):

def root(self):
    session = self.request.session if self.request.session else None
    user = self.request.user if self.request.user else None
    profiles = None
    emails = None
    if user:
        profile_keys = [ndb.Key('UserProfile', p) for p in user.auth_ids]
        profiles = ndb.get_multi(profile_keys)
        emails = models.UserEmail.get_by_user(user.key.id())
    self.render_template('home.html', {
        'user': user,
        'session': session,
        'profiles': profiles,
        'emails': emails,
    })

@UserArea
class UserHandler(Jinja2Handler):

def get(self):
    self.render_template('index-2.html', {

    })

Skipping the indenting errors... i can't seem to figure it out... i've read thought this How to make a chain of function decorators? thought i had the basic understanding for it.... but no

Any help to point me in the right way...

The error i seam to get alot is TypeError: 'NoneType' object is not callable


Solution

  • def UserArea(fuct):
    
        def Usercheck():
            return Usercheck
    

    You're using this as a decorator, but it doesn't return anything, so it returns None. So when you try to instantiate the decorated class, you are calling None() and obviously that doesn't work. Also, the wrapper function merely returns itself, which is rarely what you want.

    It's hard to tell what you actually want the decorator to do, but usually decorators are written something like this:

    import functools
    
    def UserArea(func):
    
        @functools.wraps(func)
        def usercheck(*args, **kwargs):
            if adminuser:   # however this gets defined
               return func(*args, **kwargs)
            else:
               raise Exception("not authorized")
    
        return usercheck
    

    Note that the inner function, which will be used as a wrapper for the decorated object, calls the decorated object and returns its result, allowing it to be used as a direct substitute for the decorated object in client code. If your wrapper function doesn't do this, your decorator is pretty much broken.

    As a further note, I see you're using this as a class decorator, which means it will be called when the class is instantiated. Using a class decorator that returns a function will make subclassing the class difficult because the actual class no longer has a public name. It might make more sense, then, to decorate some or all of the methods of the class rather than the class itself.