Skip to content

Commit

Permalink
Added Facility Cover image API endpoints (#791)
Browse files Browse the repository at this point in the history
* done creating facility image

* Updated Code according to changes

* updated url formation logic

* removed print statement
  • Loading branch information
Marmik2003 authored Jul 25, 2022
1 parent 964a7d6 commit a214221
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 9 deletions.
37 changes: 35 additions & 2 deletions care/facility/api/serializers/facility.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
from distutils import extension
import boto3

from django.contrib.auth import get_user_model
from django.conf import settings
from rest_framework import serializers

from care.facility.api.serializers.facility_capacity import FacilityCapacitySerializer
Expand All @@ -7,6 +11,7 @@
from care.facility.models.patient_base import reverse_choices
from care.users.api.serializers.lsg import DistrictSerializer, LocalBodySerializer, StateSerializer, WardSerializer
from config.serializers import ChoiceField
from care.utils.csp import config as cs_provider

User = get_user_model()

Expand Down Expand Up @@ -38,6 +43,7 @@ class FacilityBasicInfoSerializer(serializers.ModelSerializer):
district_object = DistrictSerializer(source="district", read_only=True)
state_object = StateSerializer(source="state", read_only=True)
facility_type = serializers.SerializerMethodField()
read_cover_image_url = serializers.CharField(read_only=True)
features = serializers.MultipleChoiceField(choices=FEATURE_CHOICES)

def get_facility_type(self, facility):
Expand All @@ -56,7 +62,7 @@ class Meta:
"district_object",
"state_object",
"facility_type",
"cover_image_url",
"read_cover_image_url",
"features",
)

Expand All @@ -69,6 +75,7 @@ class FacilitySerializer(FacilityBasicInfoSerializer):
# "latitude": 49.8782482189424,
# "longitude": 24.452545489
# }
read_cover_image_url = serializers.CharField(read_only=True)
# location = PointField(required=False)
features = serializers.MultipleChoiceField(choices=FEATURE_CHOICES)

Expand Down Expand Up @@ -103,10 +110,36 @@ class Meta:
"expected_type_b_cylinders",
"expected_type_c_cylinders",
"expected_type_d_cylinders",
"cover_image_url",
"read_cover_image_url",
]
read_only_fields = ("modified_date", "created_date")

def create(self, validated_data):
validated_data["created_by"] = self.context["request"].user
return super().create(validated_data)


class FacilityImageUploadSerializer(serializers.ModelSerializer):
cover_image = serializers.ImageField(required=True, write_only=True)

class Meta:
model = Facility
fields = ("cover_image",)

def save(self, **kwargs):
facility = self.instance
image = self.validated_data["cover_image"]
image_extension = image.name.split(".")[-1]
s3 = boto3.client(
"s3",
**cs_provider.get_client_config(cs_provider.BucketType.FACILITY.value)
)
upload_response = s3.put_object(
Bucket=settings.FACILITY_S3_BUCKET,
Key=f"cover_images/{facility.external_id}_cover.{image_extension}",
Body=image.file,
)
print(upload_response['ResponseMetadata']['HTTPHeaders']['location'])
facility.cover_image_url = f"cover_images/{facility.external_id}_cover.{image_extension}"
facility.save()
return facility
22 changes: 21 additions & 1 deletion care/facility/api/viewsets/facility.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@
from care.facility.api.serializers.facility import (
FacilityBasicInfoSerializer,
FacilitySerializer,
FacilityImageUploadSerializer
)
from care.facility.models import (
Facility,
FacilityCapacity,
FacilityPatientStatsHistory,
HospitalDoctors,
PatientRegistration,
PatientRegistration
)
from care.users.models import User

Expand Down Expand Up @@ -126,6 +127,25 @@ def list(self, request, *args, **kwargs):

return super(FacilityViewSet, self).list(request, *args, **kwargs)

@action(methods=["POST", "DELETE"], detail=True, permission_classes=[IsAuthenticated, DRYPermissions])
def cover_image(self, request, external_id):
facility = self.get_object()
if not facility:
return Response({"facility": "does not exist"}, status=status.HTTP_404_NOT_FOUND)

if request.method == "POST":
serialized_data = FacilityImageUploadSerializer(facility, data=request.data)
if serialized_data.is_valid():
serialized_data.save()
return Response(serialized_data.data)

return Response(serialized_data.errors, status=status.HTTP_400_BAD_REQUEST)

