Skip to content

Commit b8cc17d

Browse files
committed
Add Validators level check in permission (#2345)
* 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
1 parent 32af3d4 commit b8cc17d

File tree

4 files changed

+138
-4
lines changed

4 files changed

+138
-4
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import logging
2+
3+
from django.contrib.auth.models import Group, Permission
4+
from django.contrib.contenttypes.models import ContentType
5+
from django.core.management.base import BaseCommand
6+
7+
from local_units.models import LocalUnit
8+
9+
logger = logging.getLogger(__name__)
10+
11+
12+
class Command(BaseCommand):
13+
help = "Create standard local unit global validator permission class and group"
14+
15+
def handle(self, *args, **options):
16+
logger.info("Creating/Updating permissions/groups for local unit global validator")
17+
print("- Creating/Updating permissions/groups for local unit global validator")
18+
codename = "local_unit_global_validator"
19+
content_type = ContentType.objects.get_for_model(LocalUnit)
20+
permission, created = Permission.objects.get_or_create(
21+
codename=codename,
22+
name="Local Unit Global Validator",
23+
content_type=content_type,
24+
)
25+
26+
# If it's a new permission, create a group for it
27+
group, created = Group.objects.get_or_create(name="Local Unit Global Validators")
28+
group.permissions.add(permission)
29+
logger.info("Local unit global validator permission and group created")

local_units/permissions.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33

44

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

88
def has_object_permission(self, request, view, object):
99
user = request.user
10-
if user.is_superuser:
10+
11+
if user.is_superuser or user.has_perm("local_units.local_unit_global_validator"):
1112
return True
1213
country_admin_ids = [
1314
int(codename.replace("country_admin_", ""))
@@ -23,7 +24,7 @@ def has_object_permission(self, request, view, object):
2324
codename__startswith="region_admin_",
2425
).values_list("codename", flat=True)
2526
]
26-
if object.country_id in country_admin_ids or object.region_id in region_admin_ids:
27+
if object.country_id in country_admin_ids or object.country.region_id in region_admin_ids:
2728
return True
2829
return False
2930

local_units/test_views.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import datetime
22

33
import factory
4+
from django.contrib.auth.models import Group, Permission
45
from django.contrib.gis.geos import Point
6+
from django.core import management
57
from factory import fuzzy
68

79
from api.models import Country, Region
@@ -308,6 +310,29 @@ def test_detail(self):
308310

309311
class TestLocalUnitCreate(APITestCase):
310312

