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 nurse user type #1819

Merged
merged 10 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
28 changes: 14 additions & 14 deletions care/facility/api/viewsets/bed.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,20 @@
search_fields = ["name"]
filterset_class = BedFilter

def get_queryset(self):
user = self.request.user
queryset = self.queryset

Check warning on line 64 in care/facility/api/viewsets/bed.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/viewsets/bed.py#L63-L64

Added lines #L63 - L64 were not covered by tests
if user.is_superuser:
pass

Check warning on line 66 in care/facility/api/viewsets/bed.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/viewsets/bed.py#L66

Added line #L66 was not covered by tests
elif user.user_type >= User.TYPE_VALUE_MAP["StateLabAdmin"]:
queryset = queryset.filter(facility__state=user.state)

Check warning on line 68 in care/facility/api/viewsets/bed.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/viewsets/bed.py#L68

Added line #L68 was not covered by tests
elif user.user_type >= User.TYPE_VALUE_MAP["DistrictLabAdmin"]:
queryset = queryset.filter(facility__district=user.district)

Check warning on line 70 in care/facility/api/viewsets/bed.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/viewsets/bed.py#L70

Added line #L70 was not covered by tests
else:
allowed_facilities = get_accessible_facilities(user)
queryset = queryset.filter(facility__id__in=allowed_facilities)
return queryset

Check warning on line 74 in care/facility/api/viewsets/bed.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/viewsets/bed.py#L72-L74

Added lines #L72 - L74 were not covered by tests

def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
Expand All @@ -83,20 +97,6 @@
serializer.data, status=status.HTTP_201_CREATED, headers=headers
)

def get_queryset(self):
user = self.request.user
queryset = self.queryset
if user.is_superuser:
pass
elif user.user_type >= User.TYPE_VALUE_MAP["StateLabAdmin"]:
queryset = queryset.filter(facility__state=user.state)
elif user.user_type >= User.TYPE_VALUE_MAP["DistrictLabAdmin"]:
queryset = queryset.filter(facility__district=user.district)
else:
allowed_facilities = get_accessible_facilities(user)
queryset = queryset.filter(facility__id__in=allowed_facilities)
return queryset

def destroy(self, request, *args, **kwargs):
if request.user.user_type < User.TYPE_VALUE_MAP["DistrictLabAdmin"]:
raise PermissionDenied()
Expand Down
13 changes: 12 additions & 1 deletion care/facility/api/viewsets/file_upload.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django_filters import rest_framework as filters
from rest_framework.exceptions import ValidationError
from rest_framework.exceptions import PermissionDenied, ValidationError
from rest_framework.mixins import (
CreateModelMixin,
DestroyModelMixin,
Expand All @@ -18,6 +18,7 @@
check_permissions,
)
from care.facility.models.file_upload import FileUpload
from care.users.models import User


class FileUploadFilter(filters.FilterSet):
Expand Down Expand Up @@ -54,6 +55,16 @@
def get_queryset(self):
if "file_type" not in self.request.GET:
raise ValidationError({"file_type": "file_type missing in request params"})

if self.request.user.user_type in (
sainak marked this conversation as resolved.
Show resolved Hide resolved
User.TYPE_VALUE_MAP["StaffReadOnly"],
User.TYPE_VALUE_MAP["Staff"],
) and self.request.query_params.get("file_type") in (
"PATIENT",
"CONSULTATION",
):
raise PermissionDenied()

Check warning on line 66 in care/facility/api/viewsets/file_upload.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/viewsets/file_upload.py#L66

Added line #L66 was not covered by tests

if "associating_id" not in self.request.GET:
raise ValidationError(
{"associating_id": "associating_id missing in request params"}
Expand Down
12 changes: 8 additions & 4 deletions care/facility/api/viewsets/hospital_doctor.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from care.facility.api.viewsets import FacilityBaseViewset
from care.facility.models import Facility, HospitalDoctors
from care.users.models import User
from care.utils.cache.cache_allowed_facilities import get_accessible_facilities


class HospitalDoctorViewSet(FacilityBaseViewset, ListModelMixin):
Expand All @@ -24,12 +25,15 @@
facility__external_id=self.kwargs.get("facility_external_id")
)
if user.is_superuser:
return queryset
pass

