Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added message for permission denied exceptions #720

Open
wants to merge 1 commit into
base: devel
Choose a base branch
from

Conversation

marxide
Copy link

@marxide marxide commented Oct 9, 2020

I found myself wanting to pass a string to the PermissionDenied exceptions to that I could display more information to the user on the 403 page.

This PR adds an attribute permission_denied_message and an overridable method get_permission_denied_message to the PermissionRequiredMixin which can be configured with a message string that is passed to the PermissionDenied exception. By default, Django will then add the string representation of the PermissionDenied exception to the template context as exception.

If permission_denied_message is undefined, an empty string is passed to PermissionDenied.

Here are a couple of examples

  1. Simple message.

If the current user does not have the app_label.view_secretmodel permission, they will be served the 403 page that contains the message "You do not have access to the request secret object.".

# models.py
from django.db import models
from django.contrib.auth.models import User

class SecretModel(models.Model):
    name = models.CharField(max_length=30)
    owner = models.ForeignKey(User, on_delete=models.CASCADE)
# views.py
from django.views.generic import DetailView
from guardian.mixins import PermissionRequiredMixin
from app_label.models import SecretModel

class SecretObjectDetail(PermissionRequiredMixin, DetailView):
    model = SecretModel
    permission_required = "app_label.view_secretmodel"
    raise_exception = True
    permission_denied_message = "You do not have access to the requested secret object."
<!-- 403.html -->
{% extends "base.html" %}
{% block content %}
<div class="container-fluid">
  <div class="alert alert-danger" role="alert">
    <h3 class="alert-heading">Permission Denied</h3>
    {{ exception|default:"You do not have permission to view this content." }}
  </div>
</div>
{% endblock content %}
  1. More detailed message.

models.py and 403.html as above.

# views.py
from django.views.generic import DetailView
from guardian.mixins import PermissionRequiredMixin
from app_label.models import SecretModel

class SecretModelDetail(PermissionRequiredMixin, DetailView):
    model = SecretModel
    permission_required = "app_label.view_secretmodel"
    raise_exception = True

    def get_permission_denied_message(self):
        obj = self.get_object()
        return (
            f"You do not have permission to view the secret object '{obj.name}'. "
            f"Please ask the owner, {obj.owner.username}, to grant you permission."
        )

The PermissionRequiredMixin can be configured with a message string that
is passed to the PermissionDenied exception.
@marxide marxide changed the title added message for permission deined exceptions added message for permission denied exceptions Oct 9, 2020
@Rainshaw

This comment has been minimized.

message = ""
if isinstance(self.permission_denied_message, str):
message = self.permission_denied_message
return message
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I think this function is a little complex.
In django.contrib.auth.mixins.PermissionRequiredMixin, we can find that it just return the self.permission_denied_message.

# in django/contrib/auth/mixins/PermissionRequiredMixin
    def get_permission_denied_message(self):
        """
        Override this method to override the permission_denied_message attribute.
        """
        return self.permission_denied_message

@@ -138,6 +144,7 @@ class SecureView(PermissionRequiredMixin, View):
return_403 = False
return_404 = False
raise_exception = False
permission_denied_message = None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can make this be blank str '', and it would help with the get_permission_denied_message function to be simple.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants