Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature/RR-1343-export-win-admin-user-access #5322

Merged
merged 6 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion datahub/company/admin/adviser.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@

from datahub.company.admin.adviser_forms import AddAdviserFromSSOForm
from datahub.company.models import Advisor
from datahub.core.admin import ExportWinsAdminMixin


@admin.register(Advisor)
class AdviserAdmin(VersionAdmin, UserAdmin):
class AdviserAdmin(ExportWinsAdminMixin, VersionAdmin, UserAdmin):
"""Adviser admin."""

fieldsets = (
Expand Down
57 changes: 55 additions & 2 deletions datahub/core/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
from django.utils.translation import gettext, gettext_lazy
from django.views.decorators.csrf import csrf_exempt, csrf_protect

EXPORT_WIN_GROUP_NAME = 'ExportWinAdmin'


class DisabledOnFilter(admin.SimpleListFilter):
"""This filter allows us to filter values that have disabled_on value."""
Expand Down Expand Up @@ -75,7 +77,44 @@ def has_change_permission(self, request, obj=None):
return False


class BaseModelAdminMixin:
class ExportWinsAdminMixin(admin.ModelAdmin):
def has_module_permission(self, request):
return handle_export_wins_admin_permissions(
request.user,
self.opts.app_label,
super().has_module_permission(request),
)

def has_view_permission(self, request, obj=None):
return handle_export_wins_admin_permissions(
request.user,
self.opts.app_label,
super().has_view_permission(request, obj),
)

def has_add_permission(self, request):
return handle_export_wins_admin_permissions(
request.user,
self.opts.app_label,
super().has_add_permission(request),
)

def has_delete_permission(self, request, obj=None):
return handle_export_wins_admin_permissions(
request.user,
self.opts.app_label,
super().has_delete_permission(request, obj),
)

def has_change_permission(self, request, obj=None):
return handle_export_wins_admin_permissions(
request.user,
self.opts.app_label,
super().has_change_permission(request, obj),
)


class BaseModelAdminMixin(ExportWinsAdminMixin):
"""
Mixin for ModelAdmins which adds extra functionalities.
Useful when the model extends core.BaseModel
Expand Down Expand Up @@ -353,10 +392,24 @@ def pretty_source(self, obj):
return format_html('<pre>{0}</pre>', json.dumps(value, indent=2))


def handle_export_wins_admin_permissions(user, app_label, function):
if not user.is_superuser and user.groups.filter(name=EXPORT_WIN_GROUP_NAME).exists():
if app_label == 'export_win':
return True
return False

return function


def _make_admin_permission_getter(codename):
def _has_permission(self, request, obj=None):

app_label = self.opts.app_label
qualified_name = f'{app_label}.{codename}'
return request.user.has_perm(qualified_name)

return handle_export_wins_admin_permissions(
request.user,
app_label,
request.user.has_perm(qualified_name),
)
return _has_permission
45 changes: 45 additions & 0 deletions datahub/core/test/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from unittest.mock import Mock

import pytest

from django.conf import settings
from django.contrib import auth, messages as django_messages
from django.contrib.admin.templatetags.admin_urls import admin_urlname
Expand All @@ -11,6 +12,7 @@
from faker import Faker
from rest_framework import status

from datahub.company.test.factories import AdviserFactory
from datahub.core.admin import (
custom_add_permission,
custom_change_permission,
Expand All @@ -19,8 +21,10 @@
format_json_as_html,
get_change_link,
get_change_url,
handle_export_wins_admin_permissions,
RawIdWidget,
)
from datahub.core.test.factories import GroupFactory
from datahub.core.test.support.factories import BookFactory
from datahub.core.test.support.models import Book
from datahub.core.test.support.views import MAX_UPLOAD_SIZE
Expand Down Expand Up @@ -338,3 +342,44 @@ def test_admin_account_lock_out_after_too_many_attempts(self):
status.HTTP_403_FORBIDDEN
), (attempt, settings.AXES_FAILURE_LIMIT)
assert auth.get_user(client).is_authenticated is False


@pytest.mark.django_db
class TestHandleExportWinsAdminPermissions:
def test_user_is_not_superuser_not_in_export_wins_group(self):
permission_group = GroupFactory(name='Group')
user = AdviserFactory(is_superuser=False)
user.groups.add(permission_group)
expected_response = 'ABC'

result = handle_export_wins_admin_permissions(user, '', function=expected_response)

assert result == expected_response

def test_user_is_superuser_in_export_wins_group(self):
permission_group = GroupFactory(name='ExportWinAdmin')
user = AdviserFactory(is_superuser=True)
user.groups.add(permission_group)
expected_response = 'ABC'

result = handle_export_wins_admin_permissions(user, '', function=expected_response)

assert result == expected_response

def test_user_is_not_superuser_in_export_wins_group_accessing_export_win_module(self):
permission_group = GroupFactory(name='ExportWinAdmin')
user = AdviserFactory(is_superuser=False)
user.groups.add(permission_group)

result = handle_export_wins_admin_permissions(user, 'export_win', function=None)

assert result is True

def test_user_is_not_superuser_in_export_wins_group_accessing_company_module(self):
permission_group = GroupFactory(name='ExportWinAdmin')
user = AdviserFactory(is_superuser=False)
user.groups.add(permission_group)

result = handle_export_wins_admin_permissions(user, 'company', function=None)

assert result is False
8 changes: 5 additions & 3 deletions datahub/export_win/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
from django.forms import ModelForm
from reversion.admin import VersionAdmin


from datahub.core.admin import BaseModelAdminMixin
from datahub.core.admin import BaseModelAdminMixin, EXPORT_WIN_GROUP_NAME

from datahub.export_win.models import Breakdown, CustomerResponse, DeletedWin, Win, WinAdviser

Expand Down Expand Up @@ -265,6 +264,9 @@ def has_change_permission(self, request, obj=None):

def has_view_permission(self, request, obj=None):
"""Set the desired user group to access view deleted win"""
if request.user.is_superuser or request.user.groups.filter(name='ExportWinAdmin').exists():
if (
request.user.is_superuser
or request.user.groups.filter(name=EXPORT_WIN_GROUP_NAME).exists()
):
return True
return False
4 changes: 3 additions & 1 deletion datahub/investment/investor_profile/admin.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from django.contrib import admin

from datahub.core.admin import ExportWinsAdminMixin

from datahub.investment.investor_profile import models


@admin.register(models.LargeCapitalInvestorProfile)
class LargeCapitalInvestorProfileAdmin(admin.ModelAdmin):
class LargeCapitalInvestorProfileAdmin(ExportWinsAdminMixin, admin.ModelAdmin):
"""Large capital investor profile admin."""

autocomplete_fields = (
Expand Down
4 changes: 3 additions & 1 deletion datahub/investment/opportunity/admin.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from django.contrib import admin

from datahub.core.admin import ExportWinsAdminMixin

from datahub.investment.opportunity import models


@admin.register(models.LargeCapitalOpportunity)
class LargeCapitalOpportunityAdmin(admin.ModelAdmin):
class LargeCapitalOpportunityAdmin(ExportWinsAdminMixin, admin.ModelAdmin):
"""Large capital opportunity admin."""

autocomplete_fields = (
Expand Down
Loading