Skip to content

Commit

Permalink
Add Validators level check in permission (#2345)
Browse files Browse the repository at this point in the history
* Add current validators level while validators

* Add changes in validate api

* Add Global validator permission command

* Permission set for the global validator on validate api

* Change queryset value in group permission

* Fix permission issue on validator check
  • Loading branch information
susilnem committed Jan 7, 2025
1 parent da60bdd commit a326bfb
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 4 deletions.
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")
7 changes: 4 additions & 3 deletions local_units/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@


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:

if user.is_superuser or user.has_perm("local_units.local_unit_global_validator"):
return True
country_admin_ids = [
int(codename.replace("country_admin_", ""))
Expand All @@ -23,7 +24,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
86 changes: 86 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, Permission
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,29 @@ 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()

# Adding permissions to the users
global_validator_permission = Permission.objects.filter(codename="local_unit_global_validator").first()

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()

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

self.global_validator_user.user_permissions.add(global_validator_permission)

def test_create_local_unit_administrative(self):
region = Region.objects.create(name=2)
country = Country.objects.create(
Expand Down Expand Up @@ -624,3 +649,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)
20 changes: 19 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 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,27 @@ 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
if request.user.is_superuser or request.user.has_perm("local_units.local_unit_global_validator"):
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

0 comments on commit a326bfb

Please sign in to comment.