Check warning on line 28 in care/facility/api/viewsets/hospital_doctor.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/viewsets/hospital_doctor.py#L28

Added line #L28 was not covered by tests
elif self.request.user.user_type >= User.TYPE_VALUE_MAP["StateLabAdmin"]:
return queryset.filter(facility__state=user.state)
queryset = queryset.filter(facility__state=user.state)

Check warning on line 30 in care/facility/api/viewsets/hospital_doctor.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/viewsets/hospital_doctor.py#L30

Added line #L30 was not covered by tests
elif self.request.user.user_type >= User.TYPE_VALUE_MAP["DistrictLabAdmin"]:
return queryset.filter(facility__district=user.district)
return queryset.filter(facility__users__id__exact=user.id)
queryset = queryset.filter(facility__district=user.district)

Check warning on line 32 in care/facility/api/viewsets/hospital_doctor.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/viewsets/hospital_doctor.py#L32

Added line #L32 was not covered by tests
else:
allowed_facilities = get_accessible_facilities(user)
queryset = queryset.filter(facility__id__in=allowed_facilities)
return queryset

Check warning on line 36 in care/facility/api/viewsets/hospital_doctor.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/viewsets/hospital_doctor.py#L34-L36

Added lines #L34 - L36 were not covered by tests

def get_object(self):
return get_object_or_404(self.get_queryset(), area=self.kwargs.get("pk"))
Expand Down
5 changes: 4 additions & 1 deletion care/facility/api/viewsets/notification.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from drf_spectacular.utils import extend_schema, inline_serializer
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.exceptions import PermissionDenied, ValidationError
from rest_framework.generics import get_object_or_404
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin, UpdateModelMixin
from rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly
Expand All @@ -13,6 +13,7 @@

from care.facility.api.serializers.notification import NotificationSerializer
from care.facility.models.notification import Notification
from care.users.models import User
from care.utils.filters.choicefilter import CareChoiceFilter, inverse_choices
from care.utils.notification_handler import NotificationGenerator
from care.utils.queryset.facility import get_facility_queryset
Expand Down Expand Up @@ -67,6 +68,8 @@
@action(detail=False, methods=["POST"])
def notify(self, request, *args, **kwargs):
user = request.user
if user.user_type < User.TYPE_VALUE_MAP["Doctor"]:
raise PermissionDenied()

Check warning on line 72 in care/facility/api/viewsets/notification.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/viewsets/notification.py#L72

Added line #L72 was not covered by tests
if "facility" not in request.data or request.data["facility"] == "":
raise ValidationError({"facility": "is required"})
if "message" not in request.data or request.data["message"] == "":
Expand Down
6 changes: 6 additions & 0 deletions care/facility/api/viewsets/patient_external_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@
parser_classes = (MultiPartParser, FormParser, JSONParser)

def get_queryset(self):
if self.request.user.user_type in (
User.TYPE_VALUE_MAP["StaffReadOnly"],
User.TYPE_VALUE_MAP["Staff"],
):
return PermissionDenied()

Check warning on line 90 in care/facility/api/viewsets/patient_external_test.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/viewsets/patient_external_test.py#L90

Added line #L90 was not covered by tests

queryset = self.queryset
if not self.request.user.is_superuser:
if self.request.user.user_type >= User.TYPE_VALUE_MAP["StateLabAdmin"]:
Expand Down
8 changes: 7 additions & 1 deletion care/facility/api/viewsets/patient_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from dry_rest_permissions.generics import DRYPermissionFiltersBase, DRYPermissions
from rest_framework import mixins, viewsets
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.exceptions import PermissionDenied, ValidationError
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