313+
def setUp(self):
314+
super().setUp()
315+
self.region = Region.objects.create(name=2)
316+
self.country = Country.objects.create(name="Nepal", iso3="NLP", region=self.region)
317+
management.call_command("make_permissions")
318+
management.call_command("make_global_validator_permission")
319+
320+
# Permissions and different validators
321+
self.global_validator_user = UserFactory.create()
322+
self.local_unit_admin_user = UserFactory.create()
323+
self.regional_validator_user = UserFactory.create()
324+
325+
# Adding permissions to the users
326+
global_validator_permission = Permission.objects.filter(codename="local_unit_global_validator").first()
327+
328+
country_group = Group.objects.filter(name="%s Admins" % self.country.name).first()
329+
region_group = Group.objects.filter(name="%s Regional Admins" % self.region.name).first()
330+
331+
self.local_unit_admin_user.groups.add(country_group)
332+
self.regional_validator_user.groups.add(region_group)
333+
334+
self.global_validator_user.user_permissions.add(global_validator_permission)
335+
311336
def test_create_local_unit_administrative(self):
312337
region = Region.objects.create(name=2)
313338
country = Country.objects.create(
@@ -624,3 +649,64 @@ def test_latest_changes(self):
624649
self.assert_200(response)
625650
self.assertEqual(response.data["previous_data_details"]["local_branch_name"], previous_data["local_branch_name"])
626651
self.assertEqual(response.data["previous_data_details"]["english_branch_name"], previous_data["english_branch_name"])
652+
653+
def test_validate_local_unit(self):
654+
type = LocalUnitType.objects.create(code=0, name="Code 0")
655+
data = {
656+
"local_branch_name": "Silele Red Cross Clinic, Sigombeni Red Cross Clinic & Mahwalala Red Cross Clinic",
657+
"english_branch_name": None,
658+
"type": type.id,
659+
"country": self.country.id,
660+
"date_of_data": "2024-05-13",
661+
"location_json": {
662+
"lat": 42.066667,
663+
"lng": 19.983333,
664+
},
665+
}
666+
self.authenticate()
667+
response = self.client.post("/api/v2/local-units/", data=data, format="json")
668+
self.assert_201(response)
669+
670+
local_unit_id = response.data["id"]
671+
# Testing For the local unit Global validator
672+
self.authenticate(self.global_validator_user)
673+
# validating the local unit by the Global validator
674+
response = self.client.post(f"/api/v2/local-units/{local_unit_id}/validate/")
675+
self.assert_200(response)
676+
local_unit_request = LocalUnitChangeRequest.objects.filter(
677+
local_unit=local_unit_id, status=LocalUnitChangeRequest.Status.APPROVED
678+
).last()
679+
self.assertEqual(local_unit_request.current_validator, LocalUnitChangeRequest.Validator.GLOBAL)
680+
681+
# Testing For the local unit admin/Local validator
682+
self.authenticate(self.local_unit_admin_user)
683+
response = self.client.put(f"/api/v2/local-units/{local_unit_id}/", data=data, format="json")
684+
self.assert_200(response)
685+
# validating the local unit by the local unit admin
686+
response = self.client.post(f"/api/v2/local-units/{local_unit_id}/validate/")
687+
local_unit_request = LocalUnitChangeRequest.objects.filter(
688+
local_unit=local_unit_id, status=LocalUnitChangeRequest.Status.APPROVED
689+
).last()
690+
self.assertEqual(local_unit_request.current_validator, LocalUnitChangeRequest.Validator.LOCAL)
691+
692+
# Testing For the regional validator
693+
self.authenticate(self.regional_validator_user)
694+
response = self.client.put(f"/api/v2/local-units/{local_unit_id}/", data=data, format="json")
695+
self.assert_200(response)
696+
# validating the local unit by the regional validator
697+
response = self.client.post(f"/api/v2/local-units/{local_unit_id}/validate/")
698+
local_unit_request = LocalUnitChangeRequest.objects.filter(
699+
local_unit=local_unit_id, status=LocalUnitChangeRequest.Status.APPROVED
700+
).last()
701+
self.assertEqual(local_unit_request.current_validator, LocalUnitChangeRequest.Validator.REGIONAL)
702+
703+
# Testing for Root User/Global validator
704+
self.authenticate(self.root_user)
705+
response = self.client.put(f"/api/v2/local-units/{local_unit_id}/", data=data, format="json")
706+
self.assert_200(response)
707+
# validating the local unit by the global validator
708+
response = self.client.post(f"/api/v2/local-units/{local_unit_id}/validate/")
709+
local_unit_request = LocalUnitChangeRequest.objects.filter(
710+
local_unit=local_unit_id, status=LocalUnitChangeRequest.Status.APPROVED
711+
).last()
712+
self.assertEqual(local_unit_request.current_validator, LocalUnitChangeRequest.Validator.GLOBAL)

local_units/views.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from django.contrib.auth.models import Permission
12
from django.shortcuts import get_object_or_404
23
from django.utils import timezone
34
from drf_spectacular.utils import extend_schema
@@ -121,10 +122,27 @@ def get_validate(self, request, pk=None, version=None):
121122
if not change_request_instance:
122123
return bad_request("No change request found to validate")
123124

125+
# Checking the validator type
126+
127+
validator = LocalUnitChangeRequest.Validator.LOCAL
128+
if request.user.is_superuser or request.user.has_perm("local_units.local_unit_global_validator"):
129+
validator = LocalUnitChangeRequest.Validator.GLOBAL
130+
else:
131+
region_admin_ids = [
132+
int(codename.replace("region_admin_", ""))
133+
for codename in Permission.objects.filter(
134+
group__user=request.user,
135+
codename__startswith="region_admin_",
136+
).values_list("codename", flat=True)
137+
]
138+
if local_unit.country.region_id in region_admin_ids:
139+
validator = LocalUnitChangeRequest.Validator.REGIONAL
140+
141+
change_request_instance.current_validator = validator
124142
change_request_instance.status = LocalUnitChangeRequest.Status.APPROVED
125143
change_request_instance.updated_by = request.user
126144
change_request_instance.updated_at = timezone.now()
127-
change_request_instance.save(update_fields=["status", "updated_by", "updated_at"])
145+
change_request_instance.save(update_fields=["status", "updated_by", "updated_at", "current_validator"])
128146

129147
# Validate the local unit
130148
local_unit.validated = True

0 commit comments

Comments
 (0)