-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 33bb9c6
Showing
18 changed files
with
2,848 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
*.py[co] | ||
*.egg-info | ||
build | ||
dist | ||
|
||
# OSX | ||
.DS_Store | ||
|
||
# PyCharm | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
=========== | ||
aecore | ||
=========== | ||
|
||
aecore Adds Sessions, Users, & a Datastore Config to Google App Engine | ||
=========================================================================== | ||
|
||
Sessions | ||
-------- | ||
|
||
|
||
Users | ||
----- | ||
|
||
|
||
Config | ||
------ | ||
|
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
application: | ||
title: App Engine Site | ||
description: Description here. | ||
default_from_email: none | ||
|
||
aecore: | ||
secret_key: CHANGE_TO_A_SECRET_KEY # We add this here for testing only | ||
user_model: aecore.models.User | ||
cookie_key: _aecore | ||
cookie_max_age: | ||
cookie_path: / | ||
cookie_domain: | ||
cookie_secure: false | ||
cookie_httponly: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from aecore.models import Config | ||
|
||
def user_required(handler): | ||
|
||
def check_login(self, *args, **kwargs): | ||
if not self.request.user: | ||
# If handler has no login_url specified invoke a 403 error | ||
try: | ||
# set the redirect url to the current url. | ||
# self.request.set_redirect_url(self.request.path) | ||
self.redirect(Config.get('aeauth').login_url, abort=True) | ||
except (AttributeError, KeyError), e: | ||
self.abort(403) | ||
else: | ||
return handler(self, *args, **kwargs) | ||
|
||
return check_login | ||
|
||
|
||
def admin_required(handler): | ||
|
||
def check_login(self, *args, **kwargs): | ||
if not self.request.user or 'admin' not in self.request.user.roles: | ||
# If handler has no login_url specified invoke a 403 error | ||
try: | ||
# set the redirect url to the current url. | ||
# self.request.set_redirect_url(self.request.path) | ||
self.redirect(Config.get('aeauth').login_url, abort=True) | ||
except (AttributeError, KeyError), e: | ||
self.abort(403) | ||
else: | ||
return handler(self, *args, **kwargs) | ||
|
||
return check_login |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import webapp2 | ||
from webapp2_extras import jinja2 | ||
from aecore.models import Config | ||
from aecore.middleware import Request | ||
|
||
|
||
class Jinja2Handler(webapp2.RequestHandler): | ||
|
||
def dispatch(self): | ||
self.request.__class__ = Request | ||
webapp2.RequestHandler.dispatch(self) | ||
|
||
@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 add_message(self, message, level=None, key='_messages'): | ||
self.request.add_message(message, level, key) | ||
return | ||
|
||
def render_template(self, template_name, template_values=None): | ||
if template_values is None: template_values = {} | ||
messages = self.get_messages() | ||
if messages: | ||
template_values.update({'messages': messages}) | ||
|
||
template_values.update({ | ||
'application': Config.get('application'), | ||
'user': self.request.user, | ||
'session': self.request.session, | ||
}) | ||
self.response.write(self.jinja2.render_template( | ||
template_name, **template_values)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
from aecore import utils | ||
from aecore import models | ||
from webob import Response as WebobResponse | ||
from webob import Request as WebobRequest | ||
|
||
|
||
class Response(WebobResponse): | ||
|
||
def _save_session(self): | ||
session = self.request.session | ||
# Compare the hash that we set in load_session to the current one. | ||
# We only save the session and cookie if this value has changed. | ||
if self.request.session_hash == session.hash(): | ||
return session | ||
session.put() | ||
# If we have a user_id we want to updated the | ||
# session to use the user_id as the key. | ||
if session.user_id is not None: | ||
session_id = session.key.id() | ||
if session_id != session.user_id: | ||
session = models.Session.upgrade_to_user_session( | ||
session_id, session.user_id) | ||
# load cookie config | ||
config = models.Config.get('aecore') | ||
max_age = int(config.cookie_max_age) if config.cookie_max_age else None | ||
self.set_cookie( | ||
config.cookie_key.encode('ascii'), | ||
value=session.serialize(), | ||
max_age=max_age, | ||
path=config.cookie_path.encode('ascii'), | ||
domain=config.cookie_domain, | ||
secure=config.cookie_secure, | ||
httponly=config.cookie_httponly) | ||
return self | ||
|
||
def _save_user(self): | ||
# TODO: save user if modified. | ||
pass | ||
|
||
def _set_redirect(self, location, code=307): | ||
# TODO this needs to be improved | ||
# exc.HTTPTemporaryRedirect(location=location) | ||
self.headers['Location'] = location | ||
self.status = code | ||
set_redirect = _set_redirect | ||
|
||
class Request(WebobRequest): | ||
|
||
ResponseClass = Response | ||
|
||
def _load_session(self): | ||
config = models.Config.get('aecore') | ||
value = self.cookies.get(config.cookie_key) | ||
session = None | ||
if value: | ||
session = models.Session.get_by_value(value) | ||
if session is not None: | ||
# Create a hash for later comparison, | ||
# to determine if a put() is required | ||
session_hash = session.hash() | ||
else: | ||
session = models.Session.create() | ||
# set this to False to ensure a cookie | ||
# is saved later in the response. | ||
session_hash = '0' | ||
self.session = session | ||
self.session_hash = session_hash | ||
return self | ||
load_session = _load_session | ||
|
||
def _get_user_model(self): | ||
try: | ||
return utils.import_class(self._config.user_model) | ||
except ImportError, e: | ||
raise Exception('The following error occurred while attempting to '\ | ||
'import your custom user model: {}'.format(e)) | ||
except AttributeError: | ||
# This is allows for test with out the need to pass a _config. | ||
return models.User | ||
get_user_model = _get_user_model | ||
|
||
def _load_user(self, user_id=None): | ||
user = None | ||
user_model = self._get_user_model() | ||
if user_id is None and self.session is not None and self.session.user_id: | ||
user_id = self.session.user_id | ||
if user_id is not None: | ||
user = user_model.get_by_id(int(user_id)) | ||
# Add user to session | ||
self.session.user_id = user.get_id() if user else None | ||
self.user = user | ||
return self | ||
load_user = _load_user | ||
|
||
def _add_message(self, message, level=None, key='_messages'): | ||
if not self.session.data.get(key): | ||
self.session.data[key] = [] | ||
return self.session.data[key].append({ | ||
'message': message, 'level': level}) | ||
add_message = _add_message | ||
|
||
def _get_messages(self, key='_messages'): | ||
try: | ||
return self.session.data.pop(key) | ||
except KeyError: | ||
pass | ||
get_messages = _get_messages | ||
|
||
def _set_redirect_url(self, url=None): | ||
if url is not None: | ||
next_uri = url | ||
else: | ||
next_uri = self.GET.get('next') | ||
if next_uri is not None: | ||
self.session.data['_redirect_url'] = next_uri | ||
set_redirect_url = _set_redirect_url | ||
|
||
def _get_redirect_url(self): | ||
try: | ||
return self.session.data.pop('_redirect_url').encode('utf-8') | ||
except KeyError: | ||
return None | ||
get_redirect_url = _get_redirect_url | ||
|
||
|
||
class AECoreMiddleware(object): | ||
def __init__(self, app): | ||
self.app = app | ||
|
||
def __call__(self, environ, start_response): | ||
# If the request is to the admin, return | ||
if environ['PATH_INFO'].startswith('/_ah/'): | ||
return self.app(environ, start_response) | ||
|
||
# load session | ||
request = Request(environ) | ||
request.load_session() | ||
request.load_user() | ||
request.set_redirect_url() | ||
response = request.get_response(self.app) | ||
response.request = request | ||
|
||
# Save session, return response | ||
response._save_session() | ||
|
||
# see if a redirect as been saved to the session | ||
redirect = response.request.get_redirect_url() | ||
|
||
if redirect: | ||
response.set_redirect(redirect) | ||
return response(environ, start_response) | ||
|
||
|
Oops, something went wrong.