Expand Down Expand Up @@ -117,6 +117,12 @@
- district - District ID
- district_name - District name - case insensitive match
"""
if (
not self.kwargs.get("patient_external_id")
and request.user.user_type < User.TYPE_VALUE_MAP["Doctor"]
):
raise PermissionDenied()

Check warning on line 124 in care/facility/api/viewsets/patient_sample.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/viewsets/patient_sample.py#L124

Added line #L124 was not covered by tests

if settings.CSV_REQUEST_PARAMETER in request.GET:
queryset = self.filter_queryset(self.get_queryset()).values(
*PatientSample.CSV_MAPPING.keys()
Expand Down
2 changes: 1 addition & 1 deletion care/facility/api/viewsets/shifting.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ class ShifitngRequestCommentViewSet(
lookup_field = "external_id"
queryset = ShiftingRequestComment.objects.all().order_by("-created_date")

permission_classes = (IsAuthenticated,)
permission_classes = (IsAuthenticated, DRYPermissions)

def get_queryset(self):
queryset = self.queryset.filter(
Expand Down
2 changes: 1 addition & 1 deletion care/facility/migrations/0001_initial_squashed.py
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,7 @@ class Migration(migrations.Migration):
},
bases=(
models.Model,
care.facility.models.mixins.permissions.asset.AssetsPermissionMixin,
# care.facility.models.mixins.permissions.asset.AssetsPermissionMixin,
),
),
migrations.CreateModel(
Expand Down
6 changes: 4 additions & 2 deletions care/facility/models/asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
from care.facility.models import reverse_choices
from care.facility.models.facility import Facility
from care.facility.models.json_schema.asset import ASSET_META
from care.facility.models.mixins.permissions.asset import AssetsPermissionMixin
from care.facility.models.mixins.permissions.facility import (
FacilityRelatedPermissionMixin,
)
from care.users.models import User
from care.utils.assetintegration.asset_classes import AssetClasses
from care.utils.models.base import BaseModel
Expand All @@ -25,7 +27,7 @@ class AvailabilityStatus(models.TextChoices):
UNDER_MAINTENANCE = "Under Maintenance"


class AssetLocation(BaseModel, AssetsPermissionMixin):
class AssetLocation(BaseModel, FacilityRelatedPermissionMixin):
"""
This model is also used to store rooms that the assets are in, Since these rooms are mapped to
actual rooms in the hospital, Beds are also connected to this model to remove duplication of efforts
Expand Down
7 changes: 0 additions & 7 deletions care/facility/models/base.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
from care.users.models import User
from care.utils.models.base import BaseModel

READ_ONLY_USER_TYPES = [
User.TYPE_VALUE_MAP["DistrictReadOnlyAdmin"],
User.TYPE_VALUE_MAP["StateReadOnlyAdmin"],
User.TYPE_VALUE_MAP["StaffReadOnly"],
]


def pretty_boolean(val, a="YES", b="NO", c="Not Specified"):
if val is None:
Expand Down
61 changes: 19 additions & 42 deletions care/facility/models/daily_round.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,19 +519,11 @@

super(DailyRound, self).save(*args, **kwargs)

@staticmethod
def has_write_permission(request):
if "/analyse" not in request.get_full_path():
if (
request.user.user_type == User.TYPE_VALUE_MAP["DistrictReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StateReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StaffReadOnly"]
):
return False
return DailyRound.has_read_permission(request)

@staticmethod
def has_read_permission(request):
if request.user.user_type < User.TYPE_VALUE_MAP["NurseReadOnly"]:
return False

Check warning on line 525 in care/facility/models/daily_round.py

View check run for this annotation

Codecov / codecov/patch

care/facility/models/daily_round.py#L525

Added line #L525 was not covered by tests

consultation = get_object_or_404(
PatientConsultation,
external_id=request.parser_context["kwargs"]["consultation_external_id"],
Expand All @@ -552,7 +544,21 @@
)
)

@staticmethod
def has_write_permission(request):
return (
request.user.user_type not in User.READ_ONLY_TYPES
and DailyRound.has_read_permission(request)
)

