#!/usr/bin/python2.4 # # Licensed 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