-
Notifications
You must be signed in to change notification settings - Fork 288
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
Make care single source of truth for asset config on middleware #2000
Merged
Merged
Changes from 12 commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
a2e9ac2
add routes for middleware to fetch asset config
sainak c3b47fe
cache middleware jwks
sainak b6b386b
allow asset authentication for assetbed
sainak e394f3b
squash migrations
sainak 90779c6
fix key cache issue
sainak 1070ee9
fix assetbed filter for middlewares
sainak faf6ad0
return asset presets from patient_from_asset route itself
sainak 53159c5
add is_parsed_by_ocr flag to indicate ocr use for automated round
sainak cd992b7
improve regex match for hostname query
sainak 9d37cac
Merge remote-tracking branch 'origin/develop' into sainak/feat/middle…
sainak b4ea44c
squash migrations
sainak 01dd94c
Discard changes to config/settings/local.py
sainak 76d2754
Merge remote-tracking branch 'origin/develop' into sainak/feat/middle…
sainak 989c770
update migrations
sainak 41f5920
Merge remote-tracking branch 'origin/develop' into sainak/feat/middle…
sainak 1457312
add permission classes to test views
sainak ac92d0f
take jwks as kwarg for jwt generation
sainak 567f2de
split open id auth response for easier mocking
sainak 81597d9
test middleware auth
sainak 87364d6
remove indexes
sainak b873d18
remove unnessary comments
sainak 7f5270e
use request mocks to test openid auth
sainak 5aa499d
make push config logic async
sainak 7855ae3
improve query
sainak e682454
fix inconsistent validation
sainak 47b41d4
Merge remote-tracking branch 'origin/develop' into sainak/feat/middle…
sainak 0df52b4
fix signal
sainak a14e86c
Merge Develop
vigneshhari 1d9f718
Relock dependencies
vigneshhari 2044e57
update migrations
sainak File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,9 @@ | ||
import re | ||
|
||
from django.conf import settings | ||
from django.core.cache import cache | ||
from django.db.models import Exists, OuterRef, Q, Subquery | ||
from django.db.models import CharField, Exists, F, OuterRef, Q, Subquery, Value | ||
from django.db.models.functions import Cast, Coalesce, NullIf | ||
from django.db.models.signals import post_save | ||
from django.dispatch import receiver | ||
from django.http import Http404 | ||
|
@@ -9,7 +12,7 @@ | |
from django_filters import rest_framework as filters | ||
from django_filters.constants import EMPTY_VALUES | ||
from djqscsv import render_to_csv_response | ||
from drf_spectacular.utils import extend_schema, inline_serializer | ||
from drf_spectacular.utils import OpenApiParameter, extend_schema, inline_serializer | ||
from dry_rest_permissions.generics import DRYPermissions | ||
from rest_framework import exceptions | ||
from rest_framework import filters as drf_filters | ||
|
@@ -29,6 +32,7 @@ | |
from rest_framework.viewsets import GenericViewSet | ||
|
||
from care.facility.api.serializers.asset import ( | ||
AssetConfigSerializer, | ||
AssetLocationSerializer, | ||
AssetSerializer, | ||
AssetServiceSerializer, | ||
|
@@ -54,10 +58,12 @@ | |
from care.users.models import User | ||
from care.utils.assetintegration.asset_classes import AssetClasses | ||
from care.utils.assetintegration.base import BaseAssetIntegration | ||
from care.utils.assetintegration.push_config import delete_asset_from_middleware | ||
from care.utils.cache.cache_allowed_facilities import get_accessible_facilities | ||
from care.utils.filters.choicefilter import CareChoiceFilter, inverse_choices | ||
from care.utils.queryset.asset_location import get_asset_location_queryset | ||
from care.utils.queryset.facility import get_facility_queryset | ||
from config.authentication import MiddlewareAuthentication | ||
|
||
inverse_asset_type = inverse_choices(AssetTypeChoices) | ||
inverse_asset_status = inverse_choices(StatusChoices) | ||
|
@@ -305,6 +311,11 @@ | |
) | ||
return queryset | ||
|
||
def perform_destroy(self, instance: Asset) -> None: | ||
if hostname := instance.resolved_middleware: | ||
delete_asset_from_middleware(hostname["hostname"], instance.external_id) | ||
return super().perform_destroy(instance) | ||
|
||
def list(self, request, *args, **kwargs): | ||
if settings.CSV_REQUEST_PARAMETER in request.GET: | ||
mapping = Asset.CSV_MAPPING.copy() | ||
|
@@ -413,6 +424,72 @@ | |
) | ||
|
||
|
||
class AssetRetrieveConfigViewSet(ListModelMixin, GenericViewSet): | ||
queryset = Asset.objects.all() | ||
authentication_classes = [MiddlewareAuthentication] | ||
permission_classes = [IsAuthenticated] | ||
serializer_class = AssetConfigSerializer | ||
|
||
@extend_schema( | ||
tags=["asset"], | ||
parameters=[ | ||
OpenApiParameter( | ||
name="middleware_hostname", | ||
location=OpenApiParameter.QUERY, | ||
) | ||
], | ||
) | ||
def list(self, request, *args, **kwargs): | ||
""" | ||
This API is used by the middleware to retrieve assets and their configurations | ||
for a given facility and middleware hostname. | ||
""" | ||
middleware_hostname = request.query_params.get("middleware_hostname") | ||
if not middleware_hostname: | ||
return Response( | ||
{"middleware_hostname": "Middleware hostname is required"}, | ||
status=status.HTTP_400_BAD_REQUEST, | ||
) | ||
|
||
if match := re.match(r"^(https?://)?([^\s/]+)/?$", middleware_hostname): | ||
middleware_hostname = match.group(2) # extract the hostname from the URL | ||
else: | ||
return Response( | ||
{"middleware_hostname": "Invalid middleware hostname"}, | ||
status=status.HTTP_400_BAD_REQUEST, | ||
) | ||
|
||
queryset = ( | ||
self.get_queryset() | ||
.filter( | ||
current_location__facility=self.request.user.facility, | ||
asset_class__in=[ | ||
AssetClasses.ONVIF.name, | ||
AssetClasses.HL7MONITOR.name, | ||
], | ||
) | ||
.annotate( | ||
resolved_middleware_hostname=Coalesce( | ||
NullIf( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See if you can use the or statement here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Converting this to or was returning assets from other hostnames as well |
||
Cast(F("meta__middleware_hostname"), CharField()), | ||
Value('""'), | ||
), | ||
NullIf(F("current_location__middleware_address"), Value("")), | ||
F("current_location__facility__middleware_address"), | ||
output_field=CharField(), | ||
) | ||
) | ||
.filter(resolved_middleware_hostname=middleware_hostname) | ||
.exclude( | ||
Q(meta__local_ip_address__isnull=True) | ||
| Q(meta__local_ip_address__exact=""), | ||
) | ||
).only("external_id", "meta", "description", "name", "asset_class") | ||
|
||
serializer = self.get_serializer(queryset, many=True) | ||
return Response(serializer.data) | ||
|
||
|
||
class AssetTransactionFilter(filters.FilterSet): | ||
qr_code_id = filters.CharFilter(field_name="asset__qr_code_id") | ||
external_id = filters.CharFilter(field_name="asset__external_id") | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,19 @@ | ||
from django.conf import settings | ||
from django.utils.decorators import method_decorator | ||
from django.views.decorators.cache import cache_page | ||
from rest_framework.generics import GenericAPIView | ||
from rest_framework.permissions import AllowAny | ||
from rest_framework.response import Response | ||
|
||
|
||
class OpenIdConfigView(GenericAPIView): | ||
class PublicJWKsView(GenericAPIView): | ||
""" | ||
Retrieve the OpenID Connect configuration | ||
""" | ||
|
||
authentication_classes = () | ||
permission_classes = (AllowAny,) | ||
|
||
@method_decorator(cache_page(60 * 60 * 24)) | ||
def get(self, *args, **kwargs): | ||
return Response(settings.JWKS.as_dict()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Converting this to or was breaking the validation