An enhanced permission system which support object permission in Django

Overview

django-permission

Build status Coverage Requirements Status Inspection Version License Format Supported python versions Status
Author
Alisue <[email protected]>
Supported python versions
Python 2.7, 3.3, 3.4, 3.5, 3.6
Supported django versions
Django 1.8 - 1.11b

An enhanced permission library which enables a logic-based permission system to handle complex permissions in Django.

Documentation

http://django-permission.readthedocs.org/en/latest/

Installation

Use pip like:

$ pip install django-permission

Usage

The following might help you to understand as well.

Configuration

  1. Add permission to the INSTALLED_APPS in your settings module

    INSTALLED_APPS = (
        # ...
        'permission',
    )
  2. Add our extra authorization/authentication backend

    AUTHENTICATION_BACKENDS = (
        'django.contrib.auth.backends.ModelBackend', # default
        'permission.backends.PermissionBackend',
    )
  3. Follow the instructions below to apply logical permissions to django models

Autodiscovery

Like django's admin package, django-permission automatically discovers the perms.py in your application directory by running ``permission.autodiscover()``. Additionally, if the perms.py module has a PERMISSION_LOGICS variable, django-permission automatically run the following functions to apply the permission logics.

for model, permission_logic_instance in PERMISSION_LOGICS:
    if isinstance(model, str):
        model = get_model(*model.split(".", 1))
    add_permission_logic(model, permission_logic_instance)

Note

Autodiscover feature is automatically called if you are using django higher than 1.7 so no need to follow the tutorial below. To disable, use PERMISSION_AUTODISCOVER_ENABLE setting.

Quick tutorial

  1. Add import permission; permission.autodiscover() to your urls.py like:

    from django.conf.urls import patterns, include, url
    from django.contrib import admin
    
    admin.autodiscover()
    # add this line
    import permission; permission.autodiscover()
    
    urlpatterns = patterns('',
        url(r'^admin/', include(admin.site.urls)),
        # ...
    )
  2. Write perms.py in your application directory like:

    from permission.logics import AuthorPermissionLogic
    from permission.logics import CollaboratorsPermissionLogic
    
    PERMISSION_LOGICS = (
        ('your_app.Article', AuthorPermissionLogic()),
        ('your_app.Article', CollaboratorsPermissionLogic()),
    )

You can specify a different module or variable name, with PERMISSION_AUTODISCOVER_MODULE_NAME or PERMISSION_AUTODISCOVER_VARIABLE_NAME respectively.

Apply permission logic

Let's assume you wrote an article model which has an author attribute to store the creator of the article, and you want to give that author full control permissions (e.g. add, change and delete permissions).

What you need to do is just applying permission.logics.AuthorPermissionLogic to the Article model like

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


class Article(models.Model):
    title = models.CharField('title', max_length=120)
    body = models.TextField('body')
    author = models.ForeignKey(User)

    # this is just required for easy explanation
    class Meta:
        app_label='permission'

# apply AuthorPermissionLogic
from permission import add_permission_logic
from permission.logics import AuthorPermissionLogic
add_permission_logic(Article, AuthorPermissionLogic())

Note

From django-permission version 0.8.0, you can specify related object with field__name attribute like django queryset lookup. See the working example below:

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


class Article(models.Model):
    title = models.CharField('title', max_length=120)
    body = models.TextField('body')
    project = models.ForeignKey('permission.Project')

    # this is just required for easy explanation
    class Meta:
        app_label='permission'

class Project(models.Model):
    title = models.CharField('title', max_length=120)
    body = models.TextField('body')
    author = models.ForeignKey(User)

    # this is just required for easy explanation
    class Meta:
        app_label='permission'

# apply AuthorPermissionLogic to Article
from permission import add_permission_logic
from permission.logics import AuthorPermissionLogic
add_permission_logic(Article, AuthorPermissionLogic(
    field_name='project__author',
))

That's it. Now the following codes will work as expected:

user1 = User.objects.create_user(
    username='john',
    email='[email protected]',
    password='password',
)
user2 = User.objects.create_user(
    username='alice',
    email='[email protected]',
    password='password',
)

art1 = Article.objects.create(
    title="Article 1",
    body="foobar hogehoge",
    author=user1
)
art2 = Article.objects.create(
    title="Article 2",
    body="foobar hogehoge",
    author=user2
)

# You have to apply 'permission.add_article' to users manually because it
# is not an object permission.
from permission.utils.permissions import perm_to_permission
user1.user_permissions.add(perm_to_permission('permission.add_article'))

assert user1.has_perm('permission.add_article') == True
assert user1.has_perm('permission.change_article') == False
assert user1.has_perm('permission.change_article', art1) == True
assert user1.has_perm('permission.change_article', art2) == False

assert user2.has_perm('permission.add_article') == False
assert user2.has_perm('permission.delete_article') == False
assert user2.has_perm('permission.delete_article', art1) == False
assert user2.has_perm('permission.delete_article', art2) == True

#
# You may also be interested in django signals to apply 'add' permissions to the
# newly created users.
# https://docs.djangoproject.com/en/dev/ref/signals/#django.db.models.signals.post_save
#
from django.db.models.signals.post_save
from django.dispatch import receiver
from permission.utils.permissions import perm_to_permission

@receiver(post_save, sender=User)
def apply_permissions_to_new_user(sender, instance, created, **kwargs):
    if not created:
        return
    #
    # permissions you want to apply to the newly created user
    # YOU SHOULD NOT APPLY PERMISSIONS EXCEPT PERMISSIONS FOR 'ADD'
    # in this way, the applied permissions are not object permission so
    # if you apply 'permission.change_article' then the user can change
    # any article object.
    #
    permissions = [
        'permission.add_article',
    ]
    for permission in permissions:
        # apply permission
        # perm_to_permission is a utility to convert string permission
        # to permission instance.
        instance.user_permissions.add(perm_to_permission(permission))

See http://django-permission.readthedocs.org/en/latest/_modules/permission/logics/author.html#AuthorPermissionLogic to learn how this logic works.

Now, assume you add collaborators attribute to store collaborators of the article and you want to give them a change permission.

What you need to do is quite simple. Apply permission.logics.CollaboratorsPermissionLogic to the Article model as follows

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


class Article(models.Model):
    title = models.CharField('title', max_length=120)
    body = models.TextField('body')
    author = models.ForeignKey(User)
    collaborators = models.ManyToManyField(User)

    # this is just required for easy explanation
    class Meta:
        app_label='permission'

# apply AuthorPermissionLogic and CollaboratorsPermissionLogic
from permission import add_permission_logic
from permission.logics import AuthorPermissionLogic
from permission.logics import CollaboratorsPermissionLogic
add_permission_logic(Article, AuthorPermissionLogic())
add_permission_logic(Article, CollaboratorsPermissionLogic(
    field_name='collaborators',
    any_permission=False,
    change_permission=True,
    delete_permission=False,
))

Note

From django-permission version 0.8.0, you can specify related object with field_name attribute like django queryset lookup. See the working example below:

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


class Article(models.Model):
    title = models.CharField('title', max_length=120)
    body = models.TextField('body')
    project = models.ForeignKey('permission.Project')

    # this is just required for easy explanation
    class Meta:
        app_label='permission'

class Project(models.Model):
    title = models.CharField('title', max_length=120)
    body = models.TextField('body')
    collaborators = models.ManyToManyField(User)

    # this is just required for easy explanation
    class Meta:
        app_label='permission'

# apply AuthorPermissionLogic to Article
from permission import add_permission_logic
from permission.logics import CollaboratorsPermissionLogic
add_permission_logic(Article, CollaboratorsPermissionLogic(
    field_name='project__collaborators',
))

That's it. Now the following codes will work as expected:

user1 = User.objects.create_user(
    username='john',
    email='[email protected]',
    password='password',
)
user2 = User.objects.create_user(
    username='alice',
    email='[email protected]',
    password='password',
)

art1 = Article.objects.create(
    title="Article 1",
    body="foobar hogehoge",
    author=user1
)
art1.collaborators.add(user2)

assert user1.has_perm('permission.change_article') == False
assert user1.has_perm('permission.change_article', art1) == True
assert user1.has_perm('permission.delete_article', art1) == True

assert user2.has_perm('permission.change_article') == False
assert user2.has_perm('permission.change_article', art1) == True
assert user2.has_perm('permission.delete_article', art1) == False

See http://django-permission.readthedocs.org/en/latest/_modules/permission/logics/collaborators.html#CollaboratorsPermissionLogic to learn how this logic works.

There are StaffPermissionLogic and GroupInPermissionLogic for is_staff or group based permission logic as well.

Customize permission logic

Your own permission logic class must be a subclass of permission.logics.PermissionLogic and must override has_perm(user_obj, perm, obj=None) method which return boolean value.

Class, method, or function decorator

Like Django's permission_required but it can be used for object permissions and as a class, method, or function decorator. Also, you don't need to specify a object to this decorator for object permission. This decorator automatically determined the object from request (so you cannnot use this decorator for non view class/method/function but you anyway use user.has_perm in that case).

>>> from permission.decorators import permission_required
>>> # As class decorator
>>> @permission_required('auth.change_user')
>>> class UpdateAuthUserView(UpdateView):
...     pass
>>> # As method decorator
>>> class UpdateAuthUserView(UpdateView):
...     @permission_required('auth.change_user')
...     def dispatch(self, request, *args, **kwargs):
...         pass
>>> # As function decorator
>>> @permission_required('auth.change_user')
>>> def update_auth_user(request, *args, **kwargs):
...     pass

Override the builtin if template tag

django-permission overrides the builtin if tag, adding two operators to handle permissions in templates. You can write a permission test by using has keyword, and a target object with of as below.

{% if user has 'blogs.add_article' %}
    <p>This user have 'blogs.add_article' permissionp>
{% elif user has 'blog.change_article' of object %}
    <p>This user have 'blogs.change_article' permission of {{object}}p>
{% endif %}

{# If you set 'PERMISSION_REPLACE_BUILTIN_IF = False' in settings #}
{% permission user has 'blogs.add_article' %}
    <p>This user have 'blogs.add_article' permissionp>
{% elpermission user has 'blog.change_article' of object %}
    <p>This user have 'blogs.change_article' permission of {{object}}p>
{% endpermission %}

Note

From Django 1.9, users require to add 'permission.templatetags.permissionif' to 'builtins' option manually. See - https://docs.djangoproject.com/en/1.9/releases/1.9/#django-template-base-add-to-builtins-is-removed - https://docs.djangoproject.com/en/1.9/topics/templates/#module-django.template.backends.django Or following example:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'OPTIONS': {
            'builtins': ['permission.templatetags.permissionif'],
        },
    },
]

License

The MIT License (MIT)

Copyright (c) 2015 Alisue, hashnote.net

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Issues
  • Two roles with admin in project

    Two roles with admin in project

    Good Nights, this is a question, not a issue.

    I need to do two types of users, and default admin and author user. An aditional permission for two users, Admin can publish news, author can't. Author only can created news, and only edit and delect his own news.

    A friend say me that for the second restrictions i need per object permissions, but i don't know how do all of this.

    Can you help me?

    question 
    opened by SalahAdDin 30
  • Warning Django 1.9

    Warning Django 1.9

    Please, update your app, now we have this warning:

    /home/tulipan/Proyectos/TiempoTurco/lib/python3.4/importlib/_bootstrap.py:321: RemovedInDjango19Warning: django.utils.importlib will be removed in Django 1.9.
      return f(*args, **kwds)
    
    /home/tulipan/Proyectos/IspanyolHaber/lib/python3.4/importlib/_bootstrap.py:321: RemovedInDjango19Warning: The utilities in django.db.models.loading are deprecated in favor of the new application loading system.
      return f(*args, **kwds)
    
    bug 
    opened by SalahAdDin 17
  • Ready to Use ?

    Ready to Use ?

    Is this software ready to use? You've mentioned that:

    This is under development. The codes below may not works in the future

    But I wonder if I can use the "current" version for my new started project ??

    question 
    opened by vahidR 16
  • Custom permission logics documentation

    Custom permission logics documentation

    I am really struggling to understand how I am meant to use custom permission logics, I am pretty sure I am 99% of the way there, and that they're what I want, but the documentation is so sparse it's really putting me off, but yours appears to be the only library that seems to cater for this requirement.

    My current error is django.contrib.auth.models.DoesNotExist simply because the row doesn't exist in the auth_permission table.

    Now, I have no desire to maintain database records to describe my permissions – but I'd be happy to create these if necessary, but what I don't understand is what or where should be doing that, or more importantly, what binds permissions to logics, how does it know which logic class to run based on the permission being checked, and if it's multiple or all of them, what happens if one logic says yes and another says no? Unanimous voting? ¯_(ツ)_/¯

    question 
    opened by stevelacey 16
  • Question - Permissions do not seem to be taking effect

    Question - Permissions do not seem to be taking effect

    Hello,

    Have posted the same question on stackoverflow in case that is a more appropriate place to post it.

    Have prepared a simple test app (almost identical to the example used in the docs) to try to figure out how it works. I have read the documentation and tried to use the example app provided on this link.

    The issue is when the author of an article is not able to edit/ delete the article.

    The user in question has been granted all permissions in the admin section.

    Key code listed below - any help much appreciated

    test_app/models.py

    class Article(models.Model):
        created_by = models.ForeignKey(User)
        created = models.DateField(auto_now_add=True)
        modified = models.DateField(auto_now=True)
        title = models.CharField(max_length=100)
        content = models.TextField()
    
        class Meta:
            app_label = 'test_app'
    
    from permission import add_permission_logic
    from permission.logics import AuthorPermissionLogic
    
    add_permission_logic(Article, AuthorPermissionLogic(
        field_name='created_by',
        any_permission = False,
        change_permission = True,
        delete_permission = True,
    ))
    

    test_app/views.py

    @permission_required('change_article')
    def change_article(request, *args, **kwargs):
        pk = kwargs.pop('pk')
        template = 'test_app/edit.html'
        article = models.Article.objects.get(id=pk)
    
        if request.method == 'POST':
            form = forms.Article_form(request.POST, instance=article)
    
            if form.is_valid():
                article = form.save(commit=False)
    
                article.created_by = request.user
                article.title = form.cleaned_data['title']
                article.content = form.cleaned_data['content']
    
                article.save()
    
                return HttpResponseRedirect('/test/')
    
            else:
    
                raise Http404
    
        else:
            form = forms.Article_form(instance=article)
    
            return render(request, template_name=template, context={'form':form})
    

    test_app/perms.py

    PERMISSION_LOGICS = (
        ('test_app.Article', AuthorPermissionLogic()),
    )
    
    question 
    opened by djbettega 11
  • restrict access instead of allowing it

    restrict access instead of allowing it

    Hi

    I want to use django-permission for a project I am working on, but I'm not sure how to achieve what I want. I used the normal django permissions stuff until now, but now I need to restrict access to some objects. I still want to use the django permissions for defining which user is generally allowed to read/add/change/delete objects. But I also want to add a check, that checks if a object is marked as private and if yes, the user has to be in a specific group.

    Now the problem is, that as soon as a user has the read permission for all objects of that model, my custom permission code is not called. But I want my custom permission code to be executed explicitly when a user has the global permission for that model to ensure that the user also has the permission for this specific object Is there any way to do this?

    question 
    opened by phillipthelen 9
  • ImportError if django 1.9 AppConfig is used for installed apps

    ImportError if django 1.9 AppConfig is used for installed apps

    if I add permission.autodiscover() to my urls.py, the following exception is thrown, if the Django 1.9 AppConfig ist used for my apps. If the .apps.ProjectAppConfig is removed, the exception does not occur.

    INSTALLED_APPS = [
        ...
        'project_app.apps.ProjectAppConfig',  # Not working
        # 'project_app',  # Working
    ]
    
    Traceback (most recent call last):
      File "/project/env/lib/python3.4/site-packages/django/utils/autoreload.py", line 226, in wrapper
        fn(*args, **kwargs)
      File "/project/env/lib/python3.4/site-packages/django/core/management/commands/runserver.py", line 116, in inner_run
        self.check(display_num_errors=True)
      File "/project/env/lib/python3.4/site-packages/django/core/management/base.py", line 426, in check
        include_deployment_checks=include_deployment_checks,
      File "/project/env/lib/python3.4/site-packages/django/core/checks/registry.py", line 75, in run_checks
        new_errors = check(app_configs=app_configs)
      File "/project/env/lib/python3.4/site-packages/django/core/checks/urls.py", line 10, in check_url_config
        return check_resolver(resolver)
      File "/project/env/lib/python3.4/site-packages/django/core/checks/urls.py", line 19, in check_resolver
        for pattern in resolver.url_patterns:
      File "/project/env/lib/python3.4/site-packages/django/utils/functional.py", line 33, in __get__
        res = instance.__dict__[self.name] = self.func(instance)
      File "/project/env/lib/python3.4/site-packages/django/core/urlresolvers.py", line 417, in url_patterns
        patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
      File "/project/env/lib/python3.4/site-packages/django/utils/functional.py", line 33, in __get__
        res = instance.__dict__[self.name] = self.func(instance)
      File "/project/env/lib/python3.4/site-packages/django/core/urlresolvers.py", line 410, in urlconf_module
        return import_module(self.urlconf_name)
      File "/project/env/lib/python3.4/importlib/__init__.py", line 109, in import_module
        return _bootstrap._gcd_import(name[level:], package, level)
      File "<frozen importlib._bootstrap>", line 2254, in _gcd_import
      File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
      File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 1200, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 1129, in _exec
      File "<frozen importlib._bootstrap>", line 1471, in exec_module
      File "<frozen importlib._bootstrap>", line 321, in _call_with_frames_removed
      File "/project/src/project/urls.py", line 21, in <module>
        permission.autodiscover()
      File "/project/env/lib/python3.4/site-packages/permission/utils/autodiscover.py", line 19, in autodiscover
        mod = import_module(app)
      File "/project/env/lib/python3.4/importlib/__init__.py", line 109, in import_module
        return _bootstrap._gcd_import(name[level:], package, level)
      File "<frozen importlib._bootstrap>", line 2254, in _gcd_import
      File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
      File "<frozen importlib._bootstrap>", line 2221, in _find_and_load_unlocked
    ImportError: No module named 'project.apps.ProjectConfig'; 'project.apps' is not a package
    

    This hack fixes the error for now:

    #/project/env/lib/python3.4/site-packages/permission/utils/autodiscover.py:18
        for app in settings.INSTALLED_APPS:
            if '.apps.' in app:
                app = app.split('.')[0]
            mod = import_module(app)
    
    bug 
    opened by JanMalte 8
  • WIP: Refactoring

    WIP: Refactoring

    • [x] Drop ancient python/django supports
    • [x] Remove code for backward compatibilities
    • [ ] Remove handlers and directly use logics
    opened by lambdalisue 7
  • Support Django 1.11 beta

    Support Django 1.11 beta

    closes #70 closes #71

    opened by giginet 7
  • Organization?

    Organization?

    I'm not using Django recently thus I'd love to transfer the ownership to an organization if someone interested in it. Anyone?

    opened by lambdalisue 2
  • The documentation is difficult to follow

    The documentation is difficult to follow

    class Article(models.Model):
        title = models.CharField('title', max_length=120)
        body = models.TextField('body')
        project = models.ForeignKey('permission.Project')
    
        # this is just required for easy explanation
        class Meta:
            app_label='permission'
    
    class Project(models.Model):
        title = models.CharField('title', max_length=120)
        body = models.TextField('body')
        author = models.ForeignKey(User)
    
        # this is just required for easy explanation
        class Meta:
            app_label='permission'
    
    # apply AuthorPermissionLogic to Article
    from permission import add_permission_logic
    from permission.logics import AuthorPermissionLogic
    add_permission_logic(Article, AuthorPermissionLogic(
        field_name='project__author',
    ))
    

    I am really not sure what is the permission mentioned in the code block.

    1. Is it the package of the permission we just installed?
    2. Is it an app that host the Article and Project?

    It is really difficult to follow when applying to my own code on which permission should I replace and which permission should I keep.

    opened by weasteam 0
  • Stay at model level

    Stay at model level

    Hello, I love this package, it's awesome thank you. Is there a way to use the permission_required decorator on a ListView (or any CBV with a get_queryset method) on a Model level and thus checking the has_perm only once.

    Right now I'm using the django.contrib.auth.mixins.PermissionRequiredMixin, but I love the permission_required decorator.

    Basically I would love to do something like

    from permission.decorators import permission_required
    
    @permission_required('blog.view_post',stay_at_model_level=True)
    class PostList(ListView):
        model = Post
    

    Instead of doing :

    from django.contrib.auth.mixins import PermissionRequiredMixin
    
    class PostList(PermissionRequiredMixin, ListView):
        model = Post
        permission_required = 'blog.view_post'
    
    enhancement 
    opened by LucasBerbesson 1
  • Custom permission logic with @permission_required() decorator and {% if ... %} tag config issue

    Custom permission logic with @permission_required() decorator and {% if ... %} tag config issue

    Hello! I've read the docs, read #26 and #28 examples, tried to find out where I've mistaken using Kawaz sources, but still can't understand where I've made a mistake.

    I'm using Djnago 1.11 with Python 3.6.1 and django-permission 1.4.0 (also tried under django 1.10.7, python 3.6.0) I have 'console_test' project with 'console' app inside it. It has 1 model called Deal, so my models.py looks like this:

    #models.py
    from django.db import models
    
    # Create your models here.
    from django.contrib.auth.models import User
    
    class Deal(models.Model):
        title = models.CharField(max_length=200)
        desc = models.CharField(max_length=200, blank=True)
        user = models.ForeignKey(User)
    

    In settings.py of the project I've: 1)Added permission to INSTALLED_APPS:

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'console',
        'permission',
    ]
    

    2)Added 'builtins': ['permission.templatetags.permissionif'], for using {% if user has ... %} in TEMPLATES:

    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [os.path.join(BASE_DIR, 'templates')]
            ,
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
                'builtins': ['permission.templatetags.permissionif'],
    
            },
        },
    ]
    

    3)Added to the bottom of the settings.py AUTHENTICATION_BACKENDS:

    AUTHENTICATION_BACKENDS = (
        'django.contrib.auth.backends.ModelBackend', # default
        'permission.backends.PermissionBackend',
    )
    

    4)Then in project's urls.py (not app's) I've added Autodiscover

    #urls.py
    from django.conf.urls import url, include
    from django.contrib import admin
    from django.contrib.auth import views as auth_views
    
    import permission; permission.autodiscover()
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^console/', include('console.urls', namespace="console")),
        url(r'^accounts/login/$', auth_views.login, {'template_name': 'login.html'}, name='login'),
        url(r'^accounts/logout/$', auth_views.logout_then_login, name='logout'),
    ]
    

    5)Then I've created perms.py file inside 'console' app dir (Is it right? Not in 'console_test' project root?) with AuthorPermissionLogic, StaffPermissionLogic and CustomPermissionLogic (for test purposes it always returns True):

    #perms.py
    from permission.logics import AuthorPermissionLogic, StaffPermissionLogic, PermissionLogic
    
    class CustomPermissionLogic(PermissionLogic):
        def has_perm(self, user_obj, perm, obj=None):
            return True
    
    PERMISSION_LOGICS = (
        ('console.Deal', AuthorPermissionLogic()),
        ('console.Deal', StaffPermissionLogic()),
        ('console.Deal', CustomPermissionLogic()),
    )
    

    In views I have 4 views (Index, Result, Detail and Change).

    #views.py
    from django.shortcuts import render
    
    from django.shortcuts import get_object_or_404
    from django.http import HttpResponse,HttpResponseRedirect
    from django.core.urlresolvers import reverse
    
    from .models import Deal
    from django.views import generic
    from permission.decorators import permission_required
    
    class IndexView(generic.ListView):
        template_name = 'index.html'
        context_object_name = 'model_list'
    
        def get_queryset(self):
            return Deal.objects.all()
    
    def change(request, model_id):
        model = get_object_or_404(Deal, pk=model_id)
        try:
            model.title = request.POST['title']
            model.desc = request.POST['desc']
            model.save()
            return HttpResponseRedirect(reverse('console:results', args=(model.id,)))
        except:
            return HttpResponse("Error changing model")
    
    def detail(request, *args, **kwargs):
        model = get_object_or_404(Deal, pk=kwargs['model_id'])
        return render(request, 'detail.html', {'model': model})
    
    def results(request, *args, **kwargs):
        model = get_object_or_404(Deal, pk=kwargs['model_id'])
        return render(request, 'results.html', {'model': model})
    

    console app's urls.py are simple

    #urls.py
    from django.conf.urls import url
    from . import views
    urlpatterns = [
        url(r'^$', views.IndexView.as_view(), name='index'),
        url(r'^(?P<model_id>[0-9]+)/detail/$', views.detail, name='detail'),
        url(r'^(?P<model_id>[0-9]+)/results/$', views.results, name='results'),
        url(r'^(?P<model_id>[0-9]+)/change/$', views.change, name='change'),
    ]
    

    I've tried a lot to make this module working for me but unfortunately unsuccessfully.

    If I try to use, for example, 'deal.read' for permission name with @permission_required decorator I'm always getting error "Permission matching query does not exist.

    If I try to use for example, 'read' for permission name @permission_required decorator I've always being redirected to login screen (no matter what CustomPermissionLogic has_perm function returns). Could you tell me where I've made a mistake?

    So views under this decorator are unreachable for users. Super-user can reach these views (as I understand no permission checking is made for him) but {% if user has ... %} template tags inside view template also doesn't work.

    So I have some questions:

    1. If I want to use @permission_required decorator to limit access to some views (for ex. With list of models and Detail page), how can I do that? What permission name I must use to limit access with that built-in Logic?

    If I want to use AuthorPermissionLogic, StaffPermissionLogic, GroupInPermissionLogic what permission name must be? Must I use 'app_name.permission_name' or 'model_name.permission_name' or 'app_name.model_name.permission_name' or just 'permission_name'? Is it connected somehow with Logic?

    Example

    @permission_required('staff? or console.staff? or deal.staff?') How to combine them (for ex. Author and Custom), with a list (['staff','author']?

    1. The same situation, if I want to use {% if user has ... %} template tags?

    2. I've created CustomPermissionLogic and want to create permissions for viewing, deleting, and modifying Deal model objects. How can I bind by permissions to be processed by CustomPermissionLogic. I've tried to check whether has_perm function is used during permission-checking process but it seems that it is unreachable, return True or return False or raise Exception inside it has no effect at alaa. I can't understand how to bind permissions to model or to CustomPermissionLogic. How does django-permission module bind them?

    Example:

    I want Deal model to have permissions: read, modify and delete CustomPermissionLogic has has_perm function, that can process that permissions and return True or False. CustomPermissionLogic binded to Deal model via perms.py file inside console app dir ('console.Deal', CustomPermissionLogic()), How to bind my "new permissions" to Deal or to CustomPermissionLogic to use them with @permission_required() or {% if user has ... %}

    question 
    opened by tabakov 1
  • Add configuration to return False if `of obj` is specifed but `obj` is None.

    Add configuration to return False if `of obj` is specifed but `obj` is None.

    Currently when obj context is not exists in the template, something like {% if user has 'app_label.change_model' of obj %} return non object permission.

    It is a correct behavior but usually non object permission should return True based on basic django concept (https://code.djangoproject.com/wiki/RowLevelPermissions) thus the following code will render links for chaning/deleting the object even if the accessed user does not have such permissions for the object.

    {# assume if obj is None or context does not have obj #}
    {% if user has 'foo.change_bar' of obj %}
    <a href="{% url 'foo_bar_change' pk=obj.pk %}">Change</a>
    {% endif %}
    {% if user has 'foo.delete_bar' of obj %}
    <a href="{% url 'foo_bar_delete' pk=obj.pk %}">Delete</a>
    {% endif %}
    

    It is quite annoying thus add PERMISSION_RETURN_FALSE_IF_NONE_IN_TEMPLATE or whatever configuration and check obj value at https://github.com/lambdalisue/django-permission/blob/master/src/permission/templatetags/permissionif.py#L38 and return False if of obj keyword is specified but obj is None.

    enhancement 
    opened by lambdalisue 0
  • Create full sample project

    Create full sample project

    Hello, if you could create a sample project would be great. The documentation seems a bit confusing to me, working example code can be more explicit and easier to understand

    Thanks.

    enhancement question 
    opened by luzfcb 3
  • Improve documentations

    Improve documentations

    More detailed documentations like below are required.

    • The reason why django-permission is required while there are other object permission
      systems like django-guardian
      • The difference between logic based permission system and database based object permission system
      • Several use cases for django-permission (and other object permission systems)
    • Explain about making custom logic permissions
      • Explain the basic concept of logic permissions
      • Some tutorials
    • Explain about django-permission's enhanced permission_required decorator
    • User can use the decorator as a decorator of class, method, or function
    • Explain the basic mechanisms to get user instance and object instance automatically
    • Some use cases
    • Explain about django-permission's enhanced if template tag
      • Explain two newly introduced operators (has and of)
      • Explain how to disable overwriting built-in if template tag and the way to use permission tag in that case
      • Some use cases
    • Explain how to contribute the development of django-permission
      • Explain the way to test it

    I need some persons who check my English to improve the documentations lol.

    enhancement 
    opened by lambdalisue 2
JSON Web Token Authentication support for Django REST Framework

REST framework JWT Auth Notice This project is currently unmaintained. Check #484 for more details and suggested alternatives. JSON Web Token Authenti

José Padilla 3.1k Jan 18, 2022
JSON Web Token Authentication support for Django REST Framework

REST framework JWT Auth JSON Web Token Authentication support for Django REST Framework Overview This package provides JSON Web Token Authentication s

Styria Digital Development 139 Jan 8, 2022
python-social-auth and oauth2 support for django-rest-framework

Django REST Framework Social OAuth2 This module provides OAuth2 social authentication support for applications in Django REST Framework. The aim of th

null 984 Jan 13, 2022
python-social-auth and oauth2 support for django-rest-framework

Django REST Framework Social OAuth2 This module provides OAuth2 social authentication support for applications in Django REST Framework. The aim of th

null 984 Jan 13, 2022
Per object permissions for Django

django-guardian django-guardian is an implementation of per object permissions [1] on top of Django's authorization backend Documentation Online docum

null 3.1k Jan 7, 2022
REST implementation of Django authentication system.

djoser REST implementation of Django authentication system. djoser library provides a set of Django Rest Framework views to handle basic actions such

Sunscrapers 2k Jan 17, 2022
Login System Using Django

Login System Django

Nandini Chhajed 6 Dec 12, 2021
Extending the Django authentication system with a phone verification step.

Extending the Django authentication system with a phone verification step.

Miguel Grinberg 44 Dec 1, 2021
Django-registration (redux) provides user registration functionality for Django websites.

Description: Django-registration provides user registration functionality for Django websites. maintainers: Macropin, DiCato, and joshblum contributor

Andrew Cutler 874 Jan 15, 2022
Complete Two-Factor Authentication for Django providing the easiest integration into most Django projects.

Django Two-Factor Authentication Complete Two-Factor Authentication for Django. Built on top of the one-time password framework django-otp and Django'

Bouke Haarsma 1.1k Jan 16, 2022
Django Admin Two-Factor Authentication, allows you to login django admin with google authenticator.

Django Admin Two-Factor Authentication Django Admin Two-Factor Authentication, allows you to login django admin with google authenticator. Why Django

Iman Karimi 6 Dec 2, 2021
OAuthlib support for Python-Requests!

Requests-OAuthlib This project provides first-class OAuth library support for Requests. The OAuth 1 workflow OAuth 1 can seem overly complicated and i

null 1.4k Jan 12, 2022
An open source Flask extension that provides JWT support (with batteries included)!

Flask-JWT-Extended Features Flask-JWT-Extended not only adds support for using JSON Web Tokens (JWT) to Flask for protecting views, but also many help

Landon Gilbert-Bland 1.2k Jan 10, 2022
FastAPI extension that provides JWT Auth support (secure, easy to use, and lightweight)

FastAPI JWT Auth Documentation: https://indominusbyte.github.io/fastapi-jwt-auth Source Code: https://github.com/IndominusByte/fastapi-jwt-auth Featur

Nyoman Pradipta Dewantara 313 Jan 11, 2022
Easy and secure implementation of Azure AD for your FastAPI APIs 🔒 Single- and multi-tenant support.

Easy and secure implementation of Azure AD for your FastAPI APIs ?? Single- and multi-tenant support.

Intility 118 Jan 8, 2022
A host-guest based app in which host can CREATE the room. and guest can join room with room code and vote for song to skip. User is authenticated using Spotify API

A host-guest based app in which host can CREATE the room. and guest can join room with room code and vote for song to skip. User is authenticated using Spotify API

Aman Raj 4 Dec 12, 2021
Object Moderation Layer

django-oml Welcome to the documentation for django-oml! OML means Object Moderation Layer, the idea is to have a mixin model that allows you to modera

Angel Velásquez 12 Aug 22, 2019
Simple two factor authemtication system, made by me.

Simple two factor authemtication system, made by me. Honestly, i don't even know How 2FAs work I just used my knowledge and did whatever i could. Send

Refined 5 Jan 4, 2022
🔐 Login & Register System

?? Login & Register System This is a developable login and register system. Enter your username and password to register or login to account. Automati

Firdevs Akbayır 8 Dec 26, 2021