7
\$\begingroup\$

I'm trying to set up a very lightweight permission system using Google App Engine and Flask.

The end result I am hoping for is that each individual view is its own permission, and in an admin panel you can assign the views each user is allowed to see.

How would I set this up better? It works fine, but I'm going to be querying ndb on operator for each and every view everytime a page loads.

from google.appengine.api import users
from google.appengine.ext import ndb
import logging
from flask import Flask, redirect, make_response, request

def user_authorized(rule):
    user = users.get_current_user()
    username = str(user)
    user_info = Operators.query(Operators.username == username).get()
    if not user_info:
        return False
    if rule in user_info.permissions:
        return True
    else:
        return False

def forbidden_view():
    return make_response(
        'You do not have permission or this user does not exist. <a href="{0}">Login</a>'.format(users.create_login_url(request.url)),
        403
    )

class FlaskWithPermissions(Flask):
    def route(self, rule, **options):
        def decorator(f):
            endpoint = options.pop('endpoint', f.__name__)
            if user_authorized(rule):
                self.add_url_rule(rule, endpoint, f, **options)
                return f
            else:
                self.add_url_rule(rule, endpoint, forbidden_view, **options)
        return decorator

app = FlaskWithPermissions(__name__)

class Operators(ndb.Model):
    username = ndb.StringProperty()
    permissions = ndb.StringProperty(repeated=True)

@app.route('/')
def index():
    return 'OK /'

@app.route('/test')
def test():
   return 'OK /test'

@app.route('/testfail')
def testfail():
    return 'OK /testfail'

The test data I have in the database is:

Operators(username='test@example.com', permissions=['/', '/test']).put()

And then log in as test@example.com, of course.

\$\endgroup\$
  • \$\begingroup\$ Just a nit-pick, near the end of user_authorized, you could simply return rule in user_info.permissions instead of the if-else \$\endgroup\$ – janos May 29 '14 at 15:31
  • \$\begingroup\$ Thanks. That's a pattern I use quite a lot and the way you mentioned is definitely cleaner. \$\endgroup\$ – profesor_tortuga May 30 '14 at 1:23
1
\$\begingroup\$

The first thing that comes to mind is just to cache user permissions in memcache, but that might or might not be necessary. I'd try this way first and see if you run into issues.

A simpler approach would be to define each user's key to be their username, then use get_by_id(). That has the advantage of being automatically memcached by ndb and being faster (I think).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.