@staticmethod
def has_analyse_permission(request):
return DailyRound.has_read_permission(request)

Check warning on line 556 in care/facility/models/daily_round.py

View check run for this annotation

Codecov / codecov/patch

care/facility/models/daily_round.py#L556

Added line #L556 was not covered by tests

def has_object_read_permission(self, request):
if request.user.user_type < User.TYPE_VALUE_MAP["NurseReadOnly"]:
return False

Check warning on line 560 in care/facility/models/daily_round.py

View check run for this annotation

Codecov / codecov/patch

care/facility/models/daily_round.py#L560

Added line #L560 was not covered by tests

return (
request.user.is_superuser
or (
Expand Down Expand Up @@ -582,38 +588,9 @@
)

def has_object_write_permission(self, request):
if (
request.user.user_type == User.TYPE_VALUE_MAP["DistrictReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StateReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StaffReadOnly"]
):
return False
return (
request.user.is_superuser
or (
self.consultation.patient.facility
and self.consultation.patient.facility == request.user.home_facility
)
or (
self.consultation.assigned_to == request.user
or request.user == self.consultation.patient.assigned_to
)
or (
request.user.user_type >= User.TYPE_VALUE_MAP["DistrictLabAdmin"]
and (
self.consultation.patient.facility
and request.user.district
== self.consultation.patient.facility.district
)
)
or (
request.user.user_type >= User.TYPE_VALUE_MAP["StateLabAdmin"]
and (
self.consultation.patient.facility
and request.user.state
== self.consultation.patient.facility.district
)
)
request.user.user_type not in User.READ_ONLY_TYPES
and self.has_object_read_permission(request)
)

def has_object_asset_read_permission(self, request):
Expand Down
24 changes: 0 additions & 24 deletions care/facility/models/mixins/permissions/asset.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
from dry_rest_permissions.generics import DRYPermissions

from care.facility.models.mixins.permissions.base import BasePermissionMixin
from care.users.models import User


class IsAssetUser:
def has_permission(self, request, view):
Expand All @@ -23,24 +20,3 @@ class DRYAssetPermissions(DRYPermissions):

def _get_action(self, action):
return f"asset_{super()._get_action(action)}"


class AssetsPermissionMixin(BasePermissionMixin):
def has_object_read_permission(self, request):
return True

def has_object_write_permission(self, request):
if (
request.user.user_type == User.TYPE_VALUE_MAP["DistrictReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StateReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StaffReadOnly"]
):
return False

return True

def has_object_update_permission(self, request):
return self.has_object_write_permission(request)

def has_object_destroy_permission(self, request):
return self.has_object_write_permission(request)
18 changes: 3 additions & 15 deletions care/facility/models/mixins/permissions/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@ def has_read_permission(request):

@staticmethod
def has_write_permission(request):
if (
request.user.user_type == User.TYPE_VALUE_MAP["DistrictReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StateReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StaffReadOnly"]
):
if request.user.user_type in User.READ_ONLY_TYPES:
return False
return (
request.user.is_superuser
Expand All @@ -36,11 +32,7 @@ def has_object_read_permission(self, request):
)

def has_object_update_permission(self, request):
if (
request.user.user_type == User.TYPE_VALUE_MAP["DistrictReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StateReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StaffReadOnly"]
):
if request.user.user_type in User.READ_ONLY_TYPES:
return False
return (request.user.is_superuser) or (
(hasattr(self, "created_by") and request.user == self.created_by)
Expand All @@ -57,11 +49,7 @@ def has_object_update_permission(self, request):
)

def has_object_destroy_permission(self, request):
if (
request.user.user_type == User.TYPE_VALUE_MAP["DistrictReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StateReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StaffReadOnly"]
):
if request.user.user_type in User.READ_ONLY_TYPES:
return False
return request.user.is_superuser or (
hasattr(self, "created_by") and request.user == self.created_by
Expand Down
Loading
Loading