To protect your data, the CISO officer has suggested users to enable GitLab 2FA as soon as possible.

Commit 907e1846 authored by Lincoln Smith's avatar Lincoln Smith
Browse files

Flake8 and unneeded admin UserAdmin override.

parent e90ef68b
......@@ -2,12 +2,9 @@ from django.contrib import admin
from django.contrib import messages
from django.db import transaction
from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.models import Permission, User
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import Permission
from django.conf.urls import url
from django.core.exceptions import (ValidationError, ObjectDoesNotExist,
PermissionDenied, FieldError)
from django.core.exceptions import ValidationError, ObjectDoesNotExist, PermissionDenied
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db.models import Q
from django.template.response import TemplateResponse
......@@ -15,8 +12,7 @@ from functools import update_wrapper
from perfieldperms import forms
from perfieldperms import models
from perfieldperms.utils import (list_fields_for_ctype, get_non_pfp_perms,
get_m2m_remote_fields, get_manager_name, disable_fields)
from perfieldperms.utils import get_m2m_remote_fields, get_manager_name, disable_fields
class PFPModelAdminMixin(admin.ModelAdmin):
......@@ -59,12 +55,12 @@ class PerFieldPermissionAdmin(admin.ModelAdmin):
initial = {}
if request.method == 'GET':
init_data = self.get_changeform_initial_data(request)
elif request.method == 'POST':
elif request.method == 'POST':
init_data = request.POST.copy()
# Stick the GET or POST data into the form to validate it, and if it
# validates grab the cleaned data from the required fields which we'll
# use to populate the non-required fields later on
init_data = {k:v for k, v in init_data.items() if k in required_fields}
init_data = {k: v for k, v in init_data.items() if k in required_fields}
init_form = forms.PFPPermFilterForm(data=init_data)
if init_form.is_bound and init_form.is_valid():
initial['model'] = init_form.cleaned_data['model']
......@@ -141,25 +137,24 @@ class PerFieldPermissionAdmin(admin.ModelAdmin):
user_model = get_user_model()
remote_fields = get_m2m_remote_fields(Permission, role_class)
if len(remote_fields) != 1:
raise ValidationError('The role type selected has no, or multiple '
'relations to the Permissions model. Expected to find one.'
)
raise ValidationError('The role type selected has no, or multiple relations to the '
'Permissions model. Expected to find one.')
else:
role_related_query = remote_fields[0].name
initial = []
all_roles = role_class.objects.all().order_by()
# Paginate list of roles
paginator = Paginator(all_roles, 25)
page = request.GET.get('page')
try:
roles = paginator.page(page)
except PageNotAnInteger:
roles = paginator.page(1)
roles = paginator.page(1)
except EmptyPage:
roles = paginator.page(paginator.num_pages)
for role in roles:
perms = perms_qs.filter(**{role_related_query: role}).order_by()
if role_class == user_model:
......@@ -180,11 +175,10 @@ class PerFieldPermissionAdmin(admin.ModelAdmin):
"""
Add and remove permissions based on form submission.
Since it's possible users have been added/removed since the list of
users was loaded, some forms in the formset may have IDs that don't
match with what was loaded when the user last accessed the form. Skip
the user as it would be a pain to try and match them up to an entry in
the new list of users.
Since it's possible users have been added/removed since the list of users was loaded, some
forms in the formset may have IDs that don't match with what was loaded when the user last
accessed the form. Skip the user as it would be a pain to try and match them up to an entry
in the new list of users.
"""
if perm_formset.forms:
perms_offered = perm_formset.forms[0].fields['permissions'].queryset
......@@ -194,10 +188,12 @@ class PerFieldPermissionAdmin(admin.ModelAdmin):
for form in perm_formset.forms:
if form.has_changed() and 'permissions' in form.changed_data:
if 'role_id' in form.changed_data:
messages.warning(request, 'Permissions for {} were not '
'updated due to database changes since loading '
'the form. Please try again.'.format(
form.cleaned_data['role_name'])
messages.warning(
request,
'Permissions for {} were not updated due to database changes since '
'loading the form. Please try again.'.format(
form.cleaned_data['role_name']
),
)
continue
......@@ -206,9 +202,10 @@ class PerFieldPermissionAdmin(admin.ModelAdmin):
try:
role = role_class.objects.get(id=role_id)
except ObjectDoesNotExist:
messages.error(request, 'Permissions for {} were not '
'updated because the role could not be '
'found.'.format(form.cleaned_data['role_name'])
messages.error(
request,
'Permissions for {} were not updated because the role could not be '
'found.'.format(form.cleaned_data['role_name']),
)
continue
......@@ -224,12 +221,14 @@ class PerFieldPermissionAdmin(admin.ModelAdmin):
perm_manager.remove(*del_perms)
perm_manager.add(*add_perms)
messages.success(request, 'Permissions for {} were changed. '
'Added: {}. Removed: {}.'.format(
form.cleaned_data['role_name'],
len(add_perms),
len(del_perms),
))
messages.success(
request,
'Permissions for {} were changed. Added: {}. Removed: {}.'.format(
form.cleaned_data['role_name'],
len(add_perms),
len(del_perms),
)
)
def manage_view(self, request):
"""
......@@ -240,7 +239,7 @@ class PerFieldPermissionAdmin(admin.ModelAdmin):
raise PermissionDenied
context = {}
template ='{}/perfieldperm_manage.html'.format(
template = '{}/perfieldperm_manage.html'.format(
self.model._meta.app_label)
page = None
initial = self._get_filter_form_initial(request)
......@@ -249,7 +248,7 @@ class PerFieldPermissionAdmin(admin.ModelAdmin):
role_filter_form = forms.PFPRoleFilterForm(initial=initial, data=data)
if ((role_filter_form.is_bound and role_filter_form.is_valid())
and
and
(perm_filter_form.is_bound and perm_filter_form.is_valid())):
# Filter forms are valid so see if we have a valid selection form
clean_data = perm_filter_form.cleaned_data.copy()
......@@ -273,8 +272,8 @@ class PerFieldPermissionAdmin(admin.ModelAdmin):
if perm_formset.is_bound and perm_formset.is_valid():
self._process_perm_forms(request, clean_data, perm_formset)
except ValidationError:
messages.error(request, 'The form failed to validate, '
'probably due to changes to filter settings.')
messages.error(request, 'The form failed to validate, probably due to changes '
'to filter settings.')
else:
perm_formset = PermSelectFormSet(initial=perm_select_initial)
context['perm_formset'] = perm_formset
......@@ -311,19 +310,15 @@ class PerFieldPermissionAdmin(admin.ModelAdmin):
]
return urls + super().get_urls()
admin.site.register(models.PerFieldPermission, PerFieldPermissionAdmin)
@admin.register(models.PFPContentType)
class PFPContentTypeAdmin(admin.ModelAdmin):
form = forms.PFPContentTypesForm
@admin.register(models.PFPRoleType)
class PFPRoleTypeAdmin(admin.ModelAdmin):
form = forms.PFPRoleTypesForm
admin.site.unregister(User)
@admin.register(User)
class PFPUserAdmin(PFPModelAdminMixin, admin.ModelAdmin):
pass
......@@ -5,5 +5,6 @@ from django.apps import AppConfig
# ContentType of which the user object is a member.
# [('myapp.modelname', myapp.module.get_role_ids(user_obj=user_obj))]
class PerfieldpermsConfig(AppConfig):
name = 'perfieldperms'
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group, Permission
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import Permission
from django.core.exceptions import ObjectDoesNotExist
from perfieldperms.models import PerFieldPermission
......@@ -41,7 +41,7 @@ class PFPBackend(object):
"""
perm_sets = dict()
for perm in ['{}.{}'.format(ct, name) for ct, name in perms]:
perm_sets[perm]=set()
perm_sets[perm] = set()
return perm_sets
def _update_perm_sets(self, pfps, perm_sets=None):
......@@ -92,7 +92,7 @@ class PFPBackend(object):
}).values_list('content_type__app_label', 'codename')
perm_sets = self._create_perm_sets(perms)
pfps = PerFieldPermission.objects.filter(
**{user_groups_query:user_obj}
**{user_groups_query: user_obj}
).values_list(
'content_type__app_label',
'codename',
......@@ -119,11 +119,10 @@ class PFPBackend(object):
).values_list('content_type__app_label', 'codename')
perm_sets = self._create_perm_sets(perms)
else:
perm_sets = getattr(self,'_get_{}_permissions'.format(from_name))(user_obj)
perm_sets = getattr(self, '_get_{}_permissions'.format(from_name))(user_obj)
setattr(user_obj, cache_name, perm_sets)
return self._cache_to_set(getattr(user_obj, cache_name))
def get_user_permissions(self, user_obj, obj=None):
"""Get permissions granted only to this user."""
return self._get_permissions(user_obj, obj, 'user')
......@@ -147,7 +146,7 @@ class PFPBackend(object):
user_obj._pfp_perm_cache = user_obj._pfp_group_perm_cache.copy()
user_obj._pfp_perm_cache.update(user_obj._pfp_user_perm_cache)
# The below will merge caches instead of overwriting
#user_obj._pfp_perm_cache = self._merge_caches(
# user_obj._pfp_perm_cache = self._merge_caches(
# user_obj._pfp_perm_cache,
# user_obj._pfp_user_perm_cache,
# )
......@@ -203,7 +202,7 @@ class PFPBackend(object):
perm = PerFieldPermission.objects.get(
content_type__app_label=app_label,
codename=codename,
)
)
except ObjectDoesNotExist:
perm = Permission.objects.get(
content_type__app_label=app_label,
......@@ -224,5 +223,3 @@ class PFPBackend(object):
self.get_all_permissions(user_obj, obj)
cache = user_obj._pfp_perm_cache
return perm_key in cache and not cache[perm_key]
......@@ -3,11 +3,10 @@ from django.db.models import Q
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission
from django.template.defaultfilters import title
from perfieldperms.models import PFPContentType, PFPRoleType, PerFieldPermission
from perfieldperms.utils import list_fields_for_ctype, get_non_pfp_perms
def pfp_perm_select_form_factory(permissions_qs):
"""
Generate a form with options for permissions that depend on what
......
......@@ -3,6 +3,7 @@ from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError, ObjectDoesNotExist
class PFPContentType(models.Model):
"""ContentTypes to creat PerFieldPermissions for."""
content_type = models.OneToOneField(ContentType, unique=True)
......@@ -40,7 +41,7 @@ class PerFieldPermission(Permission):
)
class Meta:
permissions = (('manage_permissions','Can manage permissions'),)
permissions = (('manage_permissions', 'Can manage permissions'),)
def clean(self):
"""Ensure a PFP has the same ContentType as its parent Permission."""
......@@ -62,8 +63,7 @@ class PerFieldPermission(Permission):
except ObjectDoesNotExist:
return
if ((hasattr(self, 'id') and self.id != perm.id)
if ((hasattr(self, 'id') and self.id != perm.id)
or not hasattr(self, 'id')):
raise ValidationError("""Only one PerFieldPermission allowed for
each model permission/field combination.""")
......@@ -5,6 +5,7 @@ from django.template.defaultfilters import title
from perfieldperms.models import PerFieldPermission
def get_m2m_remote_fields(src_model, tgt_model):
"""
Get a list of fields on `tgt_model` that are part of a m2m relationship
......@@ -12,11 +13,12 @@ def get_m2m_remote_fields(src_model, tgt_model):
"""
return [
field for field in src_model._meta.get_fields()
if (field.is_relation
if (field.is_relation
and field.many_to_many
and field.related_model == tgt_model)
]
def get_manager_name(src_model, tgt_model):
"""
Get the name of the manager for an m2m relationship from `src_model` to
......@@ -27,6 +29,7 @@ def get_manager_name(src_model, tgt_model):
return fields[0].name
return None
def get_non_pfp_perms(content_type):
"""Get all model level Permission objects for `content_type`."""
return Permission.objects.filter(
......@@ -34,17 +37,19 @@ def get_non_pfp_perms(content_type):
perfieldpermission__isnull=True,
)
def list_fields_for_model(model):
"""
Get a list of (name, verbose_name) tuples of concrete fields for `model`
which is a subclass of django.db.models.Model.
"""
return [
(field.name, title(field.verbose_name))
for field in model._meta.get_fields()
if not field.auto_created # or field.concrete
(field.name, title(field.verbose_name))
for field in model._meta.get_fields()
if not field.auto_created # or field.concrete
]
def list_fields_for_ctype(content_type):
"""
Get a list of (name, verbose_name) tuples of concrete fields from a
......@@ -55,6 +60,7 @@ def list_fields_for_ctype(content_type):
model = content_type.model_class()
return list_fields_for_model(model)
def disable_fields(request, model, obj, form, perm=None):
"""
Disable the fields in `form` which the user from `request` doesn't have
......@@ -89,7 +95,5 @@ def disable_fields(request, model, obj, form, perm=None):
for fname, field in form.base_fields.items():
if fname not in pfps:
field.disabled = True
field.help_text = ('This field is disabled as you lack '
'required permissions.')
field.help_text = ('This field is disabled as you lack required permissions.')
return form
File mode changed from 100644 to 100755
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment