diff --git a/djangorestframework/mixins.py b/djangorestframework/mixins.py index f4a9c998a..1cb7d5f13 100644 --- a/djangorestframework/mixins.py +++ b/djangorestframework/mixins.py @@ -361,14 +361,14 @@ class AuthMixin(object): return AnonymousUser() # TODO: wrap this behavior around dispatch() - def _check_permissions(self): + def _check_permissions(self, test_methods=None): """ Check user permissions and either raise an ``ErrorResponse`` or return. """ user = self.user for permission_cls in self.permissions: permission = permission_cls(self) - permission.check_permission(user) + permission.check_permission(user, test_methods=test_methods) ########## Resource Mixin ########## diff --git a/djangorestframework/permissions.py b/djangorestframework/permissions.py index dfe55ce94..a6edb1919 100644 --- a/djangorestframework/permissions.py +++ b/djangorestframework/permissions.py @@ -41,7 +41,7 @@ class BasePermission(object): """ self.view = view - def check_permission(self, auth): + def check_permission(self, auth, test_methods=None, **kwargs): """ Should simply return, or raise an :exc:`response.ErrorResponse`. """ @@ -53,7 +53,7 @@ class FullAnonAccess(BasePermission): Allows full access. """ - def check_permission(self, user): + def check_permission(self, user, test_methods=None, **kwargs): pass @@ -62,7 +62,7 @@ class IsAuthenticated(BasePermission): Allows access only to authenticated users. """ - def check_permission(self, user): + def check_permission(self, user, test_methods=None, **kwargs): if not user.is_authenticated(): raise _403_FORBIDDEN_RESPONSE @@ -72,7 +72,7 @@ class IsAdminUser(BasePermission): Allows access only to admin users. """ - def check_permission(self, user): + def check_permission(self, user, test_methods=None, **kwargs): if not user.is_staff: raise _403_FORBIDDEN_RESPONSE @@ -82,10 +82,9 @@ class IsUserOrIsAnonReadOnly(BasePermission): The request is authenticated as a user, or is a read-only request. """ - def check_permission(self, user): - if (not user.is_authenticated() and - self.view.method != 'GET' and - self.view.method != 'HEAD'): + def check_permission(self, user, test_methods=None, **kwargs): + if not test_methods: test_methods = [self.view.method] + if not user.is_authenticated() and not set(['GET', 'HEAD']).issuperset(test_methods): raise _403_FORBIDDEN_RESPONSE @@ -113,11 +112,15 @@ class BaseThrottle(BasePermission): """ pass - def check_permission(self, auth): + def check_permission(self, auth, test_methods=None, **kwargs): """ Check the throttling. Return `None` or raise an :exc:`.ErrorResponse`. """ + + # Return if just testing the permission. + if test_methods: return + num, period = getattr(self.view, self.attr_name, self.default).split('/') self.num_requests = int(num) self.duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]] diff --git a/djangorestframework/renderers.py b/djangorestframework/renderers.py index bb0f789aa..aab6a20ba 100644 --- a/djangorestframework/renderers.py +++ b/djangorestframework/renderers.py @@ -17,6 +17,7 @@ from djangorestframework.utils import dict2xml, url_resolves from djangorestframework.utils.breadcrumbs import get_breadcrumbs from djangorestframework.utils.mediatypes import get_media_type_params, add_media_type_param, media_type_matches from djangorestframework import VERSION +from djangorestframework.response import ErrorResponse import string from urllib import quote_plus @@ -232,6 +233,13 @@ class DocumentingTemplateRenderer(BaseRenderer): provide a form that can be used to submit arbitrary content. """ + # Return no form if user doesn't have write access to this view + if hasattr(view, '_check_permissions'): + try: + view._check_permissions(test_methods=('POST', 'PUT', 'DELETE', 'PATCH',)) + except ErrorResponse: + return None + # Get the form instance if we have one bound to the input form_instance = None if method == getattr(view, 'method', view.request.method).lower(): diff --git a/djangorestframework/templates/renderer.html b/djangorestframework/templates/renderer.html index e396a58f5..5b80f11da 100644 --- a/djangorestframework/templates/renderer.html +++ b/djangorestframework/templates/renderer.html @@ -65,7 +65,7 @@ {# Only display the POST/PUT/DELETE forms if method tunneling via POST forms is enabled and the user has permissions on this view. #} {% if METHOD_PARAM and response.status != 403 %} - {% if 'POST' in view.allowed_methods %} + {% if 'POST' in view.allowed_methods and post_form %}
{% endif %} - {% if 'PUT' in view.allowed_methods %} + {% if 'PUT' in view.allowed_methods and put_form %}