Skip to content

Commit

Permalink
Add a sample plugin to demonstrate how to customize authentication an…
Browse files Browse the repository at this point in the history
…d authorization using Request subclasses, Request.get_user and User.transient_groups
  • Loading branch information
ejucovy committed Jul 11, 2011
1 parent 43b81c4 commit e303309
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
71 changes: 71 additions & 0 deletions zine/plugins/example_remote_auth/__init__.py
@@ -0,0 +1,71 @@
# -*- coding: utf-8 -*-
"""
zine.plugins.example_remote_auth
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sample remote authentication instead of Zine's built-in authentication.
"""

from zine.application import Request as RequestBase
from zine.database import db
from zine.utils import forms
from zine.models import User, Group

class Request(RequestBase):
def get_user(self):
# This overrides Zine's default session-based authentication
# with a custom method that looks for environ["REMOTE_USER"]
# and creates the appropriate user in the database if it doesn't
# exist yet. If there is no user logged in, this method should
# return None. The caller will handle the AnonymousUser creation
# in that case.
app = self.app
username = self.environ.get("REMOTE_USER", None)
if not username:
return None
user = User.query.filter_by(username=username).first()
if user is None:
user = User(username, None, "%s@example.com" % username)
db.session.add(user)
db.commit()
return user

def __init__(self, environ, app=None):
RequestBase.__init__(self, environ)
request_groups = set()
current_user = self.user

# We can add Group associations to the current user
# by assigning its `transient_groups` property to
# a list of Group objects. Here we'll add one Group
# if the user is authenticated, and a different one
# if the user is anonymous; and we'll also give the
# HTTP request a chance to add an additional group.
# Note that the groups must exist in the database;
# we create them here if they don't exist.
if current_user.is_somebody:
request_groups.add("Authenticated")
else:
request_groups.add("Anonymous")
group = environ.get("HTTP_X_REMOTE_GROUP", None)
if group:
request_groups.add(group)
_request_groups = []
for group_name in request_groups:
group = Group.query.filter_by(name=group_name).first()
if group is None:
group = Group(group_name)
db.session.add(group)
_request_groups.append(group)
db.commit()

self.user.transient_groups = _request_groups

def setup(app, plugin):
# The `_request_class` attribute of the app is used to
# create the Request objects; so we need to reassign it
# to our Request subclass in order for our custom
# authentication and authorization logic to be active.
# Note that we just assume that no other plugin is also
# trying to override the default Request!
app._request_class = Request
7 changes: 7 additions & 0 deletions zine/plugins/example_remote_auth/metadata.txt
@@ -0,0 +1,7 @@
Name: Example Remote Auth
Plugin URL: http://zine.pocoo.org
Author: Ethan Jucovy <ethan.jucovy@gmail.com>
Author URL: http://www.coactivate.org
License: BSD
Version: 0.1
Description: This plugin demonstrates how you can implement custom authentication and authorization logic by overriding the Request.get_user method on a subclass, and adding per-request transient Groups to the User. It is not intended to be secure or robust, so don't use it! It's just a demonstration.

0 comments on commit e303309

Please sign in to comment.