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

Add Validators level check in permission #2345

Merged
merged 6 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import logging

from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
from django.core.management.base import BaseCommand

from local_units.models import LocalUnit

logger = logging.getLogger(__name__)


class Command(BaseCommand):
help = "Create standard local unit global validator permission class and group"

def handle(self, *args, **options):
logger.info("Creating/Updating permissions/groups for local unit global validator")
print("- Creating/Updating permissions/groups for local unit global validator")
codename = ("local_unit_global_validator",)
content_type = ContentType.objects.get_for_model(LocalUnit)
permission, created = Permission.objects.get_or_create(
codename=codename,
name="Local Unit Global Validator",
content_type=content_type,
)

# If it's a new permission, create a group for it
group, created = Group.objects.get_or_create(name="Local Unit Global Validators")
group.permissions.add(permission)
logger.info("Local unit global validator permission and group created")
19 changes: 15 additions & 4 deletions local_units/permissions.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
from django.contrib.auth.models import Permission
from django.contrib.auth.models import Group, Permission
from rest_framework import permissions


class ValidateLocalUnitPermission(permissions.BasePermission):
message = "You need to be super user/ country admin/ region admin to validate local unit"
message = "You need to be super user/ global validator/ region admin/ country admin to validate local unit"

def has_object_permission(self, request, view, object):
user = request.user
if user.is_superuser:

# Check if user is superuser or in Local Unit Global Validators group
group_queryset = (
Group.objects.filter(
name="Local Unit Global Validators",
user=user,
)
.values_list("id", flat=True)
.first()
thenav56 marked this conversation as resolved.
Show resolved Hide resolved
)

if user.is_superuser or group_queryset:
return True
country_admin_ids = [
int(codename.replace("country_admin_", ""))
Expand All @@ -23,7 +34,7 @@ def has_object_permission(self, request, view, object):
codename__startswith="region_admin_",
).values_list("codename", flat=True)
]
if object.country_id in country_admin_ids or object.region_id in region_admin_ids:
if object.country_id in country_admin_ids or object.country.region_id in region_admin_ids:
return True
return False

Expand Down
85 changes: 85 additions & 0 deletions local_units/test_views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import datetime

import factory
from django.contrib.auth.models import Group
from django.contrib.gis.geos import Point
from django.core import management
from factory import fuzzy

from api.models import Country, Region
Expand Down Expand Up @@ -308,6 +310,28 @@ def test_detail(self):

class TestLocalUnitCreate(APITestCase):

def setUp(self):
super().setUp()
self.region = Region.objects.create(name=2)
self.country = Country.objects.create(name="Nepal", iso3="NLP", region=self.region)
management.call_command("make_permissions")
management.call_command("make_global_validator_permission")

# Permissions and different validators
self.global_validator_user = UserFactory.create()
self.local_unit_admin_user = UserFactory.create()
self.regional_validator_user = UserFactory.create()

country_group = Group.objects.filter(name="%s Admins" % self.country.name).first()
region_group = Group.objects.filter(name="%s Regional Admins" % self.region.name).first()
global_validator_group = Group.objects.filter(name="Local Unit Global Validators").first()

self.local_unit_admin_user.groups.add(country_group)
self.regional_validator_user.groups.add(region_group)

# Adding global validator permission to global validator
self.global_validator_user.groups.add(global_validator_group)

def test_create_local_unit_administrative(self):
region = Region.objects.create(name=2)
country = Country.objects.create(
Expand Down Expand Up @@ -624,3 +648,64 @@ def test_latest_changes(self):
self.assert_200(response)
self.assertEqual(response.data["previous_data_details"]["local_branch_name"], previous_data["local_branch_name"])
self.assertEqual(response.data["previous_data_details"]["english_branch_name"], previous_data["english_branch_name"])

def test_validate_local_unit(self):
type = LocalUnitType.objects.create(code=0, name="Code 0")
data = {
"local_branch_name": "Silele Red Cross Clinic, Sigombeni Red Cross Clinic & Mahwalala Red Cross Clinic",
"english_branch_name": None,
"type": type.id,
"country": self.country.id,
"date_of_data": "2024-05-13",
"location_json": {
"lat": 42.066667,
"lng": 19.983333,
},
}
self.authenticate()
response = self.client.post("/api/v2/local-units/", data=data, format="json")
self.assert_201(response)

local_unit_id = response.data["id"]
# Testing For the local unit Global validator
self.authenticate(self.global_validator_user)
# validating the local unit by the Global validator
response = self.client.post(f"/api/v2/local-units/{local_unit_id}/validate/")
self.assert_200(response)
local_unit_request = LocalUnitChangeRequest.objects.filter(
local_unit=local_unit_id, status=LocalUnitChangeRequest.Status.APPROVED
).last()
self.assertEqual(local_unit_request.current_validator, LocalUnitChangeRequest.Validator.GLOBAL)

# Testing For the local unit admin/Local validator
self.authenticate(self.local_unit_admin_user)
response = self.client.put(f"/api/v2/local-units/{local_unit_id}/", data=data, format="json")
self.assert_200(response)
# validating the local unit by the local unit admin
response = self.client.post(f"/api/v2/local-units/{local_unit_id}/validate/")
local_unit_request = LocalUnitChangeRequest.objects.filter(
local_unit=local_unit_id, status=LocalUnitChangeRequest.Status.APPROVED
).last()
self.assertEqual(local_unit_request.current_validator, LocalUnitChangeRequest.Validator.LOCAL)

# Testing For the regional validator
self.authenticate(self.regional_validator_user)
response = self.client.put(f"/api/v2/local-units/{local_unit_id}/", data=data, format="json")
self.assert_200(response)
# validating the local unit by the regional validator
response = self.client.post(f"/api/v2/local-units/{local_unit_id}/validate/")
local_unit_request = LocalUnitChangeRequest.objects.filter(
local_unit=local_unit_id, status=LocalUnitChangeRequest.Status.APPROVED
).last()
self.assertEqual(local_unit_request.current_validator, LocalUnitChangeRequest.Validator.REGIONAL)

# Testing for Root User/Global validator
self.authenticate(self.root_user)
response = self.client.put(f"/api/v2/local-units/{local_unit_id}/", data=data, format="json")
self.assert_200(response)
# validating the local unit by the global validator
response = self.client.post(f"/api/v2/local-units/{local_unit_id}/validate/")
local_unit_request = LocalUnitChangeRequest.objects.filter(
local_unit=local_unit_id, status=LocalUnitChangeRequest.Status.APPROVED
).last()
self.assertEqual(local_unit_request.current_validator, LocalUnitChangeRequest.Validator.GLOBAL)
Rup-Narayan-Rajbanshi marked this conversation as resolved.
Show resolved Hide resolved
28 changes: 27 additions & 1 deletion local_units/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.contrib.auth.models import Group, Permission
from django.shortcuts import get_object_or_404
from django.utils import timezone
from drf_spectacular.utils import extend_schema
Expand Down Expand Up @@ -121,10 +122,35 @@ def get_validate(self, request, pk=None, version=None):
if not change_request_instance:
return bad_request("No change request found to validate")

# Checking the validator type

validator = LocalUnitChangeRequest.Validator.LOCAL
group_queryset = (
Group.objects.filter(
name="Local Unit Global Validators",
user=request.user,
)
.values_list("id", flat=True)
.first()
)
if request.user.is_superuser or group_queryset:
validator = LocalUnitChangeRequest.Validator.GLOBAL
else:
region_admin_ids = [
int(codename.replace("region_admin_", ""))
for codename in Permission.objects.filter(
group__user=request.user,
codename__startswith="region_admin_",
).values_list("codename", flat=True)
]
if local_unit.country.region_id in region_admin_ids:
validator = LocalUnitChangeRequest.Validator.REGIONAL

change_request_instance.current_validator = validator
change_request_instance.status = LocalUnitChangeRequest.Status.APPROVED
change_request_instance.updated_by = request.user
change_request_instance.updated_at = timezone.now()
change_request_instance.save(update_fields=["status", "updated_by", "updated_at"])
change_request_instance.save(update_fields=["status", "updated_by", "updated_at", "current_validator"])

# Validate the local unit
local_unit.validated = True
Expand Down
Loading