diff --git a/benchmarks/models.py b/benchmarks/models.py index 6968afb5a..d46060c04 100644 --- a/benchmarks/models.py +++ b/benchmarks/models.py @@ -8,11 +8,11 @@ class TestModel(models.Model): class DirectUser(UserObjectPermissionBase): - content_object = models.ForeignKey('TestDirectModel', on_delete=models.CASCADE) + content_object = models.ForeignKey("TestDirectModel", on_delete=models.CASCADE) class DirectGroup(GroupObjectPermissionBase): - content_object = models.ForeignKey('TestDirectModel', on_delete=models.CASCADE) + content_object = models.ForeignKey("TestDirectModel", on_delete=models.CASCADE) class TestDirectModel(models.Model): diff --git a/benchmarks/run_benchmarks.py b/benchmarks/run_benchmarks.py index 9dd17fbf7..b0880451e 100644 --- a/benchmarks/run_benchmarks.py +++ b/benchmarks/run_benchmarks.py @@ -12,15 +12,16 @@ abspath = lambda *p: os.path.abspath(os.path.join(*p)) THIS_DIR = abspath(os.path.dirname(__file__)) -ROOT_DIR = abspath(THIS_DIR, '..') +ROOT_DIR = abspath(THIS_DIR, "..") # so the preferred guardian module is one within this repo and # not system-wide sys.path.insert(0, ROOT_DIR) -os.environ["DJANGO_SETTINGS_MODULE"] = 'benchmarks.settings' +os.environ["DJANGO_SETTINGS_MODULE"] = "benchmarks.settings" import django + django.setup() from benchmarks import settings @@ -40,11 +41,10 @@ def random_string(length=25, chars=string.ascii_letters + string.digits): - return ''.join(random.choice(chars) for i in range(length)) + return "".join(random.choice(chars) for i in range(length)) class Call: - def __init__(self, args, kwargs, start=None, finish=None): self.args = args self.kwargs = kwargs @@ -56,13 +56,12 @@ def delta(self): class Timed: - def __init__(self, action=None): self.action = action def __call__(self, func): - if not hasattr(func, 'calls'): + if not hasattr(func, "calls"): func.calls = [] def wrapper(*args, **kwargs): @@ -76,44 +75,58 @@ def wrapper(*args, **kwargs): call.finish = datetime.datetime.now() func.calls.append(call) if self.action: - print(" -> [{}] Done (Total time: {})".format(self.action, - call.delta())) + print( + " -> [{}] Done (Total time: {})".format( + self.action, call.delta() + ) + ) + return wrapper class Benchmark: - - def __init__(self, name, users_count, objects_count, - objects_with_perms_count, model, subquery): + def __init__( + self, + name, + users_count, + objects_count, + objects_with_perms_count, + model, + subquery, + ): self.name = name self.users_count = users_count self.objects_count = objects_count self.objects_with_perms_count = objects_with_perms_count self.subquery = subquery self.Model = model - self.perm = 'add_%s' % model._meta.model_name + self.perm = "add_%s" % model._meta.model_name def info(self, msg): - print(colorize(msg + '\n', fg='green')) + print(colorize(msg + "\n", fg="green")) def prepare_db(self): from django.core.management import call_command - call_command('makemigrations', interactive=False) - call_command('migrate', interactive=False) + + call_command("makemigrations", interactive=False) + call_command("migrate", interactive=False) for model in [User, Group, self.Model]: model.objects.all().delete() @Timed("Creating users") def create_users(self): - User.objects.bulk_create(User(id=x, username=random_string().capitalize()) - for x in range(self.users_count)) + User.objects.bulk_create( + User(id=x, username=random_string().capitalize()) + for x in range(self.users_count) + ) @Timed("Creating objects") def create_objects(self): Model = self.Model - Model.objects.bulk_create(Model(id=x, name=random_string(20)) - for x in range(self.objects_count)) + Model.objects.bulk_create( + Model(id=x, name=random_string(20)) for x in range(self.objects_count) + ) @Timed("Grant permissions") def grant_perms(self): @@ -140,10 +153,11 @@ def get_objects(self): ids = range(1, self.users_count) for user in User.objects.iterator(): for x in xrange(self.objects_with_perms_count): - filters = {'user': random.choice(ids), - 'permission__codename__in': [self.perm], - 'content_type': ctype - } + filters = { + "user": random.choice(ids), + "permission__codename__in": [self.perm], + "content_type": ctype, + } qs = UserObjectPermission.objects.filter(**filters).all() if not self.subquery: qs = [v.object_pk for v in qs] @@ -154,9 +168,9 @@ def check_perm(self, user, obj, perm): @Timed("Benchmark") def main(self): - self.info('=' * 80) + self.info("=" * 80) self.info(self.name.center(80)) - self.info('=' * 80) + self.info("=" * 80) self.prepare_db() self.create_users() self.create_objects() @@ -167,16 +181,29 @@ def main(self): def main(): - show_settings(settings, 'benchmarks') + show_settings(settings, "benchmarks") glob = [USERS_COUNT, OBJECTS_COUNT, OBJECTS_WIHT_PERMS_COUNT] - Benchmark('Direct relations benchmark with subqueries', *glob, - model=TestDirectModel, subquery=True).main() - - Benchmark('Direct relations benchmark without subqueries', *glob, - model=TestDirectModel, subquery=False).main() - - Benchmark('Generic relations benchmark without subqueries', *glob, - model=TestModel, subquery=False).main() - -if __name__ == '__main__': + Benchmark( + "Direct relations benchmark with subqueries", + *glob, + model=TestDirectModel, + subquery=True + ).main() + + Benchmark( + "Direct relations benchmark without subqueries", + *glob, + model=TestDirectModel, + subquery=False + ).main() + + Benchmark( + "Generic relations benchmark without subqueries", + *glob, + model=TestModel, + subquery=False + ).main() + + +if __name__ == "__main__": main() diff --git a/benchmarks/settings.py b/benchmarks/settings.py index ddaa236a4..5eb4dc6e5 100644 --- a/benchmarks/settings.py +++ b/benchmarks/settings.py @@ -7,24 +7,24 @@ abspath = lambda *p: os.path.abspath(os.path.join(*p)) THIS_DIR = abspath(os.path.dirname(__file__)) -ROOT_DIR = abspath(THIS_DIR, '..') +ROOT_DIR = abspath(THIS_DIR, "..") # so the preferred guardian module is one within this repo and # not system-wide sys.path.insert(0, ROOT_DIR) -SECRET_KEY = 'NO_NEED_SECRET' +SECRET_KEY = "NO_NEED_SECRET" INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.sessions', - 'django.contrib.contenttypes', - 'django.contrib.admin', - 'django.contrib.sites', - 'guardian', - 'benchmarks', + "django.contrib.auth", + "django.contrib.sessions", + "django.contrib.contenttypes", + "django.contrib.admin", + "django.contrib.sites", + "guardian", + "benchmarks", ) DJALOG_LEVEL = 40 -DATABASES = {'default': env.db(default="sqlite:///")} +DATABASES = {"default": env.db(default="sqlite:///")} diff --git a/docs/conf.py b/docs/conf.py index 5fdd8a37d..fcf089fc7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -11,28 +11,31 @@ import sys import os -on_rtd = os.environ.get('READTHEDOCS', None) == 'True' + +on_rtd = os.environ.get("READTHEDOCS", None) == "True" # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, os.path.abspath('..')) +sys.path.insert(0, os.path.abspath("..")) sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__)))) -os.environ['DJANGO_SETTINGS_MODULE'] = 'guardian.testapp.testsettings' -guardian = __import__('guardian') +os.environ["DJANGO_SETTINGS_MODULE"] = "guardian.testapp.testsettings" +guardian = __import__("guardian") import django + django.setup() # -- General configuration ----------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', 'exts'] +extensions = ["sphinx.ext.autodoc", "exts"] try: import rst2pdf - if rst2pdf.version >= '0.16': - extensions.append('rst2pdf.pdfbuilder') + + if rst2pdf.version >= "0.16": + extensions.append("rst2pdf.pdfbuilder") except ImportError: print("[NOTE] In order to build PDF you need rst2pdf with version >=0.16") @@ -40,20 +43,20 @@ autoclass_content = "both" # Add any paths that contain templates here, relative to this directory. -templates_path = ['templates'] +templates_path = ["templates"] # The suffix of source filenames. -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. -#source_encoding = 'utf-8' +# source_encoding = 'utf-8' # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = 'django-guardian' -copyright = 'Lukasz Balcerzak' +project = "django-guardian" +copyright = "Lukasz Balcerzak" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -66,72 +69,73 @@ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -#language = None +# language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. -#unused_docs = [] +# unused_docs = [] # List of directories, relative to source directory, that shouldn't be searched # for source files. -exclude_trees = ['build'] +exclude_trees = ["build"] # The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. -#html_theme = 'default' +# html_theme = 'default' if not on_rtd: # only import and set the theme if we're building docs locally import sphinx_rtd_theme - html_theme = 'sphinx_rtd_theme' + + html_theme = "sphinx_rtd_theme" html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +# html_theme_options = {} # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, @@ -140,80 +144,83 @@ # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_use_modindex = True +# html_use_modindex = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' +# html_file_suffix = '' # Output file base name for HTML help builder. -htmlhelp_basename = 'guardiandoc' +htmlhelp_basename = "guardiandoc" # -- Options for LaTeX output -------------------------------------------- # The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' +# latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' +# latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'guardian.tex', 'guardian Documentation', - 'Lukasz Balcerzak', 'manual'), + ("index", "guardian.tex", "guardian Documentation", "Lukasz Balcerzak", "manual"), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # Additional stuff for the LaTeX preamble. -#latex_preamble = '' +# latex_preamble = '' # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_use_modindex = True +# latex_use_modindex = True pdf_documents = [ - ('index', 'django-guardian', 'Documentation for django-guardian', - 'Lukasz Balcerzak'), + ( + "index", + "django-guardian", + "Documentation for django-guardian", + "Lukasz Balcerzak", + ), ] -pdf_stylesheets = ['sphinx', 'kerning', 'a4'] +pdf_stylesheets = ["sphinx", "kerning", "a4"] pdf_break_level = 2 pdf_inline_footnotes = True -#pdf_extensions = ['vectorpdf', 'dotted_toc'] +# pdf_extensions = ['vectorpdf', 'dotted_toc'] diff --git a/example_project/articles/admin.py b/example_project/articles/admin.py index 96966abb9..81e3e30a8 100644 --- a/example_project/articles/admin.py +++ b/example_project/articles/admin.py @@ -3,8 +3,9 @@ class ArticleAdmin(admin.ModelAdmin): - list_display = ('title', 'slug', 'created_at') - list_filter = ('created_at',) - search_fields = ('title',) + list_display = ("title", "slug", "created_at") + list_filter = ("created_at",) + search_fields = ("title",) + admin.site.register(Article, ArticleAdmin) diff --git a/example_project/articles/apps.py b/example_project/articles/apps.py index bc12dfb26..ae5c13b98 100644 --- a/example_project/articles/apps.py +++ b/example_project/articles/apps.py @@ -2,4 +2,4 @@ class ArticlesConfig(AppConfig): - name = 'articles' + name = "articles" diff --git a/example_project/articles/migrations/0001_initial.py b/example_project/articles/migrations/0001_initial.py index 795f67018..fcc385ec4 100644 --- a/example_project/articles/migrations/0001_initial.py +++ b/example_project/articles/migrations/0001_initial.py @@ -9,56 +9,115 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('auth', '0001_initial'), + ("auth", "0001_initial"), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( - name='Article', + name="Article", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=64, verbose_name='title')), - ('slug', models.SlugField(max_length=64)), - ('content', models.TextField(verbose_name='content')), - ('created_at', models.DateTimeField(auto_now_add=True, db_index=True)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("title", models.CharField(max_length=64, verbose_name="title")), + ("slug", models.SlugField(max_length=64)), + ("content", models.TextField(verbose_name="content")), + ("created_at", models.DateTimeField(auto_now_add=True, db_index=True)), ], options={ - 'get_latest_by': 'created_at', - 'default_permissions': ('add', 'change', 'delete'), - 'permissions': (('view_article', 'Can view article'),), + "get_latest_by": "created_at", + "default_permissions": ("add", "change", "delete"), + "permissions": (("view_article", "Can view article"),), }, ), migrations.CreateModel( - name='ArticleGroupObjectPermission', + name="ArticleGroupObjectPermission", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('content_object', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='articles.Article')), - ('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group')), - ('permission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Permission')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "content_object", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="articles.Article", + ), + ), + ( + "group", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="auth.Group" + ), + ), + ( + "permission", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="auth.Permission", + ), + ), ], options={ - 'abstract': False, + "abstract": False, }, ), migrations.CreateModel( - name='ArticleUserObjectPermission', + name="ArticleUserObjectPermission", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('content_object', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='articles.Article')), - ('permission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Permission')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "content_object", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="articles.Article", + ), + ), + ( + "permission", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="auth.Permission", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), ], options={ - 'abstract': False, + "abstract": False, }, ), migrations.AlterUniqueTogether( - name='articleuserobjectpermission', - unique_together={('user', 'permission', 'content_object')}, + name="articleuserobjectpermission", + unique_together={("user", "permission", "content_object")}, ), migrations.AlterUniqueTogether( - name='articlegroupobjectpermission', - unique_together={('group', 'permission', 'content_object')}, + name="articlegroupobjectpermission", + unique_together={("group", "permission", "content_object")}, ), ] diff --git a/example_project/articles/migrations/0002_custom_generic_permissions.py b/example_project/articles/migrations/0002_custom_generic_permissions.py index bcf83bc31..e57e1dafd 100644 --- a/example_project/articles/migrations/0002_custom_generic_permissions.py +++ b/example_project/articles/migrations/0002_custom_generic_permissions.py @@ -8,61 +8,124 @@ class Migration(migrations.Migration): dependencies = [ - ('auth', '0009_alter_user_last_name_max_length'), - ('contenttypes', '0002_remove_content_type_name'), + ("auth", "0009_alter_user_last_name_max_length"), + ("contenttypes", "0002_remove_content_type_name"), migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('articles', '0001_initial'), + ("articles", "0001_initial"), ] operations = [ migrations.CreateModel( - name='BigGroupObjectPermission', + name="BigGroupObjectPermission", fields=[ - ('object_pk', models.CharField(max_length=255, verbose_name='object ID')), - ('id', models.BigAutoField(editable=False, primary_key=True, serialize=False, unique=True)), - ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')), - ('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group')), - ('permission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Permission')), + ( + "object_pk", + models.CharField(max_length=255, verbose_name="object ID"), + ), + ( + "id", + models.BigAutoField( + editable=False, primary_key=True, serialize=False, unique=True + ), + ), + ( + "content_type", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="contenttypes.ContentType", + ), + ), + ( + "group", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="auth.Group" + ), + ), + ( + "permission", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="auth.Permission", + ), + ), ], options={ - 'abstract': False, + "abstract": False, }, ), migrations.CreateModel( - name='BigUserObjectPermission', + name="BigUserObjectPermission", fields=[ - ('object_pk', models.CharField(max_length=255, verbose_name='object ID')), - ('id', models.BigAutoField(editable=False, primary_key=True, serialize=False, unique=True)), - ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')), - ('permission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Permission')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ( + "object_pk", + models.CharField(max_length=255, verbose_name="object ID"), + ), + ( + "id", + models.BigAutoField( + editable=False, primary_key=True, serialize=False, unique=True + ), + ), + ( + "content_type", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="contenttypes.ContentType", + ), + ), + ( + "permission", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="auth.Permission", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), ], options={ - 'abstract': False, + "abstract": False, }, ), migrations.AddIndex( - model_name='biguserobjectpermission', - index=models.Index(fields=['content_type', 'object_pk'], name='articles_bi_content_3fff51_idx'), + model_name="biguserobjectpermission", + index=models.Index( + fields=["content_type", "object_pk"], + name="articles_bi_content_3fff51_idx", + ), ), migrations.AddIndex( - model_name='biguserobjectpermission', - index=models.Index(fields=['content_type', 'object_pk', 'user'], name='articles_bi_content_a2ac4b_idx'), + model_name="biguserobjectpermission", + index=models.Index( + fields=["content_type", "object_pk", "user"], + name="articles_bi_content_a2ac4b_idx", + ), ), migrations.AlterUniqueTogether( - name='biguserobjectpermission', - unique_together={('user', 'permission', 'object_pk')}, + name="biguserobjectpermission", + unique_together={("user", "permission", "object_pk")}, ), migrations.AddIndex( - model_name='biggroupobjectpermission', - index=models.Index(fields=['content_type', 'object_pk'], name='articles_bi_content_824ecd_idx'), + model_name="biggroupobjectpermission", + index=models.Index( + fields=["content_type", "object_pk"], + name="articles_bi_content_824ecd_idx", + ), ), migrations.AddIndex( - model_name='biggroupobjectpermission', - index=models.Index(fields=['content_type', 'object_pk', 'group'], name='articles_bi_content_61c3ef_idx'), + model_name="biggroupobjectpermission", + index=models.Index( + fields=["content_type", "object_pk", "group"], + name="articles_bi_content_61c3ef_idx", + ), ), migrations.AlterUniqueTogether( - name='biggroupobjectpermission', - unique_together={('group', 'permission', 'object_pk')}, + name="biggroupobjectpermission", + unique_together={("group", "permission", "object_pk")}, ), ] diff --git a/example_project/articles/models.py b/example_project/articles/models.py index 7fa68ce14..898fe2768 100644 --- a/example_project/articles/models.py +++ b/example_project/articles/models.py @@ -6,23 +6,21 @@ class Article(models.Model): - title = models.CharField('title', max_length=64) + title = models.CharField("title", max_length=64) slug = models.SlugField(max_length=64) - content = models.TextField('content') + content = models.TextField("content") created_at = models.DateTimeField(auto_now_add=True, db_index=True) class Meta: - default_permissions = ('add', 'change', 'delete') - permissions = ( - ('view_article', 'Can view article'), - ) - get_latest_by = 'created_at' + default_permissions = ("add", "change", "delete") + permissions = (("view_article", "Can view article"),) + get_latest_by = "created_at" def __str__(self): return self.title def get_absolute_url(self): - return reverse('articles:details', kwargs={'slug': self.slug}) + return reverse("articles:details", kwargs={"slug": self.slug}) class ArticleUserObjectPermission(UserObjectPermissionBase): @@ -35,22 +33,24 @@ class ArticleGroupObjectPermission(GroupObjectPermissionBase): from guardian.models import UserObjectPermissionAbstract, GroupObjectPermissionAbstract + class BigUserObjectPermission(UserObjectPermissionAbstract): id = models.BigAutoField(editable=False, unique=True, primary_key=True) + class Meta(UserObjectPermissionAbstract.Meta): abstract = False indexes = [ *UserObjectPermissionAbstract.Meta.indexes, - models.Index(fields=['content_type', 'object_pk', 'user']), + models.Index(fields=["content_type", "object_pk", "user"]), ] class BigGroupObjectPermission(GroupObjectPermissionAbstract): id = models.BigAutoField(editable=False, unique=True, primary_key=True) + class Meta(GroupObjectPermissionAbstract.Meta): abstract = False indexes = [ *GroupObjectPermissionAbstract.Meta.indexes, - models.Index(fields=['content_type', 'object_pk', 'group']), + models.Index(fields=["content_type", "object_pk", "group"]), ] - diff --git a/example_project/articles/tests.py b/example_project/articles/tests.py index bfe419b07..4378cdfb9 100644 --- a/example_project/articles/tests.py +++ b/example_project/articles/tests.py @@ -3,96 +3,100 @@ from django.test.client import RequestFactory from guardian.shortcuts import assign_perm from articles.models import Article -from articles.views import (ArticleCreateView, ArticleDeleteView, ArticleDetailView, - ArticleListView, ArticleUpdateView) +from articles.views import ( + ArticleCreateView, + ArticleDeleteView, + ArticleDetailView, + ArticleListView, + ArticleUpdateView, +) class ViewTestCase(TestCase): def setUp(self): - self.article = Article.objects.create(title='foo-title', - slug='foo-slug', - content='bar-content') + self.article = Article.objects.create( + title="foo-title", slug="foo-slug", content="bar-content" + ) self.factory = RequestFactory() - self.user = get_user_model().objects.create_user( - 'joe', 'joe@doe.com', 'doe') - self.client.login(username='joe', password='doe') + self.user = get_user_model().objects.create_user("joe", "joe@doe.com", "doe") + self.client.login(username="joe", password="doe") def test_list_permitted(self): - request = self.factory.get('/') + request = self.factory.get("/") request.user = self.user - assign_perm('articles.view_article', self.user, self.article) - assign_perm('articles.delete_article', self.user, self.article) + assign_perm("articles.view_article", self.user, self.article) + assign_perm("articles.delete_article", self.user, self.article) view = ArticleListView.as_view() response = view(request) response.render() - self.assertContains(response, 'foo-title') + self.assertContains(response, "foo-title") def test_list_denied(self): - request = self.factory.get('/') + request = self.factory.get("/") request.user = self.user view = ArticleListView.as_view() response = view(request) response.render() - self.assertNotContains(response, 'foo-title') + self.assertNotContains(response, "foo-title") def test_create_permitted(self): - request = self.factory.get('/~create') + request = self.factory.get("/~create") request.user = self.user - assign_perm('articles.add_article', self.user) + assign_perm("articles.add_article", self.user) view = ArticleCreateView.as_view() response = view(request) self.assertEqual(response.status_code, 200) def test_create_denied(self): - request = self.factory.get('/~create') + request = self.factory.get("/~create") request.user = self.user view = ArticleCreateView.as_view() response = view(request) self.assertEqual(response.status_code, 302) def test_detail_permitted(self): - request = self.factory.get('/foo/') + request = self.factory.get("/foo/") request.user = self.user - assign_perm('articles.view_article', self.user, self.article) + assign_perm("articles.view_article", self.user, self.article) view = ArticleDetailView.as_view() - response = view(request, slug='foo-slug') + response = view(request, slug="foo-slug") self.assertEqual(response.status_code, 200) def test_detail_denied(self): - request = self.factory.get('/foo/') + request = self.factory.get("/foo/") request.user = self.user view = ArticleDetailView.as_view() - response = view(request, slug='foo-slug') + response = view(request, slug="foo-slug") self.assertEqual(response.status_code, 302) def test_update_permitted(self): - request = self.factory.get('/') + request = self.factory.get("/") request.user = self.user - assign_perm('articles.view_article', self.user, self.article) - assign_perm('articles.change_article', self.user, self.article) + assign_perm("articles.view_article", self.user, self.article) + assign_perm("articles.change_article", self.user, self.article) view = ArticleUpdateView.as_view() - response = view(request, slug='foo-slug') + response = view(request, slug="foo-slug") self.assertEqual(response.status_code, 200) def test_update_denied(self): - request = self.factory.get('/') + request = self.factory.get("/") request.user = self.user view = ArticleUpdateView.as_view() - response = view(request, slug='foo-slug') + response = view(request, slug="foo-slug") self.assertEqual(response.status_code, 302) def test_delete_permitted(self): - request = self.factory.get('/foo-slug/~delete') + request = self.factory.get("/foo-slug/~delete") request.user = self.user - assign_perm('articles.view_article', self.user, self.article) - assign_perm('articles.delete_article', self.user, self.article) + assign_perm("articles.view_article", self.user, self.article) + assign_perm("articles.delete_article", self.user, self.article) view = ArticleDeleteView.as_view() - response = view(request, slug='foo-slug') + response = view(request, slug="foo-slug") self.assertEqual(response.status_code, 200) def test_delete_denied(self): - request = self.factory.get('/foo/~delete') + request = self.factory.get("/foo/~delete") request.user = self.user view = ArticleDeleteView.as_view() - response = view(request, slug='foo-slug') + response = view(request, slug="foo-slug") self.assertEqual(response.status_code, 302) diff --git a/example_project/articles/urls.py b/example_project/articles/urls.py index 4ec382063..3ff089b0d 100644 --- a/example_project/articles/urls.py +++ b/example_project/articles/urls.py @@ -2,16 +2,11 @@ from . import views -app_name = 'articles' +app_name = "articles" urlpatterns = [ - path('', views.ArticleListView.as_view(), - name="list"), - path('~create', views.ArticleCreateView.as_view(), - name="create"), - path('', views.ArticleDetailView.as_view(), - name="details"), - path('/~update', views.ArticleUpdateView.as_view(), - name="update"), - path('/~delete', views.ArticleDeleteView.as_view(), - name="delete"), + path("", views.ArticleListView.as_view(), name="list"), + path("~create", views.ArticleCreateView.as_view(), name="create"), + path("", views.ArticleDetailView.as_view(), name="details"), + path("/~update", views.ArticleUpdateView.as_view(), name="update"), + path("/~delete", views.ArticleDeleteView.as_view(), name="delete"), ] diff --git a/example_project/articles/views.py b/example_project/articles/views.py index e491cde37..ccca3df07 100644 --- a/example_project/articles/views.py +++ b/example_project/articles/views.py @@ -1,6 +1,11 @@ from django.urls import reverse_lazy -from django.views.generic import (CreateView, DeleteView, DetailView, ListView, - UpdateView) +from django.views.generic import ( + CreateView, + DeleteView, + DetailView, + ListView, + UpdateView, +) from guardian.mixins import PermissionRequiredMixin, PermissionListMixin from guardian.shortcuts import assign_perm from articles.models import Article @@ -8,35 +13,37 @@ class ArticleListView(PermissionListMixin, ListView): model = Article - permission_required = ['view_article', ] + permission_required = [ + "view_article", + ] class ArticleDetailView(PermissionRequiredMixin, DetailView): model = Article - permission_required = ['view_article'] + permission_required = ["view_article"] class ArticleCreateView(PermissionRequiredMixin, CreateView): model = Article permission_object = None - permission_required = ['articles.add_article'] - fields = ['title', 'slug', 'content'] + permission_required = ["articles.add_article"] + fields = ["title", "slug", "content"] def form_valid(self, *args, **kwargs): resp = super().form_valid(*args, **kwargs) - assign_perm('view_article', self.request.user, self.object) - assign_perm('change_article', self.request.user, self.object) - assign_perm('delete_article', self.request.user, self.object) + assign_perm("view_article", self.request.user, self.object) + assign_perm("change_article", self.request.user, self.object) + assign_perm("delete_article", self.request.user, self.object) return resp class ArticleUpdateView(PermissionRequiredMixin, UpdateView): model = Article - permission_required = ['view_article', 'change_article'] - fields = ['title', 'slug', 'content'] + permission_required = ["view_article", "change_article"] + fields = ["title", "slug", "content"] class ArticleDeleteView(PermissionRequiredMixin, DeleteView): model = Article - success_url = reverse_lazy('articles:list') - permission_required = ['view_article', 'delete_article'] + success_url = reverse_lazy("articles:list") + permission_required = ["view_article", "delete_article"] diff --git a/example_project/core/context_processors.py b/example_project/core/context_processors.py index fc6949573..ed404b8da 100644 --- a/example_project/core/context_processors.py +++ b/example_project/core/context_processors.py @@ -2,4 +2,4 @@ def version(request): - return {'version': guardian.get_version()} + return {"version": guardian.get_version()} diff --git a/example_project/core/migrations/0001_initial.py b/example_project/core/migrations/0001_initial.py index 5c2da744f..a633cc6eb 100644 --- a/example_project/core/migrations/0001_initial.py +++ b/example_project/core/migrations/0001_initial.py @@ -8,48 +8,127 @@ class Migration(migrations.Migration): dependencies = [ - ('auth', '0001_initial'), + ("auth", "0001_initial"), ] operations = [ migrations.CreateModel( - name='CustomUser', + name="CustomUser", fields=[ - ('id', models.AutoField(verbose_name='ID', - serialize=False, auto_created=True, primary_key=True)), - ('password', models.CharField( - max_length=128, verbose_name='password')), - ('last_login', models.DateTimeField( - null=True, verbose_name='last login', blank=True)), - ('is_superuser', models.BooleanField(default=False, - help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), - ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, max_length=30, validators=[django.core.validators.RegexValidator( - '^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.', 'invalid')], help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', unique=True, verbose_name='username')), - ('first_name', models.CharField(max_length=30, - verbose_name='first name', blank=True)), - ('last_name', models.CharField(max_length=30, - verbose_name='last name', blank=True)), - ('email', models.EmailField(max_length=254, - verbose_name='email address', blank=True)), - ('is_staff', models.BooleanField(default=False, - help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), - ('is_active', models.BooleanField( - default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), - ('date_joined', models.DateTimeField( - default=django.utils.timezone.now, verbose_name='date joined')), - ('birth_date', models.DateField(null=True, blank=True)), - ('groups', models.ManyToManyField(related_query_name='user', related_name='user_set', to='auth.Group', blank=True, - help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', verbose_name='groups')), - ('user_permissions', models.ManyToManyField(related_query_name='user', related_name='user_set', to='auth.Permission', - blank=True, help_text='Specific permissions for this user.', verbose_name='user permissions')), + ( + "id", + models.AutoField( + verbose_name="ID", + serialize=False, + auto_created=True, + primary_key=True, + ), + ), + ("password", models.CharField(max_length=128, verbose_name="password")), + ( + "last_login", + models.DateTimeField( + null=True, verbose_name="last login", blank=True + ), + ), + ( + "is_superuser", + models.BooleanField( + default=False, + help_text="Designates that this user has all permissions without explicitly assigning them.", + verbose_name="superuser status", + ), + ), + ( + "username", + models.CharField( + error_messages={ + "unique": "A user with that username already exists." + }, + max_length=30, + validators=[ + django.core.validators.RegexValidator( + "^[\\w.@+-]+$", + "Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.", + "invalid", + ) + ], + help_text="Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.", + unique=True, + verbose_name="username", + ), + ), + ( + "first_name", + models.CharField( + max_length=30, verbose_name="first name", blank=True + ), + ), + ( + "last_name", + models.CharField( + max_length=30, verbose_name="last name", blank=True + ), + ), + ( + "email", + models.EmailField( + max_length=254, verbose_name="email address", blank=True + ), + ), + ( + "is_staff", + models.BooleanField( + default=False, + help_text="Designates whether the user can log into this admin site.", + verbose_name="staff status", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.", + verbose_name="active", + ), + ), + ( + "date_joined", + models.DateTimeField( + default=django.utils.timezone.now, verbose_name="date joined" + ), + ), + ("birth_date", models.DateField(null=True, blank=True)), + ( + "groups", + models.ManyToManyField( + related_query_name="user", + related_name="user_set", + to="auth.Group", + blank=True, + help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.", + verbose_name="groups", + ), + ), + ( + "user_permissions", + models.ManyToManyField( + related_query_name="user", + related_name="user_set", + to="auth.Permission", + blank=True, + help_text="Specific permissions for this user.", + verbose_name="user permissions", + ), + ), ], options={ - 'abstract': False, - 'verbose_name': 'user', - 'verbose_name_plural': 'users', + "abstract": False, + "verbose_name": "user", + "verbose_name_plural": "users", }, managers=[ - ('objects', django.contrib.auth.models.UserManager()), + ("objects", django.contrib.auth.models.UserManager()), ], ), ] diff --git a/example_project/core/migrations/0002_auto_20190629_0848.py b/example_project/core/migrations/0002_auto_20190629_0848.py index e30f493a4..6d286bb74 100644 --- a/example_project/core/migrations/0002_auto_20190629_0848.py +++ b/example_project/core/migrations/0002_auto_20190629_0848.py @@ -7,18 +7,27 @@ class Migration(migrations.Migration): dependencies = [ - ('core', '0001_initial'), + ("core", "0001_initial"), ] operations = [ migrations.AlterField( - model_name='customuser', - name='last_name', - field=models.CharField(blank=True, max_length=150, verbose_name='last name'), + model_name="customuser", + name="last_name", + field=models.CharField( + blank=True, max_length=150, verbose_name="last name" + ), ), migrations.AlterField( - model_name='customuser', - name='username', - 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'), + model_name="customuser", + name="username", + 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", + ), ), ] diff --git a/example_project/core/models.py b/example_project/core/models.py index 08f38b656..975741121 100644 --- a/example_project/core/models.py +++ b/example_project/core/models.py @@ -10,6 +10,6 @@ class CustomUser(AbstractUser): def get_custom_anon_user(User): return User( - username='AnonymousUser', + username="AnonymousUser", birth_date=datetime.date(1410, 7, 15), ) diff --git a/example_project/posts/admin.py b/example_project/posts/admin.py index 99121509e..658c991b8 100644 --- a/example_project/posts/admin.py +++ b/example_project/posts/admin.py @@ -7,9 +7,10 @@ class PostAdmin(GuardedModelAdmin): prepopulated_fields = {"slug": ("title",)} - list_display = ('title', 'slug', 'created_at') - search_fields = ('title', 'content') - ordering = ('-created_at',) - date_hierarchy = 'created_at' + list_display = ("title", "slug", "created_at") + search_fields = ("title", "content") + ordering = ("-created_at",) + date_hierarchy = "created_at" + admin.site.register(Post, PostAdmin) diff --git a/example_project/posts/migrations/0001_initial.py b/example_project/posts/migrations/0001_initial.py index 341126782..34490b6d0 100644 --- a/example_project/posts/migrations/0001_initial.py +++ b/example_project/posts/migrations/0001_initial.py @@ -3,25 +3,30 @@ class Migration(migrations.Migration): - dependencies = [ - ] + dependencies = [] operations = [ migrations.CreateModel( - name='Post', + name="Post", fields=[ - ('id', models.AutoField(verbose_name='ID', - serialize=False, auto_created=True, primary_key=True)), - ('title', models.CharField(max_length=64, verbose_name=b'title')), - ('slug', models.SlugField(max_length=64)), - ('content', models.TextField(verbose_name=b'content')), - ('created_at', models.DateTimeField( - auto_now_add=True, db_index=True)), + ( + "id", + models.AutoField( + verbose_name="ID", + serialize=False, + auto_created=True, + primary_key=True, + ), + ), + ("title", models.CharField(max_length=64, verbose_name=b"title")), + ("slug", models.SlugField(max_length=64)), + ("content", models.TextField(verbose_name=b"content")), + ("created_at", models.DateTimeField(auto_now_add=True, db_index=True)), ], options={ - 'get_latest_by': 'created_at', - 'default_permissions': ('add', 'change', 'delete'), - 'permissions': (('view_post', 'Can view post'),), + "get_latest_by": "created_at", + "default_permissions": ("add", "change", "delete"), + "permissions": (("view_post", "Can view post"),), }, ), ] diff --git a/example_project/posts/migrations/0002_auto_20190629_0848.py b/example_project/posts/migrations/0002_auto_20190629_0848.py index 4577ea10b..6321e9b88 100644 --- a/example_project/posts/migrations/0002_auto_20190629_0848.py +++ b/example_project/posts/migrations/0002_auto_20190629_0848.py @@ -6,18 +6,18 @@ class Migration(migrations.Migration): dependencies = [ - ('posts', '0001_initial'), + ("posts", "0001_initial"), ] operations = [ migrations.AlterField( - model_name='post', - name='content', - field=models.TextField(verbose_name='content'), + model_name="post", + name="content", + field=models.TextField(verbose_name="content"), ), migrations.AlterField( - model_name='post', - name='title', - field=models.CharField(max_length=64, verbose_name='title'), + model_name="post", + name="title", + field=models.CharField(max_length=64, verbose_name="title"), ), ] diff --git a/example_project/posts/models.py b/example_project/posts/models.py index ca4d058d3..efd18427c 100644 --- a/example_project/posts/models.py +++ b/example_project/posts/models.py @@ -3,20 +3,18 @@ class Post(models.Model): - title = models.CharField('title', max_length=64) + title = models.CharField("title", max_length=64) slug = models.SlugField(max_length=64) - content = models.TextField('content') + content = models.TextField("content") created_at = models.DateTimeField(auto_now_add=True, db_index=True) class Meta: - default_permissions = ('add', 'change', 'delete') - permissions = ( - ('view_post', 'Can view post'), - ) - get_latest_by = 'created_at' + default_permissions = ("add", "change", "delete") + permissions = (("view_post", "Can view post"),) + get_latest_by = "created_at" def __str__(self): return self.title def get_absolute_url(self): - return reverse('posts_post_detail', args=(), kwargs={'slug': self.slug}) + return reverse("posts_post_detail", args=(), kwargs={"slug": self.slug}) diff --git a/example_project/posts/urls.py b/example_project/posts/urls.py index ca26d5ddd..397d793ff 100644 --- a/example_project/posts/urls.py +++ b/example_project/posts/urls.py @@ -3,6 +3,6 @@ from posts import views urlpatterns = [ - path('', views.post_list, name='posts_post_list'), - path('', views.post_detail, name='posts_post_detail'), + path("", views.post_list, name="posts_post_list"), + path("", views.post_detail, name="posts_post_detail"), ] diff --git a/example_project/posts/views.py b/example_project/posts/views.py index 0ff542a64..949936bd4 100644 --- a/example_project/posts/views.py +++ b/example_project/posts/views.py @@ -12,18 +12,17 @@ class PostList(ListView): model = Post - context_object_name = 'posts' + context_object_name = "posts" + post_list = PostList.as_view() -@permission_required_or_403('posts.view_post', (Post, 'slug', 'slug')) +@permission_required_or_403("posts.view_post", (Post, "slug", "slug")) def post_detail(request, slug, **kwargs): data = { - 'post': get_object_or_404(Post, slug=slug), - 'users': User.objects.all(), - 'groups': Group.objects.all(), + "post": get_object_or_404(Post, slug=slug), + "users": User.objects.all(), + "groups": Group.objects.all(), } - return render( - request, 'posts/post_detail.html', data, - RequestContext(request)) + return render(request, "posts/post_detail.html", data, RequestContext(request)) diff --git a/example_project/settings.py b/example_project/settings.py index 08c4e7c28..8b16179f0 100644 --- a/example_project/settings.py +++ b/example_project/settings.py @@ -8,103 +8,102 @@ DEBUG = True -SECRET_KEY = 'CHANGE_THIS_TO_SOMETHING_UNIQUE_AND_SECURE' +SECRET_KEY = "CHANGE_THIS_TO_SOMETHING_UNIQUE_AND_SECURE" PROJECT_ROOT = abspath(os.path.dirname(__file__)) -GUARDIAN_MODULE_PATH = abspath(PROJECT_ROOT, '..') +GUARDIAN_MODULE_PATH = abspath(PROJECT_ROOT, "..") sys.path.insert(0, GUARDIAN_MODULE_PATH) -DATABASES = {'default': env.db(default="sqlite://./example.db")} +DATABASES = {"default": env.db(default="sqlite://./example.db")} INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.admin', - 'django.contrib.messages', - 'guardian', - 'posts', - 'articles', - 'core', - 'django.contrib.staticfiles', + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.sites", + "django.contrib.admin", + "django.contrib.messages", + "guardian", + "posts", + "articles", + "core", + "django.contrib.staticfiles", ) -if 'GRAPPELLI' in os.environ: +if "GRAPPELLI" in os.environ: try: - __import__('grappelli') - INSTALLED_APPS = ('grappelli',) + INSTALLED_APPS + __import__("grappelli") + INSTALLED_APPS = ("grappelli",) + INSTALLED_APPS except ImportError: print("django-grappelli not installed") try: import rosetta - INSTALLED_APPS += ('rosetta',) + + INSTALLED_APPS += ("rosetta",) except ImportError: pass MIDDLEWARE = ( - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', + "django.middleware.common.CommonMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", ) -STATIC_ROOT = abspath(PROJECT_ROOT, '..', 'public', 'static') -STATIC_URL = '/static/' -STATICFILES_DIRS = [abspath(PROJECT_ROOT, 'static')] +STATIC_ROOT = abspath(PROJECT_ROOT, "..", "public", "static") +STATIC_URL = "/static/" +STATICFILES_DIRS = [abspath(PROJECT_ROOT, "static")] GUARDIAN_RAISE_403 = True -ROOT_URLCONF = 'urls' +ROOT_URLCONF = "urls" SITE_ID = 1 USE_I18N = True USE_L10N = True -LOGIN_REDIRECT_URL = '/' +LOGIN_REDIRECT_URL = "/" -TEST_RUNNER = 'django.test.runner.DiscoverRunner' +TEST_RUNNER = "django.test.runner.DiscoverRunner" AUTHENTICATION_BACKENDS = ( - 'django.contrib.auth.backends.ModelBackend', - 'guardian.backends.ObjectPermissionBackend', + "django.contrib.auth.backends.ModelBackend", + "guardian.backends.ObjectPermissionBackend", ) -GUARDIAN_GET_INIT_ANONYMOUS_USER = 'core.models.get_custom_anon_user' +GUARDIAN_GET_INIT_ANONYMOUS_USER = "core.models.get_custom_anon_user" PASSWORD_HASHERS = ( - 'django.contrib.auth.hashers.MD5PasswordHasher', - 'django.contrib.auth.hashers.SHA1PasswordHasher', + "django.contrib.auth.hashers.MD5PasswordHasher", + "django.contrib.auth.hashers.SHA1PasswordHasher", ) -AUTH_USER_MODEL = 'core.CustomUser' -GUARDIAN_USER_OBJ_PERMS_MODEL = 'articles.BigUserObjectPermission' -GUARDIAN_GROUP_OBJ_PERMS_MODEL = 'articles.BigGroupObjectPermission' +AUTH_USER_MODEL = "core.CustomUser" +GUARDIAN_USER_OBJ_PERMS_MODEL = "articles.BigUserObjectPermission" +GUARDIAN_GROUP_OBJ_PERMS_MODEL = "articles.BigGroupObjectPermission" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': ( - os.path.join(os.path.dirname(__file__), 'templates'), - ), - 'OPTIONS': { - 'debug': DEBUG, - 'loaders': ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": (os.path.join(os.path.dirname(__file__), "templates"),), + "OPTIONS": { + "debug": DEBUG, + "loaders": ( + "django.template.loaders.filesystem.Loader", + "django.template.loaders.app_directories.Loader", ), - 'context_processors': ( - 'core.context_processors.version', - 'django.contrib.auth.context_processors.auth', - 'django.template.context_processors.debug', - 'django.template.context_processors.i18n', - 'django.template.context_processors.media', - 'django.template.context_processors.static', - 'django.template.context_processors.request', - 'django.template.context_processors.tz', - 'django.contrib.messages.context_processors.messages' + "context_processors": ( + "core.context_processors.version", + "django.contrib.auth.context_processors.auth", + "django.template.context_processors.debug", + "django.template.context_processors.i18n", + "django.template.context_processors.media", + "django.template.context_processors.static", + "django.template.context_processors.request", + "django.template.context_processors.tz", + "django.contrib.messages.context_processors.messages", ), }, }, diff --git a/example_project/urls.py b/example_project/urls.py index 15c9c10e3..863bf2950 100644 --- a/example_project/urls.py +++ b/example_project/urls.py @@ -1,22 +1,26 @@ -from guardian.compat import include, handler404, handler500 +from guardian.compat import include, handler404, handler500 from django.conf import settings from django.urls import path from django.contrib import admin from django.contrib.auth.views import LogoutView -__all__ = ['handler404', 'handler500'] +__all__ = ["handler404", "handler500"] admin.autodiscover() urlpatterns = [ - path('admin/', admin.site.urls), - path('logout/', LogoutView.as_view(next_page='/'), name='logout'), - path('article/', include('articles.urls', namespace='articles')), - path('', include('posts.urls')), + path("admin/", admin.site.urls), + path("logout/", LogoutView.as_view(next_page="/"), name="logout"), + path("article/", include("articles.urls", namespace="articles")), + path("", include("posts.urls")), ] -if 'grappelli' in settings.INSTALLED_APPS: - urlpatterns += [path('grappelli/', include('grappelli.urls')), ] +if "grappelli" in settings.INSTALLED_APPS: + urlpatterns += [ + path("grappelli/", include("grappelli.urls")), + ] -if 'rosetta' in settings.INSTALLED_APPS: - urlpatterns += [path('rosetta/', include('rosetta.urls')), ] +if "rosetta" in settings.INSTALLED_APPS: + urlpatterns += [ + path("rosetta/", include("rosetta.urls")), + ] diff --git a/extras.py b/extras.py index 62f417a98..e709ef586 100644 --- a/extras.py +++ b/extras.py @@ -2,12 +2,14 @@ import os import sys from setuptools import Command -#from pyflakes.scripts import pyflakes as flakes + +# from pyflakes.scripts import pyflakes as flakes def check(filename): from pyflakes import reporter as mod_reporter from pyflakes.checker import Checker + codeString = open(filename).read() reporter = mod_reporter._makeDefaultReporter() # First, compile into an AST and handle syntax errors. @@ -24,12 +26,12 @@ def check(filename): # Avoid using msg, since for the only known case, it contains a # bogus message that claims the encoding the file declared was # unknown. - reporter.unexpectedError(filename, 'problem decoding source') + reporter.unexpectedError(filename, "problem decoding source") else: reporter.syntaxError(filename, msg, lineno, offset, text) return 1 except Exception: - reporter.unexpectedError(filename, 'problem decoding source') + reporter.unexpectedError(filename, "problem decoding source") return 1 else: # Okay, it's syntactically valid. Now check it. @@ -39,7 +41,7 @@ def check(filename): real_messages = [] for m in warnings.messages: line = lines[m.lineno - 1] - if 'pyflakes:ignore' in line.rsplit('#', 1)[-1]: + if "pyflakes:ignore" in line.rsplit("#", 1)[-1]: # ignore lines with pyflakes:ignore pass else: @@ -52,6 +54,7 @@ class RunFlakesCommand(Command): """ Runs pyflakes against guardian codebase. """ + description = "Check sources with pyflakes" user_options = [] @@ -68,21 +71,19 @@ def run(self): sys.stderr.write("No pyflakes installed!\n") sys.exit(-1) thisdir = os.path.dirname(__file__) - guardiandir = os.path.join(thisdir, 'guardian') + guardiandir = os.path.join(thisdir, "guardian") warns = 0 # Define top-level directories for topdir, dirnames, filenames in os.walk(guardiandir): - paths = (os.path.join(topdir, f) - for f in filenames if f .endswith('.py')) + paths = (os.path.join(topdir, f) for f in filenames if f.endswith(".py")) for path in paths: - if path.endswith('tests/__init__.py'): + if path.endswith("tests/__init__.py"): # ignore that module (it should only gather test cases with # *) continue warns += check(path) if warns > 0: - sys.stderr.write( - "ERROR: Finished with total %d warnings.\n" % warns) + sys.stderr.write("ERROR: Finished with total %d warnings.\n" % warns) sys.exit(1) else: print("No problems found in source codes.") diff --git a/guardian/__init__.py b/guardian/__init__.py index 30141a12f..1a193b255 100644 --- a/guardian/__init__.py +++ b/guardian/__init__.py @@ -3,13 +3,13 @@ """ from . import checks -default_app_config = 'guardian.apps.GuardianConfig' +default_app_config = "guardian.apps.GuardianConfig" # PEP 396: The __version__ attribute's value SHOULD be a string. -__version__ = '2.3.0' +__version__ = "2.3.0" # Compatibility to eg. django-rest-framework -VERSION = tuple(int(x) for x in __version__.split('.')[:3]) +VERSION = tuple(int(x) for x in __version__.split(".")[:3]) def get_version(): @@ -20,23 +20,45 @@ def monkey_patch_user(): from django.contrib.auth import get_user_model from .utils import get_anonymous_user, evict_obj_perms_cache from .utils import get_user_obj_perms_model + UserObjectPermission = get_user_obj_perms_model() User = get_user_model() # Prototype User and Group methods - setattr(User, 'get_anonymous', staticmethod(lambda: get_anonymous_user())) - setattr(User, 'add_obj_perm', - lambda self, perm, obj: UserObjectPermission.objects.assign_perm(perm, self, obj)) - setattr(User, 'del_obj_perm', - lambda self, perm, obj: UserObjectPermission.objects.remove_perm(perm, self, obj)) - setattr(User, 'evict_obj_perms_cache', evict_obj_perms_cache) + setattr(User, "get_anonymous", staticmethod(lambda: get_anonymous_user())) + setattr( + User, + "add_obj_perm", + lambda self, perm, obj: UserObjectPermission.objects.assign_perm( + perm, self, obj + ), + ) + setattr( + User, + "del_obj_perm", + lambda self, perm, obj: UserObjectPermission.objects.remove_perm( + perm, self, obj + ), + ) + setattr(User, "evict_obj_perms_cache", evict_obj_perms_cache) def monkey_patch_group(): from django.contrib.auth.models import Group, Permission from .utils import get_group_obj_perms_model + GroupObjectPermission = get_group_obj_perms_model() # Prototype Group methods - setattr(Group, 'add_obj_perm', - lambda self, perm, obj: GroupObjectPermission.objects.assign_perm(perm, self, obj)) - setattr(Group, 'del_obj_perm', - lambda self, perm, obj: GroupObjectPermission.objects.remove_perm(perm, self, obj)) + setattr( + Group, + "add_obj_perm", + lambda self, perm, obj: GroupObjectPermission.objects.assign_perm( + perm, self, obj + ), + ) + setattr( + Group, + "del_obj_perm", + lambda self, perm, obj: GroupObjectPermission.objects.remove_perm( + perm, self, obj + ), + ) diff --git a/guardian/admin.py b/guardian/admin.py index ded4e762b..d51b5efa8 100644 --- a/guardian/admin.py +++ b/guardian/admin.py @@ -11,8 +11,13 @@ from django.utils.translation import gettext from guardian.forms import GroupObjectPermissionsForm, UserObjectPermissionsForm from django.contrib.auth.models import Group -from guardian.shortcuts import (get_group_perms, get_groups_with_perms, get_perms_for_model, get_user_perms, - get_users_with_perms) +from guardian.shortcuts import ( + get_group_perms, + get_groups_with_perms, + get_perms_for_model, + get_user_perms, + get_users_with_perms, +) class AdminUserObjectPermissionsForm(UserObjectPermissionsForm): @@ -41,18 +46,15 @@ class GuardedModelAdminMixin: """ Serves as a helper for custom subclassing ``admin.ModelAdmin``. """ - change_form_template = \ - 'admin/guardian/model/change_form.html' - obj_perms_manage_template = \ - 'admin/guardian/model/obj_perms_manage.html' - obj_perms_manage_user_template = \ - 'admin/guardian/model/obj_perms_manage_user.html' - obj_perms_manage_group_template = \ - 'admin/guardian/model/obj_perms_manage_group.html' + + change_form_template = "admin/guardian/model/change_form.html" + obj_perms_manage_template = "admin/guardian/model/obj_perms_manage.html" + obj_perms_manage_user_template = "admin/guardian/model/obj_perms_manage_user.html" + obj_perms_manage_group_template = "admin/guardian/model/obj_perms_manage_group.html" user_can_access_owned_objects_only = False - user_owned_objects_field = 'user' + user_owned_objects_field = "user" user_can_access_owned_by_group_objects_only = False - group_owned_objects_field = 'group' + group_owned_objects_field = "group" include_object_permissions_urls = True def get_queryset(self, request): @@ -67,7 +69,7 @@ def get_queryset(self, request): if self.user_can_access_owned_by_group_objects_only: User = get_user_model() user_rel_name = User.groups.field.related_query_name() - qs_key = '{}__{}'.format(self.group_owned_objects_field, user_rel_name) + qs_key = "{}__{}".format(self.group_owned_objects_field, user_rel_name) filters = {qs_key: request.user} qs = qs.filter(**filters) return qs @@ -89,18 +91,21 @@ def get_urls(self): if self.include_object_permissions_urls: info = self.model._meta.app_label, self.model._meta.model_name myurls = [ - path('/permissions/', - view=self.admin_site.admin_view( - self.obj_perms_manage_view), - name='%s_%s_permissions' % info), - path('/permissions/user-manage//', - view=self.admin_site.admin_view( - self.obj_perms_manage_user_view), - name='%s_%s_permissions_manage_user' % info), - path('/permissions/group-manage//', - view=self.admin_site.admin_view( - self.obj_perms_manage_group_view), - name='%s_%s_permissions_manage_group' % info), + path( + "/permissions/", + view=self.admin_site.admin_view(self.obj_perms_manage_view), + name="%s_%s_permissions" % info, + ), + path( + "/permissions/user-manage//", + view=self.admin_site.admin_view(self.obj_perms_manage_user_view), + name="%s_%s_permissions_manage_user" % info, + ), + path( + "/permissions/group-manage//", + view=self.admin_site.admin_view(self.obj_perms_manage_group_view), + name="%s_%s_permissions_manage_group" % info, + ), ] urls = myurls + urls return urls @@ -112,17 +117,19 @@ def get_obj_perms_base_context(self, request, obj): making sure all required template vars are in the context. """ context = self.admin_site.each_context(request) - context.update({ - 'adminform': {'model_admin': self}, - 'media': self.media, - 'object': obj, - 'app_label': self.model._meta.app_label, - 'opts': self.model._meta, - 'original': str(obj), - 'has_change_permission': self.has_change_permission(request, obj), - 'model_perms': get_perms_for_model(obj), - 'title': _("Object permissions"), - }) + context.update( + { + "adminform": {"model_admin": self}, + "media": self.media, + "object": obj, + "app_label": self.model._meta.app_label, + "opts": self.model._meta, + "original": str(obj), + "has_change_permission": self.has_change_permission(request, obj), + "model_perms": get_perms_for_model(obj), + "title": _("Object permissions"), + } + ) return context def obj_perms_manage_view(self, request, object_pk): @@ -134,60 +141,54 @@ def obj_perms_manage_view(self, request, object_pk): forms presented within the page. """ if not self.has_change_permission(request, None): - post_url = reverse('admin:index', current_app=self.admin_site.name) + post_url = reverse("admin:index", current_app=self.admin_site.name) return redirect(post_url) from django.contrib.admin.utils import unquote - obj = get_object_or_404(self.get_queryset( - request), pk=unquote(object_pk)) + + obj = get_object_or_404(self.get_queryset(request), pk=unquote(object_pk)) users_perms = OrderedDict( sorted( - get_users_with_perms(obj, attach_perms=True, - with_group_users=False).items(), - key=lambda user: getattr( - user[0], get_user_model().USERNAME_FIELD) + get_users_with_perms( + obj, attach_perms=True, with_group_users=False + ).items(), + key=lambda user: getattr(user[0], get_user_model().USERNAME_FIELD), ) ) groups_perms = OrderedDict( sorted( get_groups_with_perms(obj, attach_perms=True).items(), - key=lambda group: group[0].name + key=lambda group: group[0].name, ) ) - if request.method == 'POST' and 'submit_manage_user' in request.POST: - user_form = self.get_obj_perms_user_select_form( - request)(request.POST) - group_form = self.get_obj_perms_group_select_form( - request)(request.POST) + if request.method == "POST" and "submit_manage_user" in request.POST: + user_form = self.get_obj_perms_user_select_form(request)(request.POST) + group_form = self.get_obj_perms_group_select_form(request)(request.POST) info = ( self.admin_site.name, self.model._meta.app_label, self.model._meta.model_name, ) if user_form.is_valid(): - user_id = user_form.cleaned_data['user'].pk + user_id = user_form.cleaned_data["user"].pk url = reverse( - '%s:%s_%s_permissions_manage_user' % info, - args=[obj.pk, user_id] + "%s:%s_%s_permissions_manage_user" % info, args=[obj.pk, user_id] ) return redirect(url) - elif request.method == 'POST' and 'submit_manage_group' in request.POST: - user_form = self.get_obj_perms_user_select_form( - request)(request.POST) - group_form = self.get_obj_perms_group_select_form( - request)(request.POST) + elif request.method == "POST" and "submit_manage_group" in request.POST: + user_form = self.get_obj_perms_user_select_form(request)(request.POST) + group_form = self.get_obj_perms_group_select_form(request)(request.POST) info = ( self.admin_site.name, self.model._meta.app_label, self.model._meta.model_name, ) if group_form.is_valid(): - group_id = group_form.cleaned_data['group'].id + group_id = group_form.cleaned_data["group"].id url = reverse( - '%s:%s_%s_permissions_manage_group' % info, - args=[obj.pk, group_id] + "%s:%s_%s_permissions_manage_group" % info, args=[obj.pk, group_id] ) return redirect(url) else: @@ -195,10 +196,10 @@ def obj_perms_manage_view(self, request, object_pk): group_form = self.get_obj_perms_group_select_form(request)() context = self.get_obj_perms_base_context(request, obj) - context['users_perms'] = users_perms - context['groups_perms'] = groups_perms - context['user_form'] = user_form - context['group_form'] = group_form + context["users_perms"] = users_perms + context["groups_perms"] = groups_perms + context["user_form"] = user_form + context["group_form"] = group_form # https://github.com/django/django/commit/cf1f36bb6eb34fafe6c224003ad585a647f6117b request.current_app = self.admin_site.name @@ -215,8 +216,8 @@ def get_obj_perms_manage_template(self): return ``"admin/guardian/grappelli/obj_perms_manage.html"``. """ - if 'grappelli' in settings.INSTALLED_APPS: - return 'admin/guardian/contrib/grappelli/obj_perms_manage.html' + if "grappelli" in settings.INSTALLED_APPS: + return "admin/guardian/contrib/grappelli/obj_perms_manage.html" return self.obj_perms_manage_template def obj_perms_manage_user_view(self, request, object_pk, user_id): @@ -224,7 +225,7 @@ def obj_perms_manage_user_view(self, request, object_pk, user_id): Manages selected users' permissions for current object. """ if not self.has_change_permission(request, None): - post_url = reverse('admin:index', current_app=self.admin_site.name) + post_url = reverse("admin:index", current_app=self.admin_site.name) return redirect(post_url) user = get_object_or_404(get_user_model(), pk=user_id) @@ -232,7 +233,7 @@ def obj_perms_manage_user_view(self, request, object_pk, user_id): form_class = self.get_obj_perms_manage_user_form(request) form = form_class(user, obj, request.POST or None) - if request.method == 'POST' and form.is_valid(): + if request.method == "POST" and form.is_valid(): form.save_obj_perms() msg = gettext("Permissions saved.") messages.success(request, msg) @@ -242,15 +243,14 @@ def obj_perms_manage_user_view(self, request, object_pk, user_id): self.model._meta.model_name, ) url = reverse( - '%s:%s_%s_permissions_manage_user' % info, - args=[obj.pk, user.pk] + "%s:%s_%s_permissions_manage_user" % info, args=[obj.pk, user.pk] ) return redirect(url) context = self.get_obj_perms_base_context(request, obj) - context['user_obj'] = user - context['user_perms'] = get_user_perms(user, obj) - context['form'] = form + context["user_obj"] = user + context["user_perms"] = get_user_perms(user, obj) + context["form"] = form request.current_app = self.admin_site.name @@ -266,8 +266,8 @@ def get_obj_perms_manage_user_template(self): return ``"admin/guardian/grappelli/obj_perms_manage_user.html"``. """ - if 'grappelli' in settings.INSTALLED_APPS: - return 'admin/guardian/contrib/grappelli/obj_perms_manage_user.html' + if "grappelli" in settings.INSTALLED_APPS: + return "admin/guardian/contrib/grappelli/obj_perms_manage_user.html" return self.obj_perms_manage_user_template def get_obj_perms_user_select_form(self, request): @@ -296,7 +296,7 @@ def obj_perms_manage_group_view(self, request, object_pk, group_id): Manages selected groups' permissions for current object. """ if not self.has_change_permission(request, None): - post_url = reverse('admin:index', current_app=self.admin_site.name) + post_url = reverse("admin:index", current_app=self.admin_site.name) return redirect(post_url) group = get_object_or_404(Group, id=group_id) @@ -304,7 +304,7 @@ def obj_perms_manage_group_view(self, request, object_pk, group_id): form_class = self.get_obj_perms_manage_group_form(request) form = form_class(group, obj, request.POST or None) - if request.method == 'POST' and form.is_valid(): + if request.method == "POST" and form.is_valid(): form.save_obj_perms() msg = gettext("Permissions saved.") messages.success(request, msg) @@ -314,15 +314,14 @@ def obj_perms_manage_group_view(self, request, object_pk, group_id): self.model._meta.model_name, ) url = reverse( - '%s:%s_%s_permissions_manage_group' % info, - args=[obj.pk, group.id] + "%s:%s_%s_permissions_manage_group" % info, args=[obj.pk, group.id] ) return redirect(url) context = self.get_obj_perms_base_context(request, obj) - context['group_obj'] = group - context['group_perms'] = get_group_perms(group, obj) - context['form'] = form + context["group_obj"] = group + context["group_perms"] = get_group_perms(group, obj) + context["form"] = form request.current_app = self.admin_site.name @@ -338,8 +337,8 @@ def get_obj_perms_manage_group_template(self): return ``"admin/guardian/grappelli/obj_perms_manage_group.html"``. """ - if 'grappelli' in settings.INSTALLED_APPS: - return 'admin/guardian/contrib/grappelli/obj_perms_manage_group.html' + if "grappelli" in settings.INSTALLED_APPS: + return "admin/guardian/contrib/grappelli/obj_perms_manage_group.html" return self.obj_perms_manage_group_template def get_obj_perms_manage_group_form(self, request): @@ -431,44 +430,46 @@ class AuthorAdmin(GuardedModelAdmin): class UserManage(forms.Form): - user = forms.CharField(label=_("User identification"), - max_length=200, - error_messages={'does_not_exist': _( - "This user does not exist")}, - help_text=_( - 'Enter a value compatible with User.USERNAME_FIELD') - ) + user = forms.CharField( + label=_("User identification"), + max_length=200, + error_messages={"does_not_exist": _("This user does not exist")}, + help_text=_("Enter a value compatible with User.USERNAME_FIELD"), + ) def clean_user(self): """ Returns ``User`` instance based on the given identification. """ - identification = self.cleaned_data['user'] + identification = self.cleaned_data["user"] user_model = get_user_model() try: username_field = user_model.USERNAME_FIELD except AttributeError: - username_field = 'username' + username_field = "username" try: user = user_model.objects.get(**{username_field: identification}) return user except user_model.DoesNotExist: raise forms.ValidationError( - self.fields['user'].error_messages['does_not_exist']) + self.fields["user"].error_messages["does_not_exist"] + ) class GroupManage(forms.Form): - group = forms.CharField(max_length=80, error_messages={'does_not_exist': - _("This group does not exist")}) + group = forms.CharField( + max_length=80, error_messages={"does_not_exist": _("This group does not exist")} + ) def clean_group(self): """ Returns ``Group`` instance based on the given group name. """ - name = self.cleaned_data['group'] + name = self.cleaned_data["group"] try: group = Group.objects.get(name=name) return group except Group.DoesNotExist: raise forms.ValidationError( - self.fields['group'].error_messages['does_not_exist']) + self.fields["group"].error_messages["does_not_exist"] + ) diff --git a/guardian/apps.py b/guardian/apps.py index 31adad480..452739378 100644 --- a/guardian/apps.py +++ b/guardian/apps.py @@ -4,7 +4,7 @@ class GuardianConfig(AppConfig): - name = 'guardian' + name = "guardian" def ready(self): # Must patch Group here since generic diff --git a/guardian/backends.py b/guardian/backends.py index 5e03f407a..550603ac8 100644 --- a/guardian/backends.py +++ b/guardian/backends.py @@ -80,17 +80,19 @@ def has_perm(self, user_obj, perm, obj=None): if not support: return False - if '.' in perm: - app_label, _ = perm.split('.', 1) + if "." in perm: + app_label, _ = perm.split(".", 1) if app_label != obj._meta.app_label: # Check the content_type app_label when permission # and obj app labels don't match. ctype = get_content_type(obj) if app_label != ctype.app_label: - raise WrongAppError("Passed perm has app label of '%s' while " - "given obj has app label '%s' and given obj" - "content_type has app label '%s'" % - (app_label, obj._meta.app_label, ctype.app_label)) + raise WrongAppError( + "Passed perm has app label of '%s' while " + "given obj has app label '%s' and given obj" + "content_type has app label '%s'" + % (app_label, obj._meta.app_label, ctype.app_label) + ) check = ObjectPermissionChecker(user_obj) return check.has_perm(perm, obj) diff --git a/guardian/checks.py b/guardian/checks.py index e719dd400..ecffb4ab1 100644 --- a/guardian/checks.py +++ b/guardian/checks.py @@ -5,15 +5,20 @@ # noinspection PyUnusedLocal @register(Tags.compatibility) def check_settings(app_configs, **kwargs): - """ Check that settings are implemented properly + """Check that settings are implemented properly :param app_configs: a list of apps to be checks or None for all :param kwargs: keyword arguments :return: a list of errors """ checks = [] - if 'guardian.backends.ObjectPermissionBackend' not in settings.AUTHENTICATION_BACKENDS: - msg = ("Guardian authentication backend is not hooked. You can add this in settings as eg: " - "`AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend', " - "'guardian.backends.ObjectPermissionBackend')`.") - checks.append(Warning(msg, id='guardian.W001')) + if ( + "guardian.backends.ObjectPermissionBackend" + not in settings.AUTHENTICATION_BACKENDS + ): + msg = ( + "Guardian authentication backend is not hooked. You can add this in settings as eg: " + "`AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend', " + "'guardian.backends.ObjectPermissionBackend')`." + ) + checks.append(Warning(msg, id="guardian.W001")) return checks diff --git a/guardian/compat.py b/guardian/compat.py index 515459c17..918ff6589 100644 --- a/guardian/compat.py +++ b/guardian/compat.py @@ -4,21 +4,21 @@ from django.contrib.auth.models import AnonymousUser, Group, Permission __all__ = [ - 'Group', - 'Permission', - 'AnonymousUser', - 'get_user_model', - 'user_model_label', - 'include', - 'handler404', - 'handler500', + "Group", + "Permission", + "AnonymousUser", + "get_user_model", + "user_model_label", + "include", + "handler404", + "handler500", ] # Since get_user_model() causes a circular import if called when app models are # being loaded, the user_model_label should be used when possible, with calls # to get_user_model deferred to execution time -user_model_label = getattr(settings, 'AUTH_USER_MODEL', 'auth.User') +user_model_label = getattr(settings, "AUTH_USER_MODEL", "auth.User") def get_user_model_path(): @@ -27,7 +27,7 @@ def get_user_model_path(): ``AUTH_USER_MODEL`` is set at settings it would be returned, otherwise ``auth.User`` is returned. """ - return getattr(settings, 'AUTH_USER_MODEL', 'auth.User') + return getattr(settings, "AUTH_USER_MODEL", "auth.User") def get_user_permission_full_codename(perm): @@ -38,7 +38,7 @@ def get_user_permission_full_codename(perm): """ User = get_user_model() model_name = User._meta.model_name - return '{}.{}_{}'.format(User._meta.app_label, perm, model_name) + return "{}.{}_{}".format(User._meta.app_label, perm, model_name) def get_user_permission_codename(perm): @@ -47,4 +47,4 @@ def get_user_permission_codename(perm): used, for 'change' perm this would return ``change_user`` and if ``myapp.CustomUser`` is used it would return ``change_customuser``. """ - return get_user_permission_full_codename(perm).split('.')[1] + return get_user_permission_full_codename(perm).split(".")[1] diff --git a/guardian/conf/settings.py b/guardian/conf/settings.py index 34587c7d1..a4d8c002a 100644 --- a/guardian/conf/settings.py +++ b/guardian/conf/settings.py @@ -7,33 +7,48 @@ except AttributeError: try: ANONYMOUS_USER_NAME = settings.ANONYMOUS_DEFAULT_USERNAME_VALUE - warnings.warn("The ANONYMOUS_DEFAULT_USERNAME_VALUE setting has been renamed to ANONYMOUS_USER_NAME.", DeprecationWarning) + warnings.warn( + "The ANONYMOUS_DEFAULT_USERNAME_VALUE setting has been renamed to ANONYMOUS_USER_NAME.", + DeprecationWarning, + ) except AttributeError: ANONYMOUS_USER_NAME = "AnonymousUser" -RENDER_403 = getattr(settings, 'GUARDIAN_RENDER_403', False) -TEMPLATE_403 = getattr(settings, 'GUARDIAN_TEMPLATE_403', '403.html') -RAISE_403 = getattr(settings, 'GUARDIAN_RAISE_403', False) -RENDER_404 = getattr(settings, 'GUARDIAN_RENDER_404', False) -TEMPLATE_404 = getattr(settings, 'GUARDIAN_TEMPLATE_404', '404.html') -RAISE_404 = getattr(settings, 'GUARDIAN_RAISE_404', False) -GET_INIT_ANONYMOUS_USER = getattr(settings, 'GUARDIAN_GET_INIT_ANONYMOUS_USER', - 'guardian.management.get_init_anonymous_user') +RENDER_403 = getattr(settings, "GUARDIAN_RENDER_403", False) +TEMPLATE_403 = getattr(settings, "GUARDIAN_TEMPLATE_403", "403.html") +RAISE_403 = getattr(settings, "GUARDIAN_RAISE_403", False) +RENDER_404 = getattr(settings, "GUARDIAN_RENDER_404", False) +TEMPLATE_404 = getattr(settings, "GUARDIAN_TEMPLATE_404", "404.html") +RAISE_404 = getattr(settings, "GUARDIAN_RAISE_404", False) +GET_INIT_ANONYMOUS_USER = getattr( + settings, + "GUARDIAN_GET_INIT_ANONYMOUS_USER", + "guardian.management.get_init_anonymous_user", +) -MONKEY_PATCH = getattr(settings, 'GUARDIAN_MONKEY_PATCH', True) +MONKEY_PATCH = getattr(settings, "GUARDIAN_MONKEY_PATCH", True) -GET_CONTENT_TYPE = getattr(settings, 'GUARDIAN_GET_CONTENT_TYPE', 'guardian.ctypes.get_default_content_type') +GET_CONTENT_TYPE = getattr( + settings, "GUARDIAN_GET_CONTENT_TYPE", "guardian.ctypes.get_default_content_type" +) -AUTO_PREFETCH = getattr(settings, 'GUARDIAN_AUTO_PREFETCH', False) +AUTO_PREFETCH = getattr(settings, "GUARDIAN_AUTO_PREFETCH", False) # Default to using guardian supplied generic object permission models -USER_OBJ_PERMS_MODEL = getattr(settings, 'GUARDIAN_USER_OBJ_PERMS_MODEL', 'guardian.UserObjectPermission') -GROUP_OBJ_PERMS_MODEL = getattr(settings, 'GUARDIAN_GROUP_OBJ_PERMS_MODEL', 'guardian.GroupObjectPermission') +USER_OBJ_PERMS_MODEL = getattr( + settings, "GUARDIAN_USER_OBJ_PERMS_MODEL", "guardian.UserObjectPermission" +) +GROUP_OBJ_PERMS_MODEL = getattr( + settings, "GUARDIAN_GROUP_OBJ_PERMS_MODEL", "guardian.GroupObjectPermission" +) def check_configuration(): if RENDER_403 and RAISE_403: - raise ImproperlyConfigured("Cannot use both GUARDIAN_RENDER_403 AND " - "GUARDIAN_RAISE_403 - only one of this config may be True") + raise ImproperlyConfigured( + "Cannot use both GUARDIAN_RENDER_403 AND " + "GUARDIAN_RAISE_403 - only one of this config may be True" + ) + check_configuration() diff --git a/guardian/core.py b/guardian/core.py index fa0722d27..2721bf4aa 100644 --- a/guardian/core.py +++ b/guardian/core.py @@ -7,7 +7,11 @@ from guardian.conf import settings as guardian_settings from guardian.ctypes import get_content_type -from guardian.utils import get_group_obj_perms_model, get_identity, get_user_obj_perms_model +from guardian.utils import ( + get_group_obj_perms_model, + get_identity, + get_user_obj_perms_model, +) def _get_pks_model_and_ctype(objects): @@ -18,7 +22,7 @@ def _get_pks_model_and_ctype(objects): if isinstance(objects, QuerySet): model = objects.model - pks = [force_str(pk) for pk in objects.values_list('pk', flat=True)] + pks = [force_str(pk) for pk in objects.values_list("pk", flat=True)] ctype = get_content_type(model) else: pks = [] @@ -73,8 +77,8 @@ def has_perm(self, perm, obj): return False elif self.user and self.user.is_superuser: return True - if '.' in perm: - _, perm = perm.split('.', 1) + if "." in perm: + _, perm = perm.split(".", 1) return perm in self.get_perms(obj) def get_group_filters(self, obj): @@ -84,20 +88,22 @@ def get_group_filters(self, obj): group_model = get_group_obj_perms_model(obj) group_rel_name = group_model.permission.field.related_query_name() if self.user: - fieldname = '{}__group__{}'.format( + fieldname = "{}__group__{}".format( group_rel_name, User.groups.field.related_query_name(), ) group_filters = {fieldname: self.user} else: - group_filters = {'%s__group' % group_rel_name: self.group} + group_filters = {"%s__group" % group_rel_name: self.group} if group_model.objects.is_generic(): - group_filters.update({ - '%s__content_type' % group_rel_name: ctype, - '%s__object_pk' % group_rel_name: obj.pk, - }) + group_filters.update( + { + "%s__content_type" % group_rel_name: ctype, + "%s__object_pk" % group_rel_name: obj.pk, + } + ) else: - group_filters['%s__content_object' % group_rel_name] = obj + group_filters["%s__content_object" % group_rel_name] = obj return group_filters @@ -106,14 +112,16 @@ def get_user_filters(self, obj): model = get_user_obj_perms_model(obj) related_name = model.permission.field.related_query_name() - user_filters = {'%s__user' % related_name: self.user} + user_filters = {"%s__user" % related_name: self.user} if model.objects.is_generic(): - user_filters.update({ - '%s__content_type' % related_name: ctype, - '%s__object_pk' % related_name: obj.pk, - }) + user_filters.update( + { + "%s__content_type" % related_name: ctype, + "%s__object_pk" % related_name: obj.pk, + } + ) else: - user_filters['%s__content_object' % related_name] = obj + user_filters["%s__content_object" % related_name] = obj return user_filters @@ -157,9 +165,13 @@ def get_perms(self, obj): if guardian_settings.AUTO_PREFETCH: return [] if self.user and self.user.is_superuser: - perms = list(chain(*Permission.objects - .filter(content_type=ctype) - .values_list("codename"))) + perms = list( + chain( + *Permission.objects.filter(content_type=ctype).values_list( + "codename" + ) + ) + ) elif self.user: # Query user and group permissions separately and then combine # the results to avoid a slow query @@ -192,10 +204,13 @@ def prefetch_perms(self, objects): pks, model, ctype = _get_pks_model_and_ctype(objects) if self.user and self.user.is_superuser: - perms = list(chain( - *Permission.objects - .filter(content_type=ctype) - .values_list("codename"))) + perms = list( + chain( + *Permission.objects.filter(content_type=ctype).values_list( + "codename" + ) + ) + ) for pk in pks: key = (ctype.id, force_str(pk)) @@ -206,47 +221,50 @@ def prefetch_perms(self, objects): group_model = get_group_obj_perms_model(model) if self.user: - fieldname = 'group__{}'.format( + fieldname = "group__{}".format( User.groups.field.related_query_name(), ) group_filters = {fieldname: self.user} else: - group_filters = {'group': self.group} + group_filters = {"group": self.group} if group_model.objects.is_generic(): - group_filters.update({ - 'content_type': ctype, - 'object_pk__in': pks, - }) + group_filters.update( + { + "content_type": ctype, + "object_pk__in": pks, + } + ) else: - group_filters.update({ - 'content_object_id__in': pks - }) + group_filters.update({"content_object_id__in": pks}) if self.user: model = get_user_obj_perms_model(model) user_filters = { - 'user': self.user, + "user": self.user, } if model.objects.is_generic(): - user_filters.update({ - 'content_type': ctype, - 'object_pk__in': pks - }) + user_filters.update({"content_type": ctype, "object_pk__in": pks}) else: - user_filters.update({ - 'content_object_id__in': pks - }) + user_filters.update({"content_object_id__in": pks}) # Query user and group permissions separately and then combine # the results to avoid a slow query - user_perms_qs = model.objects.filter(**user_filters).select_related('permission') - group_perms_qs = group_model.objects.filter(**group_filters).select_related('permission') + user_perms_qs = model.objects.filter(**user_filters).select_related( + "permission" + ) + group_perms_qs = group_model.objects.filter(**group_filters).select_related( + "permission" + ) perms = chain(user_perms_qs, group_perms_qs) else: perms = chain( - *(group_model.objects.filter(**group_filters).select_related('permission'),) + *( + group_model.objects.filter(**group_filters).select_related( + "permission" + ), + ) ) # initialize entry in '_obj_perms_cache' for all prefetched objects @@ -269,12 +287,15 @@ def prefetch_perms(self, objects): def _init_obj_prefetch_cache(obj, *querysets): cache = {} for qs in querysets: - perms = qs.select_related('permission__codename').values_list('content_type_id', 'object_pk', - 'permission__codename') + perms = qs.select_related("permission__codename").values_list( + "content_type_id", "object_pk", "permission__codename" + ) for p in perms: if p[:2] not in cache: cache[p[:2]] = [] - cache[p[:2]] += [p[2], ] + cache[p[:2]] += [ + p[2], + ] obj._guardian_perms_cache = cache return obj, cache @@ -285,7 +306,7 @@ def _prefetch_cache(self): obj = self.user querysets = [ UserObjectPermission.objects.filter(user=obj), - GroupObjectPermission.objects.filter(group__user=obj) + GroupObjectPermission.objects.filter(group__user=obj), ] else: obj = self.group @@ -293,7 +314,7 @@ def _prefetch_cache(self): GroupObjectPermission.objects.filter(group=obj), ] - if not hasattr(obj, '_guardian_perms_cache'): + if not hasattr(obj, "_guardian_perms_cache"): obj, cache = self._init_obj_prefetch_cache(obj, *querysets) else: cache = obj._guardian_perms_cache diff --git a/guardian/ctypes.py b/guardian/ctypes.py index f61b3b2df..05b696fa0 100644 --- a/guardian/ctypes.py +++ b/guardian/ctypes.py @@ -5,8 +5,7 @@ def get_content_type(obj): - get_content_type_function = import_string( - guardian_settings.GET_CONTENT_TYPE) + get_content_type_function = import_string(guardian_settings.GET_CONTENT_TYPE) return get_content_type_function(obj) diff --git a/guardian/decorators.py b/guardian/decorators.py index f65cae5f2..8938dc237 100644 --- a/guardian/decorators.py +++ b/guardian/decorators.py @@ -71,18 +71,19 @@ def my_view(request, username, group_name): return user.get_absolute_url() """ - login_url = kwargs.pop('login_url', settings.LOGIN_URL) - redirect_field_name = kwargs.pop( - 'redirect_field_name', REDIRECT_FIELD_NAME) - return_403 = kwargs.pop('return_403', False) - return_404 = kwargs.pop('return_404', False) - accept_global_perms = kwargs.pop('accept_global_perms', False) + login_url = kwargs.pop("login_url", settings.LOGIN_URL) + redirect_field_name = kwargs.pop("redirect_field_name", REDIRECT_FIELD_NAME) + return_403 = kwargs.pop("return_403", False) + return_404 = kwargs.pop("return_404", False) + accept_global_perms = kwargs.pop("accept_global_perms", False) # Check if perm is given as string in order not to decorate # view function itself which makes debugging harder if not isinstance(perm, str): - raise GuardianError("First argument must be in format: " - "'app_label.codename or a callable which return similar string'") + raise GuardianError( + "First argument must be in format: " + "'app_label.codename or a callable which return similar string'" + ) def decorator(view_func): def _wrapped_view(request, *args, **kwargs): @@ -93,36 +94,53 @@ def _wrapped_view(request, *args, **kwargs): model, lookups = lookup_variables[0], lookup_variables[1:] # Parse model if isinstance(model, str): - splitted = model.split('.') + splitted = model.split(".") if len(splitted) != 2: - raise GuardianError("If model should be looked up from " - "string it needs format: 'app_label.ModelClass'") + raise GuardianError( + "If model should be looked up from " + "string it needs format: 'app_label.ModelClass'" + ) model = apps.get_model(*splitted) elif issubclass(model.__class__, (Model, ModelBase, QuerySet)): pass else: - raise GuardianError("First lookup argument must always be " - "a model, string pointing at app/model or queryset. " - "Given: %s (type: %s)" % (model, type(model))) + raise GuardianError( + "First lookup argument must always be " + "a model, string pointing at app/model or queryset. " + "Given: %s (type: %s)" % (model, type(model)) + ) # Parse lookups if len(lookups) % 2 != 0: - raise GuardianError("Lookup variables must be provided " - "as pairs of lookup_string and view_arg") + raise GuardianError( + "Lookup variables must be provided " + "as pairs of lookup_string and view_arg" + ) lookup_dict = {} for lookup, view_arg in zip(lookups[::2], lookups[1::2]): if view_arg not in kwargs: - raise GuardianError("Argument %s was not passed " - "into view function" % view_arg) + raise GuardianError( + "Argument %s was not passed " + "into view function" % view_arg + ) lookup_dict[lookup] = kwargs[view_arg] obj = get_object_or_404(model, **lookup_dict) - response = get_40x_or_None(request, perms=[perm], obj=obj, - login_url=login_url, redirect_field_name=redirect_field_name, - return_403=return_403, return_404=return_404, accept_global_perms=accept_global_perms) + response = get_40x_or_None( + request, + perms=[perm], + obj=obj, + login_url=login_url, + redirect_field_name=redirect_field_name, + return_403=return_403, + return_404=return_404, + accept_global_perms=accept_global_perms, + ) if response: return response return view_func(request, *args, **kwargs) + return wraps(view_func)(_wrapped_view) + return decorator @@ -137,7 +155,7 @@ def permission_required_or_403(perm, *args, **kwargs): The only difference between ``permission_required`` decorator is that this one always set ``return_403`` parameter to ``True``. """ - kwargs['return_403'] = True + kwargs["return_403"] = True return permission_required(perm, *args, **kwargs) @@ -152,5 +170,5 @@ def permission_required_or_404(perm, *args, **kwargs): The only difference between ``permission_required`` decorator is that this one always set ``return_404`` parameter to ``True``. """ - kwargs['return_404'] = True + kwargs["return_404"] = True return permission_required(perm, *args, **kwargs) diff --git a/guardian/forms.py b/guardian/forms.py index ea6107f7f..01e9e1ef1 100644 --- a/guardian/forms.py +++ b/guardian/forms.py @@ -1,6 +1,12 @@ from django import forms from django.utils.translation import gettext as _ -from guardian.shortcuts import assign_perm, get_group_perms, get_perms_for_model, get_user_perms, remove_perm +from guardian.shortcuts import ( + assign_perm, + get_group_perms, + get_perms_for_model, + get_user_perms, + remove_perm, +) class BaseObjectPermissionsForm(forms.Form): @@ -41,7 +47,7 @@ def get_obj_perms_field_name(self): Returns name of the object permissions management field. Default: ``permission``. """ - return 'permissions' + return "permissions" def get_obj_perms_field_label(self): """ diff --git a/guardian/management/__init__.py b/guardian/management/__init__.py index 6dda55948..36e5744cd 100644 --- a/guardian/management/__init__.py +++ b/guardian/management/__init__.py @@ -12,9 +12,7 @@ def get_init_anonymous_user(User): :param User: User model - result of ``django.contrib.auth.get_user_model``. """ - kwargs = { - User.USERNAME_FIELD: guardian_settings.ANONYMOUS_USER_NAME - } + kwargs = {User.USERNAME_FIELD: guardian_settings.ANONYMOUS_USER_NAME} user = User(**kwargs) user.set_unusable_password() return user @@ -25,20 +23,26 @@ def create_anonymous_user(sender, **kwargs): Creates anonymous User instance with id and username from settings. """ User = get_user_model() - if not router.allow_migrate_model(kwargs['using'], User): + if not router.allow_migrate_model(kwargs["using"], User): return try: lookup = {User.USERNAME_FIELD: guardian_settings.ANONYMOUS_USER_NAME} - User.objects.using(kwargs['using']).get(**lookup) + User.objects.using(kwargs["using"]).get(**lookup) except User.DoesNotExist: retrieve_anonymous_function = import_string( - guardian_settings.GET_INIT_ANONYMOUS_USER) + guardian_settings.GET_INIT_ANONYMOUS_USER + ) user = retrieve_anonymous_function(User) - user.save(using=kwargs['using']) + user.save(using=kwargs["using"]) + # Only create an anonymous user if support is enabled. if guardian_settings.ANONYMOUS_USER_NAME is not None: from django.apps import apps - guardian_app = apps.get_app_config('guardian') - signals.post_migrate.connect(create_anonymous_user, sender=guardian_app, - dispatch_uid="guardian.management.create_anonymous_user") + + guardian_app = apps.get_app_config("guardian") + signals.post_migrate.connect( + create_anonymous_user, + sender=guardian_app, + dispatch_uid="guardian.management.create_anonymous_user", + ) diff --git a/guardian/management/commands/clean_orphan_obj_perms.py b/guardian/management/commands/clean_orphan_obj_perms.py index 86d2f696d..2df579bf3 100644 --- a/guardian/management/commands/clean_orphan_obj_perms.py +++ b/guardian/management/commands/clean_orphan_obj_perms.py @@ -14,10 +14,10 @@ class Command(BaseCommand): Removed 11 object permission entries with no targets """ + help = "Removes object permissions with not existing targets" def handle(self, **options): removed = clean_orphan_obj_perms() - if options['verbosity'] > 0: - print("Removed %d object permission entries with no targets" % - removed) + if options["verbosity"] > 0: + print("Removed %d object permission entries with no targets" % removed) diff --git a/guardian/managers.py b/guardian/managers.py index d9f2f0bbc..52ac136b3 100644 --- a/guardian/managers.py +++ b/guardian/managers.py @@ -10,18 +10,17 @@ class BaseObjectPermissionManager(models.Manager): - @property def user_or_group_field(self): try: - self.model._meta.get_field('user') - return 'user' + self.model._meta.get_field("user") + return "user" except FieldDoesNotExist: - return 'group' + return "group" def is_generic(self): try: - self.model._meta.get_field('object_pk') + self.model._meta.get_field("object_pk") return True except FieldDoesNotExist: return False @@ -31,21 +30,20 @@ def assign_perm(self, perm, user_or_group, obj): Assigns permission with given ``perm`` for an instance ``obj`` and ``user``. """ - if getattr(obj, 'pk', None) is None: - raise ObjectNotPersisted("Object %s needs to be persisted first" - % obj) + if getattr(obj, "pk", None) is None: + raise ObjectNotPersisted("Object %s needs to be persisted first" % obj) ctype = get_content_type(obj) if not isinstance(perm, Permission): permission = Permission.objects.get(content_type=ctype, codename=perm) else: permission = perm - kwargs = {'permission': permission, self.user_or_group_field: user_or_group} + kwargs = {"permission": permission, self.user_or_group_field: user_or_group} if self.is_generic(): - kwargs['content_type'] = ctype - kwargs['object_pk'] = obj.pk + kwargs["content_type"] = ctype + kwargs["object_pk"] = obj.pk else: - kwargs['content_object'] = obj + kwargs["content_object"] = obj obj_perm, _ = self.get_or_create(**kwargs) return obj_perm @@ -70,12 +68,15 @@ def bulk_assign_perm(self, perm, user_or_group, queryset): assigned_perms = [] for instance in queryset: if not checker.has_perm(permission.codename, instance): - kwargs = {'permission': permission, self.user_or_group_field: user_or_group} + kwargs = { + "permission": permission, + self.user_or_group_field: user_or_group, + } if self.is_generic(): - kwargs['content_type'] = ctype - kwargs['object_pk'] = instance.pk + kwargs["content_type"] = ctype + kwargs["object_pk"] = instance.pk else: - kwargs['content_object'] = instance + kwargs["content_object"] = instance assigned_perms.append(self.model(**kwargs)) self.model.objects.bulk_create(assigned_perms) @@ -87,31 +88,31 @@ def assign_perm_to_many(self, perm, users_or_groups, obj): """ ctype = get_content_type(obj) if not isinstance(perm, Permission): - permission = Permission.objects.get(content_type=ctype, - codename=perm) + permission = Permission.objects.get(content_type=ctype, codename=perm) else: permission = perm - kwargs = {'permission': permission} + kwargs = {"permission": permission} if self.is_generic(): - kwargs['content_type'] = ctype - kwargs['object_pk'] = obj.pk + kwargs["content_type"] = ctype + kwargs["object_pk"] = obj.pk else: - kwargs['content_object'] = obj + kwargs["content_object"] = obj to_add = [] field = self.user_or_group_field for user in users_or_groups: kwargs[field] = user - to_add.append( - self.model(**kwargs) - ) + to_add.append(self.model(**kwargs)) return self.model.objects.bulk_create(to_add) def assign(self, perm, user_or_group, obj): - """ Depreciated function name left in for compatibility""" - 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) + """Depreciated function name left in for compatibility""" + 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, + ) return self.assign_perm(perm, user_or_group, obj) def remove_perm(self, perm, user_or_group, obj): @@ -122,17 +123,18 @@ def remove_perm(self, perm, user_or_group, obj): use ``Queryset.delete`` method for removing it. Main implication of this is that ``post_delete`` signals would NOT be fired. """ - if getattr(obj, 'pk', None) is None: - raise ObjectNotPersisted("Object %s needs to be persisted first" - % obj) + if getattr(obj, "pk", None) is None: + raise ObjectNotPersisted("Object %s needs to be persisted first" % obj) filters = Q(**{self.user_or_group_field: user_or_group}) if isinstance(perm, Permission): filters &= Q(permission=perm) else: - filters &= Q(permission__codename=perm, - permission__content_type=get_content_type(obj)) + filters &= Q( + permission__codename=perm, + permission__content_type=get_content_type(obj), + ) if self.is_generic(): filters &= Q(object_pk=obj.pk) @@ -154,11 +156,12 @@ def bulk_remove_perm(self, perm, user_or_group, queryset): filters &= Q(permission=perm) else: ctype = get_content_type(queryset.model) - filters &= Q(permission__codename=perm, - permission__content_type=ctype) + filters &= Q(permission__codename=perm, permission__content_type=ctype) if self.is_generic(): - filters &= Q(object_pk__in=[str(pk) for pk in queryset.values_list('pk', flat=True)]) + filters &= Q( + object_pk__in=[str(pk) for pk in queryset.values_list("pk", flat=True)] + ) else: filters &= Q(content_object__in=queryset) diff --git a/guardian/migrations/0001_initial.py b/guardian/migrations/0001_initial.py index 3df8acc98..dc58699b8 100644 --- a/guardian/migrations/0001_initial.py +++ b/guardian/migrations/0001_initial.py @@ -5,48 +5,85 @@ class Migration(migrations.Migration): dependencies = [ - ('contenttypes', '0001_initial'), - ('auth', '0001_initial'), + ("contenttypes", "0001_initial"), + ("auth", "0001_initial"), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( - name='GroupObjectPermission', + name="GroupObjectPermission", fields=[ - ('id', models.AutoField(primary_key=True, - serialize=False, auto_created=True, verbose_name='ID')), - ('object_pk', models.CharField( - max_length=255, verbose_name='object ID')), - ('content_type', models.ForeignKey(to='contenttypes.ContentType', on_delete=models.CASCADE)), - ('group', models.ForeignKey(to='auth.Group', on_delete=models.CASCADE)), - ('permission', models.ForeignKey(to='auth.Permission', on_delete=models.CASCADE)), + ( + "id", + models.AutoField( + primary_key=True, + serialize=False, + auto_created=True, + verbose_name="ID", + ), + ), + ( + "object_pk", + models.CharField(max_length=255, verbose_name="object ID"), + ), + ( + "content_type", + models.ForeignKey( + to="contenttypes.ContentType", on_delete=models.CASCADE + ), + ), + ("group", models.ForeignKey(to="auth.Group", on_delete=models.CASCADE)), + ( + "permission", + models.ForeignKey(to="auth.Permission", on_delete=models.CASCADE), + ), ], - options={ - }, + options={}, bases=(models.Model,), ), migrations.CreateModel( - name='UserObjectPermission', + name="UserObjectPermission", fields=[ - ('id', models.AutoField(primary_key=True, - serialize=False, auto_created=True, verbose_name='ID')), - ('object_pk', models.CharField( - max_length=255, verbose_name='object ID')), - ('content_type', models.ForeignKey(to='contenttypes.ContentType', on_delete=models.CASCADE)), - ('permission', models.ForeignKey(to='auth.Permission', on_delete=models.CASCADE)), - ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)), + ( + "id", + models.AutoField( + primary_key=True, + serialize=False, + auto_created=True, + verbose_name="ID", + ), + ), + ( + "object_pk", + models.CharField(max_length=255, verbose_name="object ID"), + ), + ( + "content_type", + models.ForeignKey( + to="contenttypes.ContentType", on_delete=models.CASCADE + ), + ), + ( + "permission", + models.ForeignKey(to="auth.Permission", on_delete=models.CASCADE), + ), + ( + "user", + models.ForeignKey( + to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE + ), + ), ], - options={ - }, + options={}, bases=(models.Model,), ), migrations.AlterUniqueTogether( - name='userobjectpermission', - unique_together={('user', 'permission', 'object_pk')}, + name="userobjectpermission", + unique_together={("user", "permission", "object_pk")}, ), migrations.AlterUniqueTogether( - name='groupobjectpermission', - unique_together={('group', 'permission', 'object_pk')}, + name="groupobjectpermission", + unique_together={("group", "permission", "object_pk")}, ), ] diff --git a/guardian/migrations/0002_generic_permissions_index.py b/guardian/migrations/0002_generic_permissions_index.py index 9760785ac..d034c9f74 100644 --- a/guardian/migrations/0002_generic_permissions_index.py +++ b/guardian/migrations/0002_generic_permissions_index.py @@ -6,16 +6,22 @@ class Migration(migrations.Migration): dependencies = [ - ('guardian', '0001_initial'), + ("guardian", "0001_initial"), ] operations = [ migrations.AddIndex( - model_name='groupobjectpermission', - index=models.Index(fields=['content_type', 'object_pk'], name='guardian_gr_content_ae6aec_idx'), + model_name="groupobjectpermission", + index=models.Index( + fields=["content_type", "object_pk"], + name="guardian_gr_content_ae6aec_idx", + ), ), migrations.AddIndex( - model_name='userobjectpermission', - index=models.Index(fields=['content_type', 'object_pk'], name='guardian_us_content_179ed2_idx'), + model_name="userobjectpermission", + index=models.Index( + fields=["content_type", "object_pk"], + name="guardian_us_content_179ed2_idx", + ), ), ] diff --git a/guardian/mixins.py b/guardian/mixins.py index afaa0e92e..515984ee0 100644 --- a/guardian/mixins.py +++ b/guardian/mixins.py @@ -4,6 +4,7 @@ from django.contrib.auth.decorators import login_required, REDIRECT_FIELD_NAME from django.core.exceptions import ImproperlyConfigured, PermissionDenied from guardian.utils import get_user_obj_perms_model + UserObjectPermission = get_user_obj_perms_model() from guardian.utils import get_40x_or_None, get_anonymous_user from guardian.shortcuts import get_objects_for_user @@ -38,14 +39,14 @@ class LoginRequiredMixin: *Default*: ``settings.LOGIN_URL`` """ + redirect_field_name = REDIRECT_FIELD_NAME login_url = settings.LOGIN_URL def dispatch(self, request, *args, **kwargs): - return login_required(redirect_field_name=self.redirect_field_name, - login_url=self.login_url)( - super().dispatch - )(request, *args, **kwargs) + return login_required( + redirect_field_name=self.redirect_field_name, login_url=self.login_url + )(super().dispatch)(request, *args, **kwargs) class PermissionRequiredMixin: @@ -127,6 +128,7 @@ class SecureView(PermissionRequiredMixin, View): or ``self.object`` by default. """ + # default class view settings login_url = settings.LOGIN_URL permission_required = None @@ -149,17 +151,22 @@ def get_required_permissions(self, request=None): elif isinstance(self.permission_required, Iterable): perms = [p for p in self.permission_required] else: - raise ImproperlyConfigured("'PermissionRequiredMixin' requires " - "'permission_required' attribute to be set to " - "'.' but is set to '%s' instead" - % self.permission_required) + raise ImproperlyConfigured( + "'PermissionRequiredMixin' requires " + "'permission_required' attribute to be set to " + "'.' but is set to '%s' instead" + % self.permission_required + ) return perms def get_permission_object(self): - if hasattr(self, 'permission_object'): + if hasattr(self, "permission_object"): return self.permission_object - return (hasattr(self, 'get_object') and self.get_object() or - getattr(self, 'object', None)) + return ( + hasattr(self, "get_object") + and self.get_object() + or getattr(self, "object", None) + ) def check_permissions(self, request): """ @@ -170,16 +177,16 @@ def check_permissions(self, request): """ obj = self.get_permission_object() - forbidden = get_40x_or_None(request, - perms=self.get_required_permissions( - request), - obj=obj, - login_url=self.login_url, - redirect_field_name=self.redirect_field_name, - return_403=self.return_403, - return_404=self.return_404, - accept_global_perms=self.accept_global_perms - ) + forbidden = get_40x_or_None( + request, + perms=self.get_required_permissions(request), + obj=obj, + login_url=self.login_url, + redirect_field_name=self.redirect_field_name, + return_403=self.return_403, + return_404=self.return_404, + accept_global_perms=self.accept_global_perms, + ) if forbidden: self.on_permission_check_fail(request, forbidden, obj=obj) if forbidden and self.raise_exception: @@ -208,7 +215,6 @@ def dispatch(self, request, *args, **kwargs): class GuardianUserMixin: - @staticmethod def get_anonymous(): return get_anonymous_user() @@ -251,6 +257,7 @@ class SecureView(PermissionListMixin, ListView): *Default*: ``{}``, A extra params to pass for ```guardian.shortcuts.get_objects_for_user``` """ + permission_required = None get_objects_for_user_extra_kwargs = {} @@ -267,10 +274,12 @@ def get_required_permissions(self, request=None): elif isinstance(self.permission_required, Iterable): perms = [p for p in self.permission_required] else: - raise ImproperlyConfigured("'PermissionRequiredMixin' requires " - "'permission_required' attribute to be set to " - "'.' but is set to '%s' instead" - % self.permission_required) + raise ImproperlyConfigured( + "'PermissionRequiredMixin' requires " + "'permission_required' attribute to be set to " + "'.' but is set to '%s' instead" + % self.permission_required + ) return perms def get_get_objects_for_user_kwargs(self, queryset): @@ -279,10 +288,12 @@ def get_get_objects_for_user_kwargs(self, queryset): :param request: Queryset to filter """ - return dict(user=self.request.user, - perms=self.get_required_permissions(self.request), - klass=queryset, - **self.get_objects_for_user_extra_kwargs) + return dict( + user=self.request.user, + perms=self.get_required_permissions(self.request), + klass=queryset, + **self.get_objects_for_user_extra_kwargs + ) def get_queryset(self, *args, **kwargs): qs = super().get_queryset(*args, **kwargs) diff --git a/guardian/models/__init__.py b/guardian/models/__init__.py index daeed8d30..baa03e2f0 100644 --- a/guardian/models/__init__.py +++ b/guardian/models/__init__.py @@ -8,19 +8,19 @@ GroupObjectPermissionAbstract, GroupObjectPermission, Permission, - Group + Group, ) __all__ = [ - 'BaseObjectPermission', - 'BaseGenericObjectPermission', - 'UserObjectPermissionBase', - 'UserObjectPermissionAbstract', - 'GroupObjectPermissionBase', - 'GroupObjectPermissionAbstract', - 'Permission', - 'Group', - 'UserObjectPermission', - 'GroupObjectPermission' + "BaseObjectPermission", + "BaseGenericObjectPermission", + "UserObjectPermissionBase", + "UserObjectPermissionAbstract", + "GroupObjectPermissionBase", + "GroupObjectPermissionAbstract", + "Permission", + "Group", + "UserObjectPermission", + "GroupObjectPermission", ] diff --git a/guardian/models/models.py b/guardian/models/models.py index da3f2083f..c4b5ec387 100644 --- a/guardian/models/models.py +++ b/guardian/models/models.py @@ -14,35 +14,39 @@ class BaseObjectPermission(models.Model): Abstract ObjectPermission class. Actual class should additionally define a ``content_object`` field and either ``user`` or ``group`` field. """ + permission = models.ForeignKey(Permission, on_delete=models.CASCADE) class Meta: abstract = True def __str__(self): - return '{} | {} | {}'.format( + return "{} | {} | {}".format( str(self.content_object), - str(getattr(self, 'user', False) or self.group), - str(self.permission.codename)) + str(getattr(self, "user", False) or self.group), + str(self.permission.codename), + ) def save(self, *args, **kwargs): content_type = get_content_type(self.content_object) if content_type != self.permission.content_type: - raise ValidationError("Cannot persist permission not designed for " - "this class (permission's type is %r and object's type is %r)" - % (self.permission.content_type, content_type)) + raise ValidationError( + "Cannot persist permission not designed for " + "this class (permission's type is %r and object's type is %r)" + % (self.permission.content_type, content_type) + ) return super().save(*args, **kwargs) class BaseGenericObjectPermission(models.Model): content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) - object_pk = models.CharField(_('object ID'), max_length=255) - content_object = GenericForeignKey(fk_field='object_pk') + object_pk = models.CharField(_("object ID"), max_length=255) + content_object = GenericForeignKey(fk_field="object_pk") class Meta: abstract = True indexes = [ - models.Index(fields=['content_type', 'object_pk']), + models.Index(fields=["content_type", "object_pk"]), ] @@ -50,24 +54,25 @@ class UserObjectPermissionBase(BaseObjectPermission): """ **Manager**: :manager:`UserObjectPermissionManager` """ + user = models.ForeignKey(user_model_label, on_delete=models.CASCADE) objects = UserObjectPermissionManager() class Meta: abstract = True - unique_together = ['user', 'permission', 'content_object'] + unique_together = ["user", "permission", "content_object"] -class UserObjectPermissionAbstract(UserObjectPermissionBase, BaseGenericObjectPermission): - +class UserObjectPermissionAbstract( + UserObjectPermissionBase, BaseGenericObjectPermission +): class Meta(UserObjectPermissionBase.Meta, BaseGenericObjectPermission.Meta): abstract = True - unique_together = ['user', 'permission', 'object_pk'] + unique_together = ["user", "permission", "object_pk"] class UserObjectPermission(UserObjectPermissionAbstract): - class Meta(UserObjectPermissionAbstract.Meta): abstract = False @@ -76,22 +81,24 @@ class GroupObjectPermissionBase(BaseObjectPermission): """ **Manager**: :manager:`GroupObjectPermissionManager` """ + group = models.ForeignKey(Group, on_delete=models.CASCADE) objects = GroupObjectPermissionManager() class Meta: abstract = True - unique_together = ['group', 'permission', 'content_object'] - + unique_together = ["group", "permission", "content_object"] -class GroupObjectPermissionAbstract(GroupObjectPermissionBase, BaseGenericObjectPermission): +class GroupObjectPermissionAbstract( + GroupObjectPermissionBase, BaseGenericObjectPermission +): class Meta(GroupObjectPermissionBase.Meta, BaseGenericObjectPermission.Meta): abstract = True - unique_together = ['group', 'permission', 'object_pk'] + unique_together = ["group", "permission", "object_pk"] -class GroupObjectPermission(GroupObjectPermissionAbstract): +class GroupObjectPermission(GroupObjectPermissionAbstract): class Meta(GroupObjectPermissionAbstract.Meta): abstract = False diff --git a/guardian/shortcuts.py b/guardian/shortcuts.py index e9b3a1a71..995e5a09d 100644 --- a/guardian/shortcuts.py +++ b/guardian/shortcuts.py @@ -28,8 +28,18 @@ ) from guardian.core import ObjectPermissionChecker from guardian.ctypes import get_content_type -from guardian.exceptions import MixedContentTypeError, WrongAppError, MultipleIdentityAndObjectError -from guardian.utils import get_anonymous_user, get_group_obj_perms_model, get_identity, get_user_obj_perms_model +from guardian.exceptions import ( + MixedContentTypeError, + WrongAppError, + MultipleIdentityAndObjectError, +) +from guardian.utils import ( + get_anonymous_user, + get_group_obj_perms_model, + get_identity, + get_user_obj_perms_model, +) + GroupObjectPermission = get_group_obj_perms_model() UserObjectPermission = get_user_obj_perms_model() @@ -88,12 +98,15 @@ def assign_perm(perm, user_or_group, obj=None): if obj is None: if not isinstance(perm, Permission): try: - app_label, codename = perm.split('.', 1) + app_label, codename = perm.split(".", 1) except ValueError: - raise ValueError("For global permissions, first argument must be in" - " format: 'app_label.codename' (is %r)" % perm) - perm = Permission.objects.get(content_type__app_label=app_label, - codename=codename) + raise ValueError( + "For global permissions, first argument must be in" + " format: 'app_label.codename' (is %r)" % perm + ) + perm = Permission.objects.get( + content_type__app_label=app_label, codename=codename + ) if user: user.user_permissions.add(perm) @@ -103,19 +116,23 @@ def assign_perm(perm, user_or_group, obj=None): return perm if not isinstance(perm, Permission): - if '.' in perm: + if "." in perm: app_label, perm = perm.split(".", 1) if isinstance(obj, (QuerySet, list)): if isinstance(user_or_group, (QuerySet, list)): - raise MultipleIdentityAndObjectError("Only bulk operations on either users/groups OR objects supported") + raise MultipleIdentityAndObjectError( + "Only bulk operations on either users/groups OR objects supported" + ) if user: model = get_user_obj_perms_model( - obj[0] if isinstance(obj, list) else obj.model) + obj[0] if isinstance(obj, list) else obj.model + ) return model.objects.bulk_assign_perm(perm, user, obj) if group: model = get_group_obj_perms_model( - obj[0] if isinstance(obj, list) else obj.model) + obj[0] if isinstance(obj, list) else obj.model + ) return model.objects.bulk_assign_perm(perm, group, obj) if isinstance(user_or_group, (QuerySet, list)): @@ -136,10 +153,11 @@ def assign_perm(perm, user_or_group, obj=None): def assign(perm, user_or_group, obj=None): - """ Depreciated function name left in for compatibility""" + """Depreciated function name left in for compatibility""" warnings.warn( "Shortcut function 'assign' is being renamed to 'assign_perm'. Update your code accordingly as old name will be depreciated in 2.0 version.", - DeprecationWarning) + DeprecationWarning, + ) return assign_perm(perm, user_or_group, obj) @@ -163,12 +181,15 @@ def remove_perm(perm, user_or_group=None, obj=None): user, group = get_identity(user_or_group) if obj is None: try: - app_label, codename = perm.split('.', 1) + app_label, codename = perm.split(".", 1) except ValueError: - raise ValueError("For global permissions, first argument must be in" - " format: 'app_label.codename' (is %r)" % perm) - perm = Permission.objects.get(content_type__app_label=app_label, - codename=codename) + raise ValueError( + "For global permissions, first argument must be in" + " format: 'app_label.codename' (is %r)" % perm + ) + perm = Permission.objects.get( + content_type__app_label=app_label, codename=codename + ) if user: user.user_permissions.remove(perm) return @@ -177,7 +198,7 @@ def remove_perm(perm, user_or_group=None, obj=None): return if not isinstance(perm, Permission): - perm = perm.split('.')[-1] + perm = perm.split(".")[-1] if isinstance(obj, QuerySet): if user: @@ -229,7 +250,7 @@ def get_perms_for_model(cls): possible to pass Model as class or instance. """ if isinstance(cls, str): - app_label, model_name = cls.split('.') + app_label, model_name = cls.split(".") model = apps.get_model(app_label, model_name) else: model = cls @@ -237,8 +258,13 @@ def get_perms_for_model(cls): return Permission.objects.filter(content_type=ctype) -def get_users_with_perms(obj, attach_perms=False, with_superusers=False, - with_group_users=True, only_with_perms_in=None): +def get_users_with_perms( + obj, + attach_perms=False, + with_superusers=False, + with_group_users=True, + only_with_perms_in=None, +): """ Returns queryset of all ``User`` objects with *any* object permissions for the given ``obj``. @@ -289,33 +315,43 @@ def get_users_with_perms(obj, attach_perms=False, with_superusers=False, related_name = user_model.user.field.related_query_name() if user_model.objects.is_generic(): user_filters = { - '%s__content_type' % related_name: ctype, - '%s__object_pk' % related_name: obj.pk, + "%s__content_type" % related_name: ctype, + "%s__object_pk" % related_name: obj.pk, } else: - user_filters = {'%s__content_object' % related_name: obj} + user_filters = {"%s__content_object" % related_name: obj} qset = Q(**user_filters) if only_with_perms_in is not None: - permission_ids = Permission.objects.filter(content_type=ctype, codename__in=only_with_perms_in).values_list('id', flat=True) - qset &= Q(**{ - '%s__permission_id__in' % related_name: permission_ids, - }) + permission_ids = Permission.objects.filter( + content_type=ctype, codename__in=only_with_perms_in + ).values_list("id", flat=True) + qset &= Q( + **{ + "%s__permission_id__in" % related_name: permission_ids, + } + ) if with_group_users: group_model = get_group_obj_perms_model(obj) if group_model.objects.is_generic(): group_obj_perm_filters = { - 'content_type': ctype, - 'object_pk': obj.pk, + "content_type": ctype, + "object_pk": obj.pk, } else: group_obj_perm_filters = { - 'content_object': obj, + "content_object": obj, } if only_with_perms_in is not None: - group_obj_perm_filters.update({ - 'permission_id__in': permission_ids, - }) - group_ids = set(group_model.objects.filter(**group_obj_perm_filters).values_list('group_id', flat=True).distinct()) + group_obj_perm_filters.update( + { + "permission_id__in": permission_ids, + } + ) + group_ids = set( + group_model.objects.filter(**group_obj_perm_filters) + .values_list("group_id", flat=True) + .distinct() + ) qset = qset | Q(groups__in=group_ids) if with_superusers: qset = qset | Q(is_superuser=True) @@ -323,10 +359,12 @@ def get_users_with_perms(obj, attach_perms=False, with_superusers=False, else: # TODO: Do not hit db for each user! users = {} - for user in get_users_with_perms(obj, - with_group_users=with_group_users, - only_with_perms_in=only_with_perms_in, - with_superusers=with_superusers): + for user in get_users_with_perms( + obj, + with_group_users=with_group_users, + only_with_perms_in=only_with_perms_in, + with_superusers=with_superusers, + ): # TODO: Support the case of set with_group_users but not with_superusers. if with_group_users or with_superusers: users[user] = sorted(get_perms(user, obj)) @@ -371,16 +409,18 @@ def get_groups_with_perms(obj, attach_perms=False): group_rel_name = group_model.group.field.related_query_name() if group_model.objects.is_generic(): group_filters = { - '%s__content_type' % group_rel_name: ctype, - '%s__object_pk' % group_rel_name: obj.pk, + "%s__content_type" % group_rel_name: ctype, + "%s__object_pk" % group_rel_name: obj.pk, } else: - group_filters = {'%s__content_object' % group_rel_name: obj} + group_filters = {"%s__content_object" % group_rel_name: obj} return Group.objects.filter(**group_filters).distinct() else: group_perms_mapping = defaultdict(list) groups_with_perms = get_groups_with_perms(obj) - qs = group_model.objects.filter(group__in=groups_with_perms).prefetch_related('group', 'permission') + qs = group_model.objects.filter(group__in=groups_with_perms).prefetch_related( + "group", "permission" + ) if group_model is GroupObjectPermission: qs = qs.filter(object_pk=obj.pk, content_type=ctype) else: @@ -391,8 +431,15 @@ def get_groups_with_perms(obj, attach_perms=False): return dict(group_perms_mapping) -def get_objects_for_user(user, perms, klass=None, use_groups=True, any_perm=False, - with_superuser=True, accept_global_perms=True): +def get_objects_for_user( + user, + perms, + klass=None, + use_groups=True, + any_perm=False, + with_superuser=True, + accept_global_perms=True, +): """ Returns queryset of objects for which a given ``user`` has *all* permissions present at ``perms``. @@ -500,22 +547,27 @@ def get_objects_for_user(user, perms, klass=None, use_groups=True, any_perm=Fals # Compute codenames set and ctype if possible for perm in perms: - if '.' in perm: - new_app_label, codename = perm.split('.', 1) + if "." in perm: + new_app_label, codename = perm.split(".", 1) if app_label is not None and app_label != new_app_label: - raise MixedContentTypeError("Given perms must have same app " - "label (%s != %s)" % (app_label, new_app_label)) + raise MixedContentTypeError( + "Given perms must have same app " + "label (%s != %s)" % (app_label, new_app_label) + ) else: app_label = new_app_label else: codename = perm codenames.add(codename) if app_label is not None: - new_ctype = ContentType.objects.get(app_label=app_label, - permission__codename=codename) + new_ctype = ContentType.objects.get( + app_label=app_label, permission__codename=codename + ) if ctype is not None and ctype != new_ctype: - raise MixedContentTypeError("ContentType was once computed " - "to be %s and another one %s" % (ctype, new_ctype)) + raise MixedContentTypeError( + "ContentType was once computed " + "to be %s and another one %s" % (ctype, new_ctype) + ) else: ctype = new_ctype @@ -530,8 +582,9 @@ def get_objects_for_user(user, perms, klass=None, use_groups=True, any_perm=Fals else: queryset = _get_queryset(klass) if ctype.model_class() != queryset.model: - raise MixedContentTypeError("Content type for given perms and " - "klass differs") + raise MixedContentTypeError( + "Content type for given perms and " "klass differs" + ) # At this point, we should have both ctype and queryset and they should # match which means: ctype.model_class() == queryset.model @@ -552,7 +605,7 @@ def get_objects_for_user(user, perms, klass=None, use_groups=True, any_perm=Fals # a superuser has by default assigned global perms for any if accept_global_perms and with_superuser: for code in codenames: - if user.has_perm(ctype.app_label + '.' + code): + if user.has_perm(ctype.app_label + "." + code): global_perms.add(code) for code in global_perms: codenames.remove(code) @@ -576,14 +629,15 @@ def get_objects_for_user(user, perms, klass=None, use_groups=True, any_perm=Fals # Now we should extract list of pk values for which we would filter # queryset user_model = get_user_obj_perms_model(queryset.model) - user_obj_perms_queryset = (user_model.objects - .filter(user=user) - .filter(permission__content_type=ctype)) + user_obj_perms_queryset = user_model.objects.filter(user=user).filter( + permission__content_type=ctype + ) if len(codenames): user_obj_perms_queryset = user_obj_perms_queryset.filter( - permission__codename__in=codenames) - direct_fields = ['content_object__pk', 'permission__codename'] - generic_fields = ['object_pk', 'permission__codename'] + permission__codename__in=codenames + ) + direct_fields = ["content_object__pk", "permission__codename"] + generic_fields = ["object_pk", "permission__codename"] if user_model.objects.is_generic(): user_fields = generic_fields else: @@ -592,13 +646,15 @@ def get_objects_for_user(user, perms, klass=None, use_groups=True, any_perm=Fals if use_groups: group_model = get_group_obj_perms_model(queryset.model) group_filters = { - 'permission__content_type': ctype, - 'group__%s' % get_user_model().groups.field.related_query_name(): user, + "permission__content_type": ctype, + "group__%s" % get_user_model().groups.field.related_query_name(): user, } if len(codenames): - group_filters.update({ - 'permission__codename__in': codenames, - }) + group_filters.update( + { + "permission__codename__in": codenames, + } + ) groups_obj_perms_queryset = group_model.objects.filter(**group_filters) if group_model.objects.is_generic(): group_fields = generic_fields @@ -620,10 +676,10 @@ def get_objects_for_user(user, perms, klass=None, use_groups=True, any_perm=Fals return objects if not any_perm and len(codenames) > 1: - counts = user_obj_perms_queryset.values( - user_fields[0]).annotate(object_pk_count=Count(user_fields[0])) - user_obj_perms_queryset = counts.filter( - object_pk_count__gte=len(codenames)) + counts = user_obj_perms_queryset.values(user_fields[0]).annotate( + object_pk_count=Count(user_fields[0]) + ) + user_obj_perms_queryset = counts.filter(object_pk_count__gte=len(codenames)) field_pk = user_fields[0] values = user_obj_perms_queryset @@ -631,7 +687,7 @@ def get_objects_for_user(user, perms, klass=None, use_groups=True, any_perm=Fals handle_pk_field = _handle_pk_field(queryset) if handle_pk_field is not None: values = values.annotate(obj_pk=handle_pk_field(expression=field_pk)) - field_pk = 'obj_pk' + field_pk = "obj_pk" values = values.values_list(field_pk, flat=True) q = Q(pk__in=values) @@ -640,14 +696,16 @@ def get_objects_for_user(user, perms, klass=None, use_groups=True, any_perm=Fals values = groups_obj_perms_queryset if handle_pk_field is not None: values = values.annotate(obj_pk=handle_pk_field(expression=field_pk)) - field_pk = 'obj_pk' + field_pk = "obj_pk" values = values.values_list(field_pk, flat=True) q |= Q(pk__in=values) return queryset.filter(q) -def get_objects_for_group(group, perms, klass=None, any_perm=False, accept_global_perms=True): +def get_objects_for_group( + group, perms, klass=None, any_perm=False, accept_global_perms=True +): """ Returns queryset of objects for which a given ``group`` has *all* permissions present at ``perms``. @@ -712,22 +770,27 @@ def get_objects_for_group(group, perms, klass=None, any_perm=False, accept_globa # Compute codenames set and ctype if possible for perm in perms: - if '.' in perm: - new_app_label, codename = perm.split('.', 1) + if "." in perm: + new_app_label, codename = perm.split(".", 1) if app_label is not None and app_label != new_app_label: - raise MixedContentTypeError("Given perms must have same app " - "label (%s != %s)" % (app_label, new_app_label)) + raise MixedContentTypeError( + "Given perms must have same app " + "label (%s != %s)" % (app_label, new_app_label) + ) else: app_label = new_app_label else: codename = perm codenames.add(codename) if app_label is not None: - new_ctype = ContentType.objects.get(app_label=app_label, - permission__codename=codename) + new_ctype = ContentType.objects.get( + app_label=app_label, permission__codename=codename + ) if ctype is not None and ctype != new_ctype: - raise MixedContentTypeError("ContentType was once computed " - "to be %s and another one %s" % (ctype, new_ctype)) + raise MixedContentTypeError( + "ContentType was once computed " + "to be %s and another one %s" % (ctype, new_ctype) + ) else: ctype = new_ctype @@ -742,8 +805,9 @@ def get_objects_for_group(group, perms, klass=None, any_perm=False, accept_globa else: queryset = _get_queryset(klass) if ctype.model_class() != queryset.model: - raise MixedContentTypeError("Content type for given perms and " - "klass differs") + raise MixedContentTypeError( + "Content type for given perms and " "klass differs" + ) # At this point, we should have both ctype and queryset and they should # match which means: ctype.model_class() == queryset.model @@ -751,7 +815,7 @@ def get_objects_for_group(group, perms, klass=None, any_perm=False, accept_globa global_perms = set() if accept_global_perms: - global_perm_set = group.permissions.values_list('codename', flat=True) + global_perm_set = group.permissions.values_list("codename", flat=True) for code in codenames: if code in global_perm_set: global_perms.add(code) @@ -763,16 +827,17 @@ def get_objects_for_group(group, perms, klass=None, any_perm=False, accept_globa # Now we should extract list of pk values for which we would filter # queryset group_model = get_group_obj_perms_model(queryset.model) - groups_obj_perms_queryset = (group_model.objects - .filter(group=group) - .filter(permission__content_type=ctype)) + groups_obj_perms_queryset = group_model.objects.filter(group=group).filter( + permission__content_type=ctype + ) if len(codenames): groups_obj_perms_queryset = groups_obj_perms_queryset.filter( - permission__codename__in=codenames) + permission__codename__in=codenames + ) if group_model.objects.is_generic(): - fields = ['object_pk', 'permission__codename'] + fields = ["object_pk", "permission__codename"] else: - fields = ['content_object__pk', 'permission__codename'] + fields = ["content_object__pk", "permission__codename"] if not any_perm and len(codenames): groups_obj_perms = groups_obj_perms_queryset.values_list(*fields) data = list(groups_obj_perms) @@ -793,7 +858,7 @@ def get_objects_for_group(group, perms, klass=None, any_perm=False, accept_globa handle_pk_field = _handle_pk_field(queryset) if handle_pk_field is not None: values = values.annotate(obj_pk=handle_pk_field(expression=field_pk)) - field_pk = 'obj_pk' + field_pk = "obj_pk" values = values.values_list(field_pk, flat=True) return queryset.filter(pk__in=values) @@ -823,8 +888,8 @@ def _handle_pk_field(queryset): return partial(Cast, output_field=UUIDField()) return partial( Replace, - text=Value('-'), - replacement=Value(''), + text=Value("-"), + replacement=Value(""), output_field=CharField(), ) diff --git a/guardian/templatetags/guardian_tags.py b/guardian/templatetags/guardian_tags.py index 4ed793046..71c67a4b2 100644 --- a/guardian/templatetags/guardian_tags.py +++ b/guardian/templatetags/guardian_tags.py @@ -16,7 +16,6 @@ class ObjectPermissionsNode(template.Node): - def __init__(self, for_whom, obj, context_var, checker=None): self.for_whom = template.Variable(for_whom) self.obj = template.Variable(obj) @@ -35,17 +34,22 @@ def render(self, context): self.user = None self.group = for_whom else: - raise NotUserNorGroup("User or Group instance required (got %s)" - % for_whom.__class__) + raise NotUserNorGroup( + "User or Group instance required (got %s)" % for_whom.__class__ + ) obj = self.obj.resolve(context) if not obj: - return '' + return "" - check = self.checker.resolve(context) if self.checker else ObjectPermissionChecker(for_whom) + check = ( + self.checker.resolve(context) + if self.checker + else ObjectPermissionChecker(for_whom) + ) perms = check.get_perms(obj) context[self.context_var] = perms - return '' + return "" @register.tag @@ -83,16 +87,18 @@ def get_obj_perms(parser, token): """ bits = token.split_contents() format = '{% get_obj_perms user/group for obj as "context_var" perm_checker %}' - if not (6 <= len(bits) <= 7) or bits[2] != 'for' or bits[4] != 'as': - raise template.TemplateSyntaxError("get_obj_perms tag should be in " - "format: %s" % format) + if not (6 <= len(bits) <= 7) or bits[2] != "for" or bits[4] != "as": + raise template.TemplateSyntaxError( + "get_obj_perms tag should be in " "format: %s" % format + ) for_whom = bits[1] obj = bits[3] context_var = bits[5] if context_var[0] != context_var[-1] or context_var[0] not in ('"', "'"): - raise template.TemplateSyntaxError("get_obj_perms tag's context_var " - "argument should be in quotes") + raise template.TemplateSyntaxError( + "get_obj_perms tag's context_var " "argument should be in quotes" + ) context_var = context_var[1:-1] checker = bits[6] if len(bits) == 7 else None return ObjectPermissionsNode(for_whom, obj, context_var, checker) diff --git a/guardian/testapp/migrations/0001_initial.py b/guardian/testapp/migrations/0001_initial.py index 181bac5f9..8d7a0b036 100644 --- a/guardian/testapp/migrations/0001_initial.py +++ b/guardian/testapp/migrations/0001_initial.py @@ -14,150 +14,382 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('auth', '0001_initial'), + ("auth", "0001_initial"), ] operations = [ migrations.CreateModel( - name='CustomUser', + name="CustomUser", fields=[ - ('password', models.CharField(max_length=128, verbose_name='password')), - ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), - ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), - ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=30, unique=True, validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.')], verbose_name='username')), - ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')), - ('last_name', models.CharField(blank=True, max_length=30, verbose_name='last name')), - ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), - ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), - ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), - ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), - ('custom_id', models.AutoField(primary_key=True, serialize=False)), - ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')), - ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')), + ("password", models.CharField(max_length=128, verbose_name="password")), + ( + "last_login", + models.DateTimeField( + blank=True, null=True, verbose_name="last login" + ), + ), + ( + "is_superuser", + models.BooleanField( + default=False, + help_text="Designates that this user has all permissions without explicitly assigning them.", + verbose_name="superuser status", + ), + ), + ( + "username", + models.CharField( + error_messages={ + "unique": "A user with that username already exists." + }, + help_text="Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.", + max_length=30, + unique=True, + validators=[ + django.core.validators.RegexValidator( + "^[\\w.@+-]+$", + "Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.", + ) + ], + verbose_name="username", + ), + ), + ( + "first_name", + models.CharField( + blank=True, max_length=30, verbose_name="first name" + ), + ), + ( + "last_name", + models.CharField( + blank=True, max_length=30, verbose_name="last name" + ), + ), + ( + "email", + models.EmailField( + blank=True, max_length=254, verbose_name="email address" + ), + ), + ( + "is_staff", + models.BooleanField( + default=False, + help_text="Designates whether the user can log into this admin site.", + verbose_name="staff status", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.", + verbose_name="active", + ), + ), + ( + "date_joined", + models.DateTimeField( + default=django.utils.timezone.now, verbose_name="date joined" + ), + ), + ("custom_id", models.AutoField(primary_key=True, serialize=False)), + ( + "groups", + models.ManyToManyField( + blank=True, + help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.", + related_name="user_set", + related_query_name="user", + to="auth.Group", + verbose_name="groups", + ), + ), + ( + "user_permissions", + models.ManyToManyField( + blank=True, + help_text="Specific permissions for this user.", + related_name="user_set", + related_query_name="user", + to="auth.Permission", + verbose_name="user permissions", + ), + ), ], options={ - 'abstract': False, - 'verbose_name': 'user', - 'verbose_name_plural': 'users', + "abstract": False, + "verbose_name": "user", + "verbose_name_plural": "users", }, bases=(models.Model, guardian.mixins.GuardianUserMixin), managers=[ - ('objects', django.contrib.auth.models.UserManager()), + ("objects", django.contrib.auth.models.UserManager()), ], ), migrations.CreateModel( - name='CustomUsernameUser', + name="CustomUsernameUser", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('password', models.CharField(max_length=128, verbose_name='password')), - ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), - ('email', models.EmailField(max_length=100, unique=True)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("password", models.CharField(max_length=128, verbose_name="password")), + ( + "last_login", + models.DateTimeField( + blank=True, null=True, verbose_name="last login" + ), + ), + ("email", models.EmailField(max_length=100, unique=True)), ], options={ - 'abstract': False, + "abstract": False, }, bases=(models.Model, guardian.mixins.GuardianUserMixin), ), migrations.CreateModel( - name='Mixed', + name="Mixed", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=128, unique=True)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=128, unique=True)), ], ), migrations.CreateModel( - name='MixedGroupObjectPermission', + name="MixedGroupObjectPermission", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('content_object', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='testapp.Mixed')), - ('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group')), - ('permission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Permission')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "content_object", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="testapp.Mixed" + ), + ), + ( + "group", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="auth.Group" + ), + ), + ( + "permission", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="auth.Permission", + ), + ), ], options={ - 'abstract': False, + "abstract": False, }, ), migrations.CreateModel( - name='CharPKModel', + name="CharPKModel", fields=[ - ('char_pk', models.CharField(max_length=128, primary_key=True, serialize=False)), + ( + "char_pk", + models.CharField(max_length=128, primary_key=True, serialize=False), + ), ], ), migrations.CreateModel( - name='Post', + name="Post", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=64, verbose_name='title')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("title", models.CharField(max_length=64, verbose_name="title")), ], ), migrations.CreateModel( - name='Project', + name="Project", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=128, unique=True)), - ('created_at', models.DateTimeField(default=datetime.datetime.now)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=128, unique=True)), + ("created_at", models.DateTimeField(default=datetime.datetime.now)), ], options={ - 'get_latest_by': 'created_at', + "get_latest_by": "created_at", }, ), migrations.CreateModel( - name='ProjectGroupObjectPermission', + name="ProjectGroupObjectPermission", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('content_object', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='testapp.Project')), - ('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group')), - ('permission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Permission')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "content_object", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="testapp.Project", + ), + ), + ( + "group", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="auth.Group" + ), + ), + ( + "permission", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="auth.Permission", + ), + ), ], options={ - 'abstract': False, + "abstract": False, }, ), migrations.CreateModel( - name='ProjectUserObjectPermission', + name="ProjectUserObjectPermission", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('content_object', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='testapp.Project')), - ('permission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Permission')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "content_object", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="testapp.Project", + ), + ), + ( + "permission", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="auth.Permission", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), ], options={ - 'abstract': False, + "abstract": False, }, ), migrations.CreateModel( - name='ReverseMixed', + name="ReverseMixed", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=128, unique=True)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=128, unique=True)), ], ), migrations.CreateModel( - name='ReverseMixedUserObjectPermission', + name="ReverseMixedUserObjectPermission", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('content_object', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='testapp.ReverseMixed')), - ('permission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Permission')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "content_object", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="testapp.ReverseMixed", + ), + ), + ( + "permission", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="auth.Permission", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), ], options={ - 'abstract': False, + "abstract": False, }, ), migrations.AlterUniqueTogether( - name='reversemixeduserobjectpermission', - unique_together={('user', 'permission', 'content_object')}, + name="reversemixeduserobjectpermission", + unique_together={("user", "permission", "content_object")}, ), migrations.AlterUniqueTogether( - name='projectuserobjectpermission', - unique_together={('user', 'permission', 'content_object')}, + name="projectuserobjectpermission", + unique_together={("user", "permission", "content_object")}, ), migrations.AlterUniqueTogether( - name='projectgroupobjectpermission', - unique_together={('group', 'permission', 'content_object')}, + name="projectgroupobjectpermission", + unique_together={("group", "permission", "content_object")}, ), migrations.AlterUniqueTogether( - name='mixedgroupobjectpermission', - unique_together={('group', 'permission', 'content_object')}, + name="mixedgroupobjectpermission", + unique_together={("group", "permission", "content_object")}, ), ] diff --git a/guardian/testapp/migrations/0002_logentrywithgroup.py b/guardian/testapp/migrations/0002_logentrywithgroup.py index 748a1eac6..cdbe9bd71 100644 --- a/guardian/testapp/migrations/0002_logentrywithgroup.py +++ b/guardian/testapp/migrations/0002_logentrywithgroup.py @@ -6,18 +6,36 @@ class Migration(migrations.Migration): dependencies = [ - ('auth', '0001_initial'), - ('admin', '0001_initial'), - ('testapp', '0001_initial'), + ("auth", "0001_initial"), + ("admin", "0001_initial"), + ("testapp", "0001_initial"), ] operations = [ migrations.CreateModel( - name='LogEntryWithGroup', + name="LogEntryWithGroup", fields=[ - ('logentry_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='admin.LogEntry')), - ('group', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='auth.Group')), + ( + "logentry_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="admin.LogEntry", + ), + ), + ( + "group", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="auth.Group", + ), + ), ], - bases=('admin.logentry',), + bases=("admin.logentry",), ), ] diff --git a/guardian/testapp/migrations/0003_auto_20190611_0440.py b/guardian/testapp/migrations/0003_auto_20190611_0440.py index 1918ea955..84e211817 100644 --- a/guardian/testapp/migrations/0003_auto_20190611_0440.py +++ b/guardian/testapp/migrations/0003_auto_20190611_0440.py @@ -6,24 +6,27 @@ class Migration(migrations.Migration): dependencies = [ - ('testapp', '0002_logentrywithgroup'), + ("testapp", "0002_logentrywithgroup"), ] operations = [ migrations.AlterField( - model_name='customuser', - name='last_name', - field=models.CharField(blank=True, max_length=150, - verbose_name='last name'), + model_name="customuser", + name="last_name", + field=models.CharField( + blank=True, max_length=150, verbose_name="last name" + ), ), migrations.AlterField( - model_name='customuser', - name='username', - 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'), + model_name="customuser", + name="username", + 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", + ), ), ] diff --git a/guardian/testapp/migrations/0004_childtestmodel_parenttestmodel.py b/guardian/testapp/migrations/0004_childtestmodel_parenttestmodel.py index ac5c3832f..78c6b51a5 100644 --- a/guardian/testapp/migrations/0004_childtestmodel_parenttestmodel.py +++ b/guardian/testapp/migrations/0004_childtestmodel_parenttestmodel.py @@ -7,23 +7,40 @@ class Migration(migrations.Migration): dependencies = [ - ('testapp', '0003_auto_20190611_0440'), + ("testapp", "0003_auto_20190611_0440"), ] operations = [ migrations.CreateModel( - name='ParentTestModel', + name="ParentTestModel", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created_on', models.DateTimeField(auto_now_add=True)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("created_on", models.DateTimeField(auto_now_add=True)), ], ), migrations.CreateModel( - name='ChildTestModel', + name="ChildTestModel", fields=[ - ('parent_id', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='testapp.ParentTestModel')), - ('name', models.CharField(max_length=31)), + ( + "parent_id", + models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="testapp.ParentTestModel", + ), + ), + ("name", models.CharField(max_length=31)), ], - bases=('testapp.parenttestmodel',), + bases=("testapp.parenttestmodel",), ), ] diff --git a/guardian/testapp/migrations/0005_uuidpkmodel.py b/guardian/testapp/migrations/0005_uuidpkmodel.py index d2d13da30..4da683831 100644 --- a/guardian/testapp/migrations/0005_uuidpkmodel.py +++ b/guardian/testapp/migrations/0005_uuidpkmodel.py @@ -7,14 +7,22 @@ class Migration(migrations.Migration): dependencies = [ - ('testapp', '0004_childtestmodel_parenttestmodel'), + ("testapp", "0004_childtestmodel_parenttestmodel"), ] operations = [ migrations.CreateModel( - name='UUIDPKModel', + name="UUIDPKModel", fields=[ - ('uuid_pk', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ( + "uuid_pk", + models.UUIDField( + default=uuid.uuid4, + editable=False, + primary_key=True, + serialize=False, + ), + ), ], ), ] diff --git a/guardian/testapp/models.py b/guardian/testapp/models.py index 3a0d19d06..df84dfae7 100644 --- a/guardian/testapp/models.py +++ b/guardian/testapp/models.py @@ -11,14 +11,13 @@ class Post(models.Model): - title = models.CharField('title', max_length=64) + title = models.CharField("title", max_length=64) def __str__(self): return self.title class DynamicAccessor: - def __init__(self): pass @@ -27,11 +26,11 @@ def __getattr__(self, key): class ProjectUserObjectPermission(UserObjectPermissionBase): - content_object = models.ForeignKey('Project', on_delete=models.CASCADE) + content_object = models.ForeignKey("Project", on_delete=models.CASCADE) class ProjectGroupObjectPermission(GroupObjectPermissionBase): - content_object = models.ForeignKey('Project', on_delete=models.CASCADE) + content_object = models.ForeignKey("Project", on_delete=models.CASCADE) class Project(models.Model): @@ -39,7 +38,7 @@ class Project(models.Model): created_at = models.DateTimeField(default=datetime.now) class Meta: - get_latest_by = 'created_at' + get_latest_by = "created_at" def __str__(self): return self.name @@ -49,7 +48,7 @@ def __str__(self): class MixedGroupObjectPermission(GroupObjectPermissionBase): - content_object = models.ForeignKey('Mixed', on_delete=models.CASCADE) + content_object = models.ForeignKey("Mixed", on_delete=models.CASCADE) class Mixed(models.Model): @@ -57,6 +56,7 @@ class Mixed(models.Model): Model for tests obj perms checks with generic user object permissions model and direct group object permissions model. """ + name = models.CharField(max_length=128, unique=True) def __str__(self): @@ -64,7 +64,7 @@ def __str__(self): class ReverseMixedUserObjectPermission(UserObjectPermissionBase): - content_object = models.ForeignKey('ReverseMixed', on_delete=models.CASCADE) + content_object = models.ForeignKey("ReverseMixed", on_delete=models.CASCADE) class ReverseMixed(models.Model): @@ -72,6 +72,7 @@ class ReverseMixed(models.Model): Model for tests obj perms checks with generic group object permissions model and generic group object permissions model. """ + name = models.CharField(max_length=128, unique=True) def __str__(self): @@ -79,7 +80,9 @@ def __str__(self): class LogEntryWithGroup(LogEntry): - group = models.ForeignKey('auth.Group', null=True, blank=True, on_delete=models.CASCADE) + group = models.ForeignKey( + "auth.Group", null=True, blank=True, on_delete=models.CASCADE + ) objects = models.Manager() @@ -89,6 +92,7 @@ class CharPKModel(models.Model): Model for testing whether get_objects_for_user will work when the objects to be returned have varchar primary keys. """ + char_pk = models.CharField(primary_key=True, max_length=128) @@ -97,6 +101,7 @@ class UUIDPKModel(models.Model): Model for testing whether get_objects_for_user will work when the objects to be returned have UUID primary keys. """ + uuid_pk = models.UUIDField( primary_key=True, default=uuid.uuid4, @@ -110,7 +115,7 @@ class CustomUser(AbstractUser, GuardianUserMixin): class CustomUsernameUser(AbstractBaseUser, GuardianUserMixin): email = models.EmailField(max_length=100, unique=True) - USERNAME_FIELD = 'email' + USERNAME_FIELD = "email" def get_full_name(self): return self.email @@ -125,8 +130,6 @@ class ParentTestModel(models.Model): class ChildTestModel(ParentTestModel): parent_id = models.OneToOneField( - ParentTestModel, - on_delete=models.CASCADE, - parent_link=True + ParentTestModel, on_delete=models.CASCADE, parent_link=True ) name = models.CharField(max_length=31) diff --git a/guardian/testapp/tests/conf.py b/guardian/testapp/tests/conf.py index 7d46b919c..6522b9ee6 100644 --- a/guardian/testapp/tests/conf.py +++ b/guardian/testapp/tests/conf.py @@ -6,23 +6,26 @@ def skipUnlessTestApp(obj): - app = 'guardian.testapp' - return unittest.skipUnless(app in settings.INSTALLED_APPS, - 'app %r must be installed to run this test' % app)(obj) + app = "guardian.testapp" + return unittest.skipUnless( + app in settings.INSTALLED_APPS, + "app %r must be installed to run this test" % app, + )(obj) class TestDataMixin: - def setUp(self): super().setUp() from django.contrib.auth.models import Group from django.contrib.auth import get_user_model + User = get_user_model() - Group.objects.create(pk=1, name='admins') - jack_group = Group.objects.create(pk=2, name='jackGroup') + Group.objects.create(pk=1, name="admins") + jack_group = Group.objects.create(pk=2, name="jackGroup") User.objects.get_or_create(username=guardian_settings.ANONYMOUS_USER_NAME) - jack = User.objects.create(username='jack', is_active=True, - is_superuser=False, is_staff=False) + jack = User.objects.create( + username="jack", is_active=True, is_superuser=False, is_staff=False + ) jack.groups.add(jack_group) @@ -46,6 +49,7 @@ def __exit__(self, exc_type, exc_value, traceback): def __call__(self, test_func): from django.test import TransactionTestCase + if isinstance(test_func, type) and issubclass(test_func, TransactionTestCase): original_pre_setup = test_func._pre_setup original_post_teardown = test_func._post_teardown @@ -57,14 +61,17 @@ def _pre_setup(innerself): def _post_teardown(innerself): original_post_teardown(innerself) self.disable() + test_func._pre_setup = _pre_setup test_func._post_teardown = _post_teardown return test_func else: + @wraps(test_func) def inner(*args, **kwargs): with self: return test_func(*args, **kwargs) + return inner def enable(self): diff --git a/guardian/testapp/tests/test_admin.py b/guardian/testapp/tests/test_admin.py index ad7af8940..d7492d5ef 100644 --- a/guardian/testapp/tests/test_admin.py +++ b/guardian/testapp/tests/test_admin.py @@ -25,6 +25,7 @@ class ContentTypeGuardedAdmin(GuardedModelAdmin): pass + try: admin.site.unregister(ContentType) except admin.sites.NotRegistered: @@ -33,144 +34,149 @@ class ContentTypeGuardedAdmin(GuardedModelAdmin): class AdminTests(TestCase): - def setUp(self): - self.admin = User.objects.create_superuser('admin', 'admin@example.com', - 'admin') - self.user = User.objects.create_user('joe', 'joe@example.com', 'joe') - self.group = Group.objects.create(name='group') + self.admin = User.objects.create_superuser( + "admin", "admin@example.com", "admin" + ) + self.user = User.objects.create_user("joe", "joe@example.com", "joe") + self.group = Group.objects.create(name="group") self.client = Client() self.obj = ContentType.objects.create( - model='bar', app_label='fake-for-guardian-tests') + model="bar", app_label="fake-for-guardian-tests" + ) self.obj_info = self.obj._meta.app_label, self.obj._meta.model_name def tearDown(self): self.client.logout() def _login_superuser(self): - self.client.login(username='admin', password='admin') + self.client.login(username="admin", password="admin") def test_view_manage_wrong_obj(self): self._login_superuser() - url = reverse('admin:%s_%s_permissions_manage_user' % self.obj_info, - kwargs={'object_pk': -10, 'user_id': self.user.pk}) + url = reverse( + "admin:%s_%s_permissions_manage_user" % self.obj_info, + kwargs={"object_pk": -10, "user_id": self.user.pk}, + ) response = self.client.get(url) self.assertEqual(response.status_code, 404) def test_view(self): self._login_superuser() - url = reverse('admin:%s_%s_permissions' % self.obj_info, - args=[self.obj.pk]) + url = reverse("admin:%s_%s_permissions" % self.obj_info, args=[self.obj.pk]) response = self.client.get(url) self.assertEqual(response.status_code, 200) - self.assertEqual(response.context['object'], self.obj) + self.assertEqual(response.context["object"], self.obj) def test_view_manage_wrong_user(self): self._login_superuser() - url = reverse('admin:%s_%s_permissions_manage_user' % self.obj_info, - kwargs={'object_pk': self.obj.pk, 'user_id': -10}) + url = reverse( + "admin:%s_%s_permissions_manage_user" % self.obj_info, + kwargs={"object_pk": self.obj.pk, "user_id": -10}, + ) response = self.client.get(url) self.assertEqual(response.status_code, 404) def test_view_manage_user_form(self): self._login_superuser() - url = reverse('admin:%s_%s_permissions' % self.obj_info, - args=[self.obj.pk]) - data = {'user': self.user.username, 'submit_manage_user': 'submit'} + url = reverse("admin:%s_%s_permissions" % self.obj_info, args=[self.obj.pk]) + data = {"user": self.user.username, "submit_manage_user": "submit"} response = self.client.post(url, data, follow=True) self.assertEqual(len(response.redirect_chain), 1) self.assertEqual(response.redirect_chain[0][1], 302) - redirect_url = reverse('admin:%s_%s_permissions_manage_user' % - self.obj_info, kwargs={'object_pk': self.obj.pk, - 'user_id': self.user.pk}) - self.assertEqual(response.request['PATH_INFO'], redirect_url) - - @unittest.skipIf(DJANGO_VERSION >= (3, 0) and - "mysql" in os.environ.get("DATABASE_URL", ""), - "Negative ids no longer work in Django 3.0+ with MySQL.") + redirect_url = reverse( + "admin:%s_%s_permissions_manage_user" % self.obj_info, + kwargs={"object_pk": self.obj.pk, "user_id": self.user.pk}, + ) + self.assertEqual(response.request["PATH_INFO"], redirect_url) + + @unittest.skipIf( + DJANGO_VERSION >= (3, 0) and "mysql" in os.environ.get("DATABASE_URL", ""), + "Negative ids no longer work in Django 3.0+ with MySQL.", + ) def test_view_manage_negative_user_form(self): self._login_superuser() - url = reverse('admin:%s_%s_permissions' % self.obj_info, - args=[self.obj.pk]) - self.user = User.objects.create(username='negative_id_user', pk=-2010) - data = {'user': self.user.username, 'submit_manage_user': 'submit'} + url = reverse("admin:%s_%s_permissions" % self.obj_info, args=[self.obj.pk]) + self.user = User.objects.create(username="negative_id_user", pk=-2010) + data = {"user": self.user.username, "submit_manage_user": "submit"} response = self.client.post(url, data, follow=True) self.assertEqual(len(response.redirect_chain), 1) self.assertEqual(response.redirect_chain[0][1], 302) - redirect_url = reverse('admin:%s_%s_permissions_manage_user' % - self.obj_info, args=[self.obj.pk, self.user.pk]) - self.assertEqual(response.request['PATH_INFO'], redirect_url) + redirect_url = reverse( + "admin:%s_%s_permissions_manage_user" % self.obj_info, + args=[self.obj.pk, self.user.pk], + ) + self.assertEqual(response.request["PATH_INFO"], redirect_url) def test_view_manage_user_form_wrong_user(self): self._login_superuser() - url = reverse('admin:%s_%s_permissions' % self.obj_info, - args=[self.obj.pk]) - data = {'user': 'wrong-user', 'submit_manage_user': 'submit'} + url = reverse("admin:%s_%s_permissions" % self.obj_info, args=[self.obj.pk]) + data = {"user": "wrong-user", "submit_manage_user": "submit"} response = self.client.post(url, data, follow=True) self.assertEqual(len(response.redirect_chain), 0) self.assertEqual(response.status_code, 200) - self.assertTrue('user' in response.context['user_form'].errors) + self.assertTrue("user" in response.context["user_form"].errors) def test_view_manage_user_form_wrong_field(self): self._login_superuser() - url = reverse('admin:%s_%s_permissions' % self.obj_info, - args=[self.obj.pk]) - data = {'user': '', 'submit_manage_user': 'submit'} + url = reverse("admin:%s_%s_permissions" % self.obj_info, args=[self.obj.pk]) + data = {"user": "", "submit_manage_user": "submit"} response = self.client.post(url, data, follow=True) self.assertEqual(len(response.redirect_chain), 0) self.assertEqual(response.status_code, 200) - self.assertTrue('user' in response.context['user_form'].errors) + self.assertTrue("user" in response.context["user_form"].errors) def test_view_manage_user_form_empty_user(self): self._login_superuser() - url = reverse('admin:%s_%s_permissions' % self.obj_info, - args=[self.obj.pk]) - data = {'user': '', 'submit_manage_user': 'submit'} + url = reverse("admin:%s_%s_permissions" % self.obj_info, args=[self.obj.pk]) + data = {"user": "", "submit_manage_user": "submit"} response = self.client.post(url, data, follow=True) self.assertEqual(len(response.redirect_chain), 0) self.assertEqual(response.status_code, 200) - self.assertTrue('user' in response.context['user_form'].errors) + self.assertTrue("user" in response.context["user_form"].errors) def test_view_manage_user_wrong_perms(self): self._login_superuser() - url = reverse('admin:%s_%s_permissions_manage_user' % self.obj_info, - args=[self.obj.pk, self.user.pk]) - perms = ['change_user'] # This is not self.obj related permission - data = {'permissions': perms} + url = reverse( + "admin:%s_%s_permissions_manage_user" % self.obj_info, + args=[self.obj.pk, self.user.pk], + ) + perms = ["change_user"] # This is not self.obj related permission + data = {"permissions": perms} response = self.client.post(url, data, follow=True) self.assertEqual(response.status_code, 200) - self.assertTrue('permissions' in response.context['form'].errors) + self.assertTrue("permissions" in response.context["form"].errors) def test_view_manage_user(self): self._login_superuser() - url = reverse('admin:%s_%s_permissions_manage_user' % self.obj_info, - args=[self.obj.pk, self.user.pk]) + url = reverse( + "admin:%s_%s_permissions_manage_user" % self.obj_info, + args=[self.obj.pk, self.user.pk], + ) response = self.client.get(url) self.assertEqual(response.status_code, 200) - choices = {c[0] for c in - response.context['form'].fields['permissions'].choices} + choices = {c[0] for c in response.context["form"].fields["permissions"].choices} self.assertEqual( {p.codename for p in get_perms_for_model(self.obj)}, choices, ) # Add some perms and check if changes were persisted - perms = ['change_%s' % self.obj_info[ - 1], 'delete_%s' % self.obj_info[1]] - data = {'permissions': perms} + perms = ["change_%s" % self.obj_info[1], "delete_%s" % self.obj_info[1]] + data = {"permissions": perms} response = self.client.post(url, data, follow=True) self.assertEqual(len(response.redirect_chain), 1) self.assertEqual(response.redirect_chain[0][1], 302) - self.assertIn('selected', str(response.context['form'])) + self.assertIn("selected", str(response.context["form"])) self.assertEqual( set(get_perms(self.user, self.obj)), set(perms), ) # Remove perm and check if change was persisted - perms = ['change_%s' % self.obj_info[1]] - data = {'permissions': perms} + perms = ["change_%s" % self.obj_info[1]] + data = {"permissions": perms} response = self.client.post(url, data, follow=True) self.assertEqual(len(response.redirect_chain), 1) self.assertEqual(response.redirect_chain[0][1], 302) @@ -182,90 +188,92 @@ def test_view_manage_user(self): def test_view_manage_group_form(self): self._login_superuser() - url = reverse('admin:%s_%s_permissions' % self.obj_info, - args=[self.obj.pk]) - data = {'group': self.group.name, 'submit_manage_group': 'submit'} + url = reverse("admin:%s_%s_permissions" % self.obj_info, args=[self.obj.pk]) + data = {"group": self.group.name, "submit_manage_group": "submit"} response = self.client.post(url, data, follow=True) self.assertEqual(len(response.redirect_chain), 1) self.assertEqual(response.redirect_chain[0][1], 302) - redirect_url = reverse('admin:%s_%s_permissions_manage_group' % - self.obj_info, args=[self.obj.pk, self.group.id]) - self.assertEqual(response.request['PATH_INFO'], redirect_url) + redirect_url = reverse( + "admin:%s_%s_permissions_manage_group" % self.obj_info, + args=[self.obj.pk, self.group.id], + ) + self.assertEqual(response.request["PATH_INFO"], redirect_url) - @unittest.skipIf(DJANGO_VERSION >= (3, 0) and - "mysql" in os.environ.get("DATABASE_URL", ""), - "Negative ids no longer work in Django 3.0+ with MySQL.") + @unittest.skipIf( + DJANGO_VERSION >= (3, 0) and "mysql" in os.environ.get("DATABASE_URL", ""), + "Negative ids no longer work in Django 3.0+ with MySQL.", + ) def test_view_manage_negative_group_form(self): self._login_superuser() - url = reverse('admin:%s_%s_permissions' % self.obj_info, - args=[self.obj.pk]) - self.group = Group.objects.create(name='neagive_id_group', id=-2010) - data = {'group': self.group.name, 'submit_manage_group': 'submit'} + url = reverse("admin:%s_%s_permissions" % self.obj_info, args=[self.obj.pk]) + self.group = Group.objects.create(name="neagive_id_group", id=-2010) + data = {"group": self.group.name, "submit_manage_group": "submit"} response = self.client.post(url, data, follow=True) self.assertEqual(len(response.redirect_chain), 1) self.assertEqual(response.redirect_chain[0][1], 302) - redirect_url = reverse('admin:%s_%s_permissions_manage_group' % - self.obj_info, args=[self.obj.pk, self.group.id]) - self.assertEqual(response.request['PATH_INFO'], redirect_url) + redirect_url = reverse( + "admin:%s_%s_permissions_manage_group" % self.obj_info, + args=[self.obj.pk, self.group.id], + ) + self.assertEqual(response.request["PATH_INFO"], redirect_url) def test_view_manage_group_form_wrong_group(self): self._login_superuser() - url = reverse('admin:%s_%s_permissions' % self.obj_info, - args=[self.obj.pk]) - data = {'group': 'wrong-group', 'submit_manage_group': 'submit'} + url = reverse("admin:%s_%s_permissions" % self.obj_info, args=[self.obj.pk]) + data = {"group": "wrong-group", "submit_manage_group": "submit"} response = self.client.post(url, data, follow=True) self.assertEqual(len(response.redirect_chain), 0) self.assertEqual(response.status_code, 200) - self.assertTrue('group' in response.context['group_form'].errors) + self.assertTrue("group" in response.context["group_form"].errors) def test_view_manage_group_form_wrong_field(self): self._login_superuser() - url = reverse('admin:%s_%s_permissions' % self.obj_info, - args=[self.obj.pk]) - data = {'group': '', 'submit_manage_group': 'submit'} + url = reverse("admin:%s_%s_permissions" % self.obj_info, args=[self.obj.pk]) + data = {"group": "", "submit_manage_group": "submit"} response = self.client.post(url, data, follow=True) self.assertEqual(len(response.redirect_chain), 0) self.assertEqual(response.status_code, 200) - self.assertTrue('group' in response.context['group_form'].errors) + self.assertTrue("group" in response.context["group_form"].errors) def test_view_manage_group_form_empty_group(self): self._login_superuser() - url = reverse('admin:%s_%s_permissions' % self.obj_info, - args=[self.obj.pk]) - data = {'group': '', 'submit_manage_group': 'submit'} + url = reverse("admin:%s_%s_permissions" % self.obj_info, args=[self.obj.pk]) + data = {"group": "", "submit_manage_group": "submit"} response = self.client.post(url, data, follow=True) self.assertEqual(len(response.redirect_chain), 0) self.assertEqual(response.status_code, 200) - self.assertTrue('group' in response.context['group_form'].errors) + self.assertTrue("group" in response.context["group_form"].errors) def test_view_manage_group_wrong_perms(self): self._login_superuser() - url = reverse('admin:%s_%s_permissions_manage_group' % - self.obj_info, args=[self.obj.pk, self.group.id]) - perms = ['change_user'] # This is not self.obj related permission - data = {'permissions': perms} + url = reverse( + "admin:%s_%s_permissions_manage_group" % self.obj_info, + args=[self.obj.pk, self.group.id], + ) + perms = ["change_user"] # This is not self.obj related permission + data = {"permissions": perms} response = self.client.post(url, data, follow=True) self.assertEqual(response.status_code, 200) - self.assertTrue('permissions' in response.context['form'].errors) + self.assertTrue("permissions" in response.context["form"].errors) def test_view_manage_group(self): self._login_superuser() - url = reverse('admin:%s_%s_permissions_manage_group' % - self.obj_info, args=[self.obj.pk, self.group.id]) + url = reverse( + "admin:%s_%s_permissions_manage_group" % self.obj_info, + args=[self.obj.pk, self.group.id], + ) response = self.client.get(url) self.assertEqual(response.status_code, 200) - choices = {c[0] for c in - response.context['form'].fields['permissions'].choices} + choices = {c[0] for c in response.context["form"].fields["permissions"].choices} self.assertEqual( {p.codename for p in get_perms_for_model(self.obj)}, choices, ) # Add some perms and check if changes were persisted - perms = ['change_%s' % self.obj_info[ - 1], 'delete_%s' % self.obj_info[1]] - data = {'permissions': perms} + perms = ["change_%s" % self.obj_info[1], "delete_%s" % self.obj_info[1]] + data = {"permissions": perms} response = self.client.post(url, data, follow=True) self.assertEqual(len(response.redirect_chain), 1) self.assertEqual(response.redirect_chain[0][1], 302) @@ -276,8 +284,8 @@ def test_view_manage_group(self): ) # Remove perm and check if change was persisted - perms = ['delete_%s' % self.obj_info[1]] - data = {'permissions': perms} + perms = ["delete_%s" % self.obj_info[1]] + data = {"permissions": perms} response = self.client.post(url, data, follow=True) self.assertEqual(len(response.redirect_chain), 1) self.assertEqual(response.redirect_chain[0][1], 302) @@ -287,78 +295,94 @@ def test_view_manage_group(self): set(perms), ) -if 'django.contrib.admin' not in settings.INSTALLED_APPS: + +if "django.contrib.admin" not in settings.INSTALLED_APPS: # Skip admin tests if admin app is not registered # we simpy clean up AdminTests class ... # TODO: use @unittest.skipUnless('django.contrib.admin' in settings.INSTALLED_APPS) # if possible (requires Python 2.7, though) - AdminTests = type('AdminTests', (TestCase,), {}) # pyflakes:ignore + AdminTests = type("AdminTests", (TestCase,), {}) # pyflakes:ignore @skipUnlessTestApp class GuardedModelAdminTests(TestCase): - def _get_gma(self, attrs=None, name=None, model=None): """ Returns ``GuardedModelAdmin`` instance. """ attrs = attrs or {} - name = str(name or 'GMA') + name = str(name or "GMA") model = model or User GMA = type(name, (GuardedModelAdmin,), attrs) gma = GMA(model, admin.site) return gma def test_obj_perms_manage_template_attr(self): - attrs = {'obj_perms_manage_template': 'foobar.html'} + attrs = {"obj_perms_manage_template": "foobar.html"} gma = self._get_gma(attrs=attrs) - self.assertTrue(gma.get_obj_perms_manage_template(), 'foobar.html') + self.assertTrue(gma.get_obj_perms_manage_template(), "foobar.html") def test_obj_perms_manage_user_template_attr(self): - attrs = {'obj_perms_manage_user_template': 'foobar.html'} + attrs = {"obj_perms_manage_user_template": "foobar.html"} gma = self._get_gma(attrs=attrs) - self.assertTrue( - gma.get_obj_perms_manage_user_template(), 'foobar.html') + self.assertTrue(gma.get_obj_perms_manage_user_template(), "foobar.html") def test_obj_perms_manage_user_form_attr(self): - attrs = {'obj_perms_manage_user_form': forms.Form} + attrs = {"obj_perms_manage_user_form": forms.Form} gma = self._get_gma(attrs=attrs) - self.assertTrue(issubclass(gma.get_obj_perms_manage_user_form(None), forms.Form)) + self.assertTrue( + issubclass(gma.get_obj_perms_manage_user_form(None), forms.Form) + ) def test_obj_perms_user_select_form_attr(self): - attrs = {'obj_perms_user_select_form': forms.Form} + attrs = {"obj_perms_user_select_form": forms.Form} gma = self._get_gma(attrs=attrs) - self.assertTrue(issubclass(gma.get_obj_perms_user_select_form(None), forms.Form)) + self.assertTrue( + issubclass(gma.get_obj_perms_user_select_form(None), forms.Form) + ) def test_obj_perms_manage_group_template_attr(self): - attrs = {'obj_perms_manage_group_template': 'foobar.html'} + attrs = {"obj_perms_manage_group_template": "foobar.html"} gma = self._get_gma(attrs=attrs) - self.assertTrue(gma.get_obj_perms_manage_group_template(), - 'foobar.html') + self.assertTrue(gma.get_obj_perms_manage_group_template(), "foobar.html") def test_obj_perms_manage_group_form_attr(self): - attrs = {'obj_perms_manage_group_form': forms.Form} + attrs = {"obj_perms_manage_group_form": forms.Form} gma = self._get_gma(attrs=attrs) - self.assertTrue(issubclass(gma.get_obj_perms_manage_group_form(None), forms.Form)) + self.assertTrue( + issubclass(gma.get_obj_perms_manage_group_form(None), forms.Form) + ) def test_obj_perms_group_select_form_attr(self): - attrs = {'obj_perms_group_select_form': forms.Form} + attrs = {"obj_perms_group_select_form": forms.Form} gma = self._get_gma(attrs=attrs) - self.assertTrue(issubclass(gma.get_obj_perms_group_select_form(None), forms.Form)) + self.assertTrue( + issubclass(gma.get_obj_perms_group_select_form(None), forms.Form) + ) def test_user_can_acces_owned_objects_only(self): attrs = { - 'user_can_access_owned_objects_only': True, - 'user_owned_objects_field': 'user', + "user_can_access_owned_objects_only": True, + "user_owned_objects_field": "user", } gma = self._get_gma(attrs=attrs, model=LogEntry) - joe = User.objects.create_user('joe', 'joe@example.com', 'joe') - jane = User.objects.create_user('jane', 'jane@example.com', 'jane') + joe = User.objects.create_user("joe", "joe@example.com", "joe") + jane = User.objects.create_user("jane", "jane@example.com", "jane") ctype = ContentType.objects.get_for_model(User) - joe_entry = LogEntry.objects.create(user=joe, content_type=ctype, - object_id=joe.pk, action_flag=1, change_message='foo') - LogEntry.objects.create(user=jane, content_type=ctype, - object_id=jane.pk, action_flag=1, change_message='bar') + joe_entry = LogEntry.objects.create( + user=joe, + content_type=ctype, + object_id=joe.pk, + action_flag=1, + change_message="foo", + ) + LogEntry.objects.create( + user=jane, + content_type=ctype, + object_id=jane.pk, + action_flag=1, + change_message="bar", + ) request = HttpRequest() request.user = joe qs = gma.get_queryset(request) @@ -366,43 +390,69 @@ def test_user_can_acces_owned_objects_only(self): def test_user_can_acces_owned_objects_only_unless_superuser(self): attrs = { - 'user_can_access_owned_objects_only': True, - 'user_owned_objects_field': 'user', + "user_can_access_owned_objects_only": True, + "user_owned_objects_field": "user", } gma = self._get_gma(attrs=attrs, model=LogEntry) - joe = User.objects.create_superuser('joe', 'joe@example.com', 'joe') - jane = User.objects.create_user('jane', 'jane@example.com', 'jane') + joe = User.objects.create_superuser("joe", "joe@example.com", "joe") + jane = User.objects.create_user("jane", "jane@example.com", "jane") ctype = ContentType.objects.get_for_model(User) - joe_entry = LogEntry.objects.create(user=joe, content_type=ctype, - object_id=joe.pk, action_flag=1, change_message='foo') - jane_entry = LogEntry.objects.create(user=jane, content_type=ctype, - object_id=jane.pk, action_flag=1, change_message='bar') + joe_entry = LogEntry.objects.create( + user=joe, + content_type=ctype, + object_id=joe.pk, + action_flag=1, + change_message="foo", + ) + jane_entry = LogEntry.objects.create( + user=jane, + content_type=ctype, + object_id=jane.pk, + action_flag=1, + change_message="bar", + ) request = HttpRequest() request.user = joe qs = gma.get_queryset(request) - self.assertEqual(sorted([e.pk for e in qs]), - sorted([joe_entry.pk, jane_entry.pk])) + self.assertEqual( + sorted([e.pk for e in qs]), sorted([joe_entry.pk, jane_entry.pk]) + ) def test_user_can_access_owned_by_group_objects_only(self): attrs = { - 'user_can_access_owned_by_group_objects_only': True, - 'group_owned_objects_field': 'group', + "user_can_access_owned_by_group_objects_only": True, + "group_owned_objects_field": "group", } gma = self._get_gma(attrs=attrs, model=LogEntry) - joe = User.objects.create_user('joe', 'joe@example.com', 'joe') - joe_group = Group.objects.create(name='joe-group') + joe = User.objects.create_user("joe", "joe@example.com", "joe") + joe_group = Group.objects.create(name="joe-group") joe.groups.add(joe_group) - jane = User.objects.create_user('jane', 'jane@example.com', 'jane') - jane_group = Group.objects.create(name='jane-group') + jane = User.objects.create_user("jane", "jane@example.com", "jane") + jane_group = Group.objects.create(name="jane-group") jane.groups.add(jane_group) ctype = ContentType.objects.get_for_model(User) - LogEntry.objects.create(user=joe, content_type=ctype, - object_id=joe.pk, action_flag=1, change_message='foo') - LogEntry.objects.create(user=jane, content_type=ctype, - object_id=jane.pk, action_flag=1, change_message='bar') - joe_entry_group = LogEntry.objects.create(user=jane, content_type=ctype, - object_id=joe.pk, action_flag=1, change_message='foo', - group=joe_group) + LogEntry.objects.create( + user=joe, + content_type=ctype, + object_id=joe.pk, + action_flag=1, + change_message="foo", + ) + LogEntry.objects.create( + user=jane, + content_type=ctype, + object_id=jane.pk, + action_flag=1, + change_message="bar", + ) + joe_entry_group = LogEntry.objects.create( + user=jane, + content_type=ctype, + object_id=joe.pk, + action_flag=1, + change_message="foo", + group=joe_group, + ) request = HttpRequest() request.user = joe qs = gma.get_queryset(request) @@ -410,32 +460,54 @@ def test_user_can_access_owned_by_group_objects_only(self): def test_user_can_access_owned_by_group_objects_only_unless_superuser(self): attrs = { - 'user_can_access_owned_by_group_objects_only': True, - 'group_owned_objects_field': 'group', + "user_can_access_owned_by_group_objects_only": True, + "group_owned_objects_field": "group", } gma = self._get_gma(attrs=attrs, model=LogEntry) - joe = User.objects.create_superuser('joe', 'joe@example.com', 'joe') - joe_group = Group.objects.create(name='joe-group') + joe = User.objects.create_superuser("joe", "joe@example.com", "joe") + joe_group = Group.objects.create(name="joe-group") joe.groups.add(joe_group) - jane = User.objects.create_user('jane', 'jane@example.com', 'jane') - jane_group = Group.objects.create(name='jane-group') + jane = User.objects.create_user("jane", "jane@example.com", "jane") + jane_group = Group.objects.create(name="jane-group") jane.groups.add(jane_group) ctype = ContentType.objects.get_for_model(User) - LogEntry.objects.create(user=joe, content_type=ctype, - object_id=joe.pk, action_flag=1, change_message='foo') - LogEntry.objects.create(user=jane, content_type=ctype, - object_id=jane.pk, action_flag=1, change_message='bar') - LogEntry.objects.create(user=jane, content_type=ctype, - object_id=joe.pk, action_flag=1, change_message='foo', - group=joe_group) - LogEntry.objects.create(user=joe, content_type=ctype, - object_id=joe.pk, action_flag=1, change_message='foo', - group=jane_group) + LogEntry.objects.create( + user=joe, + content_type=ctype, + object_id=joe.pk, + action_flag=1, + change_message="foo", + ) + LogEntry.objects.create( + user=jane, + content_type=ctype, + object_id=jane.pk, + action_flag=1, + change_message="bar", + ) + LogEntry.objects.create( + user=jane, + content_type=ctype, + object_id=joe.pk, + action_flag=1, + change_message="foo", + group=joe_group, + ) + LogEntry.objects.create( + user=joe, + content_type=ctype, + object_id=joe.pk, + action_flag=1, + change_message="foo", + group=jane_group, + ) request = HttpRequest() request.user = joe qs = gma.get_queryset(request) - self.assertEqual(sorted(e.pk for e in qs), - sorted(LogEntry.objects.values_list('pk', flat=True))) + self.assertEqual( + sorted(e.pk for e in qs), + sorted(LogEntry.objects.values_list("pk", flat=True)), + ) class GrappelliGuardedModelAdminTests(TestCase): @@ -447,29 +519,35 @@ def _get_gma(self, attrs=None, name=None, model=None): Returns ``GuardedModelAdmin`` instance. """ attrs = attrs or {} - name = str(name or 'GMA') + name = str(name or "GMA") model = model or User GMA = type(name, (GuardedModelAdmin,), attrs) gma = GMA(model, admin.site) return gma def setUp(self): - settings.INSTALLED_APPS = ['grappelli'] + list(settings.INSTALLED_APPS) + settings.INSTALLED_APPS = ["grappelli"] + list(settings.INSTALLED_APPS) def tearDown(self): settings.INSTALLED_APPS = self.org_installed_apps def test_get_obj_perms_manage_template(self): gma = self._get_gma() - self.assertEqual(gma.get_obj_perms_manage_template(), - 'admin/guardian/contrib/grappelli/obj_perms_manage.html') + self.assertEqual( + gma.get_obj_perms_manage_template(), + "admin/guardian/contrib/grappelli/obj_perms_manage.html", + ) def test_get_obj_perms_manage_user_template(self): gma = self._get_gma() - self.assertEqual(gma.get_obj_perms_manage_user_template(), - 'admin/guardian/contrib/grappelli/obj_perms_manage_user.html') + self.assertEqual( + gma.get_obj_perms_manage_user_template(), + "admin/guardian/contrib/grappelli/obj_perms_manage_user.html", + ) def test_get_obj_perms_manage_group_template(self): gma = self._get_gma() - self.assertEqual(gma.get_obj_perms_manage_group_template(), - 'admin/guardian/contrib/grappelli/obj_perms_manage_group.html') + self.assertEqual( + gma.get_obj_perms_manage_group_template(), + "admin/guardian/contrib/grappelli/obj_perms_manage_group.html", + ) diff --git a/guardian/testapp/tests/test_checks.py b/guardian/testapp/tests/test_checks.py index 3d2b22c65..c1149436e 100644 --- a/guardian/testapp/tests/test_checks.py +++ b/guardian/testapp/tests/test_checks.py @@ -3,15 +3,13 @@ class SystemCheckTestCase(TestCase): - def test_checks(self): - """ Test custom system checks + """Test custom system checks :return: None """ self.assertFalse(check_settings(None)) with self.settings( - AUTHENTICATION_BACKENDS=( - 'django.contrib.auth.backends.ModelBackend',), + AUTHENTICATION_BACKENDS=("django.contrib.auth.backends.ModelBackend",), ): self.assertEqual(len(check_settings(None)), 1) diff --git a/guardian/testapp/tests/test_conf.py b/guardian/testapp/tests/test_conf.py index 5724417ee..96bbda1cf 100644 --- a/guardian/testapp/tests/test_conf.py +++ b/guardian/testapp/tests/test_conf.py @@ -6,19 +6,22 @@ class TestConfiguration(TestCase): - def test_check_configuration(self): - with mock.patch('guardian.conf.settings.RENDER_403', True): - with mock.patch('guardian.conf.settings.RAISE_403', True): - self.assertRaises(ImproperlyConfigured, - guardian_settings.check_configuration) + with mock.patch("guardian.conf.settings.RENDER_403", True): + with mock.patch("guardian.conf.settings.RAISE_403", True): + self.assertRaises( + ImproperlyConfigured, guardian_settings.check_configuration + ) def test_get_content_type(self): - with mock.patch('guardian.conf.settings.GET_CONTENT_TYPE', 'guardian.testapp.tests.test_conf.get_test_content_type'): - self.assertEqual(get_content_type(None), 'x') + with mock.patch( + "guardian.conf.settings.GET_CONTENT_TYPE", + "guardian.testapp.tests.test_conf.get_test_content_type", + ): + self.assertEqual(get_content_type(None), "x") def get_test_content_type(obj): - """ Used in TestConfiguration.test_get_content_type().""" - return 'x' + """Used in TestConfiguration.test_get_content_type().""" + return "x" diff --git a/guardian/testapp/tests/test_core.py b/guardian/testapp/tests/test_core.py index b343f8e4e..283a15d56 100644 --- a/guardian/testapp/tests/test_core.py +++ b/guardian/testapp/tests/test_core.py @@ -16,34 +16,39 @@ from guardian.management import create_anonymous_user from guardian.utils import evict_obj_perms_cache -from guardian.testapp.models import Project, ProjectUserObjectPermission, ProjectGroupObjectPermission +from guardian.testapp.models import ( + Project, + ProjectUserObjectPermission, + ProjectGroupObjectPermission, +) -auth_app = django_apps.get_app_config('auth') +auth_app = django_apps.get_app_config("auth") User = get_user_model() class CustomUserTests(TestCase): - def test_create_anonymous_user(self): - create_anonymous_user(object(), using='default') + create_anonymous_user(object(), using="default") self.assertEqual(1, User.objects.all().count()) anonymous = User.objects.all()[0] self.assertEqual(anonymous.username, guardian_settings.ANONYMOUS_USER_NAME) class ObjectPermissionTestCase(TestCase): - def setUp(self): - self.group, created = Group.objects.get_or_create(name='jackGroup') - self.user, created = User.objects.get_or_create(username='jack') + self.group, created = Group.objects.get_or_create(name="jackGroup") + self.user, created = User.objects.get_or_create(username="jack") self.user.groups.add(self.group) self.ctype = ContentType.objects.create( - model='bar', app_label='fake-for-guardian-tests') - self.ctype_qset = ContentType.objects.filter(model='bar', - app_label='fake-for-guardian-tests') + model="bar", app_label="fake-for-guardian-tests" + ) + self.ctype_qset = ContentType.objects.filter( + model="bar", app_label="fake-for-guardian-tests" + ) self.ctype_list = [self.ctype_qset.first()] self.anonymous_user = User.objects.get( - username=guardian_settings.ANONYMOUS_USER_NAME) + username=guardian_settings.ANONYMOUS_USER_NAME + ) def get_permission(self, codename, app_label=None): qs = Permission.objects @@ -53,7 +58,6 @@ def get_permission(self, codename, app_label=None): class ObjectPermissionCheckerTest(ObjectPermissionTestCase): - def setUp(self): super().setUp() # Required if MySQL backend is used :/ @@ -73,7 +77,7 @@ def test_cache_for_queries_count(self): # at get_user_obj_perms_model and get_group_obj_perms_model query_count = len(connection.queries) res = checker.has_perm("change_group", self.group) - if 'guardian.testapp' in settings.INSTALLED_APPS: + if "guardian.testapp" in settings.INSTALLED_APPS: expected = 5 else: # TODO: This is strange, need to investigate; totally not sure @@ -94,7 +98,7 @@ def test_cache_for_queries_count(self): self.assertEqual(len(connection.queries), query_count) # Checking for same model but other instance should spawn 2 queries - new_group = Group.objects.create(name='new-group') + new_group = Group.objects.create(name="new-group") query_count = len(connection.queries) checker.has_perm("change_group", new_group) self.assertEqual(len(connection.queries), query_count + 2) @@ -110,8 +114,9 @@ def test_cache_for_queries_count(self): settings.DEBUG = False def test_init(self): - self.assertRaises(NotUserNorGroup, ObjectPermissionChecker, - user_or_group=ContentType()) + self.assertRaises( + NotUserNorGroup, ObjectPermissionChecker, user_or_group=ContentType() + ) self.assertRaises(NotUserNorGroup, ObjectPermissionChecker) def test_anonymous_user(self): @@ -121,30 +126,35 @@ def test_anonymous_user(self): self.assertTrue([] == list(check.get_perms(self.ctype))) def test_superuser(self): - user = User.objects.create(username='superuser', is_superuser=True) + user = User.objects.create(username="superuser", is_superuser=True) check = ObjectPermissionChecker(user) ctype = ContentType.objects.get_for_model(self.ctype) - perms = sorted(chain(*Permission.objects - .filter(content_type=ctype) - .values_list('codename'))) + perms = sorted( + chain( + *Permission.objects.filter(content_type=ctype).values_list("codename") + ) + ) self.assertEqual(perms, check.get_perms(self.ctype)) for perm in perms: self.assertTrue(check.has_perm(perm, self.ctype)) def test_not_active_superuser(self): - user = User.objects.create(username='not_active_superuser', - is_superuser=True, is_active=False) + user = User.objects.create( + username="not_active_superuser", is_superuser=True, is_active=False + ) check = ObjectPermissionChecker(user) ctype = ContentType.objects.get_for_model(self.ctype) - perms = sorted(chain(*Permission.objects - .filter(content_type=ctype) - .values_list('codename'))) + perms = sorted( + chain( + *Permission.objects.filter(content_type=ctype).values_list("codename") + ) + ) self.assertEqual(check.get_perms(self.ctype), []) for perm in perms: self.assertFalse(check.has_perm(perm, self.ctype)) def test_not_active_user(self): - user = User.objects.create(username='notactive') + user = User.objects.create(username="notactive") assign_perm("change_contenttype", user, self.ctype) # new ObjectPermissionChecker is created for each User.has_perm call @@ -154,7 +164,7 @@ def test_not_active_user(self): # use on one checker only (as user's is_active attr should be checked # before try to use cache - user = User.objects.create(username='notactive-cache') + user = User.objects.create(username="notactive-cache") assign_perm("change_contenttype", user, self.ctype) check = ObjectPermissionChecker(user) @@ -163,16 +173,14 @@ def test_not_active_user(self): self.assertFalse(check.has_perm("change_contenttype", self.ctype)) def test_get_perms(self): - group = Group.objects.create(name='group') - obj1 = ContentType.objects.create( - model='foo', app_label='guardian-tests') - obj2 = ContentType.objects.create( - model='bar', app_label='guardian-tests') + group = Group.objects.create(name="group") + obj1 = ContentType.objects.create(model="foo", app_label="guardian-tests") + obj2 = ContentType.objects.create(model="bar", app_label="guardian-tests") assign_perms = { - group: ('change_group', 'delete_group'), - obj1: ('change_contenttype', 'delete_contenttype'), - obj2: ('delete_contenttype',), + group: ("change_group", "delete_group"), + obj1: ("change_contenttype", "delete_contenttype"), + obj2: ("delete_contenttype",), } check = ObjectPermissionChecker(self.user) @@ -186,8 +194,7 @@ def test_get_perms(self): for obj, perms in assign_perms.items(): for perm in perms: - GroupObjectPermission.objects.assign_perm( - perm, self.group, obj) + GroupObjectPermission.objects.assign_perm(perm, self.group, obj) self.assertEqual(sorted(perms), sorted(check.get_perms(obj))) def test_prefetch_user_perms(self): @@ -196,9 +203,9 @@ def test_prefetch_user_perms(self): from django.db import connection ContentType.objects.clear_cache() - group1 = Group.objects.create(name='group1') - group2 = Group.objects.create(name='group2') - user = User.objects.create(username='active_user', is_active=True) + group1 = Group.objects.create(name="group1") + group2 = Group.objects.create(name="group2") + user = User.objects.create(username="active_user", is_active=True) assign_perm("change_group", user, self.group) assign_perm("change_group", user, group1) checker = ObjectPermissionChecker(user) @@ -209,10 +216,7 @@ def test_prefetch_user_perms(self): query_count = len(connection.queries) # Checking cache is filled - self.assertEqual( - len(checker._obj_perms_cache), - len(prefetched_objects) - ) + self.assertEqual(len(checker._obj_perms_cache), len(prefetched_objects)) # Checking shouldn't spawn any queries checker.has_perm("change_group", self.group) @@ -241,9 +245,10 @@ def test_prefetch_superuser_perms(self): from django.db import connection ContentType.objects.clear_cache() - group1 = Group.objects.create(name='group1') - user = User.objects.create(username='active_superuser', - is_superuser=True, is_active=True) + group1 = Group.objects.create(name="group1") + user = User.objects.create( + username="active_superuser", is_superuser=True, is_active=True + ) assign_perm("change_group", user, self.group) checker = ObjectPermissionChecker(user) @@ -253,10 +258,7 @@ def test_prefetch_superuser_perms(self): query_count = len(connection.queries) # Checking cache is filled - self.assertEqual( - len(checker._obj_perms_cache), - len(prefetched_objects) - ) + self.assertEqual(len(checker._obj_perms_cache), len(prefetched_objects)) # Checking shouldn't spawn any queries checker.has_perm("change_group", self.group) @@ -279,8 +281,8 @@ def test_prefetch_group_perms(self): from django.db import connection ContentType.objects.clear_cache() - group1 = Group.objects.create(name='group1') - group2 = Group.objects.create(name='group2') + group1 = Group.objects.create(name="group1") + group2 = Group.objects.create(name="group2") assign_perm("change_group", group1, self.group) assign_perm("change_group", group1, group1) checker = ObjectPermissionChecker(group1) @@ -292,10 +294,7 @@ def test_prefetch_group_perms(self): query_count = len(connection.queries) # Checking cache is filled - self.assertEqual( - len(checker._obj_perms_cache), - len(prefetched_objects) - ) + self.assertEqual(len(checker._obj_perms_cache), len(prefetched_objects)) # Checking shouldn't spawn any queries checker.has_perm("change_group", self.group) @@ -324,10 +323,8 @@ def test_prefetch_user_perms_direct_rel(self): from django.db import connection ContentType.objects.clear_cache() - user = User.objects.create(username='active_user', is_active=True) - projects = \ - [Project.objects.create(name='Project%s' % i) - for i in range(3)] + user = User.objects.create(username="active_user", is_active=True) + projects = [Project.objects.create(name="Project%s" % i) for i in range(3)] assign_perm("change_project", user, projects[0]) assign_perm("change_project", user, projects[1]) @@ -369,10 +366,9 @@ def test_prefetch_superuser_perms_direct_rel(self): ContentType.objects.clear_cache() user = User.objects.create( - username='active_user', is_active=True, is_superuser=True) - projects = \ - [Project.objects.create(name='Project%s' % i) - for i in range(2)] + username="active_user", is_active=True, is_superuser=True + ) + projects = [Project.objects.create(name="Project%s" % i) for i in range(2)] assign_perm("change_project", user, projects[0]) checker = ObjectPermissionChecker(user) @@ -406,10 +402,8 @@ def test_prefetch_group_perms_direct_rel(self): from django.db import connection ContentType.objects.clear_cache() - group = Group.objects.create(name='new-group') - projects = \ - [Project.objects.create(name='Project%s' % i) - for i in range(3)] + group = Group.objects.create(name="new-group") + projects = [Project.objects.create(name="Project%s" % i) for i in range(3)] assign_perm("change_project", group, projects[0]) assign_perm("change_project", group, projects[1]) @@ -453,15 +447,15 @@ def test_autoprefetch_user_perms(self): from django.db import connection ContentType.objects.clear_cache() - group1 = Group.objects.create(name='group1') - group2 = Group.objects.create(name='group2') - user = User.objects.create(username='active_user', is_active=True) + group1 = Group.objects.create(name="group1") + group2 = Group.objects.create(name="group2") + user = User.objects.create(username="active_user", is_active=True) assign_groups = [self.group, group1] for group in assign_groups: assign_perm("change_group", user, group) # Faux monkeypatching - setattr(User, 'evict_obj_perms_cache', evict_obj_perms_cache) + setattr(User, "evict_obj_perms_cache", evict_obj_perms_cache) # Try to evict non-existent cache, should return false self.assertFalse(user.evict_obj_perms_cache()) @@ -477,13 +471,10 @@ def test_autoprefetch_user_perms(self): self.assertEqual(query_count - pre_query_count, 2) # Check user has cache attribute - self.assertTrue(hasattr(user, '_guardian_perms_cache')) + self.assertTrue(hasattr(user, "_guardian_perms_cache")) # Checking cache is filled - self.assertEqual( - len(checker._obj_perms_cache), - len(assign_groups) - ) + self.assertEqual(len(checker._obj_perms_cache), len(assign_groups)) # Checking shouldn't spawn any queries self.assertTrue(checker.has_perm("change_group", self.group)) @@ -510,7 +501,7 @@ def test_autoprefetch_user_perms(self): # Evict cache and verify that reloaded perms have changed self.assertTrue(user.evict_obj_perms_cache()) - self.assertFalse(hasattr(user, '_guardian_perms_cache')) + self.assertFalse(hasattr(user, "_guardian_perms_cache")) assign_perm("delete_group", user, self.group) query_count = len(connection.queries) # New checker object so that we reload perms from db @@ -520,7 +511,6 @@ def test_autoprefetch_user_perms(self): # Two more queries should have been executed self.assertEqual(len(connection.queries), query_count + 2) - finally: settings.DEBUG = False guardian_settings.AUTO_PREFETCH = False @@ -536,9 +526,10 @@ def test_autoprefetch_superuser_perms(self): from django.db import connection ContentType.objects.clear_cache() - group1 = Group.objects.create(name='group1') - user = User.objects.create(username='active_superuser', - is_superuser=True, is_active=True) + group1 = Group.objects.create(name="group1") + user = User.objects.create( + username="active_superuser", is_superuser=True, is_active=True + ) assign_perm("change_group", user, self.group) checker = ObjectPermissionChecker(user) @@ -547,7 +538,7 @@ def test_autoprefetch_superuser_perms(self): query_count = len(connection.queries) # Check user has cache attribute - self.assertTrue(hasattr(user, '_guardian_perms_cache')) + self.assertTrue(hasattr(user, "_guardian_perms_cache")) # Checking shouldn't spawn any queries self.assertTrue(checker.has_perm("change_group", self.group)) @@ -579,10 +570,8 @@ def test_autoprefetch_group_perms(self): from django.db import connection ContentType.objects.clear_cache() - group = Group.objects.create(name='new-group') - projects = \ - [Project.objects.create(name='Project%s' % i) - for i in range(3)] + group = Group.objects.create(name="new-group") + projects = [Project.objects.create(name="Project%s" % i) for i in range(3)] assign_perm("change_project", group, projects[0]) assign_perm("change_project", group, projects[1]) @@ -597,7 +586,7 @@ def test_autoprefetch_group_perms(self): self.assertEqual(query_count - pre_query_count, 1) # Check group has cache attribute - self.assertTrue(hasattr(group, '_guardian_perms_cache')) + self.assertTrue(hasattr(group, "_guardian_perms_cache")) # Checking shouldn't spawn any queries self.assertTrue(checker.has_perm("change_project", projects[0])) diff --git a/guardian/testapp/tests/test_custompkmodel.py b/guardian/testapp/tests/test_custompkmodel.py index 2bb861aab..1941f3fac 100644 --- a/guardian/testapp/tests/test_custompkmodel.py +++ b/guardian/testapp/tests/test_custompkmodel.py @@ -12,19 +12,23 @@ class CustomPKModelTest(TestCase): """ def setUp(self): - self.user = get_user_model().objects.create(username='joe') + self.user = get_user_model().objects.create(username="joe") self.ctype = ContentType.objects.create( - model='bar', app_label='fake-for-guardian-tests') + model="bar", app_label="fake-for-guardian-tests" + ) def test_assign_perm(self): - assign_perm('contenttypes.change_contenttype', self.user, self.ctype) - self.assertTrue(self.user.has_perm('contenttypes.change_contenttype', - self.ctype)) + assign_perm("contenttypes.change_contenttype", self.user, self.ctype) + self.assertTrue( + self.user.has_perm("contenttypes.change_contenttype", self.ctype) + ) def test_remove_perm(self): - assign_perm('contenttypes.change_contenttype', self.user, self.ctype) - self.assertTrue(self.user.has_perm('contenttypes.change_contenttype', - self.ctype)) - remove_perm('contenttypes.change_contenttype', self.user, self.ctype) - self.assertFalse(self.user.has_perm('contenttypes.change_contenttype', - self.ctype)) + assign_perm("contenttypes.change_contenttype", self.user, self.ctype) + self.assertTrue( + self.user.has_perm("contenttypes.change_contenttype", self.ctype) + ) + remove_perm("contenttypes.change_contenttype", self.user, self.ctype) + self.assertFalse( + self.user.has_perm("contenttypes.change_contenttype", self.ctype) + ) diff --git a/guardian/testapp/tests/test_decorators.py b/guardian/testapp/tests/test_decorators.py index c1de6de10..080d7b7ff 100644 --- a/guardian/testapp/tests/test_decorators.py +++ b/guardian/testapp/tests/test_decorators.py @@ -15,7 +15,11 @@ from guardian.compat import get_user_model_path from guardian.compat import get_user_permission_full_codename from unittest import mock -from guardian.decorators import permission_required, permission_required_or_403, permission_required_or_404 +from guardian.decorators import ( + permission_required, + permission_required_or_403, + permission_required_or_404, +) from guardian.exceptions import GuardianError from guardian.exceptions import WrongAppError from guardian.shortcuts import assign_perm @@ -29,12 +33,11 @@ @skipUnlessTestApp class PermissionRequiredTest(TestDataMixin, TestCase): - def setUp(self): super().setUp() self.anon = AnonymousUser() - self.user = User.objects.get_or_create(username='jack')[0] - self.group = Group.objects.get_or_create(name='jackGroup')[0] + self.user = User.objects.get_or_create(username="jack")[0] + self.group = Group.objects.get_or_create(name="jackGroup")[0] def _get_request(self, user=None): if user is None: @@ -46,104 +49,112 @@ def _get_request(self, user=None): def test_no_args(self): try: + @permission_required def dummy_view(request): - return HttpResponse('dummy_view') + return HttpResponse("dummy_view") + except GuardianError: pass else: - self.fail("Trying to decorate using permission_required without " - "permission as first argument should raise exception") + self.fail( + "Trying to decorate using permission_required without " + "permission as first argument should raise exception" + ) def test_RENDER_403_is_false(self): request = self._get_request(self.anon) - @permission_required_or_403('not_installed_app.change_user') + @permission_required_or_403("not_installed_app.change_user") def dummy_view(request): - return HttpResponse('dummy_view') + return HttpResponse("dummy_view") - with mock.patch('guardian.conf.settings.RENDER_403', False): + with mock.patch("guardian.conf.settings.RENDER_403", False): response = dummy_view(request) - self.assertEqual(response.content, b'') + self.assertEqual(response.content, b"") self.assertTrue(isinstance(response, HttpResponseForbidden)) def test_RENDER_404_is_false(self): request = self._get_request(self.anon) - @permission_required_or_404('not_installed_app.change_user') + @permission_required_or_404("not_installed_app.change_user") def dummy_view(request): - return HttpResponse('dummy_view') + return HttpResponse("dummy_view") - with mock.patch('guardian.conf.settings.RENDER_404', False): + with mock.patch("guardian.conf.settings.RENDER_404", False): response = dummy_view(request) - self.assertEqual(response.content, b'') + self.assertEqual(response.content, b"") self.assertTrue(isinstance(response, HttpResponseNotFound)) - @mock.patch('guardian.conf.settings.RENDER_403', True) + @mock.patch("guardian.conf.settings.RENDER_403", True) def test_TEMPLATE_403_setting(self): request = self._get_request(self.anon) - @permission_required_or_403('not_installed_app.change_user') + @permission_required_or_403("not_installed_app.change_user") def dummy_view(request): - return HttpResponse('dummy_view') + return HttpResponse("dummy_view") - with mock.patch('guardian.conf.settings.TEMPLATE_403', 'dummy403.html'): + with mock.patch("guardian.conf.settings.TEMPLATE_403", "dummy403.html"): response = dummy_view(request) - self.assertEqual(response.content, b'foobar403\n') + self.assertEqual(response.content, b"foobar403\n") - @mock.patch('guardian.conf.settings.RENDER_404', True) + @mock.patch("guardian.conf.settings.RENDER_404", True) def test_TEMPLATE_404_setting(self): request = self._get_request(self.anon) - @permission_required_or_404('not_installed_app.change_user') + @permission_required_or_404("not_installed_app.change_user") def dummy_view(request): - return HttpResponse('dummy_view') + return HttpResponse("dummy_view") - with mock.patch('guardian.conf.settings.TEMPLATE_404', 'dummy404.html'): + with mock.patch("guardian.conf.settings.TEMPLATE_404", "dummy404.html"): response = dummy_view(request) - self.assertEqual(response.content, b'foobar404\n') + self.assertEqual(response.content, b"foobar404\n") - @mock.patch('guardian.conf.settings.RENDER_403', True) + @mock.patch("guardian.conf.settings.RENDER_403", True) def test_403_response_raises_error(self): request = self._get_request(self.anon) - @permission_required_or_403('not_installed_app.change_user') + @permission_required_or_403("not_installed_app.change_user") def dummy_view(request): - return HttpResponse('dummy_view') - with mock.patch('guardian.conf.settings.TEMPLATE_403', - '_non-exisitng-403.html'): + return HttpResponse("dummy_view") + + with mock.patch( + "guardian.conf.settings.TEMPLATE_403", "_non-exisitng-403.html" + ): self.assertRaises(TemplateDoesNotExist, dummy_view, request) - @mock.patch('guardian.conf.settings.RENDER_404', True) + @mock.patch("guardian.conf.settings.RENDER_404", True) def test_404_response_raises_error(self): request = self._get_request(self.anon) - @permission_required_or_404('not_installed_app.change_user') + @permission_required_or_404("not_installed_app.change_user") def dummy_view(request): - return HttpResponse('dummy_view') - with mock.patch('guardian.conf.settings.TEMPLATE_404', - '_non-exisitng-404.html'): + return HttpResponse("dummy_view") + + with mock.patch( + "guardian.conf.settings.TEMPLATE_404", "_non-exisitng-404.html" + ): self.assertRaises(TemplateDoesNotExist, dummy_view, request) - @mock.patch('guardian.conf.settings.RENDER_403', False) - @mock.patch('guardian.conf.settings.RAISE_403', True) + @mock.patch("guardian.conf.settings.RENDER_403", False) + @mock.patch("guardian.conf.settings.RAISE_403", True) def test_RAISE_403_setting_is_true(self): request = self._get_request(self.anon) - @permission_required_or_403('not_installed_app.change_user') + @permission_required_or_403("not_installed_app.change_user") def dummy_view(request): - return HttpResponse('dummy_view') + return HttpResponse("dummy_view") self.assertRaises(PermissionDenied, dummy_view, request) - @mock.patch('guardian.conf.settings.RENDER_404', False) - @mock.patch('guardian.conf.settings.RAISE_404', True) + @mock.patch("guardian.conf.settings.RENDER_404", False) + @mock.patch("guardian.conf.settings.RAISE_404", True) def test_RAISE_404_setting_is_true(self): request = self._get_request(self.anon) - @permission_required_or_404('not_installed_app.change_user') + @permission_required_or_404("not_installed_app.change_user") def dummy_view(request): - return HttpResponse('dummy_view') + return HttpResponse("dummy_view") self.assertRaises(ObjectDoesNotExist, dummy_view, request) @@ -151,27 +162,30 @@ def test_anonymous_user_wrong_app(self): request = self._get_request(self.anon) - @permission_required_or_403('not_installed_app.change_user') + @permission_required_or_403("not_installed_app.change_user") def dummy_view(request): - return HttpResponse('dummy_view') + return HttpResponse("dummy_view") + self.assertEqual(dummy_view(request).status_code, 403) def test_anonymous_user_wrong_codename(self): request = self._get_request() - @permission_required_or_403('auth.wrong_codename') + @permission_required_or_403("auth.wrong_codename") def dummy_view(request): - return HttpResponse('dummy_view') + return HttpResponse("dummy_view") + self.assertEqual(dummy_view(request).status_code, 403) def test_anonymous_user(self): request = self._get_request() - @permission_required_or_403('auth.change_user') + @permission_required_or_403("auth.change_user") def dummy_view(request): - return HttpResponse('dummy_view') + return HttpResponse("dummy_view") + self.assertEqual(dummy_view(request).status_code, 403) def test_wrong_lookup_variables_number(self): @@ -179,34 +193,40 @@ def test_wrong_lookup_variables_number(self): request = self._get_request() try: - @permission_required_or_403('auth.change_user', (User, 'username')) + + @permission_required_or_403("auth.change_user", (User, "username")) def dummy_view(request, username): pass - dummy_view(request, username='jack') + + dummy_view(request, username="jack") except GuardianError: pass else: - self.fail("If lookup variables are passed they must be tuple of: " - "(ModelClass/app_label.ModelClass/queryset, " - ")\n" - "Otherwise GuardianError should be raised") + self.fail( + "If lookup variables are passed they must be tuple of: " + "(ModelClass/app_label.ModelClass/queryset, " + ")\n" + "Otherwise GuardianError should be raised" + ) def test_wrong_lookup_variables(self): request = self._get_request() args = ( - (2010, 'username', 'username'), - ('User', 'username', 'username'), - (User, 'username', 'no_arg'), + (2010, "username", "username"), + ("User", "username", "username"), + (User, "username", "no_arg"), ) for tup in args: try: - @permission_required_or_403('auth.change_user', tup) + + @permission_required_or_403("auth.change_user", tup) def show_user(request, username): user = get_object_or_404(User, username=username) return HttpResponse("It's %s here!" % user.username) - show_user(request, 'jack') + + show_user(request, "jack") except GuardianError: pass else: @@ -216,26 +236,27 @@ def test_user_has_no_access(self): request = self._get_request() - @permission_required_or_403('auth.change_user') + @permission_required_or_403("auth.change_user") def dummy_view(request): - return HttpResponse('dummy_view') + return HttpResponse("dummy_view") + self.assertEqual(dummy_view(request).status_code, 403) def test_user_has_access(self): - perm = get_user_permission_full_codename('change') - joe, created = User.objects.get_or_create(username='joe') + perm = get_user_permission_full_codename("change") + joe, created = User.objects.get_or_create(username="joe") assign_perm(perm, self.user, obj=joe) request = self._get_request(self.user) - @permission_required_or_403(perm, ( - user_model_path, 'username', 'username')) + @permission_required_or_403(perm, (user_model_path, "username", "username")) def dummy_view(request, username): - return HttpResponse('dummy_view') - response = dummy_view(request, username='joe') + return HttpResponse("dummy_view") + + response = dummy_view(request, username="joe") self.assertEqual(response.status_code, 200) - self.assertEqual(response.content, b'dummy_view') + self.assertEqual(response.content, b"dummy_view") def test_user_has_access_on_model_with_metaclass(self): """ @@ -244,98 +265,102 @@ def test_user_has_access_on_model_with_metaclass(self): a custom metaclass, the decorator fail because type doesn't return `ModelBase` """ - perm = get_user_permission_full_codename('change') + perm = get_user_permission_full_codename("change") class TestMeta(ModelBase): pass class ProxyUser(User): - class Meta: proxy = True app_label = User._meta.app_label + __metaclass__ = TestMeta - joe, created = ProxyUser.objects.get_or_create(username='joe') + joe, created = ProxyUser.objects.get_or_create(username="joe") assign_perm(perm, self.user, obj=joe) request = self._get_request(self.user) - @permission_required_or_403(perm, ( - ProxyUser, 'username', 'username')) + @permission_required_or_403(perm, (ProxyUser, "username", "username")) def dummy_view(request, username): - return HttpResponse('dummy_view') - response = dummy_view(request, username='joe') + return HttpResponse("dummy_view") + + response = dummy_view(request, username="joe") self.assertEqual(response.status_code, 200) - self.assertEqual(response.content, b'dummy_view') + self.assertEqual(response.content, b"dummy_view") def test_user_has_obj_access_even_if_we_also_check_for_global(self): - perm = get_user_permission_full_codename('change') - joe, created = User.objects.get_or_create(username='joe') + perm = get_user_permission_full_codename("change") + joe, created = User.objects.get_or_create(username="joe") assign_perm(perm, self.user, obj=joe) request = self._get_request(self.user) - @permission_required_or_403(perm, ( - user_model_path, 'username', 'username'), accept_global_perms=True) + @permission_required_or_403( + perm, (user_model_path, "username", "username"), accept_global_perms=True + ) def dummy_view(request, username): - return HttpResponse('dummy_view') - response = dummy_view(request, username='joe') + return HttpResponse("dummy_view") + + response = dummy_view(request, username="joe") self.assertEqual(response.status_code, 200) - self.assertEqual(response.content, b'dummy_view') + self.assertEqual(response.content, b"dummy_view") def test_user_has_no_obj_perm_access(self): - perm = get_user_permission_full_codename('change') - joe, created = User.objects.get_or_create(username='joe') + perm = get_user_permission_full_codename("change") + joe, created = User.objects.get_or_create(username="joe") request = self._get_request(self.user) - @permission_required_or_403(perm, ( - user_model_path, 'username', 'username')) + @permission_required_or_403(perm, (user_model_path, "username", "username")) def dummy_view(request, username): - return HttpResponse('dummy_view') - response = dummy_view(request, username='joe') + return HttpResponse("dummy_view") + + response = dummy_view(request, username="joe") self.assertEqual(response.status_code, 403) def test_user_has_global_perm_access_but_flag_not_set(self): - perm = get_user_permission_full_codename('change') - joe, created = User.objects.get_or_create(username='joe') + perm = get_user_permission_full_codename("change") + joe, created = User.objects.get_or_create(username="joe") assign_perm(perm, self.user) request = self._get_request(self.user) - @permission_required_or_403(perm, ( - user_model_path, 'username', 'username')) + @permission_required_or_403(perm, (user_model_path, "username", "username")) def dummy_view(request, username): - return HttpResponse('dummy_view') - response = dummy_view(request, username='joe') + return HttpResponse("dummy_view") + + response = dummy_view(request, username="joe") self.assertEqual(response.status_code, 403) def test_user_has_global_perm_access(self): - perm = get_user_permission_full_codename('change') - joe, created = User.objects.get_or_create(username='joe') + perm = get_user_permission_full_codename("change") + joe, created = User.objects.get_or_create(username="joe") assign_perm(perm, self.user) request = self._get_request(self.user) - @permission_required_or_403(perm, ( - user_model_path, 'username', 'username'), accept_global_perms=True) + @permission_required_or_403( + perm, (user_model_path, "username", "username"), accept_global_perms=True + ) def dummy_view(request, username): - return HttpResponse('dummy_view') - response = dummy_view(request, username='joe') + return HttpResponse("dummy_view") + + response = dummy_view(request, username="joe") self.assertEqual(response.status_code, 200) - self.assertEqual(response.content, b'dummy_view') + self.assertEqual(response.content, b"dummy_view") def test_model_lookup(self): request = self._get_request(self.user) - perm = get_user_permission_full_codename('change') - joe, created = User.objects.get_or_create(username='joe') + perm = get_user_permission_full_codename("change") + joe, created = User.objects.get_or_create(username="joe") assign_perm(perm, self.user, obj=joe) models = ( @@ -344,53 +369,57 @@ def test_model_lookup(self): User.objects.filter(is_active=True), ) for model in models: - @permission_required_or_403(perm, (model, 'username', 'username')) + + @permission_required_or_403(perm, (model, "username", "username")) def dummy_view(request, username): get_object_or_404(User, username=username) - return HttpResponse('hello') + return HttpResponse("hello") + response = dummy_view(request, username=joe.username) - self.assertEqual(response.content, b'hello') + self.assertEqual(response.content, b"hello") def test_redirection_raises_wrong_app_error(self): from guardian.testapp.models import Project + request = self._get_request(self.user) - User.objects.create(username='foo') - Project.objects.create(name='foobar') + User.objects.create(username="foo") + Project.objects.create(name="foobar") - @permission_required('auth.change_group', - (Project, 'name', 'group_name'), - login_url='/foobar/') + @permission_required( + "auth.change_group", (Project, "name", "group_name"), login_url="/foobar/" + ) def dummy_view(request, project_name): pass + # 'auth.change_group' is wrong permission codename (should be one # related with User - self.assertRaises(WrongAppError, dummy_view, - request, group_name='foobar') + self.assertRaises(WrongAppError, dummy_view, request, group_name="foobar") def test_redirection(self): from guardian.testapp.models import Project request = self._get_request(self.user) - User.objects.create(username='foo') - Project.objects.create(name='foobar') + User.objects.create(username="foo") + Project.objects.create(name="foobar") - @permission_required('testapp.change_project', - (Project, 'name', 'project_name'), - login_url='/foobar/') + @permission_required( + "testapp.change_project", + (Project, "name", "project_name"), + login_url="/foobar/", + ) def dummy_view(request, project_name): pass - response = dummy_view(request, project_name='foobar') + + response = dummy_view(request, project_name="foobar") self.assertTrue(isinstance(response, HttpResponseRedirect)) - self.assertTrue(response._headers['location'][1].startswith( - '/foobar/')) + self.assertTrue(response._headers["location"][1].startswith("/foobar/")) - @override_settings(LOGIN_URL='django.contrib.auth.views.login') + @override_settings(LOGIN_URL="django.contrib.auth.views.login") def test_redirection_class(self): - view_url = '/permission_required/' + view_url = "/permission_required/" response = self.client.get(view_url) # this should be '/account/login' - self.assertRedirects( - response, global_settings.LOGIN_URL + "?next=" + view_url) + self.assertRedirects(response, global_settings.LOGIN_URL + "?next=" + view_url) diff --git a/guardian/testapp/tests/test_direct_rel.py b/guardian/testapp/tests/test_direct_rel.py index 4c4e38a97..f472a4c63 100644 --- a/guardian/testapp/tests/test_direct_rel.py +++ b/guardian/testapp/tests/test_direct_rel.py @@ -20,15 +20,15 @@ @skipUnlessTestApp class TestDirectUserPermissions(TestCase): def setUp(self): - self.joe = User.objects.create_user('joe', 'joe@example.com', 'foobar') - self.project = Project.objects.create(name='Foobar') + self.joe = User.objects.create_user("joe", "joe@example.com", "foobar") + self.project = Project.objects.create(name="Foobar") def get_perm(self, codename): - filters = {'content_type__app_label': 'testapp', 'codename': codename} + filters = {"content_type__app_label": "testapp", "codename": codename} return Permission.objects.get(**filters) def test_after_perm_is_created_without_shortcut(self): - perm = self.get_perm('add_project') + perm = self.get_perm("add_project") # we should not use assign here - if generic user obj perms model is # used then everything could go fine if using assign shortcut and we # would not be able to see any problem @@ -37,81 +37,84 @@ def test_after_perm_is_created_without_shortcut(self): permission=perm, content_object=self.project, ) - self.assertTrue(self.joe.has_perm('add_project', self.project)) + self.assertTrue(self.joe.has_perm("add_project", self.project)) def test_assign_perm(self): - assign_perm('add_project', self.joe, self.project) + assign_perm("add_project", self.joe, self.project) filters = { - 'content_object': self.project, - 'permission__codename': 'add_project', - 'user': self.joe, + "content_object": self.project, + "permission__codename": "add_project", + "user": self.joe, } result = ProjectUserObjectPermission.objects.filter(**filters).count() self.assertEqual(result, 1) def test_remove_perm(self): - assign_perm('add_project', self.joe, self.project) + assign_perm("add_project", self.joe, self.project) filters = { - 'content_object': self.project, - 'permission__codename': 'add_project', - 'user': self.joe, + "content_object": self.project, + "permission__codename": "add_project", + "user": self.joe, } result = ProjectUserObjectPermission.objects.filter(**filters).count() self.assertEqual(result, 1) - remove_perm('add_project', self.joe, self.project) + remove_perm("add_project", self.joe, self.project) result = ProjectUserObjectPermission.objects.filter(**filters).count() self.assertEqual(result, 0) def test_get_users_with_perms(self): - User.objects.create_user('john', 'john@foobar.com', 'john') - jane = User.objects.create_user('jane', 'jane@foobar.com', 'jane') - assign_perm('add_project', self.joe, self.project) - assign_perm('change_project', self.joe, self.project) - assign_perm('change_project', jane, self.project) - self.assertEqual(get_users_with_perms(self.project, attach_perms=True), - { - self.joe: ['add_project', 'change_project'], - jane: ['change_project'], - }) + User.objects.create_user("john", "john@foobar.com", "john") + jane = User.objects.create_user("jane", "jane@foobar.com", "jane") + assign_perm("add_project", self.joe, self.project) + assign_perm("change_project", self.joe, self.project) + assign_perm("change_project", jane, self.project) + self.assertEqual( + get_users_with_perms(self.project, attach_perms=True), + { + self.joe: ["add_project", "change_project"], + jane: ["change_project"], + }, + ) def test_get_users_with_perms_plus_groups(self): - User.objects.create_user('john', 'john@foobar.com', 'john') - jane = User.objects.create_user('jane', 'jane@foobar.com', 'jane') - group = Group.objects.create(name='devs') + User.objects.create_user("john", "john@foobar.com", "john") + jane = User.objects.create_user("jane", "jane@foobar.com", "jane") + group = Group.objects.create(name="devs") self.joe.groups.add(group) - assign_perm('add_project', self.joe, self.project) - assign_perm('change_project', group, self.project) - assign_perm('change_project', jane, self.project) - self.assertEqual(get_users_with_perms(self.project, attach_perms=True), - { - self.joe: ['add_project', 'change_project'], - jane: ['change_project'], - }) + assign_perm("add_project", self.joe, self.project) + assign_perm("change_project", group, self.project) + assign_perm("change_project", jane, self.project) + self.assertEqual( + get_users_with_perms(self.project, attach_perms=True), + { + self.joe: ["add_project", "change_project"], + jane: ["change_project"], + }, + ) def test_get_objects_for_user(self): - foo = Project.objects.create(name='foo') - bar = Project.objects.create(name='bar') - assign_perm('add_project', self.joe, foo) - assign_perm('add_project', self.joe, bar) - assign_perm('change_project', self.joe, bar) + foo = Project.objects.create(name="foo") + bar = Project.objects.create(name="bar") + assign_perm("add_project", self.joe, foo) + assign_perm("add_project", self.joe, bar) + assign_perm("change_project", self.joe, bar) - result = get_objects_for_user(self.joe, 'testapp.add_project') - self.assertEqual(sorted(p.pk for p in result), - sorted([foo.pk, bar.pk])) + result = get_objects_for_user(self.joe, "testapp.add_project") + self.assertEqual(sorted(p.pk for p in result), sorted([foo.pk, bar.pk])) def test_get_all_permissions(self): - foo = Project.objects.create(name='foo') - assign_perm('add_project', self.joe, foo) - assign_perm('change_project', self.joe, foo) + foo = Project.objects.create(name="foo") + assign_perm("add_project", self.joe, foo) + assign_perm("change_project", self.joe, foo) result = self.joe.get_all_permissions(foo) - self.assertEqual(result, {'add_project', 'change_project'}) + self.assertEqual(result, {"add_project", "change_project"}) def test_get_all_permissions_no_object(self): - foo = Project.objects.create(name='foo') - assign_perm('add_project', self.joe, foo) - assign_perm('change_project', self.joe, foo) + foo = Project.objects.create(name="foo") + assign_perm("add_project", self.joe, foo) + assign_perm("change_project", self.joe, foo) result = self.joe.get_all_permissions() self.assertEqual(result, set()) @@ -120,17 +123,17 @@ def test_get_all_permissions_no_object(self): @skipUnlessTestApp class TestDirectGroupPermissions(TestCase): def setUp(self): - self.joe = User.objects.create_user('joe', 'joe@example.com', 'foobar') - self.group = Group.objects.create(name='admins') + self.joe = User.objects.create_user("joe", "joe@example.com", "foobar") + self.group = Group.objects.create(name="admins") self.joe.groups.add(self.group) - self.project = Project.objects.create(name='Foobar') + self.project = Project.objects.create(name="Foobar") def get_perm(self, codename): - filters = {'content_type__app_label': 'testapp', 'codename': codename} + filters = {"content_type__app_label": "testapp", "codename": codename} return Permission.objects.get(**filters) def test_after_perm_is_created_without_shortcut(self): - perm = self.get_perm('add_project') + perm = self.get_perm("add_project") # we should not use assign here - if generic user obj perms model is # used then everything could go fine if using assign shortcut and we # would not be able to see any problem @@ -139,123 +142,130 @@ def test_after_perm_is_created_without_shortcut(self): permission=perm, content_object=self.project, ) - self.assertTrue(self.joe.has_perm('add_project', self.project)) + self.assertTrue(self.joe.has_perm("add_project", self.project)) def test_assign_perm(self): - assign_perm('add_project', self.group, self.project) + assign_perm("add_project", self.group, self.project) filters = { - 'content_object': self.project, - 'permission__codename': 'add_project', - 'group': self.group, + "content_object": self.project, + "permission__codename": "add_project", + "group": self.group, } result = ProjectGroupObjectPermission.objects.filter(**filters).count() self.assertEqual(result, 1) def test_remove_perm(self): - assign_perm('add_project', self.group, self.project) + assign_perm("add_project", self.group, self.project) filters = { - 'content_object': self.project, - 'permission__codename': 'add_project', - 'group': self.group, + "content_object": self.project, + "permission__codename": "add_project", + "group": self.group, } result = ProjectGroupObjectPermission.objects.filter(**filters).count() self.assertEqual(result, 1) - remove_perm('add_project', self.group, self.project) + remove_perm("add_project", self.group, self.project) result = ProjectGroupObjectPermission.objects.filter(**filters).count() self.assertEqual(result, 0) def test_get_groups_with_perms(self): - Group.objects.create(name='managers') - devs = Group.objects.create(name='devs') - assign_perm('add_project', self.group, self.project) - assign_perm('change_project', self.group, self.project) - assign_perm('change_project', devs, self.project) - self.assertEqual(get_groups_with_perms(self.project, attach_perms=True), - { - self.group: ['add_project', 'change_project'], - devs: ['change_project'], - }) - - def test_get_groups_with_perms_doesnt_spawn_extra_queries_for_more_groups_with_perms(self): - Group.objects.create(name='managers') - devs = Group.objects.create(name='devs') - devs1 = Group.objects.create(name='devs1') - devs2 = Group.objects.create(name='devs2') - devs3 = Group.objects.create(name='devs3') - devs4 = Group.objects.create(name='devs4') - devs5 = Group.objects.create(name='devs5') - assign_perm('add_project', self.group, self.project) - assign_perm('change_project', self.group, self.project) + Group.objects.create(name="managers") + devs = Group.objects.create(name="devs") + assign_perm("add_project", self.group, self.project) + assign_perm("change_project", self.group, self.project) + assign_perm("change_project", devs, self.project) + self.assertEqual( + get_groups_with_perms(self.project, attach_perms=True), + { + self.group: ["add_project", "change_project"], + devs: ["change_project"], + }, + ) + + def test_get_groups_with_perms_doesnt_spawn_extra_queries_for_more_groups_with_perms( + self, + ): + Group.objects.create(name="managers") + devs = Group.objects.create(name="devs") + devs1 = Group.objects.create(name="devs1") + devs2 = Group.objects.create(name="devs2") + devs3 = Group.objects.create(name="devs3") + devs4 = Group.objects.create(name="devs4") + devs5 = Group.objects.create(name="devs5") + assign_perm("add_project", self.group, self.project) + assign_perm("change_project", self.group, self.project) for group in [devs, devs1, devs2, devs3, devs4, devs5]: - assign_perm('add_project', group, self.project) - assign_perm('change_project', group, self.project) + assign_perm("add_project", group, self.project) + assign_perm("change_project", group, self.project) with self.assertNumQueries(3): result = get_groups_with_perms(self.project, attach_perms=True) - self.assertEqual(result, - { - self.group: ['add_project', 'change_project'], - devs: ['add_project', 'change_project'], - devs1: ['add_project', 'change_project'], - devs2: ['add_project', 'change_project'], - devs3: ['add_project', 'change_project'], - devs4: ['add_project', 'change_project'], - devs5: ['add_project', 'change_project'], - }) + self.assertEqual( + result, + { + self.group: ["add_project", "change_project"], + devs: ["add_project", "change_project"], + devs1: ["add_project", "change_project"], + devs2: ["add_project", "change_project"], + devs3: ["add_project", "change_project"], + devs4: ["add_project", "change_project"], + devs5: ["add_project", "change_project"], + }, + ) def test_get_objects_for_group(self): - foo = Project.objects.create(name='foo') - bar = Project.objects.create(name='bar') - assign_perm('add_project', self.group, foo) - assign_perm('add_project', self.group, bar) - assign_perm('change_project', self.group, bar) + foo = Project.objects.create(name="foo") + bar = Project.objects.create(name="bar") + assign_perm("add_project", self.group, foo) + assign_perm("add_project", self.group, bar) + assign_perm("change_project", self.group, bar) - result = get_objects_for_group(self.group, 'testapp.add_project') - self.assertEqual(sorted(p.pk for p in result), - sorted([foo.pk, bar.pk])) + result = get_objects_for_group(self.group, "testapp.add_project") + self.assertEqual(sorted(p.pk for p in result), sorted([foo.pk, bar.pk])) @skipUnlessTestApp class TestMixedDirectAndGenericObjectPermission(TestCase): def setUp(self): - self.joe = User.objects.create_user('joe', 'joe@example.com', 'foobar') - self.group = Group.objects.create(name='admins') + self.joe = User.objects.create_user("joe", "joe@example.com", "foobar") + self.group = Group.objects.create(name="admins") self.joe.groups.add(self.group) - self.mixed = Mixed.objects.create(name='Foobar') - self.reverse_mixed = ReverseMixed.objects.create(name='Foobar') + self.mixed = Mixed.objects.create(name="Foobar") + self.reverse_mixed = ReverseMixed.objects.create(name="Foobar") def test_get_users_with_perms_plus_groups(self): - User.objects.create_user('john', 'john@foobar.com', 'john') - jane = User.objects.create_user('jane', 'jane@foobar.com', 'jane') - group = Group.objects.create(name='devs') + User.objects.create_user("john", "john@foobar.com", "john") + jane = User.objects.create_user("jane", "jane@foobar.com", "jane") + group = Group.objects.create(name="devs") self.joe.groups.add(group) - assign_perm('add_mixed', self.joe, self.mixed) - assign_perm('change_mixed', group, self.mixed) - assign_perm('change_mixed', jane, self.mixed) - self.assertEqual(get_users_with_perms(self.mixed, attach_perms=True), - { - self.joe: ['add_mixed', 'change_mixed'], - jane: ['change_mixed'], - }) - result = get_objects_for_user(self.joe, 'testapp.add_mixed') - self.assertEqual(sorted(p.pk for p in result), - sorted([self.mixed.pk])) + assign_perm("add_mixed", self.joe, self.mixed) + assign_perm("change_mixed", group, self.mixed) + assign_perm("change_mixed", jane, self.mixed) + self.assertEqual( + get_users_with_perms(self.mixed, attach_perms=True), + { + self.joe: ["add_mixed", "change_mixed"], + jane: ["change_mixed"], + }, + ) + result = get_objects_for_user(self.joe, "testapp.add_mixed") + self.assertEqual(sorted(p.pk for p in result), sorted([self.mixed.pk])) def test_get_users_with_perms_plus_groups_reverse_mixed(self): - User.objects.create_user('john', 'john@foobar.com', 'john') - jane = User.objects.create_user('jane', 'jane@foobar.com', 'jane') - group = Group.objects.create(name='devs') + User.objects.create_user("john", "john@foobar.com", "john") + jane = User.objects.create_user("jane", "jane@foobar.com", "jane") + group = Group.objects.create(name="devs") self.joe.groups.add(group) - assign_perm('add_reversemixed', self.joe, self.reverse_mixed) - assign_perm('change_reversemixed', group, self.reverse_mixed) - assign_perm('change_reversemixed', jane, self.reverse_mixed) - self.assertEqual(get_users_with_perms(self.reverse_mixed, attach_perms=True), - { - self.joe: ['add_reversemixed', 'change_reversemixed'], - jane: ['change_reversemixed'], - }) - result = get_objects_for_user(self.joe, 'testapp.add_reversemixed') - self.assertEqual(sorted(p.pk for p in result), - sorted([self.reverse_mixed.pk])) + assign_perm("add_reversemixed", self.joe, self.reverse_mixed) + assign_perm("change_reversemixed", group, self.reverse_mixed) + assign_perm("change_reversemixed", jane, self.reverse_mixed) + self.assertEqual( + get_users_with_perms(self.reverse_mixed, attach_perms=True), + { + self.joe: ["add_reversemixed", "change_reversemixed"], + jane: ["change_reversemixed"], + }, + ) + result = get_objects_for_user(self.joe, "testapp.add_reversemixed") + self.assertEqual(sorted(p.pk for p in result), sorted([self.reverse_mixed.pk])) diff --git a/guardian/testapp/tests/test_forms.py b/guardian/testapp/tests/test_forms.py index 2b9290563..9be919586 100644 --- a/guardian/testapp/tests/test_forms.py +++ b/guardian/testapp/tests/test_forms.py @@ -5,17 +5,16 @@ class BaseObjectPermissionsFormTests(TestCase): - def setUp(self): self.user = get_user_model().objects.create_user( - 'joe', 'joe@example.com', 'joe') + "joe", "joe@example.com", "joe" + ) self.obj = ContentType.objects.create( - model='bar', app_label='fake-for-guardian-tests') + model="bar", app_label="fake-for-guardian-tests" + ) def test_not_implemented(self): - class MyUserObjectPermissionsForm(BaseObjectPermissionsForm): - def __init__(formself, user, *args, **kwargs): self.user = user super().__init__(*args, **kwargs) diff --git a/guardian/testapp/tests/test_management.py b/guardian/testapp/tests/test_management.py index 89d5ff12e..c0ab8a802 100644 --- a/guardian/testapp/tests/test_management.py +++ b/guardian/testapp/tests/test_management.py @@ -12,8 +12,8 @@ mocked_get_init_anon = mock.Mock() multi_db_dict = { - 'default': deepcopy(settings.DATABASES['default']), - 'session': deepcopy(settings.DATABASES['default']), + "default": deepcopy(settings.DATABASES["default"]), + "session": deepcopy(settings.DATABASES["default"]), } @@ -21,64 +21,64 @@ class SessionRouter: @staticmethod def db_for_write(model, **kwargs): if model == Session: - return 'session' + return "session" else: return None @staticmethod def allow_migrate(db, app_label, **kwargs): - if db == 'session': - return app_label == 'sessions' + if db == "session": + return app_label == "sessions" else: return None class TestGetAnonymousUser(TestCase): - - @mock.patch('guardian.management.guardian_settings') + @mock.patch("guardian.management.guardian_settings") def test_uses_custom_function(self, guardian_settings): mocked_get_init_anon.reset_mock() - path = 'guardian.testapp.tests.test_management.mocked_get_init_anon' + path = "guardian.testapp.tests.test_management.mocked_get_init_anon" guardian_settings.GET_INIT_ANONYMOUS_USER = path guardian_settings.ANONYMOUS_USER_NAME = "anonymous" User = get_user_model() anon = mocked_get_init_anon.return_value = mock.Mock() - create_anonymous_user('sender', using='default') + create_anonymous_user("sender", using="default") mocked_get_init_anon.assert_called_once_with(User) - anon.save.assert_called_once_with(using='default') + anon.save.assert_called_once_with(using="default") - @mock.patch('guardian.management.guardian_settings') - @override_settings(AUTH_USER_MODEL='testapp.CustomUsernameUser') + @mock.patch("guardian.management.guardian_settings") + @override_settings(AUTH_USER_MODEL="testapp.CustomUsernameUser") def test_uses_custom_username_field_model(self, guardian_settings): mocked_get_init_anon.reset_mock() - guardian_settings.GET_INIT_ANONYMOUS_USER = 'guardian.testapp.tests.test_management.mocked_get_init_anon' - guardian_settings.ANONYMOUS_USER_NAME = 'testuser@example.com' + guardian_settings.GET_INIT_ANONYMOUS_USER = ( + "guardian.testapp.tests.test_management.mocked_get_init_anon" + ) + guardian_settings.ANONYMOUS_USER_NAME = "testuser@example.com" User = get_user_model() anon = mocked_get_init_anon.return_value = mock.Mock() - create_anonymous_user('sender', using='default') + create_anonymous_user("sender", using="default") mocked_get_init_anon.assert_called_once_with(User) - anon.save.assert_called_once_with(using='default') + anon.save.assert_called_once_with(using="default") def test_get_anonymous_user(self): anon = get_anonymous_user() self.assertFalse(anon.has_usable_password()) self.assertEqual(anon.get_username(), "AnonymousUser") - @mock.patch('guardian.management.guardian_settings') - @override_settings( - DATABASE_ROUTERS=[SessionRouter()], - DATABASES=multi_db_dict - ) + @mock.patch("guardian.management.guardian_settings") + @override_settings(DATABASE_ROUTERS=[SessionRouter()], DATABASES=multi_db_dict) def test_non_migrated_db(self, guardian_settings): mocked_get_init_anon.reset_mock() - guardian_settings.GET_INIT_ANONYMOUS_USER = 'guardian.testapp.tests.test_management.mocked_get_init_anon' + guardian_settings.GET_INIT_ANONYMOUS_USER = ( + "guardian.testapp.tests.test_management.mocked_get_init_anon" + ) - create_anonymous_user('sender', using='session') + create_anonymous_user("sender", using="session") mocked_get_init_anon.assert_not_called() diff --git a/guardian/testapp/tests/test_managers.py b/guardian/testapp/tests/test_managers.py index 37b71203c..99e7859fc 100644 --- a/guardian/testapp/tests/test_managers.py +++ b/guardian/testapp/tests/test_managers.py @@ -7,7 +7,6 @@ class TestManagers(TestCase): - def test_user_manager_assign(self): manager = UserObjectPermissionManager() manager.assign_perm = mock.Mock() @@ -15,12 +14,15 @@ def test_user_manager_assign(self): with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") - manager.assign('perm', 'user', 'object') + manager.assign("perm", "user", "object") - manager.assign_perm.assert_called_once_with('perm', 'user', 'object') + manager.assign_perm.assert_called_once_with("perm", "user", "object") self.assertTrue(issubclass(w[0].category, DeprecationWarning)) - self.assertIn("UserObjectPermissionManager method 'assign' is being renamed to 'assign_perm'.", str(w[0].message)) + self.assertIn( + "UserObjectPermissionManager method 'assign' is being renamed to 'assign_perm'.", + str(w[0].message), + ) def test_group_manager_assign(self): manager = GroupObjectPermissionManager() @@ -29,9 +31,12 @@ def test_group_manager_assign(self): with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") - manager.assign('perm', 'group', 'object') + manager.assign("perm", "group", "object") - manager.assign_perm.assert_called_once_with('perm', 'group', 'object') + manager.assign_perm.assert_called_once_with("perm", "group", "object") self.assertTrue(issubclass(w[0].category, DeprecationWarning)) - self.assertIn("UserObjectPermissionManager method 'assign' is being renamed to 'assign_perm'.", str(w[0].message)) + self.assertIn( + "UserObjectPermissionManager method 'assign' is being renamed to 'assign_perm'.", + str(w[0].message), + ) diff --git a/guardian/testapp/tests/test_mixins.py b/guardian/testapp/tests/test_mixins.py index 0ca19925f..b56d3d8c2 100644 --- a/guardian/testapp/tests/test_mixins.py +++ b/guardian/testapp/tests/test_mixins.py @@ -22,46 +22,43 @@ class DatabaseRemovedError(Exception): class RemoveDatabaseView(View): - def get(self, request, *args, **kwargs): raise DatabaseRemovedError("You've just allowed db to be removed!") class TestView(PermissionRequiredMixin, RemoveDatabaseView): - permission_required = 'testapp.change_post' + permission_required = "testapp.change_post" object = None # should be set at each tests explicitly class NoObjectView(PermissionRequiredMixin, RemoveDatabaseView): - permission_required = 'testapp.change_post' + permission_required = "testapp.change_post" class GlobalNoObjectView(PermissionRequiredMixin, RemoveDatabaseView): - permission_required = 'testapp.add_post' + permission_required = "testapp.add_post" accept_global_perms = True class PostPermissionListView(PermissionListMixin, ListView): model = Post - permission_required = 'testapp.change_post' - template_name = 'list.html' + permission_required = "testapp.change_post" + template_name = "list.html" class TestViewMixins(TestCase): - def setUp(self): - self.post = Post.objects.create(title='foo-post-title') + self.post = Post.objects.create(title="foo-post-title") self.factory = RequestFactory() - self.user = get_user_model().objects.create_user( - 'joe', 'joe@doe.com', 'doe') - self.client.login(username='joe', password='doe') + self.user = get_user_model().objects.create_user("joe", "joe@doe.com", "doe") + self.client.login(username="joe", password="doe") def test_permission_is_checked_before_view_is_computed(self): """ This test would fail if permission is checked **after** view is actually resolved. """ - request = self.factory.get('/') + request = self.factory.get("/") request.user = self.user # View.object is set view = TestView.as_view(object=self.post) @@ -80,7 +77,7 @@ def test_permission_is_checked_before_view_is_computed_perm_denied_raised(self): This test would fail if permission is checked **after** view is actually resolved. """ - request = self.factory.get('/') + request = self.factory.get("/") request.user = self.user view = TestView.as_view(raise_exception=True, object=self.post) with self.assertRaises(PermissionDenied): @@ -91,9 +88,9 @@ def test_permission_required_view_configured_wrongly(self): This test would fail if permission is checked **after** view is actually resolved. """ - request = self.factory.get('/') + request = self.factory.get("/") request.user = self.user - request.user.add_obj_perm('change_post', self.post) + request.user.add_obj_perm("change_post", self.post) view = TestView.as_view(permission_required=None, object=self.post) with self.assertRaises(ImproperlyConfigured): view(request) @@ -103,9 +100,9 @@ def test_permission_required(self): This test would fail if permission is checked **after** view is actually resolved. """ - request = self.factory.get('/') + request = self.factory.get("/") request.user = self.user - request.user.add_obj_perm('change_post', self.post) + request.user.add_obj_perm("change_post", self.post) view = TestView.as_view(object=self.post) with self.assertRaises(DatabaseRemovedError): view(request) @@ -116,9 +113,9 @@ def test_permission_required_no_object(self): object when it has none """ - request = self.factory.get('/') + request = self.factory.get("/") request.user = self.user - request.user.add_obj_perm('change_post', self.post) + request.user.add_obj_perm("change_post", self.post) view = NoObjectView.as_view() response = view(request) self.assertEqual(response.status_code, 302) @@ -129,7 +126,7 @@ def test_permission_required_global_no_object(self): object when it not set and **no** global permission """ - request = self.factory.get('/') + request = self.factory.get("/") request.user = self.user view = GlobalNoObjectView.as_view() response = view(request) @@ -141,9 +138,9 @@ def test_permission_granted_global_no_object(self): object when it not set and **has** global permission """ - request = self.factory.get('/') + request = self.factory.get("/") request.user = self.user - assign_perm('testapp.add_post', request.user) + assign_perm("testapp.add_post", request.user) view = GlobalNoObjectView.as_view() with self.assertRaises(DatabaseRemovedError): view(request) @@ -159,56 +156,54 @@ def test_permission_required_as_list(self): class SecretView(TestView): on_permission_check_fail = mock.Mock() - request = self.factory.get('/') + request = self.factory.get("/") request.user = self.user - request.user.add_obj_perm('change_post', self.post) - SecretView.permission_required = ['testapp.change_post', - 'testapp.add_post'] + request.user.add_obj_perm("change_post", self.post) + SecretView.permission_required = ["testapp.change_post", "testapp.add_post"] view = SecretView.as_view(object=self.post) response = view(request) self.assertEqual(response.status_code, 302) - SecretView.on_permission_check_fail.assert_called_once_with(request, - response, obj=self.post) + SecretView.on_permission_check_fail.assert_called_once_with( + request, response, obj=self.post + ) - request.user.add_obj_perm('add_post', self.post) + request.user.add_obj_perm("add_post", self.post) with self.assertRaises(DatabaseRemovedError): view(request) def test_login_required_mixin(self): - class SecretView(LoginRequiredMixin, View): - redirect_field_name = 'foobar' - login_url = '/let-me-in/' + redirect_field_name = "foobar" + login_url = "/let-me-in/" def get(self, request): - return HttpResponse('secret-view') + return HttpResponse("secret-view") - request = self.factory.get('/some-secret-page/') + request = self.factory.get("/some-secret-page/") request.user = AnonymousUser() view = SecretView.as_view() response = view(request) self.assertEqual(response.status_code, 302) - self.assertEqual(response['Location'], - '/let-me-in/?foobar=/some-secret-page/') + self.assertEqual(response["Location"], "/let-me-in/?foobar=/some-secret-page/") request.user = self.user response = view(request) self.assertEqual(response.status_code, 200) - self.assertEqual(response.content, b'secret-view') + self.assertEqual(response.content, b"secret-view") def test_list_permission(self): - request = self.factory.get('/some-secret-list/') + request = self.factory.get("/some-secret-list/") request.user = AnonymousUser() view = PostPermissionListView.as_view() response = view(request) - self.assertNotContains(response, b'foo-post-title') + self.assertNotContains(response, b"foo-post-title") request.user = self.user - request.user.add_obj_perm('change_post', self.post) + request.user.add_obj_perm("change_post", self.post) response = view(request) - self.assertContains(response, b'foo-post-title') + self.assertContains(response, b"foo-post-title") diff --git a/guardian/testapp/tests/test_orphans.py b/guardian/testapp/tests/test_orphans.py index 34b1542c6..cf5c34632 100644 --- a/guardian/testapp/tests/test_orphans.py +++ b/guardian/testapp/tests/test_orphans.py @@ -1,4 +1,5 @@ from django.apps import apps as django_apps + auth_app = django_apps.get_app_config("auth") from django.contrib.auth import get_user_model @@ -19,20 +20,21 @@ @skipUnlessTestApp class OrphanedObjectPermissionsTest(TestCase): - def setUp(self): # Create objects for which we would assing obj perms - self.target_user1 = User.objects.create(username='user1') - self.target_group1 = Group.objects.create(name='group1') + self.target_user1 = User.objects.create(username="user1") + self.target_group1 = Group.objects.create(name="group1") self.target_obj1 = ContentType.objects.create( - model='foo', app_label='fake-for-guardian-tests') + model="foo", app_label="fake-for-guardian-tests" + ) self.target_obj2 = ContentType.objects.create( - model='bar', app_label='fake-for-guardian-tests') + model="bar", app_label="fake-for-guardian-tests" + ) # Required if MySQL backend is used :/ create_permissions(auth_app, 1) - self.user = User.objects.create(username='user') - self.group = Group.objects.create(name='group') + self.user = User.objects.create(username="user") + self.group = Group.objects.create(name="group") def test_clean_perms(self): diff --git a/guardian/testapp/tests/test_other.py b/guardian/testapp/tests/test_other.py index c45c280c1..85c61def0 100644 --- a/guardian/testapp/tests/test_other.py +++ b/guardian/testapp/tests/test_other.py @@ -21,192 +21,230 @@ from guardian.models import GroupObjectPermission from guardian.models import UserObjectPermission from guardian.testapp.tests.conf import TestDataMixin + User = get_user_model() user_model_path = get_user_model_path() class UserPermissionTests(TestDataMixin, TestCase): - def setUp(self): super().setUp() - self.user = User.objects.get(username='jack') + self.user = User.objects.get(username="jack") self.ctype = ContentType.objects.create( - model='bar', app_label='fake-for-guardian-tests') - self.obj1 = ContentType.objects.create( - model='foo', app_label='guardian-tests') - self.obj2 = ContentType.objects.create( - model='bar', app_label='guardian-tests') + model="bar", app_label="fake-for-guardian-tests" + ) + self.obj1 = ContentType.objects.create(model="foo", app_label="guardian-tests") + self.obj2 = ContentType.objects.create(model="bar", app_label="guardian-tests") def test_assignement(self): - self.assertFalse(self.user.has_perm('change_contenttype', self.ctype)) + self.assertFalse(self.user.has_perm("change_contenttype", self.ctype)) - UserObjectPermission.objects.assign_perm('change_contenttype', self.user, - self.ctype) - self.assertTrue(self.user.has_perm('change_contenttype', self.ctype)) - self.assertTrue(self.user.has_perm('contenttypes.change_contenttype', - self.ctype)) + UserObjectPermission.objects.assign_perm( + "change_contenttype", self.user, self.ctype + ) + self.assertTrue(self.user.has_perm("change_contenttype", self.ctype)) + self.assertTrue( + self.user.has_perm("contenttypes.change_contenttype", self.ctype) + ) def test_assignement_and_remove(self): - UserObjectPermission.objects.assign_perm('change_contenttype', self.user, - self.ctype) - self.assertTrue(self.user.has_perm('change_contenttype', self.ctype)) + UserObjectPermission.objects.assign_perm( + "change_contenttype", self.user, self.ctype + ) + self.assertTrue(self.user.has_perm("change_contenttype", self.ctype)) - UserObjectPermission.objects.remove_perm('change_contenttype', - self.user, self.ctype) - self.assertFalse(self.user.has_perm('change_contenttype', self.ctype)) + UserObjectPermission.objects.remove_perm( + "change_contenttype", self.user, self.ctype + ) + self.assertFalse(self.user.has_perm("change_contenttype", self.ctype)) def test_ctypes(self): UserObjectPermission.objects.assign_perm( - 'change_contenttype', self.user, self.obj1) - self.assertTrue(self.user.has_perm('change_contenttype', self.obj1)) - self.assertFalse(self.user.has_perm('change_contenttype', self.obj2)) + "change_contenttype", self.user, self.obj1 + ) + self.assertTrue(self.user.has_perm("change_contenttype", self.obj1)) + self.assertFalse(self.user.has_perm("change_contenttype", self.obj2)) UserObjectPermission.objects.remove_perm( - 'change_contenttype', self.user, self.obj1) + "change_contenttype", self.user, self.obj1 + ) UserObjectPermission.objects.assign_perm( - 'change_contenttype', self.user, self.obj2) - self.assertTrue(self.user.has_perm('change_contenttype', self.obj2)) - self.assertFalse(self.user.has_perm('change_contenttype', self.obj1)) + "change_contenttype", self.user, self.obj2 + ) + self.assertTrue(self.user.has_perm("change_contenttype", self.obj2)) + self.assertFalse(self.user.has_perm("change_contenttype", self.obj1)) UserObjectPermission.objects.assign_perm( - 'change_contenttype', self.user, self.obj1) + "change_contenttype", self.user, self.obj1 + ) UserObjectPermission.objects.assign_perm( - 'change_contenttype', self.user, self.obj2) - self.assertTrue(self.user.has_perm('change_contenttype', self.obj2)) - self.assertTrue(self.user.has_perm('change_contenttype', self.obj1)) + "change_contenttype", self.user, self.obj2 + ) + self.assertTrue(self.user.has_perm("change_contenttype", self.obj2)) + self.assertTrue(self.user.has_perm("change_contenttype", self.obj1)) UserObjectPermission.objects.remove_perm( - 'change_contenttype', self.user, self.obj1) + "change_contenttype", self.user, self.obj1 + ) UserObjectPermission.objects.remove_perm( - 'change_contenttype', self.user, self.obj2) - self.assertFalse(self.user.has_perm('change_contenttype', self.obj2)) - self.assertFalse(self.user.has_perm('change_contenttype', self.obj1)) + "change_contenttype", self.user, self.obj2 + ) + self.assertFalse(self.user.has_perm("change_contenttype", self.obj2)) + self.assertFalse(self.user.has_perm("change_contenttype", self.obj1)) def test_assign_perm_validation(self): - self.assertRaises(Permission.DoesNotExist, - UserObjectPermission.objects.assign_perm, 'change_group', self.user, - self.user) + self.assertRaises( + Permission.DoesNotExist, + UserObjectPermission.objects.assign_perm, + "change_group", + self.user, + self.user, + ) - group = Group.objects.create(name='test_group_assign_perm_validation') + group = Group.objects.create(name="test_group_assign_perm_validation") ctype = ContentType.objects.get_for_model(group) user_ctype = ContentType.objects.get_for_model(self.user) - codename = get_user_permission_codename('change') - perm = Permission.objects.get( - codename=codename, content_type=user_ctype) + codename = get_user_permission_codename("change") + perm = Permission.objects.get(codename=codename, content_type=user_ctype) create_info = dict( - permission=perm, - user=self.user, - content_type=ctype, - object_pk=group.pk + permission=perm, user=self.user, content_type=ctype, object_pk=group.pk + ) + self.assertRaises( + ValidationError, UserObjectPermission.objects.create, **create_info ) - self.assertRaises(ValidationError, UserObjectPermission.objects.create, - **create_info) def test_errors(self): - not_saved_user = User(username='not_saved_user') - codename = get_user_permission_codename('change') - self.assertRaises(ObjectNotPersisted, - UserObjectPermission.objects.assign_perm, - codename, self.user, not_saved_user) - self.assertRaises(ObjectNotPersisted, - UserObjectPermission.objects.remove_perm, - codename, self.user, not_saved_user) + not_saved_user = User(username="not_saved_user") + codename = get_user_permission_codename("change") + self.assertRaises( + ObjectNotPersisted, + UserObjectPermission.objects.assign_perm, + codename, + self.user, + not_saved_user, + ) + self.assertRaises( + ObjectNotPersisted, + UserObjectPermission.objects.remove_perm, + codename, + self.user, + not_saved_user, + ) class GroupPermissionTests(TestDataMixin, TestCase): - def setUp(self): super().setUp() - self.user = User.objects.get(username='jack') - self.group, created = Group.objects.get_or_create(name='jackGroup') + self.user = User.objects.get(username="jack") + self.group, created = Group.objects.get_or_create(name="jackGroup") self.user.groups.add(self.group) self.ctype = ContentType.objects.create( - model='bar', app_label='fake-for-guardian-tests') - self.obj1 = ContentType.objects.create( - model='foo', app_label='guardian-tests') - self.obj2 = ContentType.objects.create( - model='bar', app_label='guardian-tests') + model="bar", app_label="fake-for-guardian-tests" + ) + self.obj1 = ContentType.objects.create(model="foo", app_label="guardian-tests") + self.obj2 = ContentType.objects.create(model="bar", app_label="guardian-tests") def test_assignement(self): - self.assertFalse(self.user.has_perm('change_contenttype', self.ctype)) - self.assertFalse(self.user.has_perm('contenttypes.change_contenttype', - self.ctype)) + self.assertFalse(self.user.has_perm("change_contenttype", self.ctype)) + self.assertFalse( + self.user.has_perm("contenttypes.change_contenttype", self.ctype) + ) - GroupObjectPermission.objects.assign_perm('change_contenttype', self.group, - self.ctype) - self.assertTrue(self.user.has_perm('change_contenttype', self.ctype)) - self.assertTrue(self.user.has_perm('contenttypes.change_contenttype', - self.ctype)) + GroupObjectPermission.objects.assign_perm( + "change_contenttype", self.group, self.ctype + ) + self.assertTrue(self.user.has_perm("change_contenttype", self.ctype)) + self.assertTrue( + self.user.has_perm("contenttypes.change_contenttype", self.ctype) + ) def test_assignement_and_remove(self): - GroupObjectPermission.objects.assign_perm('change_contenttype', self.group, - self.ctype) - self.assertTrue(self.user.has_perm('change_contenttype', self.ctype)) + GroupObjectPermission.objects.assign_perm( + "change_contenttype", self.group, self.ctype + ) + self.assertTrue(self.user.has_perm("change_contenttype", self.ctype)) - GroupObjectPermission.objects.remove_perm('change_contenttype', - self.group, self.ctype) - self.assertFalse(self.user.has_perm('change_contenttype', self.ctype)) + GroupObjectPermission.objects.remove_perm( + "change_contenttype", self.group, self.ctype + ) + self.assertFalse(self.user.has_perm("change_contenttype", self.ctype)) def test_ctypes(self): - GroupObjectPermission.objects.assign_perm('change_contenttype', self.group, - self.obj1) - self.assertTrue(self.user.has_perm('change_contenttype', self.obj1)) - self.assertFalse(self.user.has_perm('change_contenttype', self.obj2)) - - GroupObjectPermission.objects.remove_perm('change_contenttype', - self.group, self.obj1) - GroupObjectPermission.objects.assign_perm('change_contenttype', self.group, - self.obj2) - self.assertTrue(self.user.has_perm('change_contenttype', self.obj2)) - self.assertFalse(self.user.has_perm('change_contenttype', self.obj1)) - - GroupObjectPermission.objects.assign_perm('change_contenttype', self.group, - self.obj1) - GroupObjectPermission.objects.assign_perm('change_contenttype', self.group, - self.obj2) - self.assertTrue(self.user.has_perm('change_contenttype', self.obj2)) - self.assertTrue(self.user.has_perm('change_contenttype', self.obj1)) - - GroupObjectPermission.objects.remove_perm('change_contenttype', - self.group, self.obj1) - GroupObjectPermission.objects.remove_perm('change_contenttype', - self.group, self.obj2) - self.assertFalse(self.user.has_perm('change_contenttype', self.obj2)) - self.assertFalse(self.user.has_perm('change_contenttype', self.obj1)) + GroupObjectPermission.objects.assign_perm( + "change_contenttype", self.group, self.obj1 + ) + self.assertTrue(self.user.has_perm("change_contenttype", self.obj1)) + self.assertFalse(self.user.has_perm("change_contenttype", self.obj2)) + + GroupObjectPermission.objects.remove_perm( + "change_contenttype", self.group, self.obj1 + ) + GroupObjectPermission.objects.assign_perm( + "change_contenttype", self.group, self.obj2 + ) + self.assertTrue(self.user.has_perm("change_contenttype", self.obj2)) + self.assertFalse(self.user.has_perm("change_contenttype", self.obj1)) + + GroupObjectPermission.objects.assign_perm( + "change_contenttype", self.group, self.obj1 + ) + GroupObjectPermission.objects.assign_perm( + "change_contenttype", self.group, self.obj2 + ) + self.assertTrue(self.user.has_perm("change_contenttype", self.obj2)) + self.assertTrue(self.user.has_perm("change_contenttype", self.obj1)) + + GroupObjectPermission.objects.remove_perm( + "change_contenttype", self.group, self.obj1 + ) + GroupObjectPermission.objects.remove_perm( + "change_contenttype", self.group, self.obj2 + ) + self.assertFalse(self.user.has_perm("change_contenttype", self.obj2)) + self.assertFalse(self.user.has_perm("change_contenttype", self.obj1)) def test_assign_perm_validation(self): - self.assertRaises(Permission.DoesNotExist, - GroupObjectPermission.objects.assign_perm, 'change_user', self.group, - self.group) + self.assertRaises( + Permission.DoesNotExist, + GroupObjectPermission.objects.assign_perm, + "change_user", + self.group, + self.group, + ) - user = User.objects.create(username='testuser') + user = User.objects.create(username="testuser") ctype = ContentType.objects.get_for_model(user) - perm = Permission.objects.get(codename='change_group') + perm = Permission.objects.get(codename="change_group") create_info = dict( - permission=perm, - group=self.group, - content_type=ctype, - object_pk=user.pk + permission=perm, group=self.group, content_type=ctype, object_pk=user.pk + ) + self.assertRaises( + ValidationError, GroupObjectPermission.objects.create, **create_info ) - self.assertRaises(ValidationError, GroupObjectPermission.objects.create, - **create_info) def test_errors(self): - not_saved_group = Group(name='not_saved_group') - self.assertRaises(ObjectNotPersisted, - GroupObjectPermission.objects.assign_perm, - "change_group", self.group, not_saved_group) - self.assertRaises(ObjectNotPersisted, - GroupObjectPermission.objects.remove_perm, - "change_group", self.group, not_saved_group) + not_saved_group = Group(name="not_saved_group") + self.assertRaises( + ObjectNotPersisted, + GroupObjectPermission.objects.assign_perm, + "change_group", + self.group, + not_saved_group, + ) + self.assertRaises( + ObjectNotPersisted, + GroupObjectPermission.objects.remove_perm, + "change_group", + self.group, + not_saved_group, + ) class ObjectPermissionBackendTests(TestCase): - def setUp(self): - self.user = User.objects.create(username='jack') + self.user = User.objects.create(username="jack") self.backend = ObjectPermissionBackend() def test_attrs(self): @@ -217,11 +255,9 @@ def test_attrs(self): def test_authenticate(self): self.assertEqual( self.backend.authenticate( - request={}, - username=self.user.username, - password=self.user.password + request={}, username=self.user.username, password=self.user.password ), - None + None, ) def test_has_perm_noobj(self): @@ -233,19 +269,24 @@ def test_has_perm_notauthed(self): self.assertFalse(self.backend.has_perm(user, "change_user", self.user)) def test_has_perm_wrong_app(self): - self.assertRaises(WrongAppError, self.backend.has_perm, - self.user, "no_app.change_user", self.user) + self.assertRaises( + WrongAppError, + self.backend.has_perm, + self.user, + "no_app.change_user", + self.user, + ) def test_obj_is_not_model(self): for obj in (Group, 666, "String", [2, 1, 5, 7], {}): - self.assertFalse(self.backend.has_perm(self.user, - "any perm", obj)) + self.assertFalse(self.backend.has_perm(self.user, "any perm", obj)) def test_not_active_user(self): - user = User.objects.create(username='non active user') + user = User.objects.create(username="non active user") ctype = ContentType.objects.create( - model='bar', app_label='fake-for-guardian-tests') - perm = 'change_contenttype' + model="bar", app_label="fake-for-guardian-tests" + ) + perm = "change_contenttype" UserObjectPermission.objects.assign_perm(perm, user, ctype) self.assertTrue(self.backend.has_perm(user, perm, ctype)) user.is_active = False @@ -254,9 +295,8 @@ def test_not_active_user(self): class GuardianBaseTests(TestCase): - def has_attrs(self): - self.assertTrue(hasattr(guardian, '__version__')) + self.assertTrue(hasattr(guardian, "__version__")) def test_version(self): for x in guardian.VERSION: @@ -267,7 +307,6 @@ def test_get_version(self): class TestExceptions(TestCase): - def _test_error_class(self, exc_cls): self.assertTrue(isinstance(exc_cls, GuardianError)) @@ -280,27 +319,25 @@ def test_error_classes(self): @unittest.skip("test is broken") class TestMonkeyPatch(TestCase): - - @mock.patch('django.contrib.auth.get_user_model') + @mock.patch("django.contrib.auth.get_user_model") def test_monkey_patch(self, mocked_get_user_model): - class CustomUserTestClass(AbstractUser): pass mocked_get_user_model.return_value = CustomUserTestClass - self.assertFalse(getattr(CustomUserTestClass, 'get_anonymous', False)) - self.assertFalse(getattr(CustomUserTestClass, 'add_obj_perm', False)) - self.assertFalse(getattr(CustomUserTestClass, 'del_obj_perm', False)) - self.assertFalse(getattr(CustomUserTestClass, 'evict_obj_perms_cache', False)) + self.assertFalse(getattr(CustomUserTestClass, "get_anonymous", False)) + self.assertFalse(getattr(CustomUserTestClass, "add_obj_perm", False)) + self.assertFalse(getattr(CustomUserTestClass, "del_obj_perm", False)) + self.assertFalse(getattr(CustomUserTestClass, "evict_obj_perms_cache", False)) # Monkey Patch guardian.monkey_patch_user() - self.assertTrue(getattr(CustomUserTestClass, 'get_anonymous', False)) - self.assertTrue(getattr(CustomUserTestClass, 'add_obj_perm', False)) - self.assertTrue(getattr(CustomUserTestClass, 'del_obj_perm', False)) - self.assertTrue(getattr(CustomUserTestClass, 'evict_obj_perms_cache', False)) + self.assertTrue(getattr(CustomUserTestClass, "get_anonymous", False)) + self.assertTrue(getattr(CustomUserTestClass, "add_obj_perm", False)) + self.assertTrue(getattr(CustomUserTestClass, "del_obj_perm", False)) + self.assertTrue(getattr(CustomUserTestClass, "evict_obj_perms_cache", False)) user = CustomUserTestClass() self.assertFalse(user.evict_obj_perms_cache()) diff --git a/guardian/testapp/tests/test_shortcuts.py b/guardian/testapp/tests/test_shortcuts.py index 035a6f423..b35dadea1 100644 --- a/guardian/testapp/tests/test_shortcuts.py +++ b/guardian/testapp/tests/test_shortcuts.py @@ -35,22 +35,24 @@ class ShortcutsTests(ObjectPermissionTestCase): - def test_get_perms_for_model(self): expected_perms_amount = 3 if django.VERSION < (2, 1) else 4 self.assertEqual(get_perms_for_model(self.user).count(), expected_perms_amount) - self.assertTrue(list(get_perms_for_model(self.user)) == - list(get_perms_for_model(User))) + self.assertTrue( + list(get_perms_for_model(self.user)) == list(get_perms_for_model(User)) + ) self.assertEqual(get_perms_for_model(Permission).count(), expected_perms_amount) - model_str = 'contenttypes.ContentType' + model_str = "contenttypes.ContentType" self.assertEqual( sorted(get_perms_for_model(model_str).values_list()), - sorted(get_perms_for_model(ContentType).values_list())) + sorted(get_perms_for_model(ContentType).values_list()), + ) obj = ContentType() self.assertEqual( sorted(get_perms_for_model(model_str).values_list()), - sorted(get_perms_for_model(obj).values_list())) + sorted(get_perms_for_model(obj).values_list()), + ) class AssignPermTest(ObjectPermissionTestCase): @@ -59,15 +61,21 @@ class AssignPermTest(ObjectPermissionTestCase): """ def test_not_model(self): - self.assertRaises(NotUserNorGroup, assign_perm, - perm="change_object", - user_or_group="Not a Model", - obj=self.ctype) + self.assertRaises( + NotUserNorGroup, + assign_perm, + perm="change_object", + user_or_group="Not a Model", + obj=self.ctype, + ) def test_global_wrong_perm(self): - self.assertRaises(ValueError, assign_perm, - perm="change_site", # for global permissions must provide app_label - user_or_group=self.user) + self.assertRaises( + ValueError, + assign_perm, + perm="change_site", # for global permissions must provide app_label + user_or_group=self.user, + ) def test_user_assign_perm(self): assign_perm("add_contenttype", self.user, self.ctype) @@ -90,7 +98,9 @@ def test_group_assign_perm(self): def test_user_assign_perm_queryset(self): assign_perm("add_contenttype", self.user, self.ctype_qset) assign_perm("change_contenttype", self.group, self.ctype_qset) - assign_perm(self.get_permission("delete_contenttype"), self.user, self.ctype_qset) + assign_perm( + self.get_permission("delete_contenttype"), self.user, self.ctype_qset + ) for obj in self.ctype_qset: self.assertTrue(self.user.has_perm("add_contenttype", obj)) self.assertTrue(self.user.has_perm("change_contenttype", obj)) @@ -99,7 +109,9 @@ def test_user_assign_perm_queryset(self): def test_group_assign_perm_queryset(self): assign_perm("add_contenttype", self.group, self.ctype_qset) assign_perm("change_contenttype", self.group, self.ctype_qset) - assign_perm(self.get_permission("delete_contenttype"), self.group, self.ctype_qset) + assign_perm( + self.get_permission("delete_contenttype"), self.group, self.ctype_qset + ) check = ObjectPermissionChecker(self.group) for obj in self.ctype_qset: @@ -121,15 +133,17 @@ def test_group_assign_perm_global(self): def test_assign_perm_with_dots(self): Permission.objects.create( codename="contenttype.reorder", - content_type=ContentType.objects.get_for_model(self.ctype) + content_type=ContentType.objects.get_for_model(self.ctype), ) assign_perm("contenttypes.contenttype.reorder", self.user, self.ctype) - self.assertTrue(self.user.has_perm("contenttypes.contenttype.reorder", self.ctype)) + self.assertTrue( + self.user.has_perm("contenttypes.contenttype.reorder", self.ctype) + ) def test_deprecation_warning(self): with warnings.catch_warnings(record=True) as warns: - warnings.simplefilter('always') + warnings.simplefilter("always") assign("contenttypes.change_contenttype", self.group) self.assertEqual(len(warns), 1) self.assertTrue(isinstance(warns[0].message, DeprecationWarning)) @@ -141,7 +155,9 @@ def test_user_assign_perm_list(self): """ assign_perm("add_contenttype", self.user, self.ctype_list) assign_perm("change_contenttype", self.group, self.ctype_list) - assign_perm(self.get_permission("delete_contenttype"), self.user, self.ctype_list) + assign_perm( + self.get_permission("delete_contenttype"), self.user, self.ctype_list + ) for obj in self.ctype_list: self.assertTrue(self.user.has_perm("add_contenttype", obj)) self.assertTrue(self.user.has_perm("change_contenttype", obj)) @@ -154,58 +170,69 @@ def test_group_assign_perm_list(self): """ assign_perm("add_contenttype", self.group, self.ctype_list) assign_perm("change_contenttype", self.group, self.ctype_list) - assign_perm(self.get_permission("delete_contenttype"), self.group, self.ctype_list) + assign_perm( + self.get_permission("delete_contenttype"), self.group, self.ctype_list + ) check = ObjectPermissionChecker(self.group) for obj in self.ctype_list: self.assertTrue(check.has_perm("add_contenttype", obj)) self.assertTrue(check.has_perm("change_contenttype", obj)) - self.assertTrue(check.has_perm("delete_contenttype", obj)) + self.assertTrue(check.has_perm("delete_contenttype", obj)) class MultipleIdentitiesOperationsTest(ObjectPermissionTestCase): """ Tests assignment of permission to multiple users or groups """ + def setUp(self): super().setUp() self.users_list = jim, bob = [ - User.objects.create_user(username='jim'), - User.objects.create_user(username='bob') + User.objects.create_user(username="jim"), + User.objects.create_user(username="bob"), ] self.groups_list = jim_group, bob_group = [ - Group.objects.create(name='jimgroup'), - Group.objects.create(name='bobgroup') + Group.objects.create(name="jimgroup"), + Group.objects.create(name="bobgroup"), ] jim_group.user_set.add(jim) bob_group.user_set.add(bob) - self.users_qs = User.objects.exclude(username='AnonymousUser') + self.users_qs = User.objects.exclude(username="AnonymousUser") self.groups_qs = Group.objects.all() def test_assign_to_many_users_queryset(self): assign_perm("add_contenttype", self.users_qs, self.ctype) - assign_perm(self.get_permission("delete_contenttype"), self.users_qs, self.ctype) + assign_perm( + self.get_permission("delete_contenttype"), self.users_qs, self.ctype + ) for user in self.users_list: self.assertTrue(user.has_perm("add_contenttype", self.ctype)) self.assertTrue(user.has_perm("delete_contenttype", self.ctype)) def test_assign_to_many_users_list(self): assign_perm("add_contenttype", self.users_list, self.ctype) - assign_perm(self.get_permission("delete_contenttype"), self.users_list, self.ctype) + assign_perm( + self.get_permission("delete_contenttype"), self.users_list, self.ctype + ) for user in self.users_list: self.assertTrue(user.has_perm("add_contenttype", self.ctype)) self.assertTrue(user.has_perm("delete_contenttype", self.ctype)) def test_assign_to_many_groups_queryset(self): assign_perm("add_contenttype", self.groups_qs, self.ctype) - assign_perm(self.get_permission("delete_contenttype"), self.groups_qs, self.ctype) + assign_perm( + self.get_permission("delete_contenttype"), self.groups_qs, self.ctype + ) for user in self.users_list: self.assertTrue(user.has_perm("add_contenttype", self.ctype)) self.assertTrue(user.has_perm("delete_contenttype", self.ctype)) def test_assign_to_many_groups_list(self): assign_perm("add_contenttype", self.groups_list, self.ctype) - assign_perm(self.get_permission("delete_contenttype"), self.groups_list, self.ctype) + assign_perm( + self.get_permission("delete_contenttype"), self.groups_list, self.ctype + ) for user in self.users_list: self.assertTrue(user.has_perm("add_contenttype", self.ctype)) self.assertTrue(user.has_perm("delete_contenttype", self.ctype)) @@ -223,15 +250,21 @@ class RemovePermTest(ObjectPermissionTestCase): """ def test_not_model(self): - self.assertRaises(NotUserNorGroup, remove_perm, - perm="change_object", - user_or_group="Not a Model", - obj=self.ctype) + self.assertRaises( + NotUserNorGroup, + remove_perm, + perm="change_object", + user_or_group="Not a Model", + obj=self.ctype, + ) def test_global_wrong_perm(self): - self.assertRaises(ValueError, remove_perm, - perm="change_site", # for global permissions must provide app_label - user_or_group=self.user) + self.assertRaises( + ValueError, + remove_perm, + perm="change_site", # for global permissions must provide app_label + user_or_group=self.user, + ) def test_user_remove_perm(self): # assign perm first @@ -281,9 +314,10 @@ def test_group_remove_perm_global(self): perm = "contenttypes.change_contenttype" assign_perm(perm, self.group) remove_perm(perm, self.group) - app_label, codename = perm.split('.') - perm_obj = Permission.objects.get(codename=codename, - content_type__app_label=app_label) + app_label, codename = perm.split(".") + perm_obj = Permission.objects.get( + codename=codename, content_type__app_label=app_label + ) self.assertFalse(perm_obj in self.group.permissions.all()) @@ -294,9 +328,9 @@ class GetPermsTest(ObjectPermissionTestCase): """ def test_not_model(self): - self.assertRaises(NotUserNorGroup, get_perms, - user_or_group=None, - obj=self.ctype) + self.assertRaises( + NotUserNorGroup, get_perms, user_or_group=None, obj=self.ctype + ) def test_user(self): perms_to_assign = ("change_contenttype",) @@ -315,16 +349,14 @@ class GetUsersWithPermsTest(TestCase): """ def setUp(self): - self.obj1 = ContentType.objects.create( - model='foo', app_label='guardian-tests') - self.obj2 = ContentType.objects.create( - model='bar', app_label='guardian-tests') - self.user1 = User.objects.create(username='user1') - self.user2 = User.objects.create(username='user2') - self.user3 = User.objects.create(username='user3') - self.group1 = Group.objects.create(name='group1') - self.group2 = Group.objects.create(name='group2') - self.group3 = Group.objects.create(name='group3') + self.obj1 = ContentType.objects.create(model="foo", app_label="guardian-tests") + self.obj2 = ContentType.objects.create(model="bar", app_label="guardian-tests") + self.user1 = User.objects.create(username="user1") + self.user2 = User.objects.create(username="user2") + self.user3 = User.objects.create(username="user3") + self.group1 = Group.objects.create(name="group1") + self.group2 = Group.objects.create(name="group2") + self.group3 = Group.objects.create(name="group3") def test_empty(self): result = get_users_with_perms(self.obj1) @@ -341,7 +373,7 @@ def test_simple(self): assign_perm("delete_contenttype", self.user3, self.obj2) result = get_users_with_perms(self.obj1) - result_vals = result.values_list('username', flat=True) + result_vals = result.values_list("username", flat=True) self.assertEqual( set(result_vals), @@ -353,8 +385,10 @@ def test_only_with_perms_in(self): assign_perm("delete_contenttype", self.user2, self.obj1) assign_perm("delete_contenttype", self.user3, self.obj2) - result = get_users_with_perms(self.obj1, only_with_perms_in=('change_contenttype',)) - result_vals = result.values_list('username', flat=True) + result = get_users_with_perms( + self.obj1, only_with_perms_in=("change_contenttype",) + ) + result_vals = result.values_list("username", flat=True) self.assertEqual( set(result_vals), @@ -371,8 +405,12 @@ def test_only_with_perms_in_and_with_group_users(self): assign_perm("delete_contenttype", self.group2, self.obj1) assign_perm("add_contenttype", self.group3, self.obj2) - result = get_users_with_perms(self.obj1, only_with_perms_in=('change_contenttype', 'delete_contenttype'), with_group_users=True) - result_vals = result.values_list('username', flat=True) + result = get_users_with_perms( + self.obj1, + only_with_perms_in=("change_contenttype", "delete_contenttype"), + with_group_users=True, + ) + result_vals = result.values_list("username", flat=True) self.assertEqual( set(result_vals), @@ -392,8 +430,12 @@ def test_only_with_perms_in_and_not_with_group_users(self): # assign perms to user assign_perm("change_contenttype", self.user2, self.obj1) - result = get_users_with_perms(self.obj1, only_with_perms_in=('change_contenttype', 'delete_contenttype'), with_group_users=False) - result_vals = result.values_list('username', flat=True) + result = get_users_with_perms( + self.obj1, + only_with_perms_in=("change_contenttype", "delete_contenttype"), + with_group_users=False, + ) + result_vals = result.values_list("username", flat=True) self.assertEqual( set(result_vals), @@ -406,10 +448,11 @@ def test_only_with_perms_in_attached(self): assign_perm("delete_contenttype", self.user2, self.obj1) assign_perm("delete_contenttype", self.user3, self.obj2) - result = get_users_with_perms(self.obj1, only_with_perms_in=('delete_contenttype',), - attach_perms=True) + result = get_users_with_perms( + self.obj1, only_with_perms_in=("delete_contenttype",), attach_perms=True + ) - expected = {self.user2: ('change_contenttype', 'delete_contenttype')} + expected = {self.user2: ("change_contenttype", "delete_contenttype")} self.assertEqual(result.keys(), expected.keys()) for key, perms in result.items(): self.assertEqual(set(perms), set(expected[key])) @@ -422,19 +465,14 @@ def test_users_groups_perms(self): assign_perm("change_contenttype", self.group2, self.obj1) assign_perm("delete_contenttype", self.group3, self.obj2) - result = get_users_with_perms(self.obj1).values_list('pk', - flat=True) - self.assertEqual( - set(result), - {u.pk for u in (self.user1, self.user2)} - ) + result = get_users_with_perms(self.obj1).values_list("pk", flat=True) + self.assertEqual(set(result), {u.pk for u in (self.user1, self.user2)}) def test_users_groups_after_removal(self): self.test_users_groups_perms() remove_perm("change_contenttype", self.group1, self.obj1) - result = get_users_with_perms(self.obj1).values_list('pk', - flat=True) + result = get_users_with_perms(self.obj1).values_list("pk", flat=True) self.assertEqual( set(result), {self.user2.pk}, @@ -492,7 +530,7 @@ def test_mixed(self): ) def test_with_superusers(self): - admin = User.objects.create(username='admin', is_superuser=True) + admin = User.objects.create(username="admin", is_superuser=True) assign_perm("change_contenttype", self.user1, self.obj1) result = get_users_with_perms(self.obj1, with_superusers=True) @@ -517,43 +555,63 @@ def test_without_group_users_but_perms_attached(self): assign_perm("change_contenttype", self.group1, self.obj1) assign_perm("change_contenttype", self.user2, self.obj1) assign_perm("change_contenttype", self.group2, self.obj1) - result = get_users_with_perms(self.obj1, with_group_users=False, - attach_perms=True) + result = get_users_with_perms( + self.obj1, with_group_users=False, attach_perms=True + ) expected = {self.user2: ["change_contenttype"]} self.assertEqual(result, expected) def test_direct_perms_only(self): - admin = User.objects.create(username='admin', is_superuser=True) + admin = User.objects.create(username="admin", is_superuser=True) self.user1.groups.add(self.group1) self.user2.groups.add(self.group1) assign_perm("change_contenttype", self.user1, self.obj1) assign_perm("delete_contenttype", admin, self.obj1) assign_perm("delete_contenttype", self.group1, self.obj1) expected = {self.user1, self.user2, admin} - result = get_users_with_perms(self.obj1, with_superusers=False, with_group_users=True) + result = get_users_with_perms( + self.obj1, with_superusers=False, with_group_users=True + ) self.assertEqual(set(result), expected) - self.assertEqual(set(get_user_perms(self.user1, self.obj1)), {'change_contenttype'}) + self.assertEqual( + set(get_user_perms(self.user1, self.obj1)), {"change_contenttype"} + ) self.assertEqual(set(get_user_perms(self.user2, self.obj1)), set()) - self.assertEqual(set(get_user_perms(admin, self.obj1)), {'delete_contenttype'}) - result = get_users_with_perms(self.obj1, with_superusers=False, with_group_users=False) + self.assertEqual(set(get_user_perms(admin, self.obj1)), {"delete_contenttype"}) + result = get_users_with_perms( + self.obj1, with_superusers=False, with_group_users=False + ) expected = {self.user1, admin} self.assertEqual(set(result), expected) - self.assertEqual(set(get_group_perms(self.user1, self.obj1)), {'delete_contenttype'}) - self.assertEqual(set(get_group_perms(self.user2, self.obj1)), {'delete_contenttype'}) - self.assertEqual(set(get_group_perms(self.group1, self.obj1)), {'delete_contenttype'}) + self.assertEqual( + set(get_group_perms(self.user1, self.obj1)), {"delete_contenttype"} + ) + self.assertEqual( + set(get_group_perms(self.user2, self.obj1)), {"delete_contenttype"} + ) + self.assertEqual( + set(get_group_perms(self.group1, self.obj1)), {"delete_contenttype"} + ) self.assertEqual(set(get_group_perms(self.group2, self.obj1)), set()) self.assertEqual(set(get_group_perms(admin, self.obj1)), set()) - expected_permissions = ['add_contenttype', 'change_contenttype', 'delete_contenttype'] + expected_permissions = [ + "add_contenttype", + "change_contenttype", + "delete_contenttype", + ] if django.VERSION >= (2, 1): - expected_permissions.append('view_contenttype') + expected_permissions.append("view_contenttype") self.assertEqual(set(get_perms(admin, self.obj1)), set(expected_permissions)) - self.assertEqual(set(get_perms(self.user1, self.obj1)), {'change_contenttype', 'delete_contenttype'}) - self.assertEqual(set(get_perms(self.user2, self.obj1)), {'delete_contenttype'}) - self.assertEqual(set(get_perms(self.group1, self.obj1)), {'delete_contenttype'}) + self.assertEqual( + set(get_perms(self.user1, self.obj1)), + {"change_contenttype", "delete_contenttype"}, + ) + self.assertEqual(set(get_perms(self.user2, self.obj1)), {"delete_contenttype"}) + self.assertEqual(set(get_perms(self.group1, self.obj1)), {"delete_contenttype"}) self.assertEqual(set(get_perms(self.group2, self.obj1)), set()) def test_direct_perms_only_perms_attached(self): - admin = User.objects.create(username='admin', is_superuser=True) + admin = User.objects.create(username="admin", is_superuser=True) self.user1.groups.add(self.group1) self.user2.groups.add(self.group1) assign_perm("change_contenttype", self.user1, self.obj1) @@ -562,35 +620,38 @@ def test_direct_perms_only_perms_attached(self): expected = { self.user1: ["change_contenttype", "delete_contenttype"], admin: ["add_contenttype", "change_contenttype", "delete_contenttype"], - self.user2: ["delete_contenttype"] + self.user2: ["delete_contenttype"], } if django.VERSION >= (2, 1): expected[admin].append("view_contenttype") - result = get_users_with_perms(self.obj1, attach_perms=True, - with_superusers=False, with_group_users=True) + result = get_users_with_perms( + self.obj1, attach_perms=True, with_superusers=False, with_group_users=True + ) self.assertEqual(result.keys(), expected.keys()) for key, perms in result.items(): self.assertEqual(set(perms), set(expected[key])) - result = get_users_with_perms(self.obj1, attach_perms=True, - with_superusers=False, with_group_users=False) - expected = {self.user1: ["change_contenttype"], - admin: ["delete_contenttype"]} + result = get_users_with_perms( + self.obj1, attach_perms=True, with_superusers=False, with_group_users=False + ) + expected = {self.user1: ["change_contenttype"], admin: ["delete_contenttype"]} self.assertEqual(result, expected) def test_without_group_users_no_result(self): self.user1.groups.add(self.group1) assign_perm("change_contenttype", self.group1, self.obj1) - result = get_users_with_perms(self.obj1, attach_perms=True, - with_group_users=False) + result = get_users_with_perms( + self.obj1, attach_perms=True, with_group_users=False + ) expected = {} self.assertEqual(result, expected) def test_without_group_users_no_result_but_with_superusers(self): - admin = User.objects.create(username='admin', is_superuser=True) + admin = User.objects.create(username="admin", is_superuser=True) self.user1.groups.add(self.group1) assign_perm("change_contenttype", self.group1, self.obj1) - result = get_users_with_perms(self.obj1, with_group_users=False, - with_superusers=True) + result = get_users_with_perms( + self.obj1, with_group_users=False, with_superusers=True + ) expected = [admin] self.assertEqual(set(result), set(expected)) @@ -601,16 +662,14 @@ class GetGroupsWithPerms(TestCase): """ def setUp(self): - self.obj1 = ContentType.objects.create( - model='foo', app_label='guardian-tests') - self.obj2 = ContentType.objects.create( - model='bar', app_label='guardian-tests') - self.user1 = User.objects.create(username='user1') - self.user2 = User.objects.create(username='user2') - self.user3 = User.objects.create(username='user3') - self.group1 = Group.objects.create(name='group1') - self.group2 = Group.objects.create(name='group2') - self.group3 = Group.objects.create(name='group3') + self.obj1 = ContentType.objects.create(model="foo", app_label="guardian-tests") + self.obj2 = ContentType.objects.create(model="bar", app_label="guardian-tests") + self.user1 = User.objects.create(username="user1") + self.user2 = User.objects.create(username="user2") + self.user3 = User.objects.create(username="user3") + self.group1 = Group.objects.create(name="group1") + self.group2 = Group.objects.create(name="group2") + self.group3 = Group.objects.create(name="group3") def test_empty(self): result = get_groups_with_perms(self.obj1) @@ -647,8 +706,10 @@ def test_simple_attach_perms_after_removal(self): def test_filter_by_contenttype(self): # Make sure that both objects have same pk. - obj = ContentType.objects.create(pk=1042, model='baz', app_label='guardian-tests') - group = Group.objects.create(pk=1042, name='group') + obj = ContentType.objects.create( + pk=1042, model="baz", app_label="guardian-tests" + ) + group = Group.objects.create(pk=1042, name="group") assign_perm("change_group", self.group1, group) assign_perm("change_contenttype", self.group1, obj) @@ -689,332 +750,345 @@ def test_mixed_attach_perms(self): class GetObjectsForUser(TestCase): - def setUp(self): - self.user = User.objects.create(username='joe') - self.group = Group.objects.create(name='group') + self.user = User.objects.create(username="joe") + self.group = Group.objects.create(name="group") self.ctype = ContentType.objects.create( - model='bar', app_label='fake-for-guardian-tests') + model="bar", app_label="fake-for-guardian-tests" + ) def test_superuser(self): self.user.is_superuser = True ctypes = ContentType.objects.all() - objects = get_objects_for_user(self.user, - ['contenttypes.change_contenttype'], ctypes) + objects = get_objects_for_user( + self.user, ["contenttypes.change_contenttype"], ctypes + ) self.assertEqual(set(ctypes), set(objects)) def test_with_superuser_true(self): self.user.is_superuser = True ctypes = ContentType.objects.all() - objects = get_objects_for_user(self.user, - ['contenttypes.change_contenttype'], ctypes, with_superuser=True) + objects = get_objects_for_user( + self.user, ["contenttypes.change_contenttype"], ctypes, with_superuser=True + ) self.assertEqual(set(ctypes), set(objects)) def test_with_superuser_false(self): self.user.is_superuser = True ctypes = ContentType.objects.all() - obj1 = ContentType.objects.create( - model='foo', app_label='guardian-tests') - assign_perm('change_contenttype', self.user, obj1) - objects = get_objects_for_user(self.user, - ['contenttypes.change_contenttype'], ctypes, with_superuser=False) + obj1 = ContentType.objects.create(model="foo", app_label="guardian-tests") + assign_perm("change_contenttype", self.user, obj1) + objects = get_objects_for_user( + self.user, ["contenttypes.change_contenttype"], ctypes, with_superuser=False + ) self.assertEqual({obj1}, set(objects)) def test_anonymous(self): self.user = AnonymousUser() ctypes = ContentType.objects.all() - objects = get_objects_for_user(self.user, - ['contenttypes.change_contenttype'], ctypes) - - obj1 = ContentType.objects.create( - model='foo', app_label='guardian-tests') - assign_perm('change_contenttype', self.user, obj1) - objects = get_objects_for_user(self.user, - ['contenttypes.change_contenttype'], ctypes) + objects = get_objects_for_user( + self.user, ["contenttypes.change_contenttype"], ctypes + ) + + obj1 = ContentType.objects.create(model="foo", app_label="guardian-tests") + assign_perm("change_contenttype", self.user, obj1) + objects = get_objects_for_user( + self.user, ["contenttypes.change_contenttype"], ctypes + ) self.assertEqual({obj1}, set(objects)) def test_mixed_perms(self): codenames = [ - get_user_permission_full_codename('change'), - 'auth.change_permission', + get_user_permission_full_codename("change"), + "auth.change_permission", ] - self.assertRaises(MixedContentTypeError, get_objects_for_user, - self.user, codenames) + self.assertRaises( + MixedContentTypeError, get_objects_for_user, self.user, codenames + ) def test_perms_with_mixed_apps(self): codenames = [ - get_user_permission_full_codename('change'), - 'contenttypes.change_contenttype', + get_user_permission_full_codename("change"), + "contenttypes.change_contenttype", ] - self.assertRaises(MixedContentTypeError, get_objects_for_user, - self.user, codenames) + self.assertRaises( + MixedContentTypeError, get_objects_for_user, self.user, codenames + ) def test_mixed_perms_and_klass(self): - self.assertRaises(MixedContentTypeError, get_objects_for_user, - self.user, ['auth.change_group'], User) + self.assertRaises( + MixedContentTypeError, + get_objects_for_user, + self.user, + ["auth.change_group"], + User, + ) def test_no_app_label_nor_klass(self): - self.assertRaises(WrongAppError, get_objects_for_user, self.user, - ['change_group']) + self.assertRaises( + WrongAppError, get_objects_for_user, self.user, ["change_group"] + ) def test_empty_perms_sequence(self): objects = get_objects_for_user(self.user, [], Group.objects.all()) - self.assertEqual( - set(objects), - set() - ) + self.assertEqual(set(objects), set()) def test_perms_single(self): - perm = 'auth.change_group' + perm = "auth.change_group" assign_perm(perm, self.user, self.group) self.assertEqual( set(get_objects_for_user(self.user, perm)), - set(get_objects_for_user(self.user, [perm]))) + set(get_objects_for_user(self.user, [perm])), + ) def test_klass_as_model(self): - assign_perm('contenttypes.change_contenttype', self.user, self.ctype) + assign_perm("contenttypes.change_contenttype", self.user, self.ctype) - objects = get_objects_for_user(self.user, - ['contenttypes.change_contenttype'], ContentType) + objects = get_objects_for_user( + self.user, ["contenttypes.change_contenttype"], ContentType + ) self.assertEqual([obj.name for obj in objects], [self.ctype.name]) def test_klass_as_manager(self): - assign_perm('auth.change_group', self.user, self.group) - objects = get_objects_for_user(self.user, ['auth.change_group'], - Group.objects) + assign_perm("auth.change_group", self.user, self.group) + objects = get_objects_for_user(self.user, ["auth.change_group"], Group.objects) self.assertEqual([obj.name for obj in objects], [self.group.name]) def test_klass_as_queryset(self): - assign_perm('auth.change_group', self.user, self.group) - objects = get_objects_for_user(self.user, ['auth.change_group'], - Group.objects.all()) + assign_perm("auth.change_group", self.user, self.group) + objects = get_objects_for_user( + self.user, ["auth.change_group"], Group.objects.all() + ) self.assertEqual([obj.name for obj in objects], [self.group.name]) def test_ensure_returns_queryset(self): - objects = get_objects_for_user(self.user, ['auth.change_group']) + objects = get_objects_for_user(self.user, ["auth.change_group"]) self.assertTrue(isinstance(objects, QuerySet)) def test_simple(self): - group_names = ['group1', 'group2', 'group3'] + group_names = ["group1", "group2", "group3"] groups = [Group.objects.create(name=name) for name in group_names] for group in groups: - assign_perm('change_group', self.user, group) + assign_perm("change_group", self.user, group) - objects = get_objects_for_user(self.user, ['auth.change_group']) + objects = get_objects_for_user(self.user, ["auth.change_group"]) self.assertEqual(len(objects), len(groups)) self.assertTrue(isinstance(objects, QuerySet)) - self.assertEqual( - set(objects), - set(groups)) + self.assertEqual(set(objects), set(groups)) def test_multiple_perms_to_check(self): - group_names = ['group1', 'group2', 'group3'] + group_names = ["group1", "group2", "group3"] groups = [Group.objects.create(name=name) for name in group_names] for group in groups: - assign_perm('auth.change_group', self.user, group) - assign_perm('auth.delete_group', self.user, groups[1]) + assign_perm("auth.change_group", self.user, group) + assign_perm("auth.delete_group", self.user, groups[1]) - objects = get_objects_for_user(self.user, ['auth.change_group', - 'auth.delete_group']) + objects = get_objects_for_user( + self.user, ["auth.change_group", "auth.delete_group"] + ) self.assertEqual(len(objects), 1) self.assertTrue(isinstance(objects, QuerySet)) - self.assertEqual( - set(objects.values_list('name', flat=True)), - {groups[1].name}) + self.assertEqual(set(objects.values_list("name", flat=True)), {groups[1].name}) def test_multiple_perms_to_check_no_groups(self): - group_names = ['group1', 'group2', 'group3'] + group_names = ["group1", "group2", "group3"] groups = [Group.objects.create(name=name) for name in group_names] for group in groups: - assign_perm('auth.change_group', self.user, group) - assign_perm('auth.delete_group', self.user, groups[1]) + assign_perm("auth.change_group", self.user, group) + assign_perm("auth.delete_group", self.user, groups[1]) - objects = get_objects_for_user(self.user, ['auth.change_group', - 'auth.delete_group'], use_groups=False) + objects = get_objects_for_user( + self.user, ["auth.change_group", "auth.delete_group"], use_groups=False + ) self.assertEqual(len(objects), 1) self.assertTrue(isinstance(objects, QuerySet)) - self.assertEqual( - set(objects.values_list('name', flat=True)), - {groups[1].name}) + self.assertEqual(set(objects.values_list("name", flat=True)), {groups[1].name}) def test_any_of_multiple_perms_to_check(self): - group_names = ['group1', 'group2', 'group3'] + group_names = ["group1", "group2", "group3"] groups = [Group.objects.create(name=name) for name in group_names] - assign_perm('auth.change_group', self.user, groups[0]) - assign_perm('auth.delete_group', self.user, groups[2]) + assign_perm("auth.change_group", self.user, groups[0]) + assign_perm("auth.delete_group", self.user, groups[2]) - objects = get_objects_for_user(self.user, ['auth.change_group', - 'auth.delete_group'], any_perm=True) + objects = get_objects_for_user( + self.user, ["auth.change_group", "auth.delete_group"], any_perm=True + ) self.assertEqual(len(objects), 2) self.assertTrue(isinstance(objects, QuerySet)) self.assertEqual( - set(objects.values_list('name', flat=True)), - {groups[0].name, groups[2].name}) + set(objects.values_list("name", flat=True)), + {groups[0].name, groups[2].name}, + ) def test_groups_perms(self): - group1 = Group.objects.create(name='group1') - group2 = Group.objects.create(name='group2') - group3 = Group.objects.create(name='group3') + group1 = Group.objects.create(name="group1") + group2 = Group.objects.create(name="group2") + group3 = Group.objects.create(name="group3") groups = [group1, group2, group3] for group in groups: self.user.groups.add(group) # Objects to operate on - ctypes = list(ContentType.objects.all().order_by('id')) - assign_perm('auth.change_group', self.user) - assign_perm('change_contenttype', self.user, ctypes[0]) - assign_perm('change_contenttype', self.user, ctypes[1]) - assign_perm('delete_contenttype', self.user, ctypes[1]) - assign_perm('delete_contenttype', self.user, ctypes[2]) - - assign_perm('change_contenttype', groups[0], ctypes[3]) - assign_perm('change_contenttype', groups[1], ctypes[3]) - assign_perm('change_contenttype', groups[2], ctypes[4]) - assign_perm('delete_contenttype', groups[0], ctypes[0]) - - objects = get_objects_for_user(self.user, - ['contenttypes.change_contenttype']) + ctypes = list(ContentType.objects.all().order_by("id")) + assign_perm("auth.change_group", self.user) + assign_perm("change_contenttype", self.user, ctypes[0]) + assign_perm("change_contenttype", self.user, ctypes[1]) + assign_perm("delete_contenttype", self.user, ctypes[1]) + assign_perm("delete_contenttype", self.user, ctypes[2]) + + assign_perm("change_contenttype", groups[0], ctypes[3]) + assign_perm("change_contenttype", groups[1], ctypes[3]) + assign_perm("change_contenttype", groups[2], ctypes[4]) + assign_perm("delete_contenttype", groups[0], ctypes[0]) + + objects = get_objects_for_user(self.user, ["contenttypes.change_contenttype"]) self.assertEqual( - set(objects.values_list('id', flat=True)), - {ctypes[i].id for i in [0, 1, 3, 4]}) + set(objects.values_list("id", flat=True)), + {ctypes[i].id for i in [0, 1, 3, 4]}, + ) - objects = get_objects_for_user(self.user, - ['contenttypes.change_contenttype', - 'contenttypes.delete_contenttype']) + objects = get_objects_for_user( + self.user, + ["contenttypes.change_contenttype", "contenttypes.delete_contenttype"], + ) self.assertEqual( - set(objects.values_list('id', flat=True)), - {ctypes[i].id for i in [0, 1]}) + set(objects.values_list("id", flat=True)), {ctypes[i].id for i in [0, 1]} + ) - objects = get_objects_for_user(self.user, - ['contenttypes.change_contenttype']) + objects = get_objects_for_user(self.user, ["contenttypes.change_contenttype"]) self.assertEqual( - set(objects.values_list('id', flat=True)), - {ctypes[i].id for i in [0, 1, 3, 4]}) + set(objects.values_list("id", flat=True)), + {ctypes[i].id for i in [0, 1, 3, 4]}, + ) def test_has_global_permission_only(self): - group_names = ['group1', 'group2', 'group3'] + group_names = ["group1", "group2", "group3"] groups = [Group.objects.create(name=name) for name in group_names] # global permission to change any group - perm = 'auth.change_group' + perm = "auth.change_group" assign_perm(perm, self.user) objects = get_objects_for_user(self.user, perm) remove_perm(perm, self.user) - self.assertEqual(set(objects), - set(Group.objects.all())) + self.assertEqual(set(objects), set(Group.objects.all())) def test_has_global_permission_and_object_based_permission(self): - group_names = ['group1', 'group2', 'group3'] + group_names = ["group1", "group2", "group3"] groups = [Group.objects.create(name=name) for name in group_names] # global permission to change any group - perm_global = 'auth.change_group' - perm_obj = 'delete_group' + perm_global = "auth.change_group" + perm_obj = "delete_group" assign_perm(perm_global, self.user) assign_perm(perm_obj, self.user, groups[0]) objects = get_objects_for_user(self.user, [perm_global, perm_obj]) remove_perm(perm_global, self.user) - self.assertEqual(set(objects.values_list('name', flat=True)), - {groups[0].name}) + self.assertEqual(set(objects.values_list("name", flat=True)), {groups[0].name}) def test_has_global_permission_and_object_based_permission_any_perm(self): - group_names = ['group1', 'group2', 'group3'] + group_names = ["group1", "group2", "group3"] groups = [Group.objects.create(name=name) for name in group_names] # global permission to change any group - perm_global = 'auth.change_group' + perm_global = "auth.change_group" # object based permission to change only a specific group - perm_obj = 'auth.delete_group' + perm_obj = "auth.delete_group" assign_perm(perm_global, self.user) assign_perm(perm_obj, self.user, groups[0]) objects = get_objects_for_user( - self.user, [perm_global, perm_obj], any_perm=True, accept_global_perms=True) + self.user, [perm_global, perm_obj], any_perm=True, accept_global_perms=True + ) remove_perm(perm_global, self.user) - self.assertEqual(set(objects), - set(Group.objects.all())) + self.assertEqual(set(objects), set(Group.objects.all())) def test_object_based_permission_without_global_permission(self): - group_names = ['group1', 'group2', 'group3'] + group_names = ["group1", "group2", "group3"] groups = [Group.objects.create(name=name) for name in group_names] # global permission to delete any group - perm_global = 'auth.delete_group' - perm_obj = 'auth.delete_group' + perm_global = "auth.delete_group" + perm_obj = "auth.delete_group" assign_perm(perm_global, self.user) assign_perm(perm_obj, self.user, groups[0]) - objects = get_objects_for_user( - self.user, [perm_obj], accept_global_perms=False) + objects = get_objects_for_user(self.user, [perm_obj], accept_global_perms=False) remove_perm(perm_global, self.user) - self.assertEqual(set(objects.values_list('name', flat=True)), - {groups[0].name}) + self.assertEqual(set(objects.values_list("name", flat=True)), {groups[0].name}) def test_object_based_permission_with_groups_2perms(self): - group_names = ['group1', 'group2', 'group3'] + group_names = ["group1", "group2", "group3"] groups = [Group.objects.create(name=name) for name in group_names] for group in groups: self.user.groups.add(group) # Objects to operate on - ctypes = list(ContentType.objects.all().order_by('id')) - assign_perm('contenttypes.change_contenttype', self.user) - assign_perm('change_contenttype', self.user, ctypes[0]) - assign_perm('change_contenttype', self.user, ctypes[1]) - assign_perm('delete_contenttype', self.user, ctypes[1]) - assign_perm('delete_contenttype', self.user, ctypes[2]) - - assign_perm('change_contenttype', groups[0], ctypes[3]) - assign_perm('change_contenttype', groups[1], ctypes[3]) - assign_perm('change_contenttype', groups[2], ctypes[4]) - assign_perm('delete_contenttype', groups[0], ctypes[0]) - - objects = get_objects_for_user(self.user, - ['contenttypes.change_contenttype', - 'contenttypes.delete_contenttype'], accept_global_perms=True) + ctypes = list(ContentType.objects.all().order_by("id")) + assign_perm("contenttypes.change_contenttype", self.user) + assign_perm("change_contenttype", self.user, ctypes[0]) + assign_perm("change_contenttype", self.user, ctypes[1]) + assign_perm("delete_contenttype", self.user, ctypes[1]) + assign_perm("delete_contenttype", self.user, ctypes[2]) + + assign_perm("change_contenttype", groups[0], ctypes[3]) + assign_perm("change_contenttype", groups[1], ctypes[3]) + assign_perm("change_contenttype", groups[2], ctypes[4]) + assign_perm("delete_contenttype", groups[0], ctypes[0]) + + objects = get_objects_for_user( + self.user, + ["contenttypes.change_contenttype", "contenttypes.delete_contenttype"], + accept_global_perms=True, + ) self.assertEqual( - set(objects.values_list('id', flat=True)), - {ctypes[0].id, ctypes[1].id, ctypes[2].id}) + set(objects.values_list("id", flat=True)), + {ctypes[0].id, ctypes[1].id, ctypes[2].id}, + ) def test_object_based_permission_with_groups_3perms(self): - group_names = ['group1', 'group2', 'group3'] + group_names = ["group1", "group2", "group3"] groups = [Group.objects.create(name=name) for name in group_names] for group in groups: self.user.groups.add(group) # Objects to operate on - ctypes = list(ContentType.objects.all().order_by('id')) - assign_perm('contenttypes.change_contenttype', self.user) - assign_perm('change_contenttype', self.user, ctypes[0]) - assign_perm('change_contenttype', self.user, ctypes[1]) - assign_perm('delete_contenttype', self.user, ctypes[1]) - assign_perm('delete_contenttype', self.user, ctypes[2]) + ctypes = list(ContentType.objects.all().order_by("id")) + assign_perm("contenttypes.change_contenttype", self.user) + assign_perm("change_contenttype", self.user, ctypes[0]) + assign_perm("change_contenttype", self.user, ctypes[1]) + assign_perm("delete_contenttype", self.user, ctypes[1]) + assign_perm("delete_contenttype", self.user, ctypes[2]) # add_contenttype does not make sense, here just for testing purposes, # to also cover one if branch in function. - assign_perm('add_contenttype', self.user, ctypes[1]) + assign_perm("add_contenttype", self.user, ctypes[1]) - assign_perm('change_contenttype', groups[0], ctypes[3]) - assign_perm('change_contenttype', groups[1], ctypes[3]) - assign_perm('change_contenttype', groups[2], ctypes[4]) - assign_perm('delete_contenttype', groups[0], ctypes[0]) - assign_perm('add_contenttype', groups[0], ctypes[0]) + assign_perm("change_contenttype", groups[0], ctypes[3]) + assign_perm("change_contenttype", groups[1], ctypes[3]) + assign_perm("change_contenttype", groups[2], ctypes[4]) + assign_perm("delete_contenttype", groups[0], ctypes[0]) + assign_perm("add_contenttype", groups[0], ctypes[0]) - objects = get_objects_for_user(self.user, - ['contenttypes.change_contenttype', - 'contenttypes.delete_contenttype', 'contenttypes.add_contenttype'], accept_global_perms=True) + objects = get_objects_for_user( + self.user, + [ + "contenttypes.change_contenttype", + "contenttypes.delete_contenttype", + "contenttypes.add_contenttype", + ], + accept_global_perms=True, + ) self.assertEqual( - set(objects.values_list('id', flat=True)), - {ctypes[0].id, ctypes[1].id}) + set(objects.values_list("id", flat=True)), {ctypes[0].id, ctypes[1].id} + ) def test_varchar_primary_key(self): """ Verify that the function works when the objects that should be returned have varchar primary keys. """ - obj_with_char_pk = CharPKModel.objects.create( - char_pk='testprimarykey') - assign_perm('add_charpkmodel', self.user, obj_with_char_pk) + obj_with_char_pk = CharPKModel.objects.create(char_pk="testprimarykey") + assign_perm("add_charpkmodel", self.user, obj_with_char_pk) - objects = get_objects_for_user(self.user, 'testapp.add_charpkmodel') + objects = get_objects_for_user(self.user, "testapp.add_charpkmodel") self.assertEqual(len(objects), 1) self.assertTrue(isinstance(objects, QuerySet)) self.assertEqual( - set(objects.values_list('pk', flat=True)), - {obj_with_char_pk.pk}) + set(objects.values_list("pk", flat=True)), {obj_with_char_pk.pk} + ) def test_uuid_primary_key(self): """ @@ -1022,33 +1096,33 @@ def test_uuid_primary_key(self): have uuid primary keys. """ obj_with_uuid_pk = UUIDPKModel.objects.create() - assign_perm('add_uuidpkmodel', self.user, obj_with_uuid_pk) + assign_perm("add_uuidpkmodel", self.user, obj_with_uuid_pk) - objects = get_objects_for_user(self.user, 'testapp.add_uuidpkmodel') + objects = get_objects_for_user(self.user, "testapp.add_uuidpkmodel") self.assertEqual(len(objects), 1) self.assertTrue(isinstance(objects, QuerySet)) self.assertEqual( - set(objects.values_list('pk', flat=True)), - {obj_with_uuid_pk.pk}) + set(objects.values_list("pk", flat=True)), {obj_with_uuid_pk.pk} + ) def test_varchar_primary_key_with_any_perm(self): """ Verify that the function works with any_perm set to True when the objects that should be returned have varchar primary keys. """ - obj_with_char_pk = CharPKModel.objects.create( - char_pk='testprimarykey') - assign_perm('add_charpkmodel', self.user, obj_with_char_pk) + obj_with_char_pk = CharPKModel.objects.create(char_pk="testprimarykey") + assign_perm("add_charpkmodel", self.user, obj_with_char_pk) objects = get_objects_for_user( self.user, - ['testapp.add_charpkmodel', 'testapp.change_charpkmodel'], - any_perm=True) + ["testapp.add_charpkmodel", "testapp.change_charpkmodel"], + any_perm=True, + ) self.assertEqual(len(objects), 1) self.assertTrue(isinstance(objects, QuerySet)) self.assertEqual( - set(objects.values_list('pk', flat=True)), - {obj_with_char_pk.pk}) + set(objects.values_list("pk", flat=True)), {obj_with_char_pk.pk} + ) def test_uuid_primary_key_with_any_perm(self): """ @@ -1056,17 +1130,18 @@ def test_uuid_primary_key_with_any_perm(self): objects that should be returned have uuid primary keys. """ obj_with_uuid_pk = UUIDPKModel.objects.create() - assign_perm('add_uuidpkmodel', self.user, obj_with_uuid_pk) + assign_perm("add_uuidpkmodel", self.user, obj_with_uuid_pk) objects = get_objects_for_user( self.user, - ['testapp.add_uuidpkmodel', 'testapp.change_uuidpkmodel'], - any_perm=True) + ["testapp.add_uuidpkmodel", "testapp.change_uuidpkmodel"], + any_perm=True, + ) self.assertEqual(len(objects), 1) self.assertTrue(isinstance(objects, QuerySet)) self.assertEqual( - set(objects.values_list('pk', flat=True)), - {obj_with_uuid_pk.pk}) + set(objects.values_list("pk", flat=True)), {obj_with_uuid_pk.pk} + ) def test_varchar_primary_key_with_group_values(self): """ @@ -1074,27 +1149,29 @@ def test_varchar_primary_key_with_group_values(self): have varchar primary keys, and those objects are due to the user's groups. """ - obj_with_char_pk = CharPKModel.objects.create( - char_pk='testprimarykey') - assign_perm('add_charpkmodel', self.group, obj_with_char_pk) + obj_with_char_pk = CharPKModel.objects.create(char_pk="testprimarykey") + assign_perm("add_charpkmodel", self.group, obj_with_char_pk) self.user.groups.add(self.group) objects = get_objects_for_user( self.user, - ['testapp.add_charpkmodel', 'testapp.change_charpkmodel'], - any_perm=True) + ["testapp.add_charpkmodel", "testapp.change_charpkmodel"], + any_perm=True, + ) self.assertEqual(len(objects), 1) self.assertTrue(isinstance(objects, QuerySet)) self.assertEqual( - set(objects.values_list('pk', flat=True)), - {obj_with_char_pk.pk}) + set(objects.values_list("pk", flat=True)), {obj_with_char_pk.pk} + ) def test_model_inheritance(self): child_with_perm = ChildTestModel.objects.create(name="child1") - assign_perm('testapp.change_childtestmodel', self.user, child_with_perm) + assign_perm("testapp.change_childtestmodel", self.user, child_with_perm) child_without_perm = ChildTestModel.objects.create(name="child2") - children = get_objects_for_user(self.user, 'testapp.change_childtestmodel', ChildTestModel) + children = get_objects_for_user( + self.user, "testapp.change_childtestmodel", ChildTestModel + ) self.assertEqual(1, len(children)) self.assertIn(child_with_perm, children) @@ -1107,57 +1184,57 @@ def test_uuid_primary_key_with_group_values(self): groups. """ obj_with_uuid_pk = UUIDPKModel.objects.create() - assign_perm('add_uuidpkmodel', self.group, obj_with_uuid_pk) + assign_perm("add_uuidpkmodel", self.group, obj_with_uuid_pk) self.user.groups.add(self.group) objects = get_objects_for_user( self.user, - ['testapp.add_uuidpkmodel', 'testapp.change_uuidpkmodel'], - any_perm=True) + ["testapp.add_uuidpkmodel", "testapp.change_uuidpkmodel"], + any_perm=True, + ) self.assertEqual(len(objects), 1) self.assertTrue(isinstance(objects, QuerySet)) self.assertEqual( - set(objects.values_list('pk', flat=True)), - {obj_with_uuid_pk.pk}) + set(objects.values_list("pk", flat=True)), {obj_with_uuid_pk.pk} + ) def test_exception_different_ctypes(self): - self.assertRaises(MixedContentTypeError, get_objects_for_user, - self.user, ['auth.change_permission', 'auth.change_group']) + self.assertRaises( + MixedContentTypeError, + get_objects_for_user, + self.user, + ["auth.change_permission", "auth.change_group"], + ) def test_has_any_permissions(self): # We use groups as objects. - group_names = ['group1', 'group2', 'group3'] + group_names = ["group1", "group2", "group3"] groups = [Group.objects.create(name=name) for name in group_names] for group in groups: - assign_perm('change_group', self.user, group) + assign_perm("change_group", self.user, group) objects = get_objects_for_user(self.user, [], Group) self.assertEqual(len(objects), len(groups)) self.assertTrue(isinstance(objects, QuerySet)) - self.assertEqual( - set(objects), - set(groups)) + self.assertEqual(set(objects), set(groups)) def test_short_codenames_with_klass(self): - assign_perm('contenttypes.change_contenttype', self.user, self.ctype) + assign_perm("contenttypes.change_contenttype", self.user, self.ctype) - objects = get_objects_for_user(self.user, - ['change_contenttype'], ContentType) + objects = get_objects_for_user(self.user, ["change_contenttype"], ContentType) self.assertEqual([obj.name for obj in objects], [self.ctype.name]) def test_has_any_group_permissions(self): # We use groups as objects. - group_names = ['group1', 'group2', 'group3'] + group_names = ["group1", "group2", "group3"] groups = [Group.objects.create(name=name) for name in group_names] for group in groups: - assign_perm('change_group', self.group, group) + assign_perm("change_group", self.group, group) objects = get_objects_for_group(self.group, [], Group) self.assertEqual(len(objects), len(groups)) self.assertTrue(isinstance(objects, QuerySet)) - self.assertEqual( - set(objects), - set(groups)) + self.assertEqual(set(objects), set(groups)) class GetObjectsForGroup(TestCase): @@ -1166,173 +1243,201 @@ class GetObjectsForGroup(TestCase): """ def setUp(self): - self.obj1 = ContentType.objects.create( - model='foo', app_label='guardian-tests') - self.obj2 = ContentType.objects.create( - model='bar', app_label='guardian-tests') - self.obj3 = ContentType.objects.create( - model='baz', app_label='guardian-tests') - self.user1 = User.objects.create(username='user1') - self.user2 = User.objects.create(username='user2') - self.user3 = User.objects.create(username='user3') - self.group1 = Group.objects.create(name='group1') - self.group2 = Group.objects.create(name='group2') - self.group3 = Group.objects.create(name='group3') + self.obj1 = ContentType.objects.create(model="foo", app_label="guardian-tests") + self.obj2 = ContentType.objects.create(model="bar", app_label="guardian-tests") + self.obj3 = ContentType.objects.create(model="baz", app_label="guardian-tests") + self.user1 = User.objects.create(username="user1") + self.user2 = User.objects.create(username="user2") + self.user3 = User.objects.create(username="user3") + self.group1 = Group.objects.create(name="group1") + self.group2 = Group.objects.create(name="group2") + self.group3 = Group.objects.create(name="group3") def test_mixed_perms(self): codenames = [ - get_user_permission_full_codename('change'), - 'auth.change_permission', + get_user_permission_full_codename("change"), + "auth.change_permission", ] - self.assertRaises(MixedContentTypeError, get_objects_for_group, - self.group1, codenames) + self.assertRaises( + MixedContentTypeError, get_objects_for_group, self.group1, codenames + ) def test_perms_with_mixed_apps(self): codenames = [ - get_user_permission_full_codename('change'), - 'contenttypes.contenttypes.change_contenttype', + get_user_permission_full_codename("change"), + "contenttypes.contenttypes.change_contenttype", ] - self.assertRaises(MixedContentTypeError, get_objects_for_group, - self.group1, codenames) + self.assertRaises( + MixedContentTypeError, get_objects_for_group, self.group1, codenames + ) def test_mixed_perms_and_klass(self): - self.assertRaises(MixedContentTypeError, get_objects_for_group, - self.group1, ['auth.change_group'], User) + self.assertRaises( + MixedContentTypeError, + get_objects_for_group, + self.group1, + ["auth.change_group"], + User, + ) def test_no_app_label_nor_klass(self): - self.assertRaises(WrongAppError, get_objects_for_group, self.group1, - ['change_contenttype']) + self.assertRaises( + WrongAppError, get_objects_for_group, self.group1, ["change_contenttype"] + ) def test_empty_perms_sequence(self): self.assertEqual( - set(get_objects_for_group(self.group1, [], ContentType)), - set() + set(get_objects_for_group(self.group1, [], ContentType)), set() ) def test_perms_single(self): - perm = 'contenttypes.change_contenttype' + perm = "contenttypes.change_contenttype" assign_perm(perm, self.group1, self.obj1) self.assertEqual( set(get_objects_for_group(self.group1, perm)), - set(get_objects_for_group(self.group1, [perm])) + set(get_objects_for_group(self.group1, [perm])), ) def test_klass_as_model(self): - assign_perm('contenttypes.change_contenttype', self.group1, self.obj1) + assign_perm("contenttypes.change_contenttype", self.group1, self.obj1) - objects = get_objects_for_group(self.group1, - ['contenttypes.change_contenttype'], ContentType) + objects = get_objects_for_group( + self.group1, ["contenttypes.change_contenttype"], ContentType + ) self.assertEqual([obj.name for obj in objects], [self.obj1.name]) def test_klass_as_manager(self): - assign_perm('contenttypes.change_contenttype', self.group1, self.obj1) - objects = get_objects_for_group(self.group1, ['change_contenttype'], - ContentType.objects) + assign_perm("contenttypes.change_contenttype", self.group1, self.obj1) + objects = get_objects_for_group( + self.group1, ["change_contenttype"], ContentType.objects + ) self.assertEqual(list(objects), [self.obj1]) def test_klass_as_queryset(self): - assign_perm('contenttypes.change_contenttype', self.group1, self.obj1) - objects = get_objects_for_group(self.group1, ['change_contenttype'], - ContentType.objects.all()) + assign_perm("contenttypes.change_contenttype", self.group1, self.obj1) + objects = get_objects_for_group( + self.group1, ["change_contenttype"], ContentType.objects.all() + ) self.assertEqual(list(objects), [self.obj1]) def test_ensure_returns_queryset(self): objects = get_objects_for_group( - self.group1, ['contenttypes.change_contenttype']) + self.group1, ["contenttypes.change_contenttype"] + ) self.assertTrue(isinstance(objects, QuerySet)) def test_simple(self): - assign_perm('change_contenttype', self.group1, self.obj1) - assign_perm('change_contenttype', self.group1, self.obj2) + assign_perm("change_contenttype", self.group1, self.obj1) + assign_perm("change_contenttype", self.group1, self.obj2) - objects = get_objects_for_group( - self.group1, 'contenttypes.change_contenttype') + objects = get_objects_for_group(self.group1, "contenttypes.change_contenttype") self.assertEqual(len(objects), 2) self.assertTrue(isinstance(objects, QuerySet)) - self.assertEqual( - set(objects), - {self.obj1, self.obj2}) + self.assertEqual(set(objects), {self.obj1, self.obj2}) def test_simple_after_removal(self): self.test_simple() - remove_perm('change_contenttype', self.group1, self.obj1) - objects = get_objects_for_group( - self.group1, 'contenttypes.change_contenttype') + remove_perm("change_contenttype", self.group1, self.obj1) + objects = get_objects_for_group(self.group1, "contenttypes.change_contenttype") self.assertEqual(len(objects), 1) self.assertEqual(objects[0], self.obj2) def test_multiple_perms_to_check(self): - assign_perm('change_contenttype', self.group1, self.obj1) - assign_perm('delete_contenttype', self.group1, self.obj1) - assign_perm('change_contenttype', self.group1, self.obj2) + assign_perm("change_contenttype", self.group1, self.obj1) + assign_perm("delete_contenttype", self.group1, self.obj1) + assign_perm("change_contenttype", self.group1, self.obj2) - objects = get_objects_for_group(self.group1, [ - 'contenttypes.change_contenttype', - 'contenttypes.delete_contenttype']) + objects = get_objects_for_group( + self.group1, + ["contenttypes.change_contenttype", "contenttypes.delete_contenttype"], + ) self.assertEqual(len(objects), 1) self.assertTrue(isinstance(objects, QuerySet)) self.assertEqual(objects[0], self.obj1) def test_any_of_multiple_perms_to_check(self): - assign_perm('change_contenttype', self.group1, self.obj1) - assign_perm('delete_contenttype', self.group1, self.obj1) - assign_perm('add_contenttype', self.group1, self.obj2) - assign_perm('delete_contenttype', self.group1, self.obj3) - - objects = get_objects_for_group(self.group1, - ['contenttypes.change_contenttype', - 'contenttypes.delete_contenttype'], any_perm=True) + assign_perm("change_contenttype", self.group1, self.obj1) + assign_perm("delete_contenttype", self.group1, self.obj1) + assign_perm("add_contenttype", self.group1, self.obj2) + assign_perm("delete_contenttype", self.group1, self.obj3) + + objects = get_objects_for_group( + self.group1, + ["contenttypes.change_contenttype", "contenttypes.delete_contenttype"], + any_perm=True, + ) self.assertTrue(isinstance(objects, QuerySet)) - self.assertEqual([obj for obj in objects.order_by('app_label', 'id')], - [self.obj1, self.obj3]) + self.assertEqual( + [obj for obj in objects.order_by("app_label", "id")], [self.obj1, self.obj3] + ) def test_results_for_different_groups_are_correct(self): - assign_perm('change_contenttype', self.group1, self.obj1) - assign_perm('delete_contenttype', self.group2, self.obj2) + assign_perm("change_contenttype", self.group1, self.obj1) + assign_perm("delete_contenttype", self.group2, self.obj2) - self.assertEqual(set(get_objects_for_group(self.group1, 'contenttypes.change_contenttype')), - {self.obj1}) - self.assertEqual(set(get_objects_for_group(self.group2, 'contenttypes.change_contenttype')), - set()) - self.assertEqual(set(get_objects_for_group(self.group2, 'contenttypes.delete_contenttype')), - {self.obj2}) + self.assertEqual( + set(get_objects_for_group(self.group1, "contenttypes.change_contenttype")), + {self.obj1}, + ) + self.assertEqual( + set(get_objects_for_group(self.group2, "contenttypes.change_contenttype")), + set(), + ) + self.assertEqual( + set(get_objects_for_group(self.group2, "contenttypes.delete_contenttype")), + {self.obj2}, + ) def test_has_global_permission(self): - assign_perm('contenttypes.change_contenttype', self.group1) + assign_perm("contenttypes.change_contenttype", self.group1) objects = get_objects_for_group( - self.group1, ['contenttypes.change_contenttype']) - self.assertEqual(set(objects), - set(ContentType.objects.all())) + self.group1, ["contenttypes.change_contenttype"] + ) + self.assertEqual(set(objects), set(ContentType.objects.all())) def test_has_global_permission_and_object_based_permission(self): - assign_perm('contenttypes.change_contenttype', self.group1) - assign_perm('contenttypes.delete_contenttype', self.group1, self.obj1) + assign_perm("contenttypes.change_contenttype", self.group1) + assign_perm("contenttypes.delete_contenttype", self.group1, self.obj1) - objects = get_objects_for_group(self.group1, [ - 'contenttypes.change_contenttype', 'contenttypes.delete_contenttype'], any_perm=False) - self.assertEqual(set(objects), - {self.obj1}) + objects = get_objects_for_group( + self.group1, + ["contenttypes.change_contenttype", "contenttypes.delete_contenttype"], + any_perm=False, + ) + self.assertEqual(set(objects), {self.obj1}) def test_has_global_permission_and_object_based_permission_any_perm(self): - assign_perm('contenttypes.change_contenttype', self.group1) - assign_perm('contenttypes.delete_contenttype', self.group1, self.obj1) + assign_perm("contenttypes.change_contenttype", self.group1) + assign_perm("contenttypes.delete_contenttype", self.group1, self.obj1) - objects = get_objects_for_group(self.group1, [ - 'contenttypes.change_contenttype', 'contenttypes.delete_contenttype'], any_perm=True) - self.assertEqual(set(objects), - set(ContentType.objects.all())) + objects = get_objects_for_group( + self.group1, + ["contenttypes.change_contenttype", "contenttypes.delete_contenttype"], + any_perm=True, + ) + self.assertEqual(set(objects), set(ContentType.objects.all())) def test_has_global_permission_and_object_based_permission_3perms(self): - assign_perm('contenttypes.change_contenttype', self.group1) - assign_perm('contenttypes.delete_contenttype', self.group1, self.obj1) - assign_perm('contenttypes.add_contenttype', self.group1, self.obj2) + assign_perm("contenttypes.change_contenttype", self.group1) + assign_perm("contenttypes.delete_contenttype", self.group1, self.obj1) + assign_perm("contenttypes.add_contenttype", self.group1, self.obj2) - objects = get_objects_for_group(self.group1, [ - 'contenttypes.change_contenttype', 'contenttypes.delete_contenttype', 'contenttypes.add_contenttype'], any_perm=False) - self.assertEqual(set(objects), - set()) + objects = get_objects_for_group( + self.group1, + [ + "contenttypes.change_contenttype", + "contenttypes.delete_contenttype", + "contenttypes.add_contenttype", + ], + any_perm=False, + ) + self.assertEqual(set(objects), set()) def test_exception_different_ctypes(self): - self.assertRaises(MixedContentTypeError, get_objects_for_group, - self.group1, ['auth.change_permission', 'auth.change_group']) + self.assertRaises( + MixedContentTypeError, + get_objects_for_group, + self.group1, + ["auth.change_permission", "auth.change_group"], + ) diff --git a/guardian/testapp/tests/test_tags.py b/guardian/testapp/tests/test_tags.py index 8438818c6..2a5af8d88 100644 --- a/guardian/testapp/tests/test_tags.py +++ b/guardian/testapp/tests/test_tags.py @@ -22,130 +22,151 @@ def render(template, context): class GetObjPermsTagTest(TestCase): - def setUp(self): self.ctype = ContentType.objects.create( - model='bar', app_label='fake-for-guardian-tests') - self.group = Group.objects.create(name='jackGroup') - self.user = User.objects.create(username='jack') + model="bar", app_label="fake-for-guardian-tests" + ) + self.group = Group.objects.create(name="jackGroup") + self.user = User.objects.create(username="jack") self.user.groups.add(self.group) def test_wrong_formats(self): wrong_formats = ( - '{% get_obj_perms user for contenttype as obj_perms %}', # no quotes - '{% get_obj_perms user for contenttype as \'obj_perms" %}', # wrong quotes - '{% get_obj_perms user for contenttype as \'obj_perms" %}', # wrong quotes + "{% get_obj_perms user for contenttype as obj_perms %}", # no quotes + "{% get_obj_perms user for contenttype as 'obj_perms\" %}", # wrong quotes + "{% get_obj_perms user for contenttype as 'obj_perms\" %}", # wrong quotes '{% get_obj_perms user for contenttype as obj_perms" %}', # wrong quotes - '{% get_obj_perms user for contenttype as obj_perms\' %}', # wrong quotes - '{% get_obj_perms user for contenttype as %}', # no context_var + "{% get_obj_perms user for contenttype as obj_perms' %}", # wrong quotes + "{% get_obj_perms user for contenttype as %}", # no context_var '{% get_obj_perms for contenttype as "obj_perms" %}', # no user/group '{% get_obj_perms user contenttype as "obj_perms" %}', # no "for" bit '{% get_obj_perms user for contenttype "obj_perms" %}', # no "as" bit '{% get_obj_perms user for as "obj_perms" %}', # no object ) - context = {'user': User.get_anonymous(), 'contenttype': self.ctype} + context = {"user": User.get_anonymous(), "contenttype": self.ctype} for wrong in wrong_formats: - fullwrong = '{% load guardian_tags %}' + wrong + fullwrong = "{% load guardian_tags %}" + wrong try: render(fullwrong, context) - self.fail("Used wrong get_obj_perms tag format: \n\n\t%s\n\n " - "but TemplateSyntaxError have not been raised" % wrong) + self.fail( + "Used wrong get_obj_perms tag format: \n\n\t%s\n\n " + "but TemplateSyntaxError have not been raised" % wrong + ) except TemplateSyntaxError: pass def test_obj_none(self): - template = ''.join(( - '{% load guardian_tags %}', - '{% get_obj_perms user for object as "obj_perms" %}{{ perms }}', - )) - context = {'user': User.get_anonymous(), 'object': None} + template = "".join( + ( + "{% load guardian_tags %}", + '{% get_obj_perms user for object as "obj_perms" %}{{ perms }}', + ) + ) + context = {"user": User.get_anonymous(), "object": None} output = render(template, context) - self.assertEqual(output, '') + self.assertEqual(output, "") def test_anonymous_user(self): - template = ''.join(( - '{% load guardian_tags %}', - '{% get_obj_perms user for contenttype as "obj_perms" %}{{ perms }}', - )) - context = {'user': AnonymousUser(), 'contenttype': self.ctype} + template = "".join( + ( + "{% load guardian_tags %}", + '{% get_obj_perms user for contenttype as "obj_perms" %}{{ perms }}', + ) + ) + context = {"user": AnonymousUser(), "contenttype": self.ctype} anon_output = render(template, context) - context = {'user': User.get_anonymous(), 'contenttype': self.ctype} + context = {"user": User.get_anonymous(), "contenttype": self.ctype} real_anon_user_output = render(template, context) self.assertEqual(anon_output, real_anon_user_output) def test_wrong_user_or_group(self): - template = ''.join(( - '{% load guardian_tags %}', - '{% get_obj_perms some_obj for contenttype as "obj_perms" %}', - )) - context = {'some_obj': ContentType(), 'contenttype': self.ctype} + template = "".join( + ( + "{% load guardian_tags %}", + '{% get_obj_perms some_obj for contenttype as "obj_perms" %}', + ) + ) + context = {"some_obj": ContentType(), "contenttype": self.ctype} # This test would raise TemplateSyntaxError instead of NotUserNorGroup # if the template option 'debug' is set to True during tests. - template_options = settings.TEMPLATES[0]['OPTIONS'] - tmp = template_options.get('debug', False) - template_options['debug'] = False + template_options = settings.TEMPLATES[0]["OPTIONS"] + tmp = template_options.get("debug", False) + template_options["debug"] = False self.assertRaises(NotUserNorGroup, render, template, context) - template_options['debug'] = tmp + template_options["debug"] = tmp def test_superuser(self): - user = User.objects.create(username='superuser', is_superuser=True) - template = ''.join(( - '{% load guardian_tags %}', - '{% get_obj_perms user for contenttype as "obj_perms" %}', - '{{ obj_perms|join:" " }}', - )) - context = {'user': user, 'contenttype': self.ctype} + user = User.objects.create(username="superuser", is_superuser=True) + template = "".join( + ( + "{% load guardian_tags %}", + '{% get_obj_perms user for contenttype as "obj_perms" %}', + '{{ obj_perms|join:" " }}', + ) + ) + context = {"user": user, "contenttype": self.ctype} output = render(template, context) - for perm in ('add_contenttype', 'change_contenttype', 'delete_contenttype'): + for perm in ("add_contenttype", "change_contenttype", "delete_contenttype"): self.assertTrue(perm in output) def test_user(self): - UserObjectPermission.objects.assign_perm("change_contenttype", self.user, - self.ctype) - GroupObjectPermission.objects.assign_perm("delete_contenttype", self.group, - self.ctype) - - template = ''.join(( - '{% load guardian_tags %}', - '{% get_obj_perms user for contenttype as "obj_perms" %}', - '{{ obj_perms|join:" " }}', - )) - context = {'user': self.user, 'contenttype': self.ctype} + UserObjectPermission.objects.assign_perm( + "change_contenttype", self.user, self.ctype + ) + GroupObjectPermission.objects.assign_perm( + "delete_contenttype", self.group, self.ctype + ) + + template = "".join( + ( + "{% load guardian_tags %}", + '{% get_obj_perms user for contenttype as "obj_perms" %}', + '{{ obj_perms|join:" " }}', + ) + ) + context = {"user": self.user, "contenttype": self.ctype} output = render(template, context) self.assertEqual( - set(output.split(' ')), - set('change_contenttype delete_contenttype'.split(' '))) + set(output.split(" ")), + set("change_contenttype delete_contenttype".split(" ")), + ) def test_group(self): - GroupObjectPermission.objects.assign_perm("delete_contenttype", self.group, - self.ctype) - - template = ''.join(( - '{% load guardian_tags %}', - '{% get_obj_perms group for contenttype as "obj_perms" %}', - '{{ obj_perms|join:" " }}', - )) - context = {'group': self.group, 'contenttype': self.ctype} + GroupObjectPermission.objects.assign_perm( + "delete_contenttype", self.group, self.ctype + ) + + template = "".join( + ( + "{% load guardian_tags %}", + '{% get_obj_perms group for contenttype as "obj_perms" %}', + '{{ obj_perms|join:" " }}', + ) + ) + context = {"group": self.group, "contenttype": self.ctype} output = render(template, context) - self.assertEqual(output, 'delete_contenttype') + self.assertEqual(output, "delete_contenttype") def test_checker(self): - GroupObjectPermission.objects.assign_perm("delete_contenttype", self.group, - self.ctype) + GroupObjectPermission.objects.assign_perm( + "delete_contenttype", self.group, self.ctype + ) checker = ObjectPermissionChecker(self.user) checker.prefetch_perms(Group.objects.all()) - template = ''.join(( - '{% load guardian_tags %}', - '{% get_obj_perms group for contenttype as "obj_perms" checker %}', - '{{ obj_perms|join:" " }}', - )) - context = {'group': self.group, 'contenttype': self.ctype, 'checker': checker} + template = "".join( + ( + "{% load guardian_tags %}", + '{% get_obj_perms group for contenttype as "obj_perms" checker %}', + '{{ obj_perms|join:" " }}', + ) + ) + context = {"group": self.group, "contenttype": self.ctype, "checker": checker} output = render(template, context) - self.assertEqual(output, 'delete_contenttype') + self.assertEqual(output, "delete_contenttype") diff --git a/guardian/testapp/tests/test_utils.py b/guardian/testapp/tests/test_utils.py index 16125d81c..c4272f8f7 100644 --- a/guardian/testapp/tests/test_utils.py +++ b/guardian/testapp/tests/test_utils.py @@ -23,14 +23,12 @@ class GetAnonymousUserTest(TestCase): - def test(self): anon = get_anonymous_user() self.assertTrue(isinstance(anon, User)) class GetIdentityTest(ObjectPermissionTestCase): - def test_user(self): user, group = get_identity(self.user) self.assertTrue(isinstance(user, User)) @@ -75,70 +73,63 @@ def test_multiple_group_list(self): @skipUnlessTestApp class GetUserObjPermsModelTest(TestCase): - def test_for_instance(self): - project = Project(name='Foobar') - self.assertEqual(get_user_obj_perms_model(project), - ProjectUserObjectPermission) + project = Project(name="Foobar") + self.assertEqual(get_user_obj_perms_model(project), ProjectUserObjectPermission) def test_for_class(self): - self.assertEqual(get_user_obj_perms_model(Project), - ProjectUserObjectPermission) + self.assertEqual(get_user_obj_perms_model(Project), ProjectUserObjectPermission) def test_default(self): - self.assertEqual(get_user_obj_perms_model(ContentType), - UserObjectPermission) + self.assertEqual(get_user_obj_perms_model(ContentType), UserObjectPermission) def test_user_model(self): # this test assumes that there were no direct obj perms model to User # model defined (i.e. while testing guardian app in some custom # project) - self.assertEqual(get_user_obj_perms_model(User), - UserObjectPermission) + self.assertEqual(get_user_obj_perms_model(User), UserObjectPermission) @skipUnlessTestApp class GetGroupObjPermsModelTest(TestCase): - def test_for_instance(self): - project = Project(name='Foobar') - self.assertEqual(get_group_obj_perms_model(project), - ProjectGroupObjectPermission) + project = Project(name="Foobar") + self.assertEqual( + get_group_obj_perms_model(project), ProjectGroupObjectPermission + ) def test_for_class(self): - self.assertEqual(get_group_obj_perms_model(Project), - ProjectGroupObjectPermission) + self.assertEqual( + get_group_obj_perms_model(Project), ProjectGroupObjectPermission + ) def test_default(self): - self.assertEqual(get_group_obj_perms_model(ContentType), - GroupObjectPermission) + self.assertEqual(get_group_obj_perms_model(ContentType), GroupObjectPermission) def test_group_model(self): # this test assumes that there were no direct obj perms model to Group # model defined (i.e. while testing guardian app in some custom # project) - self.assertEqual(get_group_obj_perms_model(Group), - GroupObjectPermission) + self.assertEqual(get_group_obj_perms_model(Group), GroupObjectPermission) class GetObjPermsModelTest(TestCase): - def test_image_field(self): - class SomeModel(models.Model): - image = models.FileField(upload_to='images/') + image = models.FileField(upload_to="images/") obj = SomeModel() - perm_model = get_obj_perms_model(obj, UserObjectPermissionBase, - UserObjectPermission) + perm_model = get_obj_perms_model( + obj, UserObjectPermissionBase, UserObjectPermission + ) self.assertEqual(perm_model, UserObjectPermission) def test_file_field(self): - class SomeModel2(models.Model): - file = models.FileField(upload_to='images/') + file = models.FileField(upload_to="images/") obj = SomeModel2() - perm_model = get_obj_perms_model(obj, UserObjectPermissionBase, - UserObjectPermission) + perm_model = get_obj_perms_model( + obj, UserObjectPermissionBase, UserObjectPermission + ) self.assertEqual(perm_model, UserObjectPermission) diff --git a/guardian/testapp/tests/urls.py b/guardian/testapp/tests/urls.py index 4c232fb69..5c1b5a4c2 100644 --- a/guardian/testapp/tests/urls.py +++ b/guardian/testapp/tests/urls.py @@ -10,10 +10,11 @@ class TestClassRedirectView(PermissionRequiredMixin, View): - permission_required = 'testapp.change_project' + permission_required = "testapp.change_project" + urlpatterns = [ - path('admin/', admin.site.urls), - path('accounts/login/', LoginView.as_view(template_name='blank.html')), - path('permission_required/', TestClassRedirectView.as_view()), + path("admin/", admin.site.urls), + path("accounts/login/", LoginView.as_view(template_name="blank.html")), + path("permission_required/", TestClassRedirectView.as_view()), ] diff --git a/guardian/testapp/testsettings.py b/guardian/testapp/testsettings.py index 6f5a7ca75..daaf15625 100644 --- a/guardian/testapp/testsettings.py +++ b/guardian/testapp/testsettings.py @@ -13,56 +13,54 @@ GUARDIAN_MONKEY_PATCH = False INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.admin', - 'django.contrib.messages', - 'guardian', - 'guardian.testapp', + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.sites", + "django.contrib.admin", + "django.contrib.messages", + "guardian", + "guardian.testapp", ) AUTHENTICATION_BACKENDS = ( - 'django.contrib.auth.backends.ModelBackend', - 'guardian.backends.ObjectPermissionBackend', + "django.contrib.auth.backends.ModelBackend", + "guardian.backends.ObjectPermissionBackend", ) MIDDLEWARE = ( - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', + "django.middleware.common.CommonMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", ) -TEST_RUNNER = 'django.test.runner.DiscoverRunner' +TEST_RUNNER = "django.test.runner.DiscoverRunner" -ROOT_URLCONF = 'guardian.testapp.tests.urls' +ROOT_URLCONF = "guardian.testapp.tests.urls" SITE_ID = 1 -SECRET_KEY = ''.join([random.choice(string.ascii_letters) for x in range(40)]) +SECRET_KEY = "".join([random.choice(string.ascii_letters) for x in range(40)]) # Database specific -DATABASES = {'default': env.db(default="sqlite:///")} +DATABASES = {"default": env.db(default="sqlite:///")} TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': ( - os.path.join(os.path.dirname(__file__), 'tests', 'templates'), - ), - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.contrib.auth.context_processors.auth', - 'django.template.context_processors.debug', - 'django.template.context_processors.i18n', - 'django.template.context_processors.media', - 'django.template.context_processors.static', - 'django.template.context_processors.tz', - 'django.contrib.messages.context_processors.messages', + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": (os.path.join(os.path.dirname(__file__), "tests", "templates"),), + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.contrib.auth.context_processors.auth", + "django.template.context_processors.debug", + "django.template.context_processors.i18n", + "django.template.context_processors.media", + "django.template.context_processors.static", + "django.template.context_processors.tz", + "django.contrib.messages.context_processors.messages", ], }, }, diff --git a/guardian/utils.py b/guardian/utils.py index 400743ef4..ed7b8f758 100644 --- a/guardian/utils.py +++ b/guardian/utils.py @@ -87,13 +87,21 @@ def get_identity(identity): if isinstance(identity, Group): return None, identity - raise NotUserNorGroup("User/AnonymousUser or Group instance is required " - "(got %s)" % identity) - - -def get_40x_or_None(request, perms, obj=None, login_url=None, - redirect_field_name=None, return_403=False, - return_404=False, accept_global_perms=False): + raise NotUserNorGroup( + "User/AnonymousUser or Group instance is required " "(got %s)" % identity + ) + + +def get_40x_or_None( + request, + perms, + obj=None, + login_url=None, + redirect_field_name=None, + return_403=False, + return_404=False, + accept_global_perms=False, +): login_url = login_url or settings.LOGIN_URL redirect_field_name = redirect_field_name or REDIRECT_FIELD_NAME @@ -106,8 +114,7 @@ def get_40x_or_None(request, perms, obj=None, login_url=None, has_permissions = all(request.user.has_perm(perm) for perm in perms) # if still no permission granted, try obj perms if not has_permissions: - has_permissions = all(request.user.has_perm(perm, obj) - for perm in perms) + has_permissions = all(request.user.has_perm(perm, obj) for perm in perms) if not has_permissions: if return_403: @@ -128,14 +135,16 @@ def get_40x_or_None(request, perms, obj=None, login_url=None, return HttpResponseNotFound() else: from django.contrib.auth.views import redirect_to_login - return redirect_to_login(request.get_full_path(), - login_url, - redirect_field_name) + + return redirect_to_login( + request.get_full_path(), login_url, redirect_field_name + ) from django.apps import apps as django_apps from django.core.exceptions import ImproperlyConfigured + def get_obj_perm_model_by_conf(setting_name): """ Return the model that matches the guardian settings. @@ -144,10 +153,14 @@ def get_obj_perm_model_by_conf(setting_name): setting_value = getattr(guardian_settings, setting_name) return django_apps.get_model(setting_value, require_ready=False) except ValueError as e: - raise ImproperlyConfigured("{} must be of the form 'app_label.model_name'".format(setting_value)) from e + raise ImproperlyConfigured( + "{} must be of the form 'app_label.model_name'".format(setting_value) + ) from e except LookupError as e: raise ImproperlyConfigured( - "{} refers to model '{}' that has not been installed".format(setting_name, setting_value) + "{} refers to model '{}' that has not been installed".format( + setting_name, setting_value + ) ) from e @@ -163,24 +176,26 @@ def clean_orphan_obj_perms(): deleted = 0 # TODO: optimise - for perm in chain(UserObjectPermission.objects.all().iterator(), - GroupObjectPermission.objects.all().iterator()): + for perm in chain( + UserObjectPermission.objects.all().iterator(), + GroupObjectPermission.objects.all().iterator(), + ): if perm.content_object is None: logger.debug("Removing %s (pk=%d)" % (perm, perm.pk)) perm.delete() deleted += 1 - logger.info("Total removed orphan object permissions instances: %d" % - deleted) + logger.info("Total removed orphan object permissions instances: %d" % deleted) return deleted # TODO: should raise error when multiple UserObjectPermission direct relations # are defined + def get_obj_perms_model(obj, base_cls, generic_cls): """ Return the matching object permission model for the obj class - Defaults to returning the generic object permission when + Defaults to returning the generic object permission when no direct foreignkey is defined or obj is None """ # Default to the generic object permission model @@ -191,47 +206,56 @@ def get_obj_perms_model(obj, base_cls, generic_cls): if isinstance(obj, Model): obj = obj.__class__ - fields = (f for f in obj._meta.get_fields() - if (f.one_to_many or f.one_to_one) and f.auto_created) + fields = ( + f + for f in obj._meta.get_fields() + if (f.one_to_many or f.one_to_one) and f.auto_created + ) for attr in fields: - model = getattr(attr, 'related_model', None) - if (model and issubclass(model, base_cls) and - model is not generic_cls and getattr(model, 'enabled', True)): + model = getattr(attr, "related_model", None) + if ( + model + and issubclass(model, base_cls) + and model is not generic_cls + and getattr(model, "enabled", True) + ): # if model is generic one it would be returned anyway if not model.objects.is_generic(): # make sure that content_object's content_type is same as # the one of given obj - fk = model._meta.get_field('content_object') + fk = model._meta.get_field("content_object") if get_content_type(obj) == get_content_type(fk.remote_field.model): return model return generic_cls -def get_user_obj_perms_model(obj = None): +def get_user_obj_perms_model(obj=None): """ Returns model class that connects given ``obj`` and User class. If obj is not specified, then user generic object permission model returned is determined by the guardian setting 'USER_OBJ_PERMS_MODEL' """ from guardian.models import UserObjectPermissionBase - UserObjectPermission = get_obj_perm_model_by_conf('USER_OBJ_PERMS_MODEL') + + UserObjectPermission = get_obj_perm_model_by_conf("USER_OBJ_PERMS_MODEL") return get_obj_perms_model(obj, UserObjectPermissionBase, UserObjectPermission) -def get_group_obj_perms_model(obj = None): +def get_group_obj_perms_model(obj=None): """ Returns model class that connects given ``obj`` and Group class. If obj is not specified, then group generic object permission model returned is determined byt the guardian setting 'GROUP_OBJ_PERMS_MODEL'. """ from guardian.models import GroupObjectPermissionBase - GroupObjectPermission = get_obj_perm_model_by_conf('GROUP_OBJ_PERMS_MODEL') + + GroupObjectPermission = get_obj_perm_model_by_conf("GROUP_OBJ_PERMS_MODEL") return get_obj_perms_model(obj, GroupObjectPermissionBase, GroupObjectPermission) def evict_obj_perms_cache(obj): - if hasattr(obj, '_guardian_perms_cache'): - delattr(obj, '_guardian_perms_cache') + if hasattr(obj, "_guardian_perms_cache"): + delattr(obj, "_guardian_perms_cache") return True return False diff --git a/manage.py b/manage.py index feaf63a81..c19af3a5c 100755 --- a/manage.py +++ b/manage.py @@ -3,8 +3,7 @@ import sys if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", - "guardian.testapp.testsettings") + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "guardian.testapp.testsettings") from django.core.management import execute_from_command_line diff --git a/setup.py b/setup.py index 1b3ff9b9a..a03051113 100644 --- a/setup.py +++ b/setup.py @@ -3,49 +3,55 @@ from extras import RunFlakesCommand -version = '2.3.0' +version = "2.3.0" -readme_file = os.path.join(os.path.dirname(__file__), 'README.rst') +readme_file = os.path.join(os.path.dirname(__file__), "README.rst") with open(readme_file) as f: long_description = f.read() setup( - name='django-guardian', + name="django-guardian", version=version, - python_requires='>=3.5', - url='http://github.com/django-guardian/django-guardian', - author='Lukasz Balcerzak', - author_email='lukaszbalcerzak@gmail.com', - download_url='https://github.com/django-guardian/django-guardian/tags', + python_requires=">=3.5", + url="http://github.com/django-guardian/django-guardian", + author="Lukasz Balcerzak", + author_email="lukaszbalcerzak@gmail.com", + download_url="https://github.com/django-guardian/django-guardian/tags", description="Implementation of per object permissions for Django.", long_description=long_description, zip_safe=False, packages=[ - 'guardian', 'guardian.conf', 'guardian.management', - 'guardian.migrations', 'guardian.templatetags', 'guardian.testapp', - 'guardian.management.commands', 'guardian.testapp.migrations', - 'guardian.testapp.tests' + "guardian", + "guardian.conf", + "guardian.management", + "guardian.migrations", + "guardian.templatetags", + "guardian.testapp", + "guardian.management.commands", + "guardian.testapp.migrations", + "guardian.testapp.tests", ], include_package_data=True, - license='BSD', + license="BSD", install_requires=["Django>=2.2"], - tests_require=['mock', 'django-environ', 'pytest', 'pytest-django'], - classifiers=['Development Status :: 5 - Production/Stable', - 'Environment :: Web Environment', - 'Framework :: Django', - 'Framework :: Django :: 2.2', - 'Framework :: Django :: 3.0', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: BSD License', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Topic :: Security', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3 :: Only', - ], - test_suite='tests.main', - cmdclass={'flakes': RunFlakesCommand}, + tests_require=["mock", "django-environ", "pytest", "pytest-django"], + classifiers=[ + "Development Status :: 5 - Production/Stable", + "Environment :: Web Environment", + "Framework :: Django", + "Framework :: Django :: 2.2", + "Framework :: Django :: 3.0", + "Intended Audience :: Developers", + "License :: OSI Approved :: BSD License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Topic :: Security", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3 :: Only", + ], + test_suite="tests.main", + cmdclass={"flakes": RunFlakesCommand}, ) diff --git a/utils.py b/utils.py index 98652aa63..25d378db5 100644 --- a/utils.py +++ b/utils.py @@ -4,22 +4,23 @@ def show_settings(settings, action): guardian_path = guardian.__path__[0] msg = "django-guardian module's path: %r" % guardian_path - print(colorize(msg, fg='magenta')) - db_conf = settings.DATABASES['default'] + print(colorize(msg, fg="magenta")) + db_conf = settings.DATABASES["default"] output = [] - msg = "Starting {} for db backend: {}".format(action, db_conf['ENGINE']) - embracer = '=' * len(msg) + msg = "Starting {} for db backend: {}".format(action, db_conf["ENGINE"]) + embracer = "=" * len(msg) output.append(msg) for key in sorted(db_conf.keys()): - if key == 'PASSWORD': - value = '****************' + if key == "PASSWORD": + value = "****************" else: value = db_conf[key] line = ' {}: "{}"'.format(key, value) output.append(line) - embracer = colorize('=' * len(max(output, key=lambda s: len(s))), - fg='green', opts=['bold']) - output = [colorize(line, fg='blue') for line in output] + embracer = colorize( + "=" * len(max(output, key=lambda s: len(s))), fg="green", opts=["bold"] + ) + output = [colorize(line, fg="blue") for line in output] output.insert(0, embracer) output.append(embracer) - print('\n'.join(output)) + print("\n".join(output))