blob: 6fd8a3f432dafd18facfcfa31150b60ba1f7453c [file] [log] [blame]
#!/usr/bin/python2.4
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
"""Filter and decorator to wave enable django sites.
If you want to require wave authentication for every handler, just add
WaveOAuthMiddleware to your middleware. If you only want to require
authentication for specific handlers, decorate those with @waveoauth.
In any wave authenticated handler the request object should have a
waveservice field that can be used to talk to wave.
You can specify the following in your settings:
WAVE_CONSUMER_KEY: the consumer key passed to the waveservice. defaults to
anonymous if not set.
WAVE_CONSUMER_SECRET: the consumer key passed to the waveservice. defaults to
anonymous if not set.
WAVE_USE_SANDBOX: whether to use the sandbox for this app. Defaults to false.
"""
from django.conf import settings
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth import authenticate
import base64
import logging
from functools import wraps
import waveservice
class WaveOAuthMiddleware(object):
"""Wave middleware to authenticate all requests at this site."""
def process_request(self, request):
return _oauth_helper(request)
def waveoauth(func):
"""Decorator used to specify that a handler requires wave authentication."""
@wraps(func)
def inner(request, *args, **kwargs):
result = _oauth_helper(request)
if result is not None:
return result
return func(request, *args, **kwargs)
return inner
def _oauth_helper(request):
"Check if we're authenticated and if not, execute the oauth dance."
consumer_key = getattr(settings, 'WAVE_CONSUMER_KEY', 'anonymous')
consumer_secret = getattr(settings, 'WAVE_CONSUMER_SECRET', 'anonymous')
use_sandbox = getattr(settings, 'WAVE_USE_SANDBOX', False)
service = waveservice.WaveService(
consumer_key=consumer_key, consumer_secret=consumer_secret, use_sandbox=use_sandbox)
access_token = request.COOKIES.get('WAVE_ACCESS_TOKEN')
if access_token:
service.set_access_token(access_token)
request.waveservice = service
return None
# no access token. dance monkey dance.
oauth_token = request.GET.get('oauth_token')
verifier = request.GET.get('oauth_verifier')
request_token = request.COOKIES.get('WAVE_REQUEST_TOKEN')
meta = request.META
# you'd think there would be something better than this madness:
this_url = meta.get('HTTP_HOST')
if not this_url:
this_url = meta.get('SERVER_NAME')
port = meta.get('SEVER_PORT')
if port:
this_url += ':' + port
this_url += request.path
schema = meta.get('wsgi.url_scheme', 'http')
this_url = schema + '://' + this_url
if not oauth_token or not verifier or not request_token:
# we're here not returning from a callback. Start.
request_token = service.fetch_request_token(callback=this_url)
auth_url = service.generate_authorization_url()
response = HttpResponseRedirect(auth_url)
# set a session cookie
response.set_cookie('WAVE_REQUEST_TOKEN', request_token.to_string())
return response
else:
logging.info('upgrading to access token')
access_token = service.upgrade_to_access_token(request_token=request_token,
verifier=verifier)
# This redirect could be avoided if the caller would set the cookie. This way
# however we keep the cgi arguments clean.
response = HttpResponseRedirect(this_url)
response.set_cookie('WAVE_ACCESS_TOKEN', access_token.to_string(), max_age=24*3600*365)
return response