0

I have a model named Account, which is connected to the default User model. As of now, I'm looping through all permissions associated with the Account model, but I also want to check if the Account profile page's user has the one or more of the specific permissions that's being looped through. The purpose is just to create an easy overview.

I have also tried checking perms.cms.get_permission_codename.

models.py

class Account(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    site = models.CharField(max_length=50, choices=(('all', 'all'), ('danielk', 'danielk'), ('flis', 'flis'), ('vmusic', 'vmusic')), blank=True)
    site_role = models.CharField(max_length=50, choices=(('Administrator', 'Administrator'), ('Moderator', 'Moderator'), ('Editor', 'Editor')))
    phone_number = models.CharField(max_length=8)
    birth_date = models.DateField()
    street_adress = models.CharField(max_length=255)
    note = models.TextField(blank=True);
    zip_code = models.CharField(max_length=4)
    city = models.CharField(max_length=255)

    def formatedPhone(self, country=None):
        return phonenumbers.parse(Account.phone_number, "NO")

    """
    def __str__(self):
        return "%s %s" % (self.User.first_name, self.user.last_name)
    """

    def get_absolute_url(self):
        return reverse('account-detail', kwargs={'pk': self.pk})

    class Meta:
        verbose_name = 'Account meta'
        verbose_name_plural = 'Accounts meta'
        permissions = (
            ("has_user_hijack_permission", "Allows the user to log in as others"),
            ("has_user_management", "Allows a user to deactivate/delete other users"),
            ("has_user_site_edit", "Allows a user to edit site and role details"),
            ("has_user_takeout", "Can export user details"),
        )

views.py

class cms_users_user_permissions(generic.DetailView):
    model = Account
    template_name = 'cms/users/cms-users-user-permissions.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["permissions"] = Permission.objects.filter(content_type=ContentType.objects.get_for_model(Account))
        #context['permissions'] = Permission.objects.filter(content_type_id=7)
        return context

table.html

<table class="table is-fullwidth">
    <tbody>
        {% for permission in permissions %}
            <tr>
                <td style="width: 300px;">{{ permission.codename }}</td>
                 <td>{{ permission.name }}</td>

                 {% if account.user.has_perm %}
                     <td>
                         <span class="icon is-small">
                             <i class="fas fa-check-circle has-text-success"></i>
                         </span>
                     </td>
                  {% else %}
                      <td>
                          <span class="icon is-small">
                              <i class="fas fa-times-circle has-text-danger"></i>
                          </span>
                       </td>
                   {% endif %}
             </tr>
          {% endfor %}      
       </tbody>
   </table>
DanielK
  • 257
  • 2
  • 15

1 Answers1

1

I'm not sure what you are really asking, but I'll give it a go.

If you want to check in the template whether the user has any of the four permissions, you can change the

context["permissions"] = Permission.objects.filter(content_type=ContentType.objects.get_for_model(Account))

to

context["permissions"] = Permission.objects.filter(content_type=ContentType.objects.get_for_model(Account), user_set=self.request.user)

Since Permission has a ManyToMany relationship to User, the user_set for an instance of Permission will contain all Users having that permission. The result will be that context["permissions"] only contains the permissions of Account that the User has. This would mean your table doesn't show the permissions the users does not have, so this might not be what you want.

If you are having problems with the

 {% if account.user.has_perm %}

part, there are 2 solutions that pop into my mind; A static solution and a dynamic solution.

Static:
Since there are only 4 permissions to check in this case you could also try what Tim Kamanin does at https://timonweb.com/posts/how-to-get-a-list-of-all-user-permissions-available-in-django-based-project/. This would mean that you delete the loop and for each of the 4 permission you can add a block looking like

{% if perm.account.has_user_hijack_permission %}
   <td>
      <span class="icon is-small">
        <i class="fas fa-check-circle has-text-success"></i>
      </span>
   </td>
{% else %}
   <td>
      <span class="icon is-small">
        <i class="fas fa-times-circle has-text-danger"></i>
      </span>
   </td>
{% endif %}

Dynamic:
At Check permission inside a template in Django it is written that {{ perms }} contains all the permissions a user has, so a dynamic solution would be

{% for permission in permissions %}
  {% if permission in perms %}
   <td>
      <span class="icon is-small">
        <i class="fas fa-check-circle has-text-success"></i>
      </span>
   </td>
  {% else %}
   <td>
      <span class="icon is-small">
        <i class="fas fa-times-circle has-text-danger"></i>
      </span>
   </td>
  {% endif %}
{% endfor %}

The dynamic solution has more flexibility and is more RESTFUL, since if you expand the query in context["permissions"] or add more permissions to the Account class this still works.

--- edits to account for comments ---

In case you want the permissions of the User you are accessing instead of the User you are signed in with, you can, according to How to get user permissions? , replace {{ perms }} with {{ accessed_user_permissions }} after adding

context["accessed_user_permissions "] = user.user_permissions.all()

Note that this does not include group permissions. If you want to include groep permission, you need to do something like

context["accessed_user_permissions "] = user.user_permissions.all() | user.group_permissions.all()
ChocolateRain
  • 203
  • 2
  • 9
  • Thanks for the quick reply. I'm sorry if the OP was a bit confusing. The Account model is used to create profile pages for each individual user. It seems like you've answered the question in the last part of your post (dynamic way), which is what i aim to do. Your sugestions however, did not quite work: https://i.imgur.com/f2nzVl6.png. The account page in question has the assigned permissions has_user_hijack_permission and has_user_takeout, which (ideally) should become green checkmarks in the overview. Do you have any other suggestions? – DanielK Feb 02 '19 at 13:50
  • So lets say i'm user1 and is visiting user2's profile, i want to be able to see all permissions in the table, where the permissions given to user2 is a green checkmark. Checking in `{{ perms }}` will only check my own (user1´s) permissions, or am i completely wrong? – DanielK Feb 03 '19 at 22:45
  • Ah. `{{ perms }}` are indeed only the permissions of the signed in user. I edited my answer in a way that should do the trick. – ChocolateRain Feb 04 '19 at 10:25
  • Ok. Thanks for bearing with me. Adding `context["accessed_user_permissions"] = User.user_permissions.all()` to `views.py` returns the error `'ManyToManyDescriptor' object has no attribute 'all'`. I had to change the `user.user_permissions.all()` to `User.user_permissions.all()` btw. Trying only with 'User.group_permissions.all()` returns `type object 'User' has no attribute 'group_permissions'`. Is there anything i must import to make it work? Once i've gotten this to work, i would simply have to check `{% if permission in accessed_user_permissions %}` in the if statement to make it work? – DanielK Feb 04 '19 at 12:46
  • `User.user_permissions.all()` might reference to the `User` class you have. If your code doesn't work try accessing the user stored in the context through `context["user"]`; this would given `context["user"].user_permissions.all()`. – ChocolateRain Feb 04 '19 at 21:47
  • I had a hunch it would be `group_permissions` based on the syntax for `user_permissions`(maybe it's part of django guardian). You could try `Permission.objects.filter(group__user=user)` as suggested in the link I just as reference instead. – ChocolateRain Feb 04 '19 at 21:48
  • @DanielK, did you manage to find a solution? If you did using my answer, could you accept it as an answer? If not, could you tell what is still unclear? – ChocolateRain Mar 03 '19 at 16:08