Commits

Jesper Nøhr committed 6a73311

cleaning up a bit, documenting things

Comments (0)

Files changed (1)

piston/authentication.py

 from django.http import HttpResponse
 from django.contrib.auth.models import User
 from django.contrib.auth.decorators import login_required
+from django.template import loader
 from django.conf import settings
 
 import oauth
+from store import DataStore
 
 def django_auth(username, password):
+    """
+    Basic callback for `HttpBasicAuthentication`
+    which checks the username and password up
+    against Djangos built-in authentication system.
+    
+    On success, returns the `User`, *not* boolean!
+    """
     try:
         user = User.objects.get(username=username)
         if user.check_password(password):
         resp.status_code = 401
         return resp
 
-
-from store import DataStore
-
-OAUTH_REALM_KEY_NAME = 'OAUTH_REALM_KEY_NAME'
-
 def initialize_server_request(request):
     """Shortcut for initialization."""
-    oauth_request = oauth.OAuthRequest.from_request(request.method, 
-                                                    request.build_absolute_uri(), 
-                                                    headers=request.META,
-                                                    parameters=dict(request.REQUEST.items()),
-                                                    query_string=request.environ.get('QUERY_STRING', ''))
+    oauth_request = oauth.OAuthRequest.from_request(
+        request.method, request.build_absolute_uri(), 
+        headers=request.META, parameters=dict(request.REQUEST.items()),
+        query_string=request.environ.get('QUERY_STRING', ''))
+        
     if oauth_request:
         oauth_server = oauth.OAuthServer(DataStore(oauth_request))
         oauth_server.add_signature_method(oauth.OAuthSignatureMethod_PLAINTEXT())
     response = HttpResponse(err.message.encode('utf-8'))
     response.status_code = 401
     # return the authenticate header
-    realm = getattr(settings, OAUTH_REALM_KEY_NAME, 'Bitbucket.org OAuth')
+    realm = 'Bitbucket.org OAuth'
     header = oauth.build_authenticate_header(realm=realm)
     for k, v in header.iteritems():
         response[k] = v
     """
     def __init__(self, realm='Bitbucket.org HTTP'):
         self.realm = realm
+        self.builder = oauth.build_authenticate_header
     
     def is_authenticated(self, request):
+        """
+        Checks whether a means of specifying authentication
+        is provided, and if so, if it is a valid token.
+        
+        Read the documentation on `HttpBasicAuthentication`
+        for more information about what goes on here.
+        """
         if self.is_valid_request(request):
             try:
                 consumer, token, parameters = self.validate_token(request)
             except oauth.OAuthError, err:
-                print send_oauth_error(err)
                 return False
 
             if consumer and token:
         return False
         
     def challenge(self):
-        return INVALID_PARAMS_RESPONSE
+        """
+        Returns a 401 response with a small bit on
+        what OAuth is, and where to learn more about it.
+        
+        When this was written, browsers did not understand
+        OAuth authentication on the browser side, and hence
+        the helpful template we render. Maybe some day in the
+        future, browsers will take care of this stuff for us
+        and understand the 401 with the realm we give it.
+        """
+        response = HttpResponse()
+        response.status_code = 401
+        realm = 'Bitbucket.org OAuth'
+
+        for k, v in self.builder(realm=realm).iteritems():
+            response[k] = v
+
+        tmpl = loader.render_to_string('oauth/challenge.html',
+            { 'MEDIA_URL': settings.MEDIA_URL })
+
+        response.content = tmpl
+
+        return response
         
     @staticmethod
     def is_valid_request(request):
-        try:
-            auth_params = request.META["HTTP_AUTHORIZATION"]
-        except KeyError:
-            in_auth = False
-        else:
-            in_auth = 'oauth_consumer_key' in auth_params \
-                and 'oauth_token' in auth_params \
-                and 'oauth_signature_method' in auth_params \
-                and 'oauth_signature' in auth_params \
-                and 'oauth_timestamp' in auth_params \
-                and 'oauth_nonce' in auth_params
-               
-        # also try the request, which covers POST and GET
+        """
+        Checks whether the required parameters are either in
+        the http-authorization header sent by some clients,
+        which is by the way the preferred method according to
+        OAuth spec, but otherwise fall back to `GET` and `POST`.
+        """
+        must_have = [ 'oauth_'+s for s in [
+            'consumer_key', 'token', 'signature',
+            'signature_method', 'timestamp', 'nonce' ] ]
+        
+        is_in = lambda l: False not in [ (p in l) for p in must_have ]
+
+        auth_params = request.META.get("HTTP_AUTHORIZATION", "")
         req_params = request.REQUEST
-        in_req = 'oauth_consumer_key' in req_params \
-            and 'oauth_token' in req_params \
-            and 'oauth_signature_method' in req_params \
-            and 'oauth_signature' in req_params \
-            and 'oauth_timestamp' in req_params \
-            and 'oauth_nonce' in req_params
              
-        return in_auth or in_req
+        return is_in(auth_params) or is_in(req_params)
         
     @staticmethod
     def validate_token(request, check_timestamp=True, check_nonce=True):
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.