Ian Lewis avatar Ian Lewis committed 9e7f7bd

Fixed the explore admin view so that it checks view permissions

Comments (0)

Files changed (6)

hgwebproxy/admin.py

         # Redirect the user to the public repository view if
         # The user does not have permission to change the repository.
         obj = self.get_object(request, unquote(object_id))
-        if (obj.has_view_permission(request.user) and not
-                obj.has_change_permission(request.user)):
+        if (self.has_view_permission(request.user, obj) and not
+                self.has_change_permission(request.user, obj)):
             return redirect(obj)
         else:
             return super(RepositoryAdmin, self).change_view(request, object_id, extra_context)
         if not obj.owner:
             obj.owner = request.user
         obj.save()
+
+    def has_view_permission(self, request, obj=None):
+        opts = self.opts
+        perm_name = 'view_repository'
+        has_perm = request.user.has_perm(opts.app_label + '.' + perm_name)
+        if obj:
+            has_perm = has_perm and obj.has_view_permission(request.user)
+        return has_perm 
     
     def has_change_permission(self, request, obj=None):
         has_perm = super(RepositoryAdmin, self).has_change_permission(request, obj)
 
         response = HttpResponse()
         repo = get_object_or_404(Repository, pk=id)
+        if not self.has_view_permission(request, repo):
+            raise PermissionDenied
+
         hgr = HgRequestWrapper(
             request,
             response,

hgwebproxy/fixtures/basic.json

             "last_name": "user", 
             "is_active": true, 
             "is_superuser": false, 
-            "is_staff": false, 
+            "is_staff": true, 
             "last_login": "2009-12-21 05:36:38", 
             "groups": [], 
             "user_permissions": [], 
             "last_name": "user", 
             "is_active": true, 
             "is_superuser": false, 
-            "is_staff": false, 
+            "is_staff": true, 
             "last_login": "2009-12-21 05:37:07", 
             "groups": [], 
             "user_permissions": [], 
             "last_name": "user", 
             "is_active": true, 
             "is_superuser": false, 
-            "is_staff": false, 
+            "is_staff": true, 
             "last_login": "2009-12-21 05:37:33", 
             "groups": [], 
             "user_permissions": [], 
             "last_name": "user", 
             "is_active": true, 
             "is_superuser": false, 
-            "is_staff": false, 
+            "is_staff": true, 
             "last_login": "2009-12-21 05:38:22", 
             "groups": [
                 1
             "last_name": "user", 
             "is_active": true, 
             "is_superuser": false, 
-            "is_staff": false, 
+            "is_staff": true, 
             "last_login": "2009-12-21 05:38:53", 
             "groups": [
                 2
             "last_name": "user", 
             "is_active": true, 
             "is_superuser": false, 
-            "is_staff": false, 
+            "is_staff": true, 
             "last_login": "2009-12-21 05:38:53", 
             "groups": [], 
             "user_permissions": [], 

hgwebproxy/tests/__init__.py

 #:coding=utf-8:
 
 from api_tests import * 
+from admin_tests import *
 from permission_tests import * 
 from web_tests import * 

hgwebproxy/tests/admin_tests.py

+#:coding=utf-8:
+
+import os
+
+from django.contrib.auth.models import User,Permission
+from django.test import TestCase as DjangoTestCase
+from django.core.urlresolvers import reverse
+from django.conf import settings
+
+from hgwebproxy.tests.base import RepoTestCase, RequestTestCaseMixin
+from hgwebproxy import settings as hgwebproxy_settings
+
+class AdminTests(RequestTestCaseMixin, RepoTestCase):
+    def test_explore_forbidden(self):
+        self.client.login(username="no_perms", password="no_perms")
+        user = User.objects.get(username="no_perms")
+        user.user_permissions.add(
+            Permission.objects.get_by_natural_key(
+                "view_repository",
+                "hgwebproxy",
+                "repository",
+            )
+        )
+        self.assertFalse(self.test_repo.has_view_permission(user))
+
+        response = self.client.get(reverse("admin:hgwebproxy_repository_explore", kwargs={
+            'id': self.test_repo.pk,    
+        }))
+        self.assertAdminLogin(response)

hgwebproxy/tests/base.py

 
 from django.contrib.auth.models import User, Group
 from django.test import TestCase as DjangoTestCase
+from django.utils.encoding import smart_str
 from django.conf import settings
 
 from hgwebproxy import settings as hgwebproxy_settings
         repo.writers.add(User.objects.get(username="writer"))
         repo.reader_groups.add(Group.objects.get(name="readers"))
         repo.writer_groups.add(Group.objects.get(name="writers"))
+        self.test_repo = repo
 
     def tearDown(self):
         # Leave items in the base directory in case of
         # test failures. Developers can check these repositories
         # to get clues as to what went wrong.
         pass
+
+class RequestTestCaseMixin(object):
+
+    def assertStatus(self, response, status=200):
+        self.assertEquals(response.status_code, status)
+
+    def assertOk(self, response):
+        self.assertStatus(response)
+
+    def assertBadRequest(self, response):
+        self.assertStatus(response, 400)
+
+    def assertForbidden(self, response):
+        self.assertStatus(response, 403)
+
+    def assertNotFound(self, response):
+        self.assertStatus(response, 404)
+
+    def assertRedirect(self, response, redirect_url=None):
+        self.assertStatus(response, 302)
+        self._assertLocationHeader(response, redirect_url)
+
+    def assertPermanentRedirect(self, response, request_url=None):
+        self.assertStatus(response, 301)
+        self._assertLocationHeader(response, redirect_url)
+
+    def _assertLocationHeader(self, response, request_url=None):
+        if request_url is None: 
+            self.assertTrue(response.get("Location", None) is not None)
+        else:
+            self.assertEquals(response.get("Location", None), request_url)
+
+    def assertNotAllowed(self, response, allow=None):
+        self.assertEquals(response.status_code, 405)
+        if allow is not None:
+            self.assertEquals(response["Allow"], allow)
+
+    def assertGone(self, response):
+        self.assertEquals(response.status_code, 410)
+
+    def assertHtml(self, response, status_code=200):
+        self.assertBody(response, "<html") # open tag
+        self.assertBody(response, "</html>") # close tag
+        self.assertBody(response, "<head")
+        self.assertBody(response, "</head>")
+        self.assertBody(response, "<body")
+        self.assertBody(response, "</body>")
+
+    def assertHeader(self, response, header_name, value):
+        self.assertEquals(response[header_name], value)
+
+    def assertBody(self, response, text, count=None,
+                       msg_prefix=''):
+        """
+        Asserts that ``text`` occurs ``count`` times in the content of the response.
+        If ``count`` is None, the count doesn't matter - the assertion is true
+        if the text occurs at least once in the response.
+        """
+        if msg_prefix:
+            msg_prefix += ": "
+
+        text = smart_str(text, response._charset)
+        real_count = response.content.count(text)
+        if count is not None:
+            self.assertEqual(real_count, count,
+                msg_prefix + "Found %d instances of '%s' in response"
+                " (expected %d)" % (real_count, text, count))
+        else:
+            self.failUnless(real_count != 0,
+                msg_prefix + "Couldn't find '%s' in response" % text)
+
+    def assertAdminLogin(self, response):
+        self.assertContains(response, '<input type="submit" value="Log in" />')

hgwebproxy/tests/web_tests.py

 
 import os
 
-from django.utils.encoding import smart_str
 from django.contrib.auth.models import User
 from django.test import TestCase as DjangoTestCase
 from django.core.urlresolvers import reverse
+from django.utils.http import urlencode
 from django.conf import settings
 
-from hgwebproxy.tests.base import RepoTestCase
+from hgwebproxy.tests.base import RepoTestCase, RequestTestCaseMixin
 from hgwebproxy import settings as hgwebproxy_settings
 
-class RequestTestCaseMixin(object):
-
-    def assertStatus(self, response, status=200):
-        self.assertEquals(response.status_code, status)
-
-    def assertOk(self, response):
-        self.assertStatus(response)
-
-    def assertBadRequest(self, response):
-        self.assertStatus(response, 400)
-
-    def assertForbidden(self, response):
-        self.assertStatus(response, 403)
-
-    def assertNotFound(self, response):
-        self.assertStatus(response, 404)
-
-    def assertRedirect(self, response, redirect_url=None):
-        self.assertStatus(response, 302)
-        self._assertLocationHeader(response, redirect_url)
-
-    def assertPermanentRedirect(self, response, request_url=None):
-        self.assertStatus(response, 301)
-        self._assertLocationHeader(response, redirect_url)
-
-    def _assertLocationHeader(self, response, request_url=None):
-        if request_url is None: 
-            self.assertTrue(response.get("Location", None) is not None)
-        else:
-            self.assertEquals(response.get("Location", None), request_url)
-
-    def assertNotAllowed(self, response, allow=None):
-        self.assertEquals(response.status_code, 405)
-        if allow is not None:
-            self.assertEquals(response["Allow"], allow)
-
-    def assertGone(self, response):
-        self.assertEquals(response.status_code, 410)
-
-    def assertHtml(self, response, status_code=200):
-        self.assertBody(response, "<html") # open tag
-        self.assertBody(response, "</html>") # close tag
-        self.assertBody(response, "<head")
-        self.assertBody(response, "</head>")
-        self.assertBody(response, "<body")
-        self.assertBody(response, "</body>")
-
-    def assertHeader(self, response, header_name, value):
-        self.assertEquals(response[header_name], value)
-
-    def assertBody(self, response, text, count=None,
-                       msg_prefix=''):
-        """
-        Asserts that ``text`` occurs ``count`` times in the content of the response.
-        If ``count`` is None, the count doesn't matter - the assertion is true
-        if the text occurs at least once in the response.
-        """
-        if msg_prefix:
-            msg_prefix += ": "
-
-        text = smart_str(text, response._charset)
-        real_count = response.content.count(text)
-        if count is not None:
-            self.assertEqual(real_count, count,
-                msg_prefix + "Found %d instances of '%s' in response"
-                " (expected %d)" % (real_count, text, count))
-        else:
-            self.failUnless(real_count != 0,
-                msg_prefix + "Couldn't find '%s' in response" % text)
-
 class HgWebTest(RequestTestCaseMixin, RepoTestCase):
 
     def test_hgwebdir_top(self):
         super(DebugStaticFilesTest, self).tearDown()
         settings.DEBUG = self.old_debug
 
+    def _get_environ(self, path, data={}):
+        import urllib
+        from urlparse import urlparse, urlunparse, urlsplit
+        from django.test.client import FakePayload
+
+        parsed = urlparse(path)
+        r = {
+            'CONTENT_TYPE':    'text/html; charset=utf-8',
+            'PATH_INFO':       urllib.unquote(parsed[2]),
+            'QUERY_STRING':    urlencode(data, doseq=True) or parsed[4],
+            'REQUEST_METHOD': 'GET',
+            'wsgi.input':      FakePayload('')
+        }
+        environ = {
+            'HTTP_COOKIE':       self.client.cookies.output(header='', sep='; '),
+            'PATH_INFO':         '/',
+            'QUERY_STRING':      '',
+            'REMOTE_ADDR':       '127.0.0.1',
+            'REQUEST_METHOD':    'GET',
+            'SCRIPT_NAME':       '',
+            'SERVER_NAME':       'testserver',
+            'SERVER_PORT':       '80',
+            'SERVER_PROTOCOL':   'HTTP/1.1',
+            'wsgi.version':      (1,0),
+            'wsgi.url_scheme':   'http',
+            'wsgi.errors':       self.client.errors,
+            'wsgi.multiprocess': True,
+            'wsgi.multithread':  False,
+            'wsgi.run_once':     False,
+        }
+        environ.update(r)
+        return environ
+
     def test_static_file(self):
-        response = self.client.get(reverse("repo_static_file", kwargs={"file_name":"hglogo.png"}))
+        from django.core.handlers.wsgi import WSGIRequest
+        from hgwebproxy.views import static_file
+
+        request = WSGIRequest(self._get_environ('/hg/static/hglogo.png'))
+        response = static_file(request, 'hglogo.png')
         self.assertOk(response)
         self.assertHeader(response, "Content-Type", "image/png")
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.