74 строки
2.8 KiB
Python
74 строки
2.8 KiB
Python
from functools import partial
|
|
|
|
import commonware.log
|
|
import jingo
|
|
from piston.authentication.oauth import OAuthAuthentication, views
|
|
|
|
from django.contrib.auth.models import AnonymousUser
|
|
|
|
from access.middleware import ACLMiddleware
|
|
from users.models import UserProfile
|
|
from zadmin import jinja_for_django
|
|
|
|
# This allows the views in piston.authentication.oauth to cope with
|
|
# Jinja2 templates as opposed to Django templates.
|
|
# Piston view passes: template, context, request_context
|
|
jfd = lambda a, b, c: jinja_for_django(a, b, context_instance=c)
|
|
views.render_to_response = jfd
|
|
|
|
|
|
log = commonware.log.getLogger('z.api')
|
|
|
|
|
|
class AMOOAuthAuthentication(OAuthAuthentication):
|
|
"""^^^MOO!!! Adds amo_user to the request object."""
|
|
|
|
def is_authenticated(self, request):
|
|
if request.user and request.user.is_authenticated():
|
|
return True
|
|
|
|
# To avoid patching django-piston, use a partial to cope with
|
|
# piston not sending in request when called later.
|
|
self.challenge = partial(self._challenge, request=request)
|
|
|
|
# Authenticate the user using Piston, rv will be True or False
|
|
# depending upon how it went.
|
|
rv = super(AMOOAuthAuthentication, self).is_authenticated(request)
|
|
|
|
if rv and request.user:
|
|
# The user is there, but we need to alter the user to be
|
|
# a user specified in the request. Specifically chose this
|
|
# term to avoid conflict with user, which could be used elsewhere.
|
|
if self.two_legged and 'authenticate_as' in request.REQUEST:
|
|
pk = request.REQUEST.get('authenticate_as')
|
|
try:
|
|
profile = UserProfile.objects.get(pk=pk)
|
|
except UserProfile.DoesNotExist:
|
|
log.warning('Cannot find user: %s' % pk)
|
|
return False
|
|
|
|
if profile.deleted or profile.confirmationcode:
|
|
log.warning('Tried to use deleted or unconfirmed user: %s'
|
|
% pk)
|
|
return False
|
|
|
|
log.info('Authenticating as: %s' % pk)
|
|
request.user = profile.user
|
|
|
|
# If that worked and request.user got set, setup AMO specific bits.
|
|
ACLMiddleware().process_request(request)
|
|
else:
|
|
# The piston middleware could find a consumer, but no
|
|
# user on that consumer. If it does it returns True, but
|
|
# request.user is None, which then blows up other things.
|
|
request.user = AnonymousUser()
|
|
return False
|
|
|
|
return rv
|
|
|
|
def _challenge(self, request):
|
|
response = jingo.render(request, 'piston/oauth/challenge.html',
|
|
status=401)
|
|
response['WWW-Authenticate'] = 'OAuth realm="API"'
|
|
return response
|