if request.method == "DELETE":
facility.cover_image_url = None
facility.save()
return Response(status=status.HTTP_204_NO_CONTENT)


class AllFacilityViewSet(
mixins.RetrieveModelMixin,
Expand Down
18 changes: 18 additions & 0 deletions care/facility/models/facility.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import boto3
from django.conf import settings

from django.contrib.auth import get_user_model
from django.core.validators import MinValueValidator
from django.db import models
Expand All @@ -10,6 +13,7 @@
FacilityRelatedPermissionMixin,
)
from care.users.models import District, LocalBody, State, Ward
from utils.csp import config as cs_provider

from multiselectfield import MultiSelectField

Expand Down Expand Up @@ -147,6 +151,20 @@ class Facility(FacilityBaseModel, FacilityPermissionMixin):
class Meta:
verbose_name_plural = "Facilities"

def read_cover_image_url(self):
s3Client = boto3.client("s3", **cs_provider.get_client_config(
cs_provider.BucketType.FACILITY.value
))
signed_url = s3Client.generate_presigned_url(
"get_object",
Params={
"Bucket": settings.FACILITY_S3_BUCKET,
"Key": self.cover_image_url,
},
ExpiresIn=60 * 60, # One Hour
)
return signed_url

def __str__(self):
return f"{self.name}"

Expand Down
27 changes: 21 additions & 6 deletions care/utils/csp/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,32 @@ class CSProvider(enum.Enum):
AZURE = "AZURE"


class BucketType(enum.Enum):
PATIENT = "PATIENT"
FACILITY = "FACILITY"


DEFAULT = CSProvider.AWS.value


def get_client_config():
def get_client_config(bucket_type=BucketType.PATIENT.value):
config = {
"region_name": settings.CLOUD_REGION,
"aws_access_key_id": settings.FILE_UPLOAD_KEY,
"aws_secret_access_key": settings.FILE_UPLOAD_SECRET,
BucketType.PATIENT.value: {
"region_name": settings.CLOUD_REGION,
"aws_access_key_id": settings.FILE_UPLOAD_KEY,
"aws_secret_access_key": settings.FILE_UPLOAD_SECRET,
"endpoint_url": settings.FILE_UPLOAD_BUCKET_ENDPOINT,
},
BucketType.FACILITY.value: {
"region_name": settings.CLOUD_REGION,
"aws_access_key_id": settings.FACILITY_S3_KEY,
"aws_secret_access_key": settings.FACILITY_S3_SECRET,
"endpoint_url": settings.FACILITY_S3_BUCKET_ENDPOINT,
},
}

if settings.CLOUD_PROVIDER == CSProvider.GCP.value:
config["endpoint_url"] = "https://storage.googleapis.com"
for key in config.keys():
config[key]["endpoint_url"] = "https://storage.googleapis.com"

return config
return config[bucket_type]
6 changes: 6 additions & 0 deletions config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,12 @@ def GETKEY(group, request):
# FILE_UPLOAD_REGION = env("FILE_UPLOAD_REGION", default="care-patient-staging")
FILE_UPLOAD_KEY = env("FILE_UPLOAD_KEY", default="")
FILE_UPLOAD_SECRET = env("FILE_UPLOAD_SECRET", default="")
FILE_UPLOAD_BUCKET_ENDPOINT = env("FILE_UPLOAD_BUCKET_ENDPOINT", default=f"https://{FILE_UPLOAD_BUCKET}.s3.amazonaws.com")

FACILITY_S3_BUCKET = env("FACILITY_S3_BUCKET", default="")
FACILITY_S3_KEY = env("FACILITY_S3_KEY", default="")
FACILITY_S3_SECRET = env("FACILITY_S3_SECRET", default="")
FACILITY_S3_BUCKET_ENDPOINT = env("FACILITY_S3_BUCKET_ENDPOINT", default=f"https://{FACILITY_S3_BUCKET}.s3.amazonaws.com")


# Audit logs
Expand Down
4 changes: 4 additions & 0 deletions config/settings/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,7 @@
AUDIT_LOG_ENABLED = True

DISABLE_RATELIMIT = True


FILE_UPLOAD_BUCKET_ENDPOINT = "http://localstack:4566"
FACILITY_S3_BUCKET_ENDPOINT = "http://localstack:4566"

0 comments on commit a214221

Please sign in to comment.