Codebase list django-guardian / 420613e
Update upstream source from tag 'upstream/2.0.0' Update to upstream version '2.0.0' with Debian dir 5e492424f38ca2f3963c4ed7805deff6c71f6090 Thomas Goirand 4 years ago
101 changed file(s) with 990 addition(s) and 1164 deletion(s). Raw diff Collapse all Expand all
2020 .idea/
2121 .eggs/
2222 .cache/
23 .mypy_cache/
24 .pytest_cache/
2325
2426 # WebDAV remote filesystem
2527 .DAV
00 language: python
1 sudo: false
1 dist: xenial
22
33 cache: pip
44
5 python:
6 - 2.7
7 - 3.4
8 - 3.5
9 - 3.6
10
11 env:
12 - DJANGO_VERSION=1.8 DATABASE_URL=postgres://postgres@/django_guardian
13 - DJANGO_VERSION=1.10 DATABASE_URL=postgres://postgres@/django_guardian
14 - DJANGO_VERSION=1.11 DATABASE_URL=postgres://postgres@/django_guardian
15 - DJANGO_VERSION=master DATABASE_URL=postgres://postgres@/django_guardian
16
17 - DJANGO_VERSION=1.8 DATABASE_URL=mysql://root:@localhost/django_guardian
18 - DJANGO_VERSION=1.10 DATABASE_URL=mysql://root:@localhost/django_guardian
19 - DJANGO_VERSION=1.11 DATABASE_URL=mysql://root:@localhost/django_guardian
20 - DJANGO_VERSION=master DATABASE_URL=mysql://root:@localhost/django_guardian
21
22 - DJANGO_VERSION=1.8 DATABASE_URL=sqlite://
23 - DJANGO_VERSION=1.10 DATABASE_URL=sqlite://
24 - DJANGO_VERSION=1.11 DATABASE_URL=sqlite://
25 - DJANGO_VERSION=master DATABASE_URL=sqlite://
26
27 before_install:
28 - pip install -q -U pytest
29
305 install:
31 - travis_retry pip install -q mock==1.0.1 pytest pytest-django pytest-cov django-environ setuptools_scm
32 # Install django master or version
33 - bash -c "if [[ "$DJANGO_VERSION" == 'master' ]]; then pip install 'https://github.com/django/django/archive/master.tar.gz'; else pip install Django==$DJANGO_VERSION; fi; "
34 # Install database drivers
35 - bash -c "if [[ $DATABASE_URL = postgres* ]]; then pip install psycopg2==2.7.1; fi; "
36 - bash -c "if [[ $DATABASE_URL = mysql* ]]; then pip install mysqlclient==1.3.10; fi; "
6 - ./contrib/travis/install.sh
377
388 script:
39 - python ./setup.py --version
40 - py.test --cov=guardian
41 - bash -c "if [[ $DJANGO_VERSION = 1.10 || $DJANGO_VERSION = 1.11 || $DJANGO_VERSION = "master" ]]; then pip install .; cd example_project; python manage.py test; fi; "
9 - ./contrib/travis/test.sh
4210
4311 notifications:
4412 irc: "irc.freenode.net#django-guardian"
4513
14 templates:
15 django21: &django21 DJANGO_VERSION=2.1.*
16 django22: &django22 DJANGO_VERSION=2.2.*
17 djangomaster: &djangomaster DJANGO_VERSION=master
18
19 postgres: &postgres DATABASE_URL=postgres://postgres@/django_guardian
20 mysql: &mysql DATABASE_URL=mysql://root:@localhost/django_guardian
21 sqlite: &sqlite DATABASE_URL=sqlite://
22
23 pgdb: &pgdb
24 addons: {postgresql: "10"}
25 mariadb: &mariadb
26 addons: {mariadb: "10.3"}
27
4628
4729 matrix:
4830 fast_finish: true
49 exclude:
50 - python: 2.7
51 env: DJANGO_VERSION=master DATABASE_URL=postgres://postgres@/django_guardian
52 - python: 2.7
53 env: DJANGO_VERSION=master DATABASE_URL=mysql://root:@localhost/django_guardian
54 - python: 2.7
55 env: DJANGO_VERSION=master DATABASE_URL=sqlite://
56 - python: 3.4
57 env: DJANGO_VERSION=master DATABASE_URL=postgres://postgres@/django_guardian
58 - python: 3.4
59 env: DJANGO_VERSION=master DATABASE_URL=mysql://root:@localhost/django_guardian
60 - python: 3.4
61 env: DJANGO_VERSION=master DATABASE_URL=sqlite://
31 include:
32 - { python: 3.5, env: [*django21, *postgres], <<: *pgdb}
33 - { python: 3.5, env: [*django21, *mysql], <<: *mariadb}
34 - { python: 3.5, env: [*django21, *sqlite]}
35 - { python: 3.5, env: [*django22, *postgres], <<: *pgdb}
36 - { python: 3.5, env: [*django22, *mysql], <<: *mariadb}
37 - { python: 3.5, env: [*django22, *sqlite]}
38
39 - { python: 3.6, env: [*django21, *postgres], <<: *pgdb}
40 - { python: 3.6, env: [*django21, *mysql], <<: *mariadb}
41 - { python: 3.6, env: [*django21, *sqlite]}
42 - { python: 3.6, env: [*django22, *postgres], <<: *pgdb}
43 - { python: 3.6, env: [*django22, *mysql], <<: *mariadb}
44 - { python: 3.6, env: [*django22, *sqlite]}
45 - { python: 3.6, env: [*djangomaster, *postgres], <<: *pgdb}
46 - { python: 3.6, env: [*djangomaster, *mysql], <<: *mariadb}
47 - { python: 3.6, env: [*djangomaster, *sqlite]}
48
49 - { python: 3.7, env: [*django21, *postgres], <<: *pgdb}
50 - { python: 3.7, env: [*django21, *mysql], <<: *mariadb}
51 - { python: 3.7, env: [*django21, *sqlite]}
52 - { python: 3.7, env: [*django22, *postgres], <<: *pgdb}
53 - { python: 3.7, env: [*django22, *mysql], <<: *mariadb}
54 - { python: 3.7, env: [*django22, *sqlite]}
55 - { python: 3.7, env: [*djangomaster, *postgres], <<: *pgdb}
56 - { python: 3.7, env: [*djangomaster, *mysql], <<: *mariadb}
57 - { python: 3.7, env: [*djangomaster, *sqlite]}
6258 allow_failures:
63 - env: DJANGO_VERSION=master DATABASE_URL=postgres://postgres@/django_guardian
64 - env: DJANGO_VERSION=master DATABASE_URL=mysql://root:@localhost/django_guardian
65 - env: DJANGO_VERSION=master DATABASE_URL=sqlite://
59 - env: [*djangomaster, *postgres]
60 - env: [*djangomaster, *mysql]
61 - env: [*djangomaster, *sqlite]
5555 - Frank Wickström <frank@bambuser.com>
5656 - George Karakostas <gckarakostas@gmail.com>
5757 - Adam Dobrawy <guardian@jawnosc.tk>
58 - Jeff Hackshaw <intrepidevio@gmail.com>
0 Release 2.0.0 (June 11, 2019)
1 ==========================
2
3 * Drop support for Python 2.7 & 3.4 and Django 1.11 & 2.0
4
5 Release 1.5.1 (May 2, 2019)
6 ==========================
7
8 * Restore compatibility with Python 2.7
9
10 .. important::
11 The 1.5.x release line will be the last one that has support for Python 2.7.
12
13 Release 1.5.0 (Jan 31, 2019)
14 ==========================
15
16 * Updates for compatibility with latest Python and Django versions.
17
018 Release 1.4.9 (Jul 01, 2017)
119 ============================
220
4462 * Moved queryset support in remove_perms to its own function
4563 * Consolidated {User,Group}ObjectPermissionManager, move logic of bulk_*_perm
4664 to managers
47 * `assign_perm` and `remove_perm` shortcuts accept `Permission`
65 * `assign_perm` and `remove_perm` shortcuts accept `Permission`
4866 instance as `perm` and `QuerySet` as `obj` too.
4967 * Consolidated bulk_assign_perm to assign_perm and bulk_remove_perm to remove_perm
5068 * Upgraded Grappelli templates breadcrumbs block to new Django 1.9 and
+0
-141
PKG-INFO less more
0 Metadata-Version: 1.1
1 Name: django-guardian
2 Version: 1.4.9
3 Summary: Implementation of per object permissions for Django.
4 Home-page: http://github.com/django-guardian/django-guardian
5 Author: Lukasz Balcerzak
6 Author-email: lukaszbalcerzak@gmail.com
7 License: BSD
8 Download-URL: https://github.com/django-guardian/django-guardian/tags
9 Description: ===============
10 django-guardian
11 ===============
12
13 .. image:: https://travis-ci.org/django-guardian/django-guardian.svg?branch=devel
14 :target: https://travis-ci.org/django-guardian/django-guardian
15
16 ``django-guardian`` is an implementation of per object permissions [1]_ on top
17 of Django's authorization backend
18
19 Documentation
20 -------------
21
22 Online documentation is available at https://django-guardian.readthedocs.io/.
23
24 Requirements
25 ------------
26
27 * Python 2.7 or 3.4+
28 * A supported version of Django (currently 1.8+)
29
30 Travis CI tests on Django version 1.8, 1.10, and 1.11.
31
32 Installation
33 ------------
34
35 To install ``django-guardian`` simply run::
36
37 pip install django-guardian
38
39 Configuration
40 -------------
41
42 We need to hook ``django-guardian`` into our project.
43
44 1. Put ``guardian`` into your ``INSTALLED_APPS`` at settings module:
45
46 .. code:: python
47
48 INSTALLED_APPS = (
49 ...
50 'guardian',
51 )
52
53 2. Add extra authorization backend to your ``settings.py``:
54
55 .. code:: python
56
57 AUTHENTICATION_BACKENDS = (
58 'django.contrib.auth.backends.ModelBackend', # default
59 'guardian.backends.ObjectPermissionBackend',
60 )
61
62 3. Create ``guardian`` database tables by running::
63
64 python manage.py migrate
65
66 Usage
67 -----
68
69 After installation and project hooks we can finally use object permissions
70 with Django_.
71
72 Lets start really quickly:
73
74 .. code:: python
75
76 >>> from django.contrib.auth.models import User, Group
77 >>> jack = User.objects.create_user('jack', 'jack@example.com', 'topsecretagentjack')
78 >>> admins = Group.objects.create(name='admins')
79 >>> jack.has_perm('change_group', admins)
80 False
81 >>> from guardian.models import UserObjectPermission
82 >>> UserObjectPermission.objects.assign_perm('change_group', jack, obj=admins)
83 <UserObjectPermission: admins | jack | change_group>
84 >>> jack.has_perm('change_group', admins)
85 True
86
87 Of course our agent jack here would not be able to *change_group* globally:
88
89 .. code:: python
90
91 >>> jack.has_perm('change_group')
92 False
93
94 Admin integration
95 -----------------
96
97 Replace ``admin.ModelAdmin`` with ``GuardedModelAdmin`` for those models
98 which should have object permissions support within admin panel.
99
100 For example:
101
102 .. code:: python
103
104 from django.contrib import admin
105 from myapp.models import Author
106 from guardian.admin import GuardedModelAdmin
107
108 # Old way:
109 #class AuthorAdmin(admin.ModelAdmin):
110 # pass
111
112 # With object permissions support
113 class AuthorAdmin(GuardedModelAdmin):
114 pass
115
116 admin.site.register(Author, AuthorAdmin)
117
118
119 .. [1] Great paper about this feature is available at `djangoadvent articles <https://github.com/djangoadvent/djangoadvent-articles/blob/master/1.2/06_object-permissions.rst>`_.
120
121 .. _Django: http://www.djangoproject.com/
122
123
124 Platform: UNKNOWN
125 Classifier: Development Status :: 5 - Production/Stable
126 Classifier: Environment :: Web Environment
127 Classifier: Framework :: Django
128 Classifier: Framework :: Django :: 1.8
129 Classifier: Framework :: Django :: 1.9
130 Classifier: Framework :: Django :: 1.10
131 Classifier: Framework :: Django :: 1.11
132 Classifier: Intended Audience :: Developers
133 Classifier: License :: OSI Approved :: BSD License
134 Classifier: Operating System :: OS Independent
135 Classifier: Programming Language :: Python
136 Classifier: Topic :: Security
137 Classifier: Programming Language :: Python :: 2.7
138 Classifier: Programming Language :: Python :: 3.4
139 Classifier: Programming Language :: Python :: 3.5
140 Classifier: Programming Language :: Python :: 3.6
1515 Requirements
1616 ------------
1717
18 * Python 2.7 or 3.4+
19 * A supported version of Django (currently 1.8+)
18 * Python 3.5+
19 * A supported version of Django (currently 2.1+)
2020
21 Travis CI tests on Django version 1.8, 1.10, and 1.11.
21 Travis CI tests on Django version 2.1, 2.2, and master.
2222
2323 Installation
2424 ------------
4040 ...
4141 'guardian',
4242 )
43
43
4444 2. Add extra authorization backend to your ``settings.py``:
4545
4646 .. code:: python
110110 .. [1] Great paper about this feature is available at `djangoadvent articles <https://github.com/djangoadvent/djangoadvent-articles/blob/master/1.2/06_object-permissions.rst>`_.
111111
112112 .. _Django: http://www.djangoproject.com/
113
4242 return ''.join(random.choice(chars) for i in range(length))
4343
4444
45 def get_model_name(model):
46 """
47 Returns the name of the model
48 """
49 # model._meta.module_name is deprecated in django version 1.7 and removed in django version 1.8.
50 # It is replaced by model._meta.model_name
51 return model._meta.model_name
52
53
54 class Call(object):
45 class Call:
5546
5647 def __init__(self, args, kwargs, start=None, finish=None):
5748 self.args = args
6354 return self.finish - self.start
6455
6556
66 class Timed(object):
57 class Timed:
6758
6859 def __init__(self, action=None):
6960 self.action = action
8980 return wrapper
9081
9182
92 class Benchmark(object):
83 class Benchmark:
9384
9485 def __init__(self, name, users_count, objects_count,
9586 objects_with_perms_count, model, subquery):
9990 self.objects_with_perms_count = objects_with_perms_count
10091 self.subquery = subquery
10192 self.Model = model
102 self.perm = 'add_%s' % get_model_name(model)
93 self.perm = 'add_%s' % model._meta.model_name
10394
10495 def info(self, msg):
10596 print(colorize(msg + '\n', fg='green'))
10697
10798 def prepare_db(self):
10899 from django.core.management import call_command
109 call_command('syncdb', interactive=False)
100 call_command('makemigrations', interactive=False)
101 call_command('migrate', interactive=False)
110102
111103 for model in [User, Group, self.Model]:
112104 model.objects.all().delete()
0 #!/bin/bash
1
2 set -ev
3
4 pip install -U pip
5
6 # Array of packages
7 PACKAGES=('mock==1.0.1' 'pytest' 'pytest-django' 'pytest-cov' 'django-environ' 'setuptools_scm')
8 # Install django master or version
9 if [[ "$DJANGO_VERSION" == 'master' ]]; then
10 PACKAGES+=('https://github.com/django/django/archive/master.tar.gz');
11 else
12 PACKAGES+=("Django==$DJANGO_VERSION");
13 fi;
14
15 # Install database drivers
16 if [[ $DATABASE_URL = postgres* ]]; then
17 PACKAGES+=('psycopg2==2.7.5');
18 fi;
19
20 if [[ $DATABASE_URL = mysql* ]]; then
21 PACKAGES+=('mysqlclient==1.3.13');
22 fi;
23 echo "Install " ${PACKAGES[*]};
24 pip install --upgrade --upgrade-strategy=only-if-needed ${PACKAGES[*]};
25 pip check
0 #!/bin/bash
1
2 python ./setup.py --version
3 py.test --cov=guardian
4
5 # Test example_project on supported django versions
6 if [ "${DJANGO_VERSION:0:3}" = "2.1" ] || \
7 [ "${DJANGO_VERSION:0:3}" = "2.2" ] || \
8 [ "$DJANGO_VERSION" = "master" ]; then
9 pip install .;
10 cd example_project;
11 python -Wa manage.py test;
12 fi;
+0
-141
django_guardian.egg-info/PKG-INFO less more
0 Metadata-Version: 1.1
1 Name: django-guardian
2 Version: 1.4.9
3 Summary: Implementation of per object permissions for Django.
4 Home-page: http://github.com/django-guardian/django-guardian
5 Author: Lukasz Balcerzak
6 Author-email: lukaszbalcerzak@gmail.com
7 License: BSD
8 Download-URL: https://github.com/django-guardian/django-guardian/tags
9 Description: ===============
10 django-guardian
11 ===============
12
13 .. image:: https://travis-ci.org/django-guardian/django-guardian.svg?branch=devel
14 :target: https://travis-ci.org/django-guardian/django-guardian
15
16 ``django-guardian`` is an implementation of per object permissions [1]_ on top
17 of Django's authorization backend
18
19 Documentation
20 -------------
21
22 Online documentation is available at https://django-guardian.readthedocs.io/.
23
24 Requirements
25 ------------
26
27 * Python 2.7 or 3.4+
28 * A supported version of Django (currently 1.8+)
29
30 Travis CI tests on Django version 1.8, 1.10, and 1.11.
31
32 Installation
33 ------------
34
35 To install ``django-guardian`` simply run::
36
37 pip install django-guardian
38
39 Configuration
40 -------------
41
42 We need to hook ``django-guardian`` into our project.
43
44 1. Put ``guardian`` into your ``INSTALLED_APPS`` at settings module:
45
46 .. code:: python
47
48 INSTALLED_APPS = (
49 ...
50 'guardian',
51 )
52
53 2. Add extra authorization backend to your ``settings.py``:
54
55 .. code:: python
56
57 AUTHENTICATION_BACKENDS = (
58 'django.contrib.auth.backends.ModelBackend', # default
59 'guardian.backends.ObjectPermissionBackend',
60 )
61
62 3. Create ``guardian`` database tables by running::
63
64 python manage.py migrate
65
66 Usage
67 -----
68
69 After installation and project hooks we can finally use object permissions
70 with Django_.
71
72 Lets start really quickly:
73
74 .. code:: python
75
76 >>> from django.contrib.auth.models import User, Group
77 >>> jack = User.objects.create_user('jack', 'jack@example.com', 'topsecretagentjack')
78 >>> admins = Group.objects.create(name='admins')
79 >>> jack.has_perm('change_group', admins)
80 False
81 >>> from guardian.models import UserObjectPermission
82 >>> UserObjectPermission.objects.assign_perm('change_group', jack, obj=admins)
83 <UserObjectPermission: admins | jack | change_group>
84 >>> jack.has_perm('change_group', admins)
85 True
86
87 Of course our agent jack here would not be able to *change_group* globally:
88
89 .. code:: python
90
91 >>> jack.has_perm('change_group')
92 False
93
94 Admin integration
95 -----------------
96
97 Replace ``admin.ModelAdmin`` with ``GuardedModelAdmin`` for those models
98 which should have object permissions support within admin panel.
99
100 For example:
101
102 .. code:: python
103
104 from django.contrib import admin
105 from myapp.models import Author
106 from guardian.admin import GuardedModelAdmin
107
108 # Old way:
109 #class AuthorAdmin(admin.ModelAdmin):
110 # pass
111
112 # With object permissions support
113 class AuthorAdmin(GuardedModelAdmin):
114 pass
115
116 admin.site.register(Author, AuthorAdmin)
117
118
119 .. [1] Great paper about this feature is available at `djangoadvent articles <https://github.com/djangoadvent/djangoadvent-articles/blob/master/1.2/06_object-permissions.rst>`_.
120
121 .. _Django: http://www.djangoproject.com/
122
123
124 Platform: UNKNOWN
125 Classifier: Development Status :: 5 - Production/Stable
126 Classifier: Environment :: Web Environment
127 Classifier: Framework :: Django
128 Classifier: Framework :: Django :: 1.8
129 Classifier: Framework :: Django :: 1.9
130 Classifier: Framework :: Django :: 1.10
131 Classifier: Framework :: Django :: 1.11
132 Classifier: Intended Audience :: Developers
133 Classifier: License :: OSI Approved :: BSD License
134 Classifier: Operating System :: OS Independent
135 Classifier: Programming Language :: Python
136 Classifier: Topic :: Security
137 Classifier: Programming Language :: Python :: 2.7
138 Classifier: Programming Language :: Python :: 3.4
139 Classifier: Programming Language :: Python :: 3.5
140 Classifier: Programming Language :: Python :: 3.6
+0
-186
django_guardian.egg-info/SOURCES.txt less more
0 .gitignore
1 .isort.cfg
2 .travis.yml
3 AUTHORS
4 CHANGES
5 LICENSE
6 MANIFEST.in
7 README.rst
8 extras.py
9 manage.py
10 pytest.ini
11 requirements.txt
12 run_test_and_report.sh
13 setup.cfg
14 setup.py
15 tox.ini
16 utils.py
17 benchmarks/__init__.py
18 benchmarks/models.py
19 benchmarks/run_benchmarks.py
20 benchmarks/settings.py
21 django_guardian.egg-info/PKG-INFO
22 django_guardian.egg-info/SOURCES.txt
23 django_guardian.egg-info/dependency_links.txt
24 django_guardian.egg-info/not-zip-safe
25 django_guardian.egg-info/requires.txt
26 django_guardian.egg-info/top_level.txt
27 docs/Makefile
28 docs/conf.py
29 docs/configuration.rst
30 docs/exts.py
31 docs/index.rst
32 docs/installation.rst
33 docs/license.rst
34 docs/make.bat
35 docs/overview.rst
36 docs/watch-docs.sh
37 docs/api/guardian.admin.rst
38 docs/api/guardian.backends.rst
39 docs/api/guardian.core.rst
40 docs/api/guardian.decorators.rst
41 docs/api/guardian.forms.rst
42 docs/api/guardian.management.commands.rst
43 docs/api/guardian.managers.rst
44 docs/api/guardian.mixins.rst
45 docs/api/guardian.models.rst
46 docs/api/guardian.shortcuts.rst
47 docs/api/guardian.templatetags.guardian_tags.rst
48 docs/api/guardian.utils.rst
49 docs/api/index.rst
50 docs/develop/changes.rst
51 docs/develop/index.rst
52 docs/develop/overview.rst
53 docs/develop/supported-versions.rst
54 docs/develop/testing.rst
55 docs/userguide/admin-integration.rst
56 docs/userguide/assign.rst
57 docs/userguide/caveats.rst
58 docs/userguide/check.rst
59 docs/userguide/custom-user-model.rst
60 docs/userguide/example_project.rst
61 docs/userguide/index.rst
62 docs/userguide/performance.rst
63 docs/userguide/remove.rst
64 example_project/__init__.py
65 example_project/manage.py
66 example_project/requirements.txt
67 example_project/settings.py
68 example_project/urls.py
69 example_project/articles/__init__.py
70 example_project/articles/admin.py
71 example_project/articles/apps.py
72 example_project/articles/models.py
73 example_project/articles/tests.py
74 example_project/articles/urls.py
75 example_project/articles/views.py
76 example_project/articles/migrations/0001_initial.py
77 example_project/articles/migrations/0002_auto_20160622_1050.py
78 example_project/articles/migrations/__init__.py
79 example_project/articles/templates/articles/article_confirm_delete.html
80 example_project/articles/templates/articles/article_detail.html
81 example_project/articles/templates/articles/article_form.html
82 example_project/articles/templates/articles/article_list.html
83 example_project/core/__init__.py
84 example_project/core/admin.py
85 example_project/core/context_processors.py
86 example_project/core/models.py
87 example_project/core/migrations/0001_initial.py
88 example_project/core/migrations/__init__.py
89 example_project/posts/__init__.py
90 example_project/posts/admin.py
91 example_project/posts/models.py
92 example_project/posts/urls.py
93 example_project/posts/views.py
94 example_project/posts/migrations/0001_initial.py
95 example_project/posts/migrations/__init__.py
96 example_project/posts/templates/posts/post_detail.html
97 example_project/posts/templates/posts/post_list.html
98 example_project/static/css/bootstrap.min.css
99 example_project/static/img/glyphicons-halflings-white.png
100 example_project/static/img/glyphicons-halflings.png
101 example_project/static/js/bootstrap.min.js
102 example_project/templates/403.html
103 example_project/templates/404.html
104 example_project/templates/500.html
105 example_project/templates/base.html
106 example_project/templates/home.html
107 guardian/__init__.py
108 guardian/admin.py
109 guardian/apps.py
110 guardian/backends.py
111 guardian/checks.py
112 guardian/compat.py
113 guardian/core.py
114 guardian/ctypes.py
115 guardian/decorators.py
116 guardian/exceptions.py
117 guardian/forms.py
118 guardian/managers.py
119 guardian/mixins.py
120 guardian/models.py
121 guardian/shortcuts.py
122 guardian/utils.py
123 guardian/conf/__init__.py
124 guardian/conf/settings.py
125 guardian/locale/es/LC_MESSAGES/django.mo
126 guardian/locale/es/LC_MESSAGES/django.po
127 guardian/locale/fr/LC_MESSAGES/django.mo
128 guardian/locale/fr/LC_MESSAGES/django.po
129 guardian/locale/pl/LC_MESSAGES/django.mo
130 guardian/locale/pl/LC_MESSAGES/django.po
131 guardian/locale/pt_BR/LC_MESSAGES/django.mo
132 guardian/locale/pt_BR/LC_MESSAGES/django.po
133 guardian/locale/ru/LC_MESSAGES/django.mo
134 guardian/locale/ru/LC_MESSAGES/django.po
135 guardian/management/__init__.py
136 guardian/management/commands/__init__.py
137 guardian/management/commands/clean_orphan_obj_perms.py
138 guardian/migrations/0001_initial.py
139 guardian/migrations/__init__.py
140 guardian/static/guardian/img/icon-no.svg
141 guardian/static/guardian/img/icon-yes.svg
142 guardian/templates/admin/guardian/contrib/grappelli/field.html
143 guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage.html
144 guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage_group.html
145 guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage_user.html
146 guardian/templates/admin/guardian/model/change_form.html
147 guardian/templates/admin/guardian/model/field.html
148 guardian/templates/admin/guardian/model/obj_perms_manage.html
149 guardian/templates/admin/guardian/model/obj_perms_manage_group.html
150 guardian/templates/admin/guardian/model/obj_perms_manage_user.html
151 guardian/templates/admin/guardian/model/obj_perms_no.html
152 guardian/templates/admin/guardian/model/obj_perms_yes.html
153 guardian/templatetags/__init__.py
154 guardian/templatetags/guardian_tags.py
155 guardian/testapp/__init__.py
156 guardian/testapp/models.py
157 guardian/testapp/testsettings.py
158 guardian/testapp/migrations/0001_initial.py
159 guardian/testapp/migrations/0002_logentrywithgroup.py
160 guardian/testapp/migrations/__init__.py
161 guardian/testapp/tests/__init__.py
162 guardian/testapp/tests/conf.py
163 guardian/testapp/tests/test_admin.py
164 guardian/testapp/tests/test_checks.py
165 guardian/testapp/tests/test_conf.py
166 guardian/testapp/tests/test_core.py
167 guardian/testapp/tests/test_custompkmodel.py
168 guardian/testapp/tests/test_decorators.py
169 guardian/testapp/tests/test_direct_rel.py
170 guardian/testapp/tests/test_forms.py
171 guardian/testapp/tests/test_management.py
172 guardian/testapp/tests/test_managers.py
173 guardian/testapp/tests/test_mixins.py
174 guardian/testapp/tests/test_orphans.py
175 guardian/testapp/tests/test_other.py
176 guardian/testapp/tests/test_shortcuts.py
177 guardian/testapp/tests/test_tags.py
178 guardian/testapp/tests/test_utils.py
179 guardian/testapp/tests/urls.py
180 guardian/testapp/tests/templates/404.html
181 guardian/testapp/tests/templates/500.html
182 guardian/testapp/tests/templates/blank.html
183 guardian/testapp/tests/templates/dummy403.html
184 guardian/testapp/tests/templates/dummy404.html
185 guardian/testapp/tests/templates/list.html
+0
-1
django_guardian.egg-info/dependency_links.txt less more
0
+0
-1
django_guardian.egg-info/not-zip-safe less more
0
+0
-1
django_guardian.egg-info/requires.txt less more
0 six
+0
-1
django_guardian.egg-info/top_level.txt less more
0 guardian
1313 .. autoclass:: guardian.admin.GuardedModelAdmin
1414 :members:
1515
16 GuardedModelAdminMixin
17 ----------------------
18
19 .. autoclass:: guardian.admin.GuardedModelAdminMixin
20 :members:
21
0 # -*- coding: utf-8 -*-
1 #
20 # django-guardian documentation build configuration file, created by
31 # sphinx-quickstart on Thu Feb 18 23:18:28 2010.
42 #
2020
2121 .. note::
2222 Once project is configured to work with ``django-guardian``, calling
23 ``syncdb`` management command would create ``User`` instance for
23 ``migrate`` management command would create ``User`` instance for
2424 anonymous user support (with name of ``AnonymousUser``).
2525
2626 .. note::
3232
3333 .. code-block:: python
3434
35 from guardian.compat import get_user_model
35 from django.contrib.auth import get_user_model
3636 User = get_user_model()
3737 anon = User.get_anonymous()
38 anon.is_anonymous() # returns False
38 anon.is_anonymous # returns False
3939
4040 We can change id to whatever we like. Project should be now ready to use object
4141 permissions.
42
42
4343
4444 Optional settings
4545 =================
113113
114114 Defaults to ``"AnonymousUser"``.
115115
116 .. seealso:: https://docs.djangoproject.com/en/1.5/topics/auth/customizing/#substituting-a-custom-user-model
116 .. seealso:: https://docs.djangoproject.com/en/2.1/topics/auth/customizing/#substituting-a-custom-user-model
117117
118118
119119 .. setting:: GUARDIAN_GET_INIT_ANONYMOUS_USER
126126 Guardian supports object level permissions for anonymous users, however when
127127 in our project we use custom User model, default function might fail. This can
128128 lead to issues as ``guardian`` tries to create anonymous user after each
129 ``syncdb`` call. Object that is going to be created is retrieved using function
129 ``migrate`` call. Object that is going to be created is retrieved using function
130130 pointed by this setting. Once retrieved, ``save`` method would be called on
131131 that instance.
132132
151151 polymorphic models and the regular model ``ContentType`` for non-polymorphic
152152 classes.
153153
154 Defaults to ``"guardian.ctypes.get_default_content_type"``.
154 Defaults to ``"guardian.ctypes.get_default_content_type"``.
8585 * Commit changes of codebase, e.g. ``git commit -m "Release 1.4.8" -a``.
8686 * Tag a new release, e.g. ``git tag "v1.4.8"``.
8787 * Push new tag to repo - ``git push origin --tags``.
88 * Push a new release to PyPI - ``python setup.py sdist bdist_wheel upload``.
88 * Push a new release to PyPI - ``python3 setup.py sdist bdist_wheel upload``.
22 Supported versions
33 ==================
44
5 ``django-guardian`` supports Python 2.7+/3.3+ and Django 1.7+.
5 ``django-guardian`` supports Python 3.5+ and Django 2.1+.
66
77 Rules
88 -----
99
10 * We would support Python 2.7. We also support Python 3.3+.
11 * Support for Python 3.3 may get dropped in the future.
12 * We support Django 1.7+. This is due to many simplifications in code we could
10 * We support Python 3.5+.
11 * We support Django 2.1+. This is due to many simplifications in code we could
1312 do.
22 Installation
33 ============
44
5 This application requires Django_ 1.7 or higher and it is the only prerequisite
5 This application requires Django_ 1.11 or higher and it is the only prerequisite
66 before ``django-guardian`` may be used.
77
88 In order to install ``django-guardian`` simply use ``pip``::
3030
3131 class Meta:
3232 permissions = (
33 ('view_post', 'Can view post'),
33 ('hide_post', 'Can hide post'),
3434 )
3535 get_latest_by = 'created_at'
3636
37 def __unicode__(self):
37 def __str__(self):
3838 return self.title
3939
4040 def get_absolute_url(self):
8989 .. note::
9090 Example above is shipped with ``django-guardian`` package with the example
9191 project.
92
1818 reported_by = models.ForeignKey(User, on_delete=models.CASCADE)
1919 created_at = models.DateTimeField(auto_now_add=True)
2020
21 ... and we want to be able to set custom permission *view_task*. We let Django
21 ... and we want to be able to set custom permission *assign_task*. We let Django
2222 know to do so by adding ``permissions`` tuple to ``Meta`` class and our final
2323 model could look like:
2424
3232
3333 class Meta:
3434 permissions = (
35 ('view_task', 'View task'),
35 ('assign_task', 'Assign task'),
3636 )
3737
38 After we call ``syncdb`` (with a ``--all`` switch if you are using south)
39 management command our *view_task* permission would be added to default set of
40 permissions.
38 After we call management commands ``makemigrations`` and ``migrate``
39 our *assign_task* permission would be added to default set of permissions.
4140
4241 .. note::
4342 By default, Django adds 3 permissions for each registered model:
4544 - *add_modelname*
4645 - *change_modelname*
4746 - *delete_modelname*
47 - *view_modelname* (since Django 2.1)
4848
4949 (where *modelname* is a simplified name of our model's class). See
5050 https://docs.djangoproject.com/en/dev/topics/auth/default/#default-permissions for
5151 more detail.
52
53 .. note::
54 When upgrading to Django 2.1 custom created *view_modelname* permissions
55 clash with the newly built-in ones. The simplest way to fix this is to
56 add ``default_permissions = ('add', 'change', 'delete')`` to ``Meta``.
5257
5358 There is nothing new here since creation of permissions is
5459 `handled by django <http://docs.djangoproject.com/en/1.2/topics/auth/#id1>`_.
6570 For user
6671 ~~~~~~~~
6772
68 Continuing our example we now can allow Joe user to view some task:
73 Continuing our example we now can allow Joe user to assign some task:
6974
7075 .. code-block:: python
7176
7378 >>> boss = User.objects.create(username='Big Boss')
7479 >>> joe = User.objects.create(username='joe')
7580 >>> task = Task.objects.create(summary='Some job', content='', reported_by=boss)
76 >>> joe.has_perm('view_task', task)
81 >>> joe.has_perm('assign_task', task)
7782 False
7883
7984 Well, not so fast Joe, let us create an object permission finally:
8186 .. code-block:: python
8287
8388 >>> from guardian.shortcuts import assign_perm
84 >>> assign_perm('view_task', joe, task)
85 >>> joe.has_perm('view_task', task)
89 >>> assign_perm('assign_task', joe, task)
90 >>> joe.has_perm('assign_task', task)
8691 True
8792
8893
7979
8080 .. code-block:: python
8181
82 from django.shortcuts import render_to_response
82 from django.shortcuts import render
8383 from django.template import RequestContext
8484 from projects.models import Project
8585 from guardian.shortcuts import get_objects_for_user
8686
8787 def user_dashboard(request, template_name='projects/dashboard.html'):
8888 projects = get_objects_for_user(request.user, 'projects.view_project')
89 return render_to_response(template_name, {'projects': projects},
89 return render(request, template_name, {'projects': projects},
9090 RequestContext(request))
9191
9292 It is also possible to provide list of permissions rather than single string,
44
55 .. versionadded:: 1.1
66
7 Django 1.5 comes with the ability to customize default ``auth.User`` model
7 Django comes with the ability to customize default ``auth.User`` model
88 - either by subclassing ``AbstractUser`` or defining very own class. This can be
99 very powerful, it must be done with caution, though. Basically, if we subclass
1010 ``AbstractUser`` or define many-to-many relation with ``auth.Group`` (and give
2525 auth.Group relation django-guardian will BREAK**.
2626
2727
28 .. seealso:: Read more about customizing User model introduced in Django 1.5
29 here: https://docs.djangoproject.com/en/1.5/topics/auth/customizing/#substituting-a-custom-user-model.
28 .. seealso:: Read more about customizing User model
29 here: https://docs.djangoproject.com/en/2.1/topics/auth/customizing/#substituting-a-custom-user-model.
3030
3131
3232 .. _custom-user-model-anonymous:
104104 is discouraged (it's not consistent and might be a quick road to hell from the
105105 maintainence point of view, especially).
106106
107 To temporarily disable the detection of this direct relation model, add
108 ``enabled = False`` to the object permission model classes. This is useful to
109 allow the ORM to create the tables for you and for you to migrate data from the
110 generic model tables before using the direct models.
111
107112 .. note::
108113 By defining direct relation models we can also tweak that object permission
109114 model, i.e. by adding some fields.
0 from __future__ import unicode_literals
1
20 from django.apps import AppConfig
31
42
0 # -*- coding: utf-8 -*-
10 # Generated by Django 1.9.4 on 2016-06-22 05:23
2 from __future__ import unicode_literals
3
41 from django.conf import settings
52 from django.db import migrations, models
63 import django.db.models.deletion
2724 ],
2825 options={
2926 'get_latest_by': 'created_at',
30 'permissions': (('view_articlew', 'Can view article'),),
27 'default_permissions': ('add', 'change', 'delete'),
28 'permissions': (('view_article', 'Can view article'),),
3129 },
3230 ),
3331 migrations.CreateModel(
+0
-19
example_project/articles/migrations/0002_auto_20160622_1050.py less more
0 # -*- coding: utf-8 -*-
1 # Generated by Django 1.9.4 on 2016-06-22 10:50
2 from __future__ import unicode_literals
3
4 from django.db import migrations
5
6
7 class Migration(migrations.Migration):
8
9 dependencies = [
10 ('articles', '0001_initial'),
11 ]
12
13 operations = [
14 migrations.AlterModelOptions(
15 name='article',
16 options={'get_latest_by': 'created_at', 'permissions': (('view_article', 'Can view article'),)},
17 ),
18 ]
0 from __future__ import unicode_literals
1
20 from django.db import models
3 from guardian.compat import reverse
1 from django.urls import reverse
42
53
64 from guardian.models import GroupObjectPermissionBase, UserObjectPermissionBase
1311 created_at = models.DateTimeField(auto_now_add=True, db_index=True)
1412
1513 class Meta:
14 default_permissions = ('add', 'change', 'delete')
1615 permissions = (
1716 ('view_article', 'Can view article'),
1817 )
1918 get_latest_by = 'created_at'
2019
21 def __unicode__(self):
20 def __str__(self):
2221 return self.title
2322
2423 def get_absolute_url(self):
0 from django.contrib.auth import get_user_model
01 from django.test import TestCase
12 from django.test.client import RequestFactory
2 from guardian.compat import get_user_model
33 from guardian.shortcuts import assign_perm
44 from articles.models import Article
55 from articles.views import (ArticleCreateView, ArticleDeleteView, ArticleDetailView,
0 # -*- coding: utf-8 -*-
1 from __future__ import unicode_literals
2
30 from django.conf.urls import url
41 from . import views
52
0 from django.urls import reverse_lazy
01 from django.views.generic import (CreateView, DeleteView, DetailView, ListView,
12 UpdateView)
2 from guardian.compat import reverse_lazy
33 from guardian.mixins import PermissionRequiredMixin, PermissionListMixin
44 from guardian.shortcuts import assign_perm
55 from articles.models import Article
2222 fields = ['title', 'slug', 'content']
2323
2424 def form_valid(self, *args, **kwargs):
25 resp = super(ArticleCreateView, self).form_valid(*args, **kwargs)
25 resp = super().form_valid(*args, **kwargs)
2626 assign_perm('view_article', self.request.user, self.object)
2727 assign_perm('change_article', self.request.user, self.object)
2828 assign_perm('delete_article', self.request.user, self.object)
0 # -*- coding: utf-8 -*-
1 from __future__ import unicode_literals
20 import django
31 from django.db import migrations, models
42 import django.utils.timezone
53 import django.core.validators
64 import django.contrib.auth.models
7
8 if django.VERSION >= (1, 8):
9 django_version_depend = {'managers': [
10 ('objects', django.contrib.auth.models.UserManager()),
11 ]}
12 else:
13 django_version_depend = {}
145
156
167 class Migration(migrations.Migration):
5647 'verbose_name': 'user',
5748 'verbose_name_plural': 'users',
5849 },
59 **django_version_depend
50 managers=[
51 ('objects', django.contrib.auth.models.UserManager()),
52 ],
6053 ),
6154 ]
0 import datetime
1
02 from django.contrib.auth.models import AbstractUser
13 from django.db import models
2 import datetime
34
45
56 class CustomUser(AbstractUser):
00 #!/usr/bin/env python
1 import django
21 import os
32 import sys
4
5 if django.VERSION < (1, 5):
6 sys.stderr.write("ERROR: guardian's example project must be run with "
7 "Django 1.8 or later!\n")
8 sys.exit(1)
93
104
115 if __name__ == "__main__":
0 # -*- coding: utf-8 -*-
1 from __future__ import unicode_literals
2
30 from django.db import migrations, models
41
52
2219 ],
2320 options={
2421 'get_latest_by': 'created_at',
22 'default_permissions': ('add', 'change', 'delete'),
2523 'permissions': (('view_post', 'Can view post'),),
2624 },
2725 ),
00 from django.db import models
1 from django.urls import reverse
12
23
34 class Post(models.Model):
78 created_at = models.DateTimeField(auto_now_add=True, db_index=True)
89
910 class Meta:
11 default_permissions = ('add', 'change', 'delete')
1012 permissions = (
1113 ('view_post', 'Can view post'),
1214 )
1315 get_latest_by = 'created_at'
1416
15 def __unicode__(self):
17 def __str__(self):
1618 return self.title
1719
18 @models.permalink
1920 def get_absolute_url(self):
20 return ('posts_post_detail', (), {'slug': self.slug})
21 return reverse('posts_post_detail', args=(), kwargs={'slug': self.slug})
0 from django.contrib.auth import get_user_model
01 from django.contrib.auth.models import Group
1 from django.shortcuts import render_to_response, get_object_or_404
2 from django.shortcuts import render, get_object_or_404
23 from django.views.generic import ListView
34 from django.template import RequestContext
45 from guardian.decorators import permission_required_or_403
5 from guardian.compat import get_user_model
66
77 from .models import Post
88
2323 'users': User.objects.all(),
2424 'groups': Group.objects.all(),
2525 }
26 return render_to_response(
27 'posts/post_detail.html', data,
26 return render(
27 request, 'posts/post_detail.html', data,
2828 RequestContext(request))
0 Django==1.9.4
1 django-environ==0.4.0
2 django-rosetta==0.7.8
3 microsofttranslator==0.7
4 polib==1.0.7
5 six==1.10.0
0 Django==2.1.*
1 django-environ==0.4.5
2 django-rosetta==0.9.3
3 microsofttranslator==0.8
4 polib==1.1.0
00 import os
11 import sys
2 from django.conf import global_settings
32 import environ
43
54 env = environ.Env()
87
98
109 DEBUG = True
11 TEMPLATE_DEBUG = DEBUG
1210 SECRET_KEY = 'CHANGE_THIS_TO_SOMETHING_UNIQUE_AND_SECURE'
1311
1412 PROJECT_ROOT = abspath(os.path.dirname(__file__))
4442 except ImportError:
4543 pass
4644
47 MIDDLEWARE_CLASSES = (
45 MIDDLEWARE = (
4846 'django.middleware.common.CommonMiddleware',
4947 'django.contrib.sessions.middleware.SessionMiddleware',
5048 'django.middleware.csrf.CsrfViewMiddleware',
5856 GUARDIAN_RAISE_403 = True
5957
6058 ROOT_URLCONF = 'urls'
61
62 TEMPLATE_CONTEXT_PROCESSORS = (
63 'core.context_processors.version',
64 "django.contrib.auth.context_processors.auth",
65 "django.template.context_processors.debug",
66 "django.template.context_processors.i18n",
67 "django.template.context_processors.media",
68 "django.template.context_processors.static",
69 "django.template.context_processors.request",
70 "django.template.context_processors.tz",
71 "django.contrib.messages.context_processors.messages"
72 )
73 TEMPLATE_LOADERS = (
74 'django.template.loaders.filesystem.Loader',
75 'django.template.loaders.app_directories.Loader',
76 )
77
78 TEMPLATE_DIRS = (
79 os.path.join(os.path.dirname(__file__), 'templates'),
80 )
8159
8260 SITE_ID = 1
8361
10684 TEMPLATES = [
10785 {
10886 'BACKEND': 'django.template.backends.django.DjangoTemplates',
109 'DIRS': TEMPLATE_DIRS,
87 'DIRS': (
88 os.path.join(os.path.dirname(__file__), 'templates'),
89 ),
11090 'OPTIONS': {
111 'debug': TEMPLATE_DEBUG,
112 'loaders': TEMPLATE_LOADERS,
113 'context_processors': TEMPLATE_CONTEXT_PROCESSORS,
91 'debug': DEBUG,
92 'loaders': (
93 'django.template.loaders.filesystem.Loader',
94 'django.template.loaders.app_directories.Loader',
95 ),
96 'context_processors': (
97 'core.context_processors.version',
98 'django.contrib.auth.context_processors.auth',
99 'django.template.context_processors.debug',
100 'django.template.context_processors.i18n',
101 'django.template.context_processors.media',
102 'django.template.context_processors.static',
103 'django.template.context_processors.request',
104 'django.template.context_processors.tz',
105 'django.contrib.messages.context_processors.messages'
106 ),
114107 },
115108 },
116109 ]
00 from guardian.compat import include, url, handler404, handler500
11 from django.conf import settings
22 from django.contrib import admin
3 from django.contrib.auth.views import logout
3 from django.contrib.auth.views import LogoutView
44
55 __all__ = ['handler404', 'handler500']
66
99
1010 urlpatterns = [
1111 url(r'^admin/', admin.site.urls),
12 url(r'^logout/$', logout, {'next_page': '/'}, name='logout'),
12 url(r'^logout/$', LogoutView.as_view(next_page='/'), name='logout'),
1313 url(r'^article/', include('articles.urls', namespace='articles')),
1414 url(r'^', include('posts.urls')),
1515 ]
00 """
11 Implementation of per object permissions for Django.
22 """
3 from __future__ import unicode_literals
43 from . import checks
54
65 default_app_config = 'guardian.apps.GuardianConfig'
76
87 # PEP 396: The __version__ attribute's value SHOULD be a string.
9 __version__ = '1.4.9'
8 __version__ = '2.0.0'
109
1110 # Compatibility to eg. django-rest-framework
1211 VERSION = tuple(int(x) for x in __version__.split('.')[:3])
1716
1817
1918 def monkey_patch_user():
20 from .compat import get_user_model
19 from django.contrib.auth import get_user_model
2120 from .utils import get_anonymous_user
2221 from .models import UserObjectPermission
2322 User = get_user_model()
0 from __future__ import unicode_literals
1
20 from collections import OrderedDict
31
42 from django import forms
53 from django.conf import settings
64 from django.contrib import admin, messages
75 from django.contrib.admin.widgets import FilteredSelectMultiple
8 from django.shortcuts import get_object_or_404, redirect, render_to_response, render
9 from django.template import RequestContext
6 from django.contrib.auth import get_user_model
7 from django.shortcuts import get_object_or_404, redirect, render
8 from django.urls import reverse
109 from django.utils.translation import ugettext_lazy as _
1110 from django.utils.translation import ugettext
12 from guardian.compat import get_model_name, get_user_model, url, reverse
11 from guardian.compat import url
1312 from guardian.forms import GroupObjectPermissionsForm, UserObjectPermissionsForm
1413 from guardian.models import Group
1514 from guardian.shortcuts import (get_group_perms, get_groups_with_perms, get_perms_for_model, get_user_perms,
1615 get_users_with_perms)
1716
18 import django
19
2017
2118 class AdminUserObjectPermissionsForm(UserObjectPermissionsForm):
2219 """
4037 return FilteredSelectMultiple(_("Permissions"), False)
4138
4239
43 class GuardedModelAdminMixin(object):
40 class GuardedModelAdminMixin:
4441 """
4542 Serves as a helper for custom subclassing ``admin.ModelAdmin``.
4643 """
5956 include_object_permissions_urls = True
6057
6158 def get_queryset(self, request):
62 # Prefer the Django >= 1.6 interface but maintain
63 # backward compatibility
64 method = getattr(
65 super(GuardedModelAdminMixin, self), 'get_queryset',
66 getattr(super(GuardedModelAdminMixin, self), 'queryset', None))
67 qs = method(request)
59 qs = super().get_queryset(request)
6860
6961 if request.user.is_superuser:
7062 return qs
9385 ``/admin/flatpages/1/``)
9486
9587 """
96 urls = super(GuardedModelAdminMixin, self).get_urls()
88 urls = super().get_urls()
9789 if self.include_object_permissions_urls:
98 info = self.model._meta.app_label, get_model_name(self.model)
90 info = self.model._meta.app_label, self.model._meta.model_name
9991 myurls = [
10092 url(r'^(?P<object_pk>.+)/permissions/$',
10193 view=self.admin_site.admin_view(
116108 def get_obj_perms_base_context(self, request, obj):
117109 """
118110 Returns context dictionary with common admin and object permissions
119 related content. It uses AdminSite.each_context (available in Django >= 1.8,
111 related content. It uses AdminSite.each_context,
120112 making sure all required template vars are in the context.
121113 """
122 if django.VERSION >= (1, 8):
123 context = self.admin_site.each_context(request)
124 else:
125 context = {}
126 context.update( {
114 context = self.admin_site.each_context(request)
115 context.update({
127116 'adminform': {'model_admin': self},
128117 'media': self.media,
129118 'object': obj,
130119 'app_label': self.model._meta.app_label,
131120 'opts': self.model._meta,
132 'original': hasattr(obj, '__unicode__') and obj.__unicode__() or str(obj),
121 'original': str(obj),
133122 'has_change_permission': self.has_change_permission(request, obj),
134123 'model_perms': get_perms_for_model(obj),
135124 'title': _("Object permissions"),
148137 post_url = reverse('admin:index', current_app=self.admin_site.name)
149138 return redirect(post_url)
150139
151 try:
152 # django >= 1.7
153 from django.contrib.admin.utils import unquote
154 except ImportError:
155 # django < 1.7
156 from django.contrib.admin.util import unquote
140 from django.contrib.admin.utils import unquote
157141 obj = get_object_or_404(self.get_queryset(
158142 request), pk=unquote(object_pk))
159143 users_perms = OrderedDict(
178162 info = (
179163 self.admin_site.name,
180164 self.model._meta.app_label,
181 get_model_name(self.model)
165 self.model._meta.model_name,
182166 )
183167 if user_form.is_valid():
184168 user_id = user_form.cleaned_data['user'].pk
193177 info = (
194178 self.admin_site.name,
195179 self.model._meta.app_label,
196 get_model_name(self.model)
180 self.model._meta.model_name,
197181 )
198182 if group_form.is_valid():
199183 group_id = group_form.cleaned_data['group'].id
215199 # https://github.com/django/django/commit/cf1f36bb6eb34fafe6c224003ad585a647f6117b
216200 request.current_app = self.admin_site.name
217201
218 if django.VERSION >= (1, 10):
219 return render(request, self.get_obj_perms_manage_template(), context)
220
221 return render_to_response(self.get_obj_perms_manage_template(), context, RequestContext(request))
202 return render(request, self.get_obj_perms_manage_template(), context)
222203
223204 def get_obj_perms_manage_template(self):
224205 """
254235 info = (
255236 self.admin_site.name,
256237 self.model._meta.app_label,
257 get_model_name(self.model)
238 self.model._meta.model_name,
258239 )
259240 url = reverse(
260241 '%s:%s_%s_permissions_manage_user' % info,
269250
270251 request.current_app = self.admin_site.name
271252
272 if django.VERSION >= (1, 10):
273 return render(request, self.get_obj_perms_manage_user_template(), context)
274
275 return render_to_response(self.get_obj_perms_manage_user_template(), context, RequestContext(request))
253 return render(request, self.get_obj_perms_manage_user_template(), context)
276254
277255 def get_obj_perms_manage_user_template(self):
278256 """
330308 info = (
331309 self.admin_site.name,
332310 self.model._meta.app_label,
333 get_model_name(self.model)
311 self.model._meta.model_name,
334312 )
335313 url = reverse(
336314 '%s:%s_%s_permissions_manage_group' % info,
345323
346324 request.current_app = self.admin_site.name
347325
348 if django.VERSION >= (1, 10):
349 return render(request, self.get_obj_perms_manage_group_template(), context)
350
351 return render_to_response(self.get_obj_perms_manage_group_template(), context, RequestContext(request))
326 return render(request, self.get_obj_perms_manage_group_template(), context)
352327
353328 def get_obj_perms_manage_group_template(self):
354329 """
0 from __future__ import unicode_literals
0 from django.contrib.auth import get_user_model
11 from django.db import models
2 from guardian.compat import get_user_model, is_authenticated
32 from guardian.conf import settings
43 from guardian.core import ObjectPermissionChecker
54 from guardian.ctypes import get_content_type
2625 """
2726 # This is how we support anonymous users - simply try to retrieve User
2827 # instance and perform checks for that predefined user
29 if not is_authenticated(user_obj):
28 if not user_obj.is_authenticated:
3029 # If anonymous user permission is disabled then they are always
3130 # unauthorized
3231 if settings.ANONYMOUS_USER_NAME is None:
4746 return obj_support and user_support, user_obj
4847
4948
50 class ObjectPermissionBackend(object):
49 class ObjectPermissionBackend:
5150 supports_object_permissions = True
5251 supports_anonymous_user = True
5352 supports_inactive_user = True
5453
55 def authenticate(self, username, password):
54 def authenticate(self, request, username, password):
5655 return None
5756
5857 def has_perm(self, user_obj, perm, obj=None):
8180 return False
8281
8382 if '.' in perm:
84 app_label, perm = perm.split('.')
83 app_label, _ = perm.split('.', 1)
8584 if app_label != obj._meta.app_label:
8685 # Check the content_type app_label when permission
8786 # and obj app labels don't match.
0 from __future__ import unicode_literals
1
20 from django.conf import settings
31 from django.conf.urls import handler404, handler500, include, url
2 from django.contrib.auth import get_user_model
43 from django.contrib.auth.models import AnonymousUser, Group, Permission
5 from importlib import import_module
6
7 import django
8 import six
9 import sys
104
115 __all__ = [
12 'User',
136 'Group',
147 'Permission',
158 'AnonymousUser',
169 'get_user_model',
17 'import_string',
1810 'user_model_label',
1911 'url',
20 'patterns',
2112 'include',
2213 'handler404',
2314 'handler500',
2415 ]
2516
26 # Django 1.5 compatibility utilities, providing support for custom User models.
2717 # Since get_user_model() causes a circular import if called when app models are
2818 # being loaded, the user_model_label should be used when possible, with calls
2919 # to get_user_model deferred to execution time
3020
3121 user_model_label = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')
32
33 try:
34 from django.contrib.auth import get_user_model
35 except ImportError:
36 from django.contrib.auth.models import User
37 get_user_model = lambda: User
3822
3923
4024 def get_user_model_path():
6448 ``myapp.CustomUser`` is used it would return ``change_customuser``.
6549 """
6650 return get_user_permission_full_codename(perm).split('.')[1]
67
68
69 def import_string(dotted_path):
70 """
71 Import a dotted module path and return the attribute/class designated by the
72 last name in the path. Raise ImportError if the import failed.
73
74 Backported from Django 1.7
75 """
76 try:
77 module_path, class_name = dotted_path.rsplit('.', 1)
78 except ValueError:
79 msg = "%s doesn't look like a module path" % dotted_path
80 six.reraise(ImportError, ImportError(msg), sys.exc_info()[2])
81
82 module = import_module(module_path)
83
84 try:
85 return getattr(module, class_name)
86 except AttributeError:
87 msg = 'Module "%s" does not define a "%s" attribute/class' % (
88 dotted_path, class_name)
89 six.reraise(ImportError, ImportError(msg), sys.exc_info()[2])
90
91
92 # Python 3
93 try:
94 unicode = unicode # pyflakes:ignore
95 basestring = basestring # pyflakes:ignore
96 str = str # pyflakes:ignore
97 except NameError:
98 basestring = unicode = str = str
99
100
101 # Django 1.7 compatibility
102 # create_permission API changed: skip the create_models (second
103 # positional argument) if we have django 1.7+ and 2+ positional
104 # arguments with the second one being a list/tuple
105 def create_permissions(*args, **kwargs):
106 from django.contrib.auth.management import create_permissions as original_create_permissions
107
108 if len(args) > 1 and isinstance(args[1], (list, tuple)):
109 args = args[:1] + args[2:]
110 return original_create_permissions(*args, **kwargs)
111
112 __all__ = ['User', 'Group', 'Permission', 'AnonymousUser']
113
114
115 def get_model_name(model):
116 """
117 Returns the name of the model
118 """
119 # model._meta.module_name is deprecated in django version 1.7 and removed
120 # in django version 1.8. It is replaced by model._meta.model_name
121 return model._meta.model_name
122
123
124 def template_debug_setter(value):
125 if hasattr(settings, 'TEMPLATE_DEBUG'):
126 settings.TEMPLATE_DEBUG = value
127 settings.TEMPLATES[0]['OPTIONS']['DEBUG'] = value
128
129
130 def template_debug_getter():
131 if hasattr(settings, 'TEMPLATE_DEBUG'):
132 return settings.TEMPLATE_DEBUG
133 return settings.TEMPLATES[0]['OPTIONS'].get('DEBUG', False)
134
135
136 # Django 1.9 compatibility
137 def remote_field(field):
138 """
139 https://docs.djangoproject.com/en/1.9/releases/1.9/#field-rel-changes
140 """
141 if django.VERSION < (1, 9):
142 return field.rel
143 return field.remote_field
144
145
146 def remote_model(field):
147 if django.VERSION < (1, 9):
148 return remote_field(field).to
149 return remote_field(field).model
150
151
152 # Django 1.10 compatibility
153 def is_authenticated(user):
154 if django.VERSION < (1, 10):
155 return user.is_authenticated()
156 return user.is_authenticated
157
158
159 def is_anonymous(user):
160 if django.VERSION < (1, 10):
161 return user.is_anonymous()
162 return user.is_anonymous
163
164 try:
165 from django.urls import reverse, reverse_lazy
166 except ImportError:
167 from django.core.urlresolvers import reverse, reverse_lazy
0 from __future__ import unicode_literals
0 from __future__ import unicode_literals
10 import warnings
21 from django.conf import settings
32 from django.core.exceptions import ImproperlyConfigured
0 from __future__ import unicode_literals
0 from itertools import chain
1
2 from django.contrib.auth import get_user_model
13 from django.contrib.auth.models import Permission
24 from django.db.models.query import QuerySet
35 from django.utils.encoding import force_text
4 from guardian.compat import get_user_model
56 from guardian.ctypes import get_content_type
67 from guardian.utils import get_group_obj_perms_model, get_identity, get_user_obj_perms_model
7 from itertools import chain
88
99
1010 def _get_pks_model_and_ctype(objects):
2828 return pks, model, ctype
2929
3030
31 class ObjectPermissionChecker(object):
31 class ObjectPermissionChecker:
3232 """
3333 Generic object permissions checker class being the heart of
3434 ``django-guardian``.
7070 return False
7171 elif self.user and self.user.is_superuser:
7272 return True
73 perm = perm.split('.')[-1]
73 if '.' in perm:
74 _, perm = perm.split('.', 1)
7475 return perm in self.get_perms(obj)
7576
7677 def get_group_filters(self, obj):
156157 group_perms = self.get_group_perms(obj)
157158 perms = list(set(chain(user_perms, group_perms)))
158159 else:
159 group_filters = self.get_group_filters(obj)
160 perms = list(set(chain(*Permission.objects
161 .filter(content_type=ctype)
162 .filter(**group_filters)
163 .values_list("codename"))))
160 perms = list(set(self.get_group_perms(obj)))
164161 self._obj_perms_cache[key] = perms
165162 return self._obj_perms_cache[key]
166163
0 from __future__ import unicode_literals
1
20 from django.contrib.contenttypes.models import ContentType
1 from django.utils.module_loading import import_string
32
43 from guardian.conf import settings as guardian_settings
5 from guardian.compat import import_string
64
75
86 def get_content_type(obj):
0 from __future__ import unicode_literals
10 from django.apps import apps
21 from django.conf import settings
32 from django.contrib.auth import REDIRECT_FIELD_NAME
65 from django.db.models.query import QuerySet
76 from django.shortcuts import get_object_or_404
87 from django.utils.functional import wraps
9 from guardian.compat import basestring
108 from guardian.exceptions import GuardianError
119 from guardian.utils import get_40x_or_None
1210
8179
8280 # Check if perm is given as string in order not to decorate
8381 # view function itself which makes debugging harder
84 if not isinstance(perm, basestring):
82 if not isinstance(perm, str):
8583 raise GuardianError("First argument must be in format: "
8684 "'app_label.codename or a callable which return similar string'")
8785
9391 if lookup_variables:
9492 model, lookups = lookup_variables[0], lookup_variables[1:]
9593 # Parse model
96 if isinstance(model, basestring):
94 if isinstance(model, str):
9795 splitted = model.split('.')
9896 if len(splitted) != 2:
9997 raise GuardianError("If model should be looked up from "
11 Exceptions used by django-guardian. All internal and guardian-specific errors
22 should extend GuardianError class.
33 """
4 from __future__ import unicode_literals
54
65
76 class GuardianError(Exception):
2221
2322 class MixedContentTypeError(GuardianError):
2423 pass
24
25
26 class MultipleIdentityAndObjectError(GuardianError):
27 pass
0 from __future__ import unicode_literals
10 from django import forms
21 from django.utils.translation import ugettext as _
32 from guardian.shortcuts import assign_perm, get_group_perms, get_perms_for_model, get_user_perms, remove_perm
1716 permissions"
1817 """
1918 self.obj = obj
20 super(BaseObjectPermissionsForm, self).__init__(*args, **kwargs)
19 super().__init__(*args, **kwargs)
2120 field_name = self.get_obj_perms_field_name()
2221 self.fields[field_name] = self.get_obj_perms_field()
2322
118117
119118 def __init__(self, user, *args, **kwargs):
120119 self.user = user
121 super(UserObjectPermissionsForm, self).__init__(*args, **kwargs)
120 super().__init__(*args, **kwargs)
122121
123122 def get_obj_perms_field_initial(self):
124123 perms = get_user_perms(self.user, self.obj)
131130
132131 Should be called *after* form is validated.
133132 """
134 perms = self.cleaned_data[self.get_obj_perms_field_name()]
135 model_perms = [c[0] for c in self.get_obj_perms_field_choices()]
133 perms = set(self.cleaned_data[self.get_obj_perms_field_name()])
134 model_perms = set([c[0] for c in self.get_obj_perms_field_choices()])
135 init_perms = set(self.get_obj_perms_field_initial())
136136
137 to_remove = set(model_perms) - set(perms)
137 to_remove = (model_perms - perms) & init_perms
138138 for perm in to_remove:
139139 remove_perm(perm, self.user, self.obj)
140140
141 for perm in perms:
141 for perm in perms - init_perms:
142142 assign_perm(perm, self.user, self.obj)
143143
144144
165165
166166 def __init__(self, group, *args, **kwargs):
167167 self.group = group
168 super(GroupObjectPermissionsForm, self).__init__(*args, **kwargs)
168 super().__init__(*args, **kwargs)
169169
170170 def get_obj_perms_field_initial(self):
171171 perms = get_group_perms(self.group, self.obj)
178178
179179 Should be called *after* form is validated.
180180 """
181 perms = self.cleaned_data[self.get_obj_perms_field_name()]
182 model_perms = [c[0] for c in self.get_obj_perms_field_choices()]
181 perms = set(self.cleaned_data[self.get_obj_perms_field_name()])
182 model_perms = set([c[0] for c in self.get_obj_perms_field_choices()])
183 init_perms = set(self.get_obj_perms_field_initial())
183184
184 to_remove = set(model_perms) - set(perms)
185 to_remove = (model_perms - perms) & init_perms
185186 for perm in to_remove:
186187 remove_perm(perm, self.group, self.obj)
187188
188 for perm in perms:
189 for perm in perms - init_perms:
189190 assign_perm(perm, self.group, self.obj)
0 # Dutch translation of django-guardian
1 # This file is distributed under the same license as the PACKAGE package.
2 # Translator: Melvyn Sopacua <melvyn@pluggable.nl>, 2017.
3 #
4 msgid ""
5 msgstr ""
6 "Project-Id-Version: 1.4.9\n"
7 "Report-Msgid-Bugs-To: \n"
8 "POT-Creation-Date: 2017-10-16 07:58+0200\n"
9 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
10 "Last-Translator: Melvyn Sopacua <melvyn@pluggable.nl>\n"
11 "Language: nl\n"
12 "MIME-Version: 1.0\n"
13 "Content-Type: text/plain; charset=UTF-8\n"
14 "Content-Transfer-Encoding: 8bit\n"
15 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
16
17 #: admin.py:30 admin.py:41 forms.py:52
18 msgid "Permissions"
19 msgstr "Permissies"
20
21 #: admin.py:136
22 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:24
23 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage_group.html:24
24 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage_group.html:29
25 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage_group.html:40
26 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage_user.html:24
27 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage_user.html:29
28 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage_user.html:40
29 #: templates/admin/guardian/model/change_form.html:6
30 #: templates/admin/guardian/model/obj_perms_manage.html:16
31 #: templates/admin/guardian/model/obj_perms_manage_group.html:14
32 #: templates/admin/guardian/model/obj_perms_manage_group.html:25
33 #: templates/admin/guardian/model/obj_perms_manage_user.html:14
34 #: templates/admin/guardian/model/obj_perms_manage_user.html:25
35 msgid "Object permissions"
36 msgstr "Object permissies"
37
38 #: admin.py:253 admin.py:329
39 msgid "Permissions saved."
40 msgstr "Permissies zijn opgeslagen."
41
42 #: admin.py:457
43 msgid "User identification"
44 msgstr "Gebruikersindentificatie"
45
46 #: admin.py:460
47 msgid "This user does not exist"
48 msgstr "Deze gebruiker bestaat niet"
49
50 #: admin.py:462
51 msgid "Enter a value compatible with User.USERNAME_FIELD"
52 msgstr "Voer een waarde in die compatible is met User.USERNAME_FIELD"
53
54 #: admin.py:485
55 msgid "This group does not exist"
56 msgstr "Deze groep bestaat niet"
57
58 #: models.py:46
59 msgid "object ID"
60 msgstr "object ID"
61
62 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:9
63 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage_group.html:11
64 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage_user.html:11
65 #: templates/admin/guardian/model/obj_perms_manage.html:12
66 #: templates/admin/guardian/model/obj_perms_manage_group.html:10
67 #: templates/admin/guardian/model/obj_perms_manage_user.html:10
68 msgid "Home"
69 msgstr "Home"
70
71 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:33
72 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:94
73 msgid "Please correct the error below."
74 msgid_plural "Please correct the errors below."
75 msgstr[0] "Corrigeer de fout hieronder."
76 msgstr[1] "Corrigeer de fouten hieronder."
77
78 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:37
79 #: templates/admin/guardian/model/obj_perms_manage.html:31
80 msgid "Users"
81 msgstr "Gebruikers"
82
83 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:40
84 #: templates/admin/guardian/model/obj_perms_manage.html:37
85 msgid "User permissions"
86 msgstr "Gebruiker's permissies"
87
88 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:45
89 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage_user.html:49
90 #: templates/admin/guardian/model/obj_perms_manage.html:40
91 #: templates/admin/guardian/model/obj_perms_manage_user.html:30
92 msgid "User"
93 msgstr "Gebruiker"
94
95 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:49
96 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:110
97 #: templates/admin/guardian/model/obj_perms_manage.html:44
98 #: templates/admin/guardian/model/obj_perms_manage.html:98
99 msgid "Action"
100 msgstr "Actie"
101
102 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:66
103 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:127
104 #: templates/admin/guardian/model/obj_perms_manage.html:61
105 #: templates/admin/guardian/model/obj_perms_manage.html:115
106 msgid "Edit"
107 msgstr "Veranderen"
108
109 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:82
110 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage_user.html:31
111 #: templates/admin/guardian/model/obj_perms_manage.html:72
112 #: templates/admin/guardian/model/obj_perms_manage_user.html:15
113 msgid "Manage user"
114 msgstr "Beheer de gebruiker"
115
116 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:98
117 #: templates/admin/guardian/model/obj_perms_manage.html:85
118 msgid "Groups"
119 msgstr "Groepen"
120
121 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:101
122 #: templates/admin/guardian/model/obj_perms_manage.html:91
123 msgid "Group permissions"
124 msgstr "Groep permissies"
125
126 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:106
127 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage_group.html:49
128 #: templates/admin/guardian/model/obj_perms_manage.html:94
129 #: templates/admin/guardian/model/obj_perms_manage_group.html:30
130 msgid "Group"
131 msgstr "Groep"
132
133 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:144
134 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage_group.html:31
135 #: templates/admin/guardian/model/obj_perms_manage.html:126
136 #: templates/admin/guardian/model/obj_perms_manage_group.html:15
137 msgid "Manage group"
138 msgstr "Beheer de groep"
139
140 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage_group.html:43
141 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage_user.html:43
142 #: templates/admin/guardian/model/obj_perms_manage_group.html:27
143 #: templates/admin/guardian/model/obj_perms_manage_user.html:27
144 msgid "Object"
145 msgstr "Object"
146
147 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage_group.html:60
148 #: templates/admin/guardian/contrib/grappelli/obj_perms_manage_user.html:60
149 #: templates/admin/guardian/model/obj_perms_manage_group.html:37
150 #: templates/admin/guardian/model/obj_perms_manage_user.html:37
151 msgid "Save"
152 msgstr "Opslaan"
153
154 #: templates/admin/guardian/model/obj_perms_manage.html:27
155 #: templates/admin/guardian/model/obj_perms_manage.html:81
156 msgid "Please correct the errors below."
157 msgstr "Corrigeer de fout hieronder."
0 # SOME DESCRIPTIVE TITLE.
1 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
2 # This file is distributed under the same license as the PACKAGE package.
3 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
4 #
5 #, fuzzy
6 msgid ""
7 msgstr ""
8 "Project-Id-Version: PACKAGE VERSION\n"
9 "Report-Msgid-Bugs-To: \n"
10 "POT-Creation-Date: 2018-07-27 10:10+0800\n"
11 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
12 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13 "Language-Team: LANGUAGE <LL@li.org>\n"
14 "Language: \n"
15 "MIME-Version: 1.0\n"
16 "Content-Type: text/plain; charset=UTF-8\n"
17 "Content-Transfer-Encoding: 8bit\n"
18 "Plural-Forms: nplurals=1; plural=0;\n"
19
20 #: guardian/admin.py:30 guardian/admin.py:41 guardian/forms.py:52
21 msgid "Permissions"
22 msgstr "权限"
23
24 #: guardian/admin.py:136
25 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:24
26 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage_group.html:24
27 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage_group.html:29
28 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage_group.html:40
29 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage_user.html:24
30 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage_user.html:29
31 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage_user.html:40
32 #: guardian/templates/admin/guardian/model/change_form.html:6
33 #: guardian/templates/admin/guardian/model/obj_perms_manage.html:16
34 #: guardian/templates/admin/guardian/model/obj_perms_manage_group.html:14
35 #: guardian/templates/admin/guardian/model/obj_perms_manage_group.html:25
36 #: guardian/templates/admin/guardian/model/obj_perms_manage_user.html:14
37 #: guardian/templates/admin/guardian/model/obj_perms_manage_user.html:25
38 msgid "Object permissions"
39 msgstr "对象权限"
40
41 #: guardian/admin.py:253 guardian/admin.py:329
42 msgid "Permissions saved."
43 msgstr "权限已保存"
44
45 #: guardian/admin.py:457
46 msgid "User identification"
47 msgstr "用户 ID"
48
49 #: guardian/admin.py:460
50 msgid "This user does not exist"
51 msgstr "用户不存在"
52
53 #: guardian/admin.py:462
54 msgid "Enter a value compatible with User.USERNAME_FIELD"
55 msgstr "输入对应 User.USERNAME_FIELD 的值"
56
57 #: guardian/admin.py:485
58 msgid "This group does not exist"
59 msgstr "组不存在"
60
61 #: guardian/models.py:46
62 msgid "object ID"
63 msgstr "对象 ID"
64
65 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:9
66 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage_group.html:11
67 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage_user.html:11
68 #: guardian/templates/admin/guardian/model/obj_perms_manage.html:12
69 #: guardian/templates/admin/guardian/model/obj_perms_manage_group.html:10
70 #: guardian/templates/admin/guardian/model/obj_perms_manage_user.html:10
71 msgid "Home"
72 msgstr "首页"
73
74 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:33
75 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:94
76 msgid "Please correct the error below."
77 msgid_plural "Please correct the errors below."
78 msgstr[0] "请修复下列错误"
79 msgstr[1] "请修复下列错误"
80
81 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:37
82 #: guardian/templates/admin/guardian/model/obj_perms_manage.html:31
83 msgid "Users"
84 msgstr "用户"
85
86 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:40
87 #: guardian/templates/admin/guardian/model/obj_perms_manage.html:37
88 msgid "User permissions"
89 msgstr "用户权限"
90
91 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:45
92 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage_user.html:49
93 #: guardian/templates/admin/guardian/model/obj_perms_manage.html:40
94 #: guardian/templates/admin/guardian/model/obj_perms_manage_user.html:30
95 msgid "User"
96 msgstr "用户"
97
98 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:49
99 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:110
100 #: guardian/templates/admin/guardian/model/obj_perms_manage.html:44
101 #: guardian/templates/admin/guardian/model/obj_perms_manage.html:98
102 msgid "Action"
103 msgstr "行为"
104
105 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:66
106 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:127
107 #: guardian/templates/admin/guardian/model/obj_perms_manage.html:61
108 #: guardian/templates/admin/guardian/model/obj_perms_manage.html:115
109 msgid "Edit"
110 msgstr "编辑"
111
112 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:82
113 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage_user.html:31
114 #: guardian/templates/admin/guardian/model/obj_perms_manage.html:72
115 #: guardian/templates/admin/guardian/model/obj_perms_manage_user.html:15
116 msgid "Manage user"
117 msgstr "管理用户"
118
119 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:98
120 #: guardian/templates/admin/guardian/model/obj_perms_manage.html:85
121 msgid "Groups"
122 msgstr "组"
123
124 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:101
125 #: guardian/templates/admin/guardian/model/obj_perms_manage.html:91
126 msgid "Group permissions"
127 msgstr "组权限"
128
129 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:106
130 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage_group.html:49
131 #: guardian/templates/admin/guardian/model/obj_perms_manage.html:94
132 #: guardian/templates/admin/guardian/model/obj_perms_manage_group.html:30
133 msgid "Group"
134 msgstr "组"
135
136 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage.html:144
137 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage_group.html:31
138 #: guardian/templates/admin/guardian/model/obj_perms_manage.html:126
139 #: guardian/templates/admin/guardian/model/obj_perms_manage_group.html:15
140 msgid "Manage group"
141 msgstr "管理组"
142
143 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage_group.html:43
144 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage_user.html:43
145 #: guardian/templates/admin/guardian/model/obj_perms_manage_group.html:27
146 #: guardian/templates/admin/guardian/model/obj_perms_manage_user.html:27
147 msgid "Object"
148 msgstr "对象"
149
150 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage_group.html:60
151 #: guardian/templates/admin/guardian/contrib/grappelli/obj_perms_manage_user.html:60
152 #: guardian/templates/admin/guardian/model/obj_perms_manage_group.html:37
153 #: guardian/templates/admin/guardian/model/obj_perms_manage_user.html:37
154 msgid "Save"
155 msgstr "保存"
156
157 #: guardian/templates/admin/guardian/model/obj_perms_manage.html:27
158 #: guardian/templates/admin/guardian/model/obj_perms_manage.html:81
159 msgid "Please correct the errors below."
160 msgstr "请修复下列错误"
0 from __future__ import unicode_literals
1
20 import django
1 from django.contrib.auth import get_user_model
32 from django.db.models import signals
3 from django.utils.module_loading import import_string
44
55 from guardian.conf import settings as guardian_settings
6 from guardian.compat import get_user_model
7 from guardian.compat import import_string
86
97
108 def get_init_anonymous_user(User):
3836
3937 # Only create an anonymous user if support is enabled.
4038 if guardian_settings.ANONYMOUS_USER_NAME is not None:
41 # Django 1.7+ uses post_migrate signal
4239 from django.apps import apps
4340 guardian_app = apps.get_app_config('guardian')
4441 signals.post_migrate.connect(create_anonymous_user, sender=guardian_app,
0 from __future__ import unicode_literals
0 from __future__ import unicode_literals
10 from django.core.management.base import BaseCommand
21
32 from guardian.utils import clean_orphan_obj_perms
0 from __future__ import unicode_literals
10 from django.db import models
21 from django.db.models import Q
32 from guardian.core import ObjectPermissionChecker
7776
7877 return assigned_perms
7978
79 def assign_perm_to_many(self, perm, users_or_groups, obj):
80 """
81 Bulk assigns given ``perm`` for the object ``obj`` to a set of users or a set of groups.
82 """
83 ctype = get_content_type(obj)
84 if not isinstance(perm, Permission):
85 permission = Permission.objects.get(content_type=ctype,
86 codename=perm)
87 else:
88 permission = perm
89
90 kwargs = {'permission': permission}
91 if self.is_generic():
92 kwargs['content_type'] = ctype
93 kwargs['object_pk'] = obj.pk
94 else:
95 kwargs['content_object'] = obj
96
97 to_add = []
98 field = self.user_or_group_field
99 for user in users_or_groups:
100 kwargs[field] = user
101 to_add.append(
102 self.model(**kwargs)
103 )
104
105 return self.model.objects.bulk_create(to_add)
106
80107 def assign(self, perm, user_or_group, obj):
81108 """ Depreciated function name left in for compatibility"""
82109 warnings.warn("UserObjectPermissionManager method 'assign' is being renamed to 'assign_perm'. Update your code accordingly as old name will be depreciated in 2.0 version.", DeprecationWarning)
126153 permission__content_type=ctype)
127154
128155 if self.is_generic():
129 filters &= Q(object_pk__in = [str(pk) for pk in queryset.values_list('pk', flat=True)])
156 filters &= Q(object_pk__in=[str(pk) for pk in queryset.values_list('pk', flat=True)])
130157 else:
131158 filters &= Q(content_object__in=queryset)
132159
0 # -*- coding: utf-8 -*-
1 from __future__ import unicode_literals
2
30 from django.db import models, migrations
41 from django.conf import settings
52
0 from __future__ import unicode_literals
1 from collections import Iterable
0 from collections.abc import Iterable
1
22 from django.conf import settings
33 from django.contrib.auth.decorators import login_required, REDIRECT_FIELD_NAME
44 from django.core.exceptions import ImproperlyConfigured, PermissionDenied
5 from guardian.compat import basestring
65 from guardian.models import UserObjectPermission
76 from guardian.utils import get_40x_or_None, get_anonymous_user
87 from guardian.shortcuts import get_objects_for_user
98
109
11 class LoginRequiredMixin(object):
10 class LoginRequiredMixin:
1211 """
1312 A login required mixin for use with class based views. This Class is a
1413 light wrapper around the `login_required` decorator and hence function
4342 def dispatch(self, request, *args, **kwargs):
4443 return login_required(redirect_field_name=self.redirect_field_name,
4544 login_url=self.login_url)(
46 super(LoginRequiredMixin, self).dispatch
45 super().dispatch
4746 )(request, *args, **kwargs)
4847
4948
50 class PermissionRequiredMixin(object):
49 class PermissionRequiredMixin:
5150 """
5251 A view mixin that verifies if the current logged in user has the specified
5352 permission by wrapping the ``request.user.has_perm(..)`` method.
143142
144143 :param request: Original request.
145144 """
146 if isinstance(self.permission_required, basestring):
145 if isinstance(self.permission_required, str):
147146 perms = [self.permission_required]
148147 elif isinstance(self.permission_required, Iterable):
149148 perms = [p for p in self.permission_required]
203202 response = self.check_permissions(request)
204203 if response:
205204 return response
206 return super(PermissionRequiredMixin, self).dispatch(request, *args,
207 **kwargs)
208
209
210 class GuardianUserMixin(object):
205 return super().dispatch(request, *args, **kwargs)
206
207
208 class GuardianUserMixin:
211209
212210 @staticmethod
213211 def get_anonymous():
220218 return UserObjectPermission.objects.remove_perm(perm, self, obj)
221219
222220
223 class PermissionListMixin(object):
221 class PermissionListMixin:
224222 """
225223 A view mixin that filter object in queryset for the current logged by required permission.
226224
262260
263261 :param request: Original request.
264262 """
265 if isinstance(self.permission_required, basestring):
263 if isinstance(self.permission_required, str):
266264 perms = [self.permission_required]
267265 elif isinstance(self.permission_required, Iterable):
268266 perms = [p for p in self.permission_required]
285283 **self.get_objects_for_user_extra_kwargs)
286284
287285 def get_queryset(self, *args, **kwargs):
288 qs = super(PermissionListMixin, self).get_queryset(*args, **kwargs)
286 qs = super().get_queryset(*args, **kwargs)
289287 return get_objects_for_user(**self.get_get_objects_for_user_kwargs(qs))
0 from __future__ import unicode_literals
10 from django.contrib.auth.models import Group, Permission
1 from django.contrib.contenttypes.fields import GenericForeignKey
22 from django.contrib.contenttypes.models import ContentType
33 from django.core.exceptions import ValidationError
44 from django.db import models
55 from django.utils.translation import ugettext_lazy as _
6 from guardian.compat import unicode, user_model_label
6 from guardian.compat import user_model_label
77 from guardian.ctypes import get_content_type
88 from guardian.managers import GroupObjectPermissionManager, UserObjectPermissionManager
9
10 try:
11 from django.contrib.contenttypes.fields import GenericForeignKey
12 except ImportError:
13 from django.contrib.contenttypes.generic import GenericForeignKey
149
1510
1611 class BaseObjectPermission(models.Model):
2318 class Meta:
2419 abstract = True
2520
26 def __unicode__(self):
21 def __str__(self):
2722 return '%s | %s | %s' % (
28 unicode(self.content_object),
29 unicode(getattr(self, 'user', False) or self.group),
30 unicode(self.permission.codename))
23 str(self.content_object),
24 str(getattr(self, 'user', False) or self.group),
25 str(self.permission.codename))
3126
3227 def save(self, *args, **kwargs):
3328 content_type = get_content_type(self.content_object)
3530 raise ValidationError("Cannot persist permission not designed for "
3631 "this class (permission's type is %r and object's type is %r)"
3732 % (self.permission.content_type, content_type))
38 return super(BaseObjectPermission, self).save(*args, **kwargs)
33 return super().save(*args, **kwargs)
3934
4035
4136 class BaseGenericObjectPermission(models.Model):
00 """
11 Convenient shortcuts to manage or check object permissions.
22 """
3 from __future__ import unicode_literals
4
53 import warnings
64 from collections import defaultdict
75 from itertools import groupby
86
97 from django.apps import apps
8 from django.contrib.auth import get_user_model
109 from django.contrib.auth.models import Group, Permission
1110 from django.contrib.contenttypes.models import ContentType
1211 from django.db.models import Count, Q, QuerySet
1312 from django.shortcuts import _get_queryset
1413
15 from guardian.compat import basestring, get_user_model, is_anonymous
1614 from guardian.core import ObjectPermissionChecker
1715 from guardian.ctypes import get_content_type
18 from guardian.exceptions import MixedContentTypeError, WrongAppError
16 from guardian.exceptions import MixedContentTypeError, WrongAppError, MultipleIdentityAndObjectError
1917 from guardian.models import GroupObjectPermission
2018 from guardian.utils import get_anonymous_user, get_group_obj_perms_model, get_identity, get_user_obj_perms_model
2119
2927 If ``obj`` is not given, must be in format ``app_label.codename`` or
3028 ``Permission`` instance.
3129
32 :param user_or_group: instance of ``User``, ``AnonymousUser`` or ``Group``;
30 :param user_or_group: instance of ``User``, ``AnonymousUser``, ``Group``,
31 list of ``User`` or ``Group``, or queryset of ``User`` or ``Group``;
3332 passing any other object would raise
3433 ``guardian.exceptions.NotUserNorGroup`` exception
3534
6867 <Permission: sites | site | Can change site>
6968
7069 """
71
7270 user, group = get_identity(user_or_group)
7371 # If obj is None we try to operate on global permissions
7472 if obj is None:
9290 perm = perm.split('.')[-1]
9391
9492 if isinstance(obj, QuerySet):
93 if isinstance(user_or_group, (QuerySet, list)):
94 raise MultipleIdentityAndObjectError("Only bulk operations on either users/groups OR objects supported")
9595 if user:
9696 model = get_user_obj_perms_model(obj.model)
9797 return model.objects.bulk_assign_perm(perm, user, obj)
9898 if group:
9999 model = get_group_obj_perms_model(obj.model)
100100 return model.objects.bulk_assign_perm(perm, group, obj)
101
102 if isinstance(user_or_group, (QuerySet, list)):
103 if user:
104 model = get_user_obj_perms_model(obj)
105 return model.objects.assign_perm_to_many(perm, user, obj)
106 if group:
107 model = get_group_obj_perms_model(obj)
108 return model.objects.assign_perm_to_many(perm, group, obj)
101109
102110 if user:
103111 model = get_user_obj_perms_model(obj)
201209 Returns queryset of all Permission objects for the given class. It is
202210 possible to pass Model as class or instance.
203211 """
204 if isinstance(cls, basestring):
212 if isinstance(cls, str):
205213 app_label, model_name = cls.split('.')
206214 model = apps.get_model(app_label, model_name)
207215 else:
211219
212220
213221 def get_users_with_perms(obj, attach_perms=False, with_superusers=False,
214 with_group_users=True):
222 with_group_users=True, only_with_perms_in=None):
215223 """
216224 Returns queryset of all ``User`` objects with *any* object permissions for
217225 the given ``obj``.
228236 :param with_group_users: Default: ``True``. If set to ``False`` result would
229237 **not** contain those users who have only group permissions for given
230238 ``obj``.
239
240 :param only_with_perms_in: Default: ``None``. If set to an iterable of
241 permission strings then only users with those permissions would be
242 returned.
231243
232244 Example::
233245
237249 >>>
238250 >>> page = FlatPage.objects.create(title='Some page', path='/some/page/')
239251 >>> joe = User.objects.create_user('joe', 'joe@example.com', 'joesecret')
252 >>> dan = User.objects.create_user('dan', 'dan@example.com', 'dansecret')
240253 >>> assign_perm('change_flatpage', joe, page)
254 >>> assign_perm('delete_flatpage', dan, page)
241255 >>>
242256 >>> get_users_with_perms(page)
243 [<User: joe>]
257 [<User: joe>, <User: dan>]
244258 >>>
245259 >>> get_users_with_perms(page, attach_perms=True)
246 {<User: joe>: [u'change_flatpage']}
260 {<User: joe>: [u'change_flatpage'], <User: dan>: [u'delete_flatpage']}
261 >>> get_users_with_perms(page, only_with_perms_in=['change_flatpage'])
262 [<User: joe>]
247263
248264 """
249265 ctype = get_content_type(obj)
260276 else:
261277 user_filters = {'%s__content_object' % related_name: obj}
262278 qset = Q(**user_filters)
279 if only_with_perms_in is not None:
280 permission_ids = Permission.objects.filter(content_type=ctype, codename__in=only_with_perms_in).values_list('id', flat=True)
281 qset &= Q(**{
282 '%s__permission_id__in' % related_name: permission_ids,
283 })
263284 if with_group_users:
264285 group_model = get_group_obj_perms_model(obj)
265286 group_rel_name = group_model.group.field.related_query_name()
272293 group_filters = {
273294 'groups__%s__content_object' % group_rel_name: obj,
274295 }
296 if only_with_perms_in is not None:
297 group_filters.update({
298 'groups__%s__permission_id__in' % group_rel_name: permission_ids,
299 })
275300 qset = qset | Q(**group_filters)
276301 if with_superusers:
277302 qset = qset | Q(is_superuser=True)
281306 users = {}
282307 for user in get_users_with_perms(obj,
283308 with_group_users=with_group_users,
309 only_with_perms_in=only_with_perms_in,
284310 with_superusers=with_superusers):
285311 # TODO: Support the case of set with_group_users but not with_superusers.
286312 if with_group_users or with_superusers:
337363 groups_with_perms = get_groups_with_perms(obj)
338364 qs = group_model.objects.filter(group__in=groups_with_perms).prefetch_related('group', 'permission')
339365 if group_model is GroupObjectPermission:
340 qs = qs.filter(object_pk=obj.pk)
366 qs = qs.filter(object_pk=obj.pk, content_type=ctype)
341367 else:
342368 qs = qs.filter(content_object_id=obj.pk)
343369
447473 - If accept_global_perms is ``True``: Empty list.
448474 - If accept_global_perms is ``False``: Empty list.
449475 """
450 if isinstance(perms, basestring):
476 if isinstance(perms, str):
451477 perms = [perms]
452478 ctype = None
453479 app_label = None
499525 # Check if the user is anonymous. The
500526 # django.contrib.auth.models.AnonymousUser object doesn't work for queries
501527 # and it's nice to be able to pass in request.user blindly.
502 if is_anonymous(user):
528 if user.is_anonymous:
503529 user = get_anonymous_user()
504530
505531 global_perms = set()
650676 [<Task some task>]
651677
652678 """
653 if isinstance(perms, basestring):
679 if isinstance(perms, str):
654680 perms = [perms]
655681 ctype = None
656682 app_label = None
3838 <div class="l-2c-fluid l-d-4">
3939 <div class="c-1"><label for="user-permissions" class="required">{% trans "User permissions" %}</label></div>
4040 <div class="c-2">
41 <table id="user-permissions" class="object-perms">
41 <table id="user-permissions" class="grp-table object-perms">
4242 <thead>
4343 <tr>
4444 <th>{% trans "User" %}</th>
9999 <div class="l-2c-fluid l-d-4">
100100 <div class="c-1"><label for="group-permissions" class="required">{% trans "Group permissions" %}</label></div>
101101 <div class="c-2">
102 <table id="group-permissions" class="object-perms">
102 <table id="group-permissions" class="grp-table object-perms">
103103 <thead>
104104 <tr>
105105 <th>{% trans "Group" %}</th>
147147 </fieldset>
148148 </div>
149149 </form>
150 {% endblock %}
150 {% endblock %}
99 {% block breadcrumbs %}{% if not is_popup %}
1010 <div class="breadcrumbs">
1111 <a href="../../../../">{% trans "Home" %}</a> &rsaquo;
12 <a href="../../../">{{ app_label|capfirst|escape }}</a> &rsaquo;
13 {% if has_change_permission %}<a href="../../">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %} &rsaquo;
12 <a href="../../../">{{ opts.app_config.verbose_name|capfirst|escape }}</a> &rsaquo;
13 {% if has_change_permission %}<a href="../../">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %} &rsaquo;
1414 {% if has_change_permission %}<a href="../">{{ original|truncatewords:"18" }}</a>{% else %}{{ original|truncatewords:"18" }}{% endif %} &rsaquo;
1515 {% trans "Object permissions" %}
1616 </div>
9494 {% for perm in model_perms %}
9595 <th>{{ perm.name }}</th>
9696 {% endfor %}
97 <th>{% trans "Action" %}</th>
97 <th>{% trans "Action" %}</th>
9898 </tr>
9999 </thead>
100100 <tbody>
112112 {% endfor %}
113113 <td>
114114 <a href="group-manage/{{ group.id|safe }}/">{% trans "Edit" %}</a>
115 </td>
115 </td>
116116 </tr>
117117 {% endfor %}
118118 </tbody>
77 {% block breadcrumbs %}{% if not is_popup %}
88 <div class="breadcrumbs">
99 <a href="../../../../../../">{% trans "Home" %}</a> &rsaquo;
10 <a href="../../../../../">{{ app_label|capfirst|escape }}</a> &rsaquo;
11 {% if has_change_permission %}<a href="../../../../">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %} &rsaquo;
10 <a href="../../../../../">{{ opts.app_config.verbose_name|capfirst|escape }}</a> &rsaquo;
11 {% if has_change_permission %}<a href="../../../../">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %} &rsaquo;
1212 {% if has_change_permission %}<a href="../../../">{{ original|truncatewords:"18" }}</a>{% else %}{{ original|truncatewords:"18" }}{% endif %} &rsaquo;
1313 {% if has_change_permission %}<a href="../../">{% trans "Object permissions" %}</a>{% else %}{% trans "Object permissions" %}{% endif %} &rsaquo;
1414 {% trans "Manage group" %}: {{ group_obj|truncatewords:"18" }}
77 {% block breadcrumbs %}{% if not is_popup %}
88 <div class="breadcrumbs">
99 <a href="../../../../../../">{% trans "Home" %}</a> &rsaquo;
10 <a href="../../../../../">{{ app_label|capfirst|escape }}</a> &rsaquo;
11 {% if has_change_permission %}<a href="../../../../">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %} &rsaquo;
10 <a href="../../../../../">{{ opts.app_config.verbose_name|capfirst|escape }}</a> &rsaquo;
11 {% if has_change_permission %}<a href="../../../../">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %} &rsaquo;
1212 {% if has_change_permission %}<a href="../../../">{{ original|truncatewords:"18" }}</a>{% else %}{{ original|truncatewords:"18" }}{% endif %} &rsaquo;
1313 {% if has_change_permission %}<a href="../../">{% trans "Object permissions" %}</a>{% else %}{% trans "Object permissions" %}{% endif %} &rsaquo;
1414 {% trans "Manage user" %}: {{ user_obj|truncatewords:"18" }}
0 from __future__ import unicode_literals
44 {% load guardian_tags %}
55
66 """
7 from __future__ import unicode_literals
8
97 from django import template
8 from django.contrib.auth import get_user_model
109 from django.contrib.auth.models import AnonymousUser, Group
1110
12 from guardian.compat import get_user_model
1311 from guardian.core import ObjectPermissionChecker
1412 from guardian.exceptions import NotUserNorGroup
1513
4139 obj = self.obj.resolve(context)
4240 if not obj:
4341 return ''
44
42
4543 check = self.checker.resolve(context) if self.checker else ObjectPermissionChecker(for_whom)
4644 perms = check.get_perms(obj)
4745
0 from __future__ import unicode_literals
0 # -*- coding: utf-8 -*-
10 # Generated by Django 1.9.9 on 2016-09-18 17:52
2 from __future__ import unicode_literals
3
41 import datetime
52 from django.conf import settings
63 import django.contrib.auth.models
0 # -*- coding: utf-8 -*-
10 # Generated by Django 1.9.9 on 2016-09-18 17:52
2 from __future__ import unicode_literals
3
41 from django.db import migrations, models
52 import django.db.models.deletion
63
0 # Generated by Django 2.2.2 on 2019-06-11 04:40
1
2 import django.contrib.auth.validators
3 from django.db import migrations, models
4
5
6 class Migration(migrations.Migration):
7
8 dependencies = [
9 ('testapp', '0002_logentrywithgroup'),
10 ]
11
12 operations = [
13 migrations.AlterField(
14 model_name='customuser',
15 name='last_name',
16 field=models.CharField(blank=True, max_length=150, verbose_name='last name'),
17 ),
18 migrations.AlterField(
19 model_name='customuser',
20 name='username',
21 field=models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username'),
22 ),
23 ]
0 from __future__ import unicode_literals
10 from datetime import datetime
21
32 from django.db import models
43 from django.contrib.admin.models import LogEntry
54 from django.contrib.auth.models import AbstractUser, AbstractBaseUser
6 from django.utils.encoding import python_2_unicode_compatible
75
86 from guardian.mixins import GuardianUserMixin
97 from guardian.models import UserObjectPermissionBase
108 from guardian.models import GroupObjectPermissionBase
119
1210
13 @python_2_unicode_compatible
1411 class Post(models.Model):
1512 title = models.CharField('title', max_length=64)
1613
1815 return self.title
1916
2017
21 class DynamicAccessor(object):
18 class DynamicAccessor:
2219
2320 def __init__(self):
2421 pass
5350 content_object = models.ForeignKey('Mixed', on_delete=models.CASCADE)
5451
5552
56 @python_2_unicode_compatible
5753 class Mixed(models.Model):
5854 """
5955 Model for tests obj perms checks with generic user object permissions model
6965 content_object = models.ForeignKey('ReverseMixed', on_delete=models.CASCADE)
7066
7167
72 @python_2_unicode_compatible
7368 class ReverseMixed(models.Model):
7469 """
7570 Model for tests obj perms checks with generic group object permissions model
0 from __future__ import unicode_literals
0 from __future__ import unicode_literals
1 import os
20 import unittest
3 from guardian.utils import abspath
41 from guardian.conf import settings as guardian_settings
52 from django.conf import settings
63 from django.conf import UserSettingsHolder
74 from django.utils.functional import wraps
8
9
10 THIS = abspath(os.path.dirname(__file__))
11 TEST_TEMPLATES_DIR = abspath(THIS, 'templates')
12
13
14 TEST_SETTINGS = dict(
15 TEMPLATE_DIRS=[TEST_TEMPLATES_DIR],
16 )
175
186
197 def skipUnlessTestApp(obj):
2210 'app %r must be installed to run this test' % app)(obj)
2311
2412
25 class TestDataMixin(object):
13 class TestDataMixin:
2614
2715 def setUp(self):
28 super(TestDataMixin, self).setUp()
16 super().setUp()
2917 from django.contrib.auth.models import Group
30 try:
31 from django.contrib.auth import get_user_model
32 User = get_user_model()
33 except ImportError:
34 from django.contrib.auth.models import User
18 from django.contrib.auth import get_user_model
19 User = get_user_model()
3520 Group.objects.create(pk=1, name='admins')
3621 jack_group = Group.objects.create(pk=2, name='jackGroup')
3722 User.objects.get_or_create(username=guardian_settings.ANONYMOUS_USER_NAME)
4025 jack.groups.add(jack_group)
4126
4227
43 class override_settings(object):
28 class override_settings:
4429 """
4530 Acts as either a decorator, or a context manager. If it's a decorator it
4631 takes a function and returns a wrapped function. If it's a contextmanager
0 from __future__ import unicode_literals
10 import copy
21
32 from django import forms
43 from django.conf import settings
54 from django.contrib import admin
5 from django.contrib.auth import get_user_model
66 from django.contrib.contenttypes.models import ContentType
77 from django.http import HttpRequest
88 from django.test import TestCase
99 from django.test.client import Client
10 from django.urls import reverse
1011
1112 from guardian.admin import GuardedModelAdmin
12 from guardian.compat import get_user_model, get_model_name
13 from guardian.compat import reverse
14 from guardian.compat import str
1513 from guardian.shortcuts import get_perms
1614 from guardian.shortcuts import get_perms_for_model
17 from guardian.testapp.tests.conf import TEST_SETTINGS
18 from guardian.testapp.tests.conf import override_settings
1915 from guardian.models import Group
2016 from guardian.testapp.tests.conf import skipUnlessTestApp
2117 from guardian.testapp.models import LogEntryWithGroup as LogEntry
3329 admin.site.register(ContentType, ContentTypeGuardedAdmin)
3430
3531
36 @override_settings(**TEST_SETTINGS)
3732 class AdminTests(TestCase):
3833
3934 def setUp(self):
4439 self.client = Client()
4540 self.obj = ContentType.objects.create(
4641 model='bar', app_label='fake-for-guardian-tests')
47 self.obj_info = self.obj._meta.app_label, get_model_name(self.obj)
42 self.obj_info = self.obj._meta.app_label, self.obj._meta.model_name
4843
4944 def tearDown(self):
5045 self.client.logout()
0 from __future__ import unicode_literals
10 from django.core.exceptions import ImproperlyConfigured
21 from django.test import TestCase
32 import mock
0 from __future__ import unicode_literals
10 from itertools import chain
21
32 from django.conf import settings
43 from guardian.conf import settings as guardian_settings
5 # Try the new app settings (Django 1.7) and fall back to the old system
6 try:
7 from django.apps import apps as django_apps
8 auth_app = django_apps.get_app_config("auth")
9 except ImportError:
10 from django.contrib.auth import models as auth_app
4 from django.apps import apps as django_apps
5 from django.contrib.auth import get_user_model
6 from django.contrib.auth.management import create_permissions
117 from django.contrib.auth.models import Group, Permission, AnonymousUser
128 from django.contrib.contenttypes.models import ContentType
139 from django.test import TestCase
1410
1511 from guardian.core import ObjectPermissionChecker
16 from guardian.compat import get_user_model, create_permissions
1712 from guardian.exceptions import NotUserNorGroup
1813 from guardian.models import UserObjectPermission, GroupObjectPermission
1914 from guardian.shortcuts import assign_perm
2116
2217 from guardian.testapp.models import Project
2318
19 auth_app = django_apps.get_app_config('auth')
2420 User = get_user_model()
2521
2622
5652 class ObjectPermissionCheckerTest(ObjectPermissionTestCase):
5753
5854 def setUp(self):
59 super(ObjectPermissionCheckerTest, self).setUp()
55 super().setUp()
6056 # Required if MySQL backend is used :/
61 create_permissions(auth_app, [], 1)
57 create_permissions(auth_app, 1)
6258
6359 def test_cache_for_queries_count(self):
6460 settings.DEBUG = True
0 from __future__ import unicode_literals
0 from django.contrib.auth import get_user_model
11 from django.contrib.contenttypes.models import ContentType
22 from django.test import TestCase
33
4 from guardian.compat import get_user_model
54 from guardian.shortcuts import assign_perm, remove_perm
65
76
0 from __future__ import unicode_literals
1 from django.conf import settings, global_settings
0 from django.conf import global_settings
1 from django.contrib.auth import get_user_model
22 from django.contrib.auth.models import Group, AnonymousUser
33 from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
44 from django.db.models.base import ModelBase
1111 from django.template import TemplateDoesNotExist
1212 from django.test import TestCase
1313
14 from guardian.compat import get_user_model
1514 from guardian.compat import get_user_model_path
1615 from guardian.compat import get_user_permission_full_codename
1716 import mock
1918 from guardian.exceptions import GuardianError
2019 from guardian.exceptions import WrongAppError
2120 from guardian.shortcuts import assign_perm
22 from guardian.testapp.tests.conf import TEST_SETTINGS
2321 from guardian.testapp.tests.conf import TestDataMixin
2422 from guardian.testapp.tests.conf import override_settings
2523 from guardian.testapp.tests.conf import skipUnlessTestApp
26 from django import get_version as django_get_version
2724
2825 User = get_user_model()
2926 user_model_path = get_user_model_path()
3027
3128
32 @override_settings(**TEST_SETTINGS)
3329 @skipUnlessTestApp
3430 class PermissionRequiredTest(TestDataMixin, TestCase):
3531
3632 def setUp(self):
37 super(PermissionRequiredTest, self).setUp()
33 super().setUp()
3834 self.anon = AnonymousUser()
3935 self.user = User.objects.get_or_create(username='jack')[0]
4036 self.group = Group.objects.get_or_create(name='jackGroup')[0]
393389 def test_redirection_class(self):
394390 view_url = '/permission_required/'
395391
396 if django_get_version() < "1.5":
397 # skip this test for django versions < 1.5
398 return
399
400392 response = self.client.get(view_url)
401393 # this should be '/account/login'
402394 self.assertRedirects(
0 from __future__ import unicode_literals
1
0 from django.contrib.auth import get_user_model
21 from django.contrib.auth.models import Group, Permission
32 from django.test import TestCase
43
5 from guardian.compat import get_user_model
64 from guardian.shortcuts import assign_perm
75 from guardian.shortcuts import get_groups_with_perms
86 from guardian.shortcuts import get_objects_for_group
0 from __future__ import unicode_literals
1
0 from django.contrib.auth import get_user_model
21 from django.contrib.contenttypes.models import ContentType
32 from django.test import TestCase
4 from guardian.compat import get_user_model
53 from guardian.forms import BaseObjectPermissionsForm
64
75
1917
2018 def __init__(formself, user, *args, **kwargs):
2119 self.user = user
22 super(MyUserObjectPermissionsForm, formself).__init__(*args,
23 **kwargs)
20 super().__init__(*args, **kwargs)
2421
2522 form = MyUserObjectPermissionsForm(self.user, self.obj, {})
2623 self.assertRaises(NotImplementedError, form.save_obj_perms)
0 from __future__ import absolute_import
1 from __future__ import unicode_literals
0 from django.contrib.auth import get_user_model
21 from django.test import TestCase, override_settings
32
4 from guardian.compat import get_user_model
53 import mock
64 from guardian.management import create_anonymous_user
75 from guardian.utils import get_anonymous_user
0 from __future__ import unicode_literals
0 import warnings
1
2 import mock
13 from django.test import TestCase
2 import mock
3 import warnings
44 from guardian.managers import UserObjectPermissionManager
55 from guardian.managers import GroupObjectPermissionManager
66
0 from __future__ import unicode_literals
1
0 from django.contrib.auth import get_user_model
21 from django.contrib.auth.models import AnonymousUser
32 from django.core.exceptions import ImproperlyConfigured
43 from django.core.exceptions import PermissionDenied
98 from django.views.generic import ListView
109
1110 from guardian.shortcuts import assign_perm
12 from guardian.compat import get_user_model
1311 import mock
1412 from guardian.mixins import LoginRequiredMixin
1513 from guardian.mixins import PermissionRequiredMixin
0 from __future__ import unicode_literals
1
20 from django.apps import apps as django_apps
31 auth_app = django_apps.get_app_config("auth")
42
3 from django.contrib.auth import get_user_model
4 from django.contrib.auth.management import create_permissions
55 from django.contrib.contenttypes.models import ContentType
66 from django.core.management import call_command
77 from django.test import TestCase
88
9 from guardian.compat import get_user_model, create_permissions, get_model_name
109 from guardian.utils import clean_orphan_obj_perms
1110 from guardian.shortcuts import assign_perm
1211 from guardian.models import Group
1413
1514
1615 User = get_user_model()
17 user_module_name = get_model_name(User)
16 user_module_name = User._meta.model_name
1817
1918
2019 @skipUnlessTestApp
2928 self.target_obj2 = ContentType.objects.create(
3029 model='bar', app_label='fake-for-guardian-tests')
3130 # Required if MySQL backend is used :/
32 create_permissions(auth_app, [], 1)
31 create_permissions(auth_app, 1)
3332
3433 self.user = User.objects.create(username='user')
3534 self.group = Group.objects.create(name='group')
0 from __future__ import unicode_literals
1
20 import mock
31 import unittest
42
3 from django.contrib.auth import get_user_model
4 from django.contrib.auth.models import AbstractUser
55 from django.contrib.auth.models import AnonymousUser
66 from django.contrib.auth.models import Group
77 from django.contrib.auth.models import Permission
1111
1212 import guardian
1313 from guardian.backends import ObjectPermissionBackend
14 from guardian.compat import get_user_model
1514 from guardian.compat import get_user_model_path
1615 from guardian.compat import get_user_permission_codename
17 from guardian.compat import basestring
18 from guardian.compat import unicode
1916 from guardian.exceptions import GuardianError
2017 from guardian.exceptions import NotUserNorGroup
2118 from guardian.exceptions import ObjectNotPersisted
3027 class UserPermissionTests(TestDataMixin, TestCase):
3128
3229 def setUp(self):
33 super(UserPermissionTests, self).setUp()
30 super().setUp()
3431 self.user = User.objects.get(username='jack')
3532 self.ctype = ContentType.objects.create(
3633 model='bar', app_label='fake-for-guardian-tests')
105102 self.assertRaises(ValidationError, UserObjectPermission.objects.create,
106103 **create_info)
107104
108 def test_unicode(self):
109 codename = get_user_permission_codename('change')
110 obj_perm = UserObjectPermission.objects.assign_perm(codename,
111 self.user, self.user)
112 self.assertTrue(isinstance(obj_perm.__unicode__(), unicode))
113
114105 def test_errors(self):
115106 not_saved_user = User(username='not_saved_user')
116107 codename = get_user_permission_codename('change')
125116 class GroupPermissionTests(TestDataMixin, TestCase):
126117
127118 def setUp(self):
128 super(GroupPermissionTests, self).setUp()
119 super().setUp()
129120 self.user = User.objects.get(username='jack')
130121 self.group, created = Group.objects.get_or_create(name='jackGroup')
131122 self.user.groups.add(self.group)
200191 )
201192 self.assertRaises(ValidationError, GroupObjectPermission.objects.create,
202193 **create_info)
203
204 def test_unicode(self):
205 obj_perm = GroupObjectPermission.objects.assign_perm("change_group",
206 self.group, self.group)
207 self.assertTrue(isinstance(obj_perm.__unicode__(), unicode))
208194
209195 def test_errors(self):
210196 not_saved_group = Group(name='not_saved_group')
267253
268254 def test_version(self):
269255 for x in guardian.VERSION:
270 self.assertTrue(isinstance(x, (int, basestring)))
256 self.assertTrue(isinstance(x, (int, str)))
271257
272258 def test_get_version(self):
273 self.assertTrue(isinstance(guardian.get_version(), basestring))
259 self.assertTrue(isinstance(guardian.get_version(), str))
274260
275261
276262 class TestExceptions(TestCase):
288274 @unittest.skip("test is broken")
289275 class TestMonkeyPatch(TestCase):
290276
291 @mock.patch('guardian.compat.get_user_model')
277 @mock.patch('django.contrib.auth.get_user_model')
292278 def test_monkey_patch(self, mocked_get_user_model):
293 # Import AbstractUser here as it is only available since Django 1.5
294 from django.contrib.auth.models import AbstractUser
295279
296280 class CustomUserTestClass(AbstractUser):
297281 pass
0 from __future__ import unicode_literals
1
0 import warnings
1
2 import django
3 from django.contrib.auth import get_user_model
24 from django.contrib.auth.models import AnonymousUser
35 from django.contrib.contenttypes.models import ContentType
46 from django.db.models.query import QuerySet
68
79 from guardian.shortcuts import get_perms_for_model
810 from guardian.core import ObjectPermissionChecker
9 from guardian.compat import get_user_model
10 from guardian.compat import get_user_permission_full_codename, get_model_name
11 from guardian.compat import get_user_permission_full_codename
1112 from guardian.shortcuts import assign
1213 from guardian.shortcuts import assign_perm
1314 from guardian.shortcuts import remove_perm
2122 from guardian.exceptions import MixedContentTypeError
2223 from guardian.exceptions import NotUserNorGroup
2324 from guardian.exceptions import WrongAppError
25 from guardian.exceptions import MultipleIdentityAndObjectError
2426 from guardian.testapp.models import NonIntPKModel
2527 from guardian.testapp.tests.test_core import ObjectPermissionTestCase
2628 from guardian.models import Group, Permission
2729
28 import warnings
29
3030
3131 User = get_user_model()
3232 user_app_label = User._meta.app_label
33 user_module_name = get_model_name(User)
33 user_module_name = User._meta.model_name
3434
3535
3636 class ShortcutsTests(ObjectPermissionTestCase):
3737
3838 def test_get_perms_for_model(self):
39 self.assertEqual(get_perms_for_model(self.user).count(), 3)
39 expected_perms_amount = 3 if django.VERSION < (2, 1) else 4
40 self.assertEqual(get_perms_for_model(self.user).count(), expected_perms_amount)
4041 self.assertTrue(list(get_perms_for_model(self.user)) ==
4142 list(get_perms_for_model(User)))
42 self.assertEqual(get_perms_for_model(Permission).count(), 3)
43 self.assertEqual(get_perms_for_model(Permission).count(), expected_perms_amount)
4344
4445 model_str = 'contenttypes.ContentType'
4546 self.assertEqual(
124125 self.assertTrue(isinstance(warns[0].message, DeprecationWarning))
125126
126127
128 class MultipleIdentitiesOperationsTest(ObjectPermissionTestCase):
129 """
130 Tests assignment of permission to multiple users or groups
131 """
132 def setUp(self):
133 super().setUp()
134 self.users_list = jim, bob = [
135 User.objects.create_user(username='jim'),
136 User.objects.create_user(username='bob')
137 ]
138 self.groups_list = jim_group, bob_group = [
139 Group.objects.create(name='jimgroup'),
140 Group.objects.create(name='bobgroup')
141 ]
142 jim_group.user_set.add(jim)
143 bob_group.user_set.add(bob)
144 self.users_qs = User.objects.exclude(username='AnonymousUser')
145 self.groups_qs = Group.objects.all()
146
147 def test_assign_to_many_users_queryset(self):
148 assign_perm("add_contenttype", self.users_qs, self.ctype)
149 assign_perm(self.get_permission("delete_contenttype"), self.users_qs, self.ctype)
150 for user in self.users_list:
151 self.assertTrue(user.has_perm("add_contenttype", self.ctype))
152 self.assertTrue(user.has_perm("delete_contenttype", self.ctype))
153
154 def test_assign_to_many_users_list(self):
155 assign_perm("add_contenttype", self.users_list, self.ctype)
156 assign_perm(self.get_permission("delete_contenttype"), self.users_list, self.ctype)
157 for user in self.users_list:
158 self.assertTrue(user.has_perm("add_contenttype", self.ctype))
159 self.assertTrue(user.has_perm("delete_contenttype", self.ctype))
160
161 def test_assign_to_many_groups_queryset(self):
162 assign_perm("add_contenttype", self.groups_qs, self.ctype)
163 assign_perm(self.get_permission("delete_contenttype"), self.groups_qs, self.ctype)
164 for user in self.users_list:
165 self.assertTrue(user.has_perm("add_contenttype", self.ctype))
166 self.assertTrue(user.has_perm("delete_contenttype", self.ctype))
167
168 def test_assign_to_many_groups_list(self):
169 assign_perm("add_contenttype", self.groups_list, self.ctype)
170 assign_perm(self.get_permission("delete_contenttype"), self.groups_list, self.ctype)
171 for user in self.users_list:
172 self.assertTrue(user.has_perm("add_contenttype", self.ctype))
173 self.assertTrue(user.has_perm("delete_contenttype", self.ctype))
174
175 def test_assign_to_multiple_identity_and_obj(self):
176 with self.assertRaises(MultipleIdentityAndObjectError):
177 assign_perm("add_contenttype", self.users_list, self.ctype_qset)
178 with self.assertRaises(MultipleIdentityAndObjectError):
179 assign_perm("add_contenttype", self.users_qs, self.ctype_qset)
180
181
127182 class RemovePermTest(ObjectPermissionTestCase):
128183 """
129184 Tests object permissions removal.
164219 assign_perm("change_contenttype", self.user, self.ctype_qset)
165220 remove_perm("change_contenttype", self.user, self.ctype_qset.none())
166221
167 self.assertEquals(list(self.ctype_qset.none()), [])
222 self.assertEqual(list(self.ctype_qset.none()), [])
168223 for obj in self.ctype_qset:
169224 self.assertTrue(self.user.has_perm("change_contenttype", obj))
170225
254309 set(result_vals),
255310 set([user.username for user in (self.user1, self.user2)]),
256311 )
312
313 def test_only_with_perms_in(self):
314 assign_perm("change_contenttype", self.user1, self.obj1)
315 assign_perm("delete_contenttype", self.user2, self.obj1)
316 assign_perm("delete_contenttype", self.user3, self.obj2)
317
318 result = get_users_with_perms(self.obj1, only_with_perms_in=('change_contenttype',))
319 result_vals = result.values_list('username', flat=True)
320
321 self.assertEqual(
322 set(result_vals),
323 set((self.user1.username,)),
324 )
325
326 def test_only_with_perms_in_and_with_group_users(self):
327 self.user1.groups.add(self.group1)
328 self.user2.groups.add(self.group2)
329 self.user3.groups.add(self.group3)
330
331 # assign perms to groups
332 assign_perm("change_contenttype", self.group1, self.obj1)
333 assign_perm("delete_contenttype", self.group2, self.obj1)
334 assign_perm("add_contenttype", self.group3, self.obj2)
335
336 result = get_users_with_perms(self.obj1, only_with_perms_in=('change_contenttype', 'delete_contenttype'), with_group_users=True)
337 result_vals = result.values_list('username', flat=True)
338
339 self.assertEqual(
340 set(result_vals),
341 set((self.user1.username, self.user2.username)),
342 )
343
344 def test_only_with_perms_in_and_not_with_group_users(self):
345 self.user1.groups.add(self.group1)
346 self.user2.groups.add(self.group2)
347 self.user3.groups.add(self.group3)
348
349 # assign perms to groups
350 assign_perm("change_contenttype", self.group1, self.obj1)
351 assign_perm("delete_contenttype", self.group2, self.obj1)
352 assign_perm("delete_contenttype", self.group3, self.obj2)
353
354 # assign perms to user
355 assign_perm("change_contenttype", self.user2, self.obj1)
356
357 result = get_users_with_perms(self.obj1, only_with_perms_in=('change_contenttype', 'delete_contenttype'), with_group_users=False)
358 result_vals = result.values_list('username', flat=True)
359
360 self.assertEqual(
361 set(result_vals),
362 set((self.user2.username,)),
363 )
364
365 def test_only_with_perms_in_attached(self):
366 assign_perm("change_contenttype", self.user1, self.obj1)
367 assign_perm("change_contenttype", self.user2, self.obj1)
368 assign_perm("delete_contenttype", self.user2, self.obj1)
369 assign_perm("delete_contenttype", self.user3, self.obj2)
370
371 result = get_users_with_perms(self.obj1, only_with_perms_in=('delete_contenttype',),
372 attach_perms=True)
373
374 expected = {self.user2: ('change_contenttype', 'delete_contenttype')}
375 self.assertEqual(result.keys(), expected.keys())
376 for key, perms in result.items():
377 self.assertEqual(set(perms), set(expected[key]))
257378
258379 def test_users_groups_perms(self):
259380 self.user1.groups.add(self.group1)
384505 self.assertEqual(set(get_group_perms(self.group1, self.obj1)), set(['delete_contenttype']))
385506 self.assertEqual(set(get_group_perms(self.group2, self.obj1)), set([]))
386507 self.assertEqual(set(get_group_perms(admin, self.obj1)), set([]))
387 self.assertEqual(set(get_perms(admin, self.obj1)), set(['add_contenttype', 'change_contenttype', 'delete_contenttype']))
508 expected_permissions = ['add_contenttype', 'change_contenttype', 'delete_contenttype']
509 if django.VERSION >= (2, 1):
510 expected_permissions.append('view_contenttype')
511 self.assertEqual(set(get_perms(admin, self.obj1)), set(expected_permissions))
388512 self.assertEqual(set(get_perms(self.user1, self.obj1)), set(['change_contenttype', 'delete_contenttype']))
389513 self.assertEqual(set(get_perms(self.user2, self.obj1)), set(['delete_contenttype']))
390514 self.assertEqual(set(get_perms(self.group1, self.obj1)), set(['delete_contenttype']))
402526 admin: ["add_contenttype", "change_contenttype", "delete_contenttype"],
403527 self.user2: ["delete_contenttype"]
404528 }
529 if django.VERSION >= (2, 1):
530 expected[admin].append("view_contenttype")
405531 result = get_users_with_perms(self.obj1, attach_perms=True,
406532 with_superusers=False, with_group_users=True)
407533 self.assertEqual(result.keys(), expected.keys())
480606 remove_perm("change_contenttype", self.group1, self.obj1)
481607 result = get_groups_with_perms(self.obj1, attach_perms=True)
482608 self.assertEqual(len(result), 0)
609
610 def test_filter_by_contenttype(self):
611 # Make sure that both objects have same pk.
612 obj = ContentType.objects.create(pk=1042, model='baz', app_label='guardian-tests')
613 group = Group.objects.create(pk=1042, name='group')
614
615 assign_perm("change_group", self.group1, group)
616 assign_perm("change_contenttype", self.group1, obj)
617
618 result = get_groups_with_perms(obj, attach_perms=True)
619 # No group permissions should be included, even though objects have same pk.
620 self.assertEqual(result[self.group1], ["change_contenttype"])
483621
484622 def test_mixed(self):
485623 assign_perm("change_contenttype", self.group1, self.obj1)
10621200
10631201 objects = get_objects_for_group(
10641202 self.group1, ['contenttypes.change_contenttype'])
1065 self.assertEquals(set(objects),
1203 self.assertEqual(set(objects),
10661204 set(ContentType.objects.all()))
10671205
10681206 def test_has_global_permission_and_object_based_permission(self):
10711209
10721210 objects = get_objects_for_group(self.group1, [
10731211 'contenttypes.change_contenttype', 'contenttypes.delete_contenttype'], any_perm=False)
1074 self.assertEquals(set(objects),
1212 self.assertEqual(set(objects),
10751213 set([self.obj1]))
10761214
10771215 def test_has_global_permission_and_object_based_permission_any_perm(self):
10801218
10811219 objects = get_objects_for_group(self.group1, [
10821220 'contenttypes.change_contenttype', 'contenttypes.delete_contenttype'], any_perm=True)
1083 self.assertEquals(set(objects),
1221 self.assertEqual(set(objects),
10841222 set(ContentType.objects.all()))
10851223
10861224 def test_has_global_permission_and_object_based_permission_3perms(self):
10891227 assign_perm('contenttypes.add_contenttype', self.group1, self.obj2)
10901228
10911229 objects = get_objects_for_group(self.group1, [
1092 'contenttypes.change_contenttype', 'contenttypes.delete_contenttype', 'contenttypes.add_contenttype'], any_perm=False)
1093 self.assertEquals(set(objects),
1230 'contenttypes.change_contenttype', 'contenttypes.delete_contenttype', 'contenttypes.add_contenttype'], any_perm=False)
1231 self.assertEqual(set(objects),
10941232 set())
10951233
10961234 def test_exception_different_ctypes(self):
0 from __future__ import unicode_literals
1
0 from django.conf import settings
1 from django.contrib.auth import get_user_model
22 from django.contrib.auth.models import Group, AnonymousUser
33 from django.contrib.contenttypes.models import ContentType
44 from django.template import Template, Context, TemplateSyntaxError
55 from django.test import TestCase
66
7 from guardian.compat import get_user_model, template_debug_getter, template_debug_setter
87 from guardian.core import ObjectPermissionChecker
98 from guardian.exceptions import NotUserNorGroup
109 from guardian.models import UserObjectPermission, GroupObjectPermission
8180 ))
8281 context = {'some_obj': ContentType(), 'contenttype': self.ctype}
8382 # This test would raise TemplateSyntaxError instead of NotUserNorGroup
84 # if TEMPLATE_DEBUG is set to True during tests
85 tmp = template_debug_getter()
86 template_debug_setter(False)
83 # if the template option 'debug' is set to True during tests.
84 template_options = settings.TEMPLATES[0]['OPTIONS']
85 tmp = template_options.get('debug', False)
86 template_options['debug'] = False
8787 self.assertRaises(NotUserNorGroup, render, template, context)
88 template_debug_setter(tmp)
88 template_options['debug'] = tmp
8989
9090 def test_superuser(self):
9191 user = User.objects.create(username='superuser', is_superuser=True)
131131 output = render(template, context)
132132
133133 self.assertEqual(output, 'delete_contenttype')
134
134
135135 def test_checker(self):
136136 GroupObjectPermission.objects.assign_perm("delete_contenttype", self.group,
137137 self.ctype)
138138
139139 checker = ObjectPermissionChecker(self.user)
140140 checker.prefetch_perms(Group.objects.all())
141
141
142142 template = ''.join((
143143 '{% load guardian_tags %}',
144144 '{% get_obj_perms group for contenttype as "obj_perms" checker %}',
0 from __future__ import unicode_literals
10 from django.test import TestCase
1 from django.contrib.auth import get_user_model
22 from django.contrib.contenttypes.models import ContentType
33 from django.contrib.auth.models import Group, AnonymousUser
44 from django.db import models
55
6 from guardian.compat import get_user_model
76 from guardian.testapp.tests.conf import skipUnlessTestApp
87 from guardian.testapp.tests.test_core import ObjectPermissionTestCase
98 from guardian.testapp.models import Project
5150 self.assertRaises(NotUserNorGroup, get_identity, 1)
5251 self.assertRaises(NotUserNorGroup, get_identity, "User")
5352 self.assertRaises(NotUserNorGroup, get_identity, User)
53
54 def test_multiple_user_qs(self):
55 user, group = get_identity(User.objects.all())
56 self.assertIsInstance(user, models.QuerySet)
57 self.assertIsNone(group)
58
59 def test_multiple_user_list(self):
60 user, group = get_identity([self.user])
61 self.assertIsInstance(user, list)
62 self.assertIsNone(group)
63
64 def test_multiple_group_qs(self):
65 user, group = get_identity(Group.objects.all())
66 self.assertIsInstance(group, models.QuerySet)
67 self.assertIsNone(user)
68
69 def test_multiple_group_list(self):
70 user, group = get_identity([self.group])
71 self.assertIsInstance(group, list)
72 self.assertIsNone(user)
5473
5574
5675 @skipUnlessTestApp
0 from __future__ import unicode_literals
10 # handler404 and handler500 are needed for admin tests
2 from guardian.compat import include, url, handler404, handler500 # pyflakes:ignore
1 from guardian.compat import url, handler404, handler500 # pyflakes:ignore
32 from guardian.mixins import PermissionRequiredMixin
43 from django.contrib import admin
5 from django.contrib.auth.views import login
4 from django.contrib.auth.views import LoginView
65 from django.views.generic import View
76
87 admin.autodiscover()
1312
1413 urlpatterns = [
1514 url(r'^admin/', admin.site.urls),
16 url(r'^accounts/login/', login, {'template_name': 'blank.html'}),
15 url(r'^accounts/login/', LoginView.as_view(template_name='blank.html')),
1716 url(r'^permission_required/', TestClassRedirectView.as_view()),
1817 ]
11 import random
22 import string
33 import environ
4 import django
54
65 env = environ.Env()
76
2827 'guardian.backends.ObjectPermissionBackend',
2928 )
3029
31 # this fixes warnings in django 1.10
3230 MIDDLEWARE = (
3331 'django.middleware.common.CommonMiddleware',
3432 'django.contrib.sessions.middleware.SessionMiddleware',
3533 'django.contrib.auth.middleware.AuthenticationMiddleware',
3634 'django.contrib.messages.middleware.MessageMiddleware',
3735 )
38
39 if django.VERSION < (1, 10):
40 MIDDLEWARE_CLASSES = MIDDLEWARE
4136
4237 TEST_RUNNER = 'django.test.runner.DiscoverRunner'
4338
7166 },
7267 },
7368 ]
74
75 if django.VERSION < (1, 8):
76 TEMPLATE_DIRS = TEMPLATES[0]['DIRS']
44 internal functionality. They are **not** guaranteed to be stable - which means
55 they actual input parameters/output type may change in future releases.
66 """
7 from __future__ import unicode_literals
7 import logging
8 import os
9 from itertools import chain
10
811 from django.conf import settings
9 from django.contrib.auth import REDIRECT_FIELD_NAME
12 from django.contrib.auth import REDIRECT_FIELD_NAME, get_user_model
1013 from django.contrib.auth.models import AnonymousUser, Group
1114 from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
12 from django.db.models import Model
15 from django.db.models import Model, QuerySet
1316 from django.http import HttpResponseForbidden, HttpResponseNotFound
14 from django.shortcuts import render_to_response
15 from django.template import RequestContext
16 from guardian.compat import get_user_model, remote_model
17 from django.shortcuts import render
1718 from guardian.conf import settings as guardian_settings
1819 from guardian.ctypes import get_content_type
1920 from guardian.exceptions import NotUserNorGroup
20 from itertools import chain
21
22 import django
23 import logging
24 import os
2521
2622 logger = logging.getLogger(__name__)
2723 abspath = lambda *p: os.path.abspath(os.path.join(*p))
7167 if isinstance(identity, AnonymousUser):
7268 identity = get_anonymous_user()
7369
70 # get identity from queryset model type
71 if isinstance(identity, QuerySet):
72 identity_model_type = identity.model
73 if identity_model_type == get_user_model():
74 return identity, None
75 elif identity_model_type == Group:
76 return None, identity
77
78 # get identity from first element in list
79 if isinstance(identity, list) and isinstance(identity[0], get_user_model()):
80 return identity, None
81 if isinstance(identity, list) and isinstance(identity[0], Group):
82 return None, identity
83
7484 if isinstance(identity, get_user_model()):
7585 return identity, None
76 elif isinstance(identity, Group):
86 if isinstance(identity, Group):
7787 return None, identity
7888
7989 raise NotUserNorGroup("User/AnonymousUser or Group instance is required "
101111 if not has_permissions:
102112 if return_403:
103113 if guardian_settings.RENDER_403:
104 response = render_to_response(
105 guardian_settings.TEMPLATE_403, {},
106 RequestContext(request))
114 response = render(request, guardian_settings.TEMPLATE_403)
107115 response.status_code = 403
108116 return response
109117 elif guardian_settings.RAISE_403:
111119 return HttpResponseForbidden()
112120 if return_404:
113121 if guardian_settings.RENDER_404:
114 response = render_to_response(
115 guardian_settings.TEMPLATE_404, {},
116 RequestContext(request))
122 response = render(request, guardian_settings.TEMPLATE_404)
117123 response.status_code = 404
118124 return response
119125 elif guardian_settings.RAISE_404:
157163 obj = obj.__class__
158164 ctype = get_content_type(obj)
159165
160 if django.VERSION >= (1, 8):
161 fields = (f for f in obj._meta.get_fields()
162 if (f.one_to_many or f.one_to_one) and f.auto_created)
163 else:
164 fields = obj._meta.get_all_related_objects()
166 fields = (f for f in obj._meta.get_fields()
167 if (f.one_to_many or f.one_to_one) and f.auto_created)
165168
166169 for attr in fields:
167 if django.VERSION < (1, 8):
168 model = getattr(attr, 'model', None)
169 else:
170 model = getattr(attr, 'related_model', None)
170 model = getattr(attr, 'related_model', None)
171171 if (model and issubclass(model, base_cls) and
172 model is not generic_cls):
172 model is not generic_cls and getattr(model, 'enabled', True)):
173173 # if model is generic one it would be returned anyway
174174 if not model.objects.is_generic():
175175 # make sure that content_object's content_type is same as
176176 # the one of given obj
177177 fk = model._meta.get_field('content_object')
178 if ctype == get_content_type(remote_model(fk)):
178 if ctype == get_content_type(fk.remote_field.model):
179179 return model
180180 return generic_cls
181181
00 [pytest]
11 DJANGO_SETTINGS_MODULE=guardian.testapp.testsettings
2
3 filterwarnings =
4 once::DeprecationWarning
5 once::PendingDeprecationWarning
0 Django>=1.10.6
1 six
0 Django>=2.1
21 django-environ
32 bumpversion
3 mock
00 [bumpversion]
1 current_version = 1.4.9
1 current_version = 2.0.0
22
33 [build_sphinx]
44 source-dir = docs/
99 upload-dir = docs/build/html
1010
1111 [bdist_rpm]
12 requires = Django >= 1.8
13
14 [wheel]
15 universal = 1
12 requires = Django >= 2.1
1613
1714 [aliases]
1815 test = pytest
2421 [bumpversion:file:guardian/__init__.py]
2522 search = __version__ = '{current_version}'
2623 replace = __version__ = '{new_version}'
27
28 [egg_info]
29 tag_build =
30 tag_date = 0
31 tag_svn_revision = 0
32
22 from extras import RunFlakesCommand
33
44
5 version = '1.4.9'
5 version = '2.0.0'
66
77 readme_file = os.path.join(os.path.dirname(__file__), 'README.rst')
88 with open(readme_file, 'r') as f:
1111 setup(
1212 name='django-guardian',
1313 version=version,
14 python_requires='>=3.5',
1415 setup_requires=['pytest-runner', ],
1516 url='http://github.com/django-guardian/django-guardian',
1617 author='Lukasz Balcerzak',
2728 ],
2829 include_package_data=True,
2930 license='BSD',
30 install_requires=[
31 'six',
32 ],
31 install_requires=[],
3332 tests_require=['mock', 'django-environ', 'pytest', 'pytest-django'],
3433 classifiers=['Development Status :: 5 - Production/Stable',
3534 'Environment :: Web Environment',
3635 'Framework :: Django',
37 'Framework :: Django :: 1.8',
38 'Framework :: Django :: 1.9',
39 'Framework :: Django :: 1.10',
40 'Framework :: Django :: 1.11',
36 'Framework :: Django :: 2.1',
37 'Framework :: Django :: 2.2',
4138 'Intended Audience :: Developers',
4239 'License :: OSI Approved :: BSD License',
4340 'Operating System :: OS Independent',
4441 'Programming Language :: Python',
4542 'Topic :: Security',
46 'Programming Language :: Python :: 2.7',
47 'Programming Language :: Python :: 3.4',
4843 'Programming Language :: Python :: 3.5',
4944 'Programming Language :: Python :: 3.6',
45 'Programming Language :: Python :: 3.7',
46 'Programming Language :: Python :: 3 :: Only',
5047 ],
5148 test_suite='tests.main',
5249 cmdclass={'flakes': RunFlakesCommand},
00 [tox]
11 downloadcache = {toxworkdir}/cache/
2 envlist =
3 {core,docs}-py27-django18,
4 {core}-py34-django18,
5 {core,docs}-py35-django18,
6 {core,example,docs}-py27-django110,
7 {core,example,docs}-py27-django111,
8 {core}-py34-django110,
9 {core}-py34-django111,
10 {core,example,docs}-py35-django110
11 {core,example,docs}-py35-django111
12 {core,example,docs}-py36-django110
13 {core,example,docs}-py36-django111
2 envlist = # sort by django version, next by python version
3 {core,example,docs}-py{35,36,py37}-django21,
4 {core,example,docs}-py{35,36,py37}-django22,
145
156 [testenv]
167 passenv = DATABASE_URL
178 basepython =
18 py27: python2.7
19 py34: python3.4
209 py35: python3.5
2110 py36: python3.6
11 py37: python3.7
2212 changedir =
2313 example: example_project
2414 docs: docs
2515 commands =
16 django21: python {toxinidir}/manage.py makemigrations --check --dry-run
17 django22: python {toxinidir}/manage.py makemigrations --check --dry-run
2618 core: py.test --cov=guardian
2719 docs: sphinx-build -b html -d {envtmpdir}/doctrees . {envtmpdir}/html
2820 example: python manage.py test
3830 docs: sphinx
3931 docs: sphinx_rtd_theme
4032 docs: setuptools_scm
41 django18: django==1.8.17
42 django110: django>=1.10<1.11
43 django111: django>=1.11<1.12
33 django21: django>=2.1,<2.2
34 django22: django>=2.2,<2.3