From 147f3c377758a995763c5c97c3f410c081560f7e Mon Sep 17 00:00:00 2001 From: Jacobjohnjeevan Date: Fri, 6 Dec 2024 19:14:58 +0530 Subject: [PATCH 1/6] Facility users filter out deleted users --- care/facility/api/viewsets/facility_users.py | 1 + care/facility/tests/test_facilityuser_api.py | 23 ++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/care/facility/api/viewsets/facility_users.py b/care/facility/api/viewsets/facility_users.py index fb2cf25916..7d72af9833 100644 --- a/care/facility/api/viewsets/facility_users.py +++ b/care/facility/api/viewsets/facility_users.py @@ -39,6 +39,7 @@ def get_queryset(self): external_id=self.kwargs.get("facility_external_id"), ) queryset = facility.users.filter( + is_active=True, deleted=False, ).order_by("-last_login") return queryset.prefetch_related( diff --git a/care/facility/tests/test_facilityuser_api.py b/care/facility/tests/test_facilityuser_api.py index 9ade78e875..3df7ed7e69 100644 --- a/care/facility/tests/test_facilityuser_api.py +++ b/care/facility/tests/test_facilityuser_api.py @@ -65,3 +65,26 @@ def test_user_access_to_facility_on_user_type(self): self.client.force_authenticate(user=district_lab_admin) response = self.client.get(f"/api/v1/facility/{self.facility.external_id}/") self.assertIs(response.status_code, status.HTTP_200_OK) + + def test_user_is_not_listed_if_deleted(self): + # Testing FE's delete functionality (soft delete/is_active is set to false when user is deleted) + response = self.client.get( + f"/api/v1/facility/{self.facility.external_id}/get_users/" + ) + response_json = response.json() + results = response_json["results"] + self.assertIs(response.status_code, status.HTTP_200_OK) + self.assertEqual(len(results), 2) + self.assertIn(self.super_user.username, [user["username"] for user in results]) + self.assertIn(self.user.username, [user["username"] for user in results]) + self.user.is_active = False + self.user.save() + response = self.client.get( + f"/api/v1/facility/{self.facility.external_id}/get_users/" + ) + response_json = response.json() + results = response_json["results"] + self.assertIs(response.status_code, status.HTTP_200_OK) + self.assertEqual(len(results), 1) + self.assertIn(self.super_user.username, [user["username"] for user in results]) + self.assertNotIn(self.user.username, [user["username"] for user in results]) From 21181ce256f64156c37065bfe42e0fdead4cab34 Mon Sep 17 00:00:00 2001 From: Aakash Singh Date: Wed, 11 Dec 2024 19:50:19 +0530 Subject: [PATCH 2/6] fix dev docker file and enable sql logging --- config/settings/local.py | 5 +++-- docker/.local.env | 3 ++- docker/dev.Dockerfile | 4 ++-- scripts/start-dev.sh | 6 +++--- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/config/settings/local.py b/config/settings/local.py index ccaf43208c..477f287315 100644 --- a/config/settings/local.py +++ b/config/settings/local.py @@ -19,8 +19,9 @@ # django-silk # ------------------------------------------------------------------------------ # https://github.com/jazzband/django-silk#requirements -INSTALLED_APPS += ["silk"] -MIDDLEWARE += ["silk.middleware.SilkyMiddleware"] +if env("ENABLE_SILK", default=False): + INSTALLED_APPS += ["silk"] + MIDDLEWARE += ["silk.middleware.SilkyMiddleware"] # https://github.com/jazzband/django-silk#profiling SILKY_PYTHON_PROFILER = True diff --git a/docker/.local.env b/docker/.local.env index b00327fc9b..9d7dc6043a 100644 --- a/docker/.local.env +++ b/docker/.local.env @@ -7,7 +7,8 @@ DATABASE_URL=postgres://postgres:postgres@db:5432/care REDIS_URL=redis://redis:6379 CELERY_BROKER_URL=redis://redis:6379/0 -DJANGO_DEBUG=False +DJANGO_DEBUG=true +ATTACH_DEBUGGER=false BUCKET_REGION=ap-south-1 BUCKET_KEY=key diff --git a/docker/dev.Dockerfile b/docker/dev.Dockerfile index 9bbb9e492a..6b605913d8 100644 --- a/docker/dev.Dockerfile +++ b/docker/dev.Dockerfile @@ -31,9 +31,9 @@ RUN ARCH=$(dpkg --print-architecture) && \ rm -rf typst.tar.xz typst-${TYPST_ARCH} # use pipenv to manage virtualenv -RUN pip install pipenv==2024.4.0 - RUN python -m venv /.venv +RUN --mount=type=cache,target=/root/.cache/pip pip install pipenv==2024.4.0 + COPY Pipfile Pipfile.lock $APP_HOME/ RUN --mount=type=cache,target=/root/.cache/pip pipenv install --system --categories "packages dev-packages docs" diff --git a/scripts/start-dev.sh b/scripts/start-dev.sh index 1071bc6f67..f220165d5d 100755 --- a/scripts/start-dev.sh +++ b/scripts/start-dev.sh @@ -11,9 +11,9 @@ python manage.py collectstatic --noinput python manage.py compilemessages -v 0 echo "starting server..." -if [[ "${DJANGO_DEBUG,,}" == "true" ]]; then +if [[ "${ATTACH_DEBUGGER}" == "true" ]]; then echo "waiting for debugger..." - python -m debugpy --wait-for-client --listen 0.0.0.0:9876 manage.py runserver_plus 0.0.0.0:9000 + python -m debugpy --wait-for-client --listen 0.0.0.0:9876 manage.py runserver_plus 0.0.0.0:9000 --print-sql else - python manage.py runserver 0.0.0.0:9000 + python manage.py runserver_plus 0.0.0.0:9000 --print-sql fi From 53cab4e1152f1140f52b59f42210ec45861c4d33 Mon Sep 17 00:00:00 2001 From: Prafful Date: Thu, 12 Dec 2024 21:56:01 +0530 Subject: [PATCH 3/6] added filter for deleted=false --- care/facility/api/viewsets/camera_preset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/care/facility/api/viewsets/camera_preset.py b/care/facility/api/viewsets/camera_preset.py index bfb168834b..f6143d6291 100644 --- a/care/facility/api/viewsets/camera_preset.py +++ b/care/facility/api/viewsets/camera_preset.py @@ -38,7 +38,7 @@ def get_serializer_context(self): class CameraPresetViewSet(GenericViewSet, ListModelMixin): serializer_class = CameraPresetSerializer - queryset = CameraPreset.objects.all().select_related( + queryset = CameraPreset.objects.filter(asset_bed__deleted=False).select_related( "asset_bed", "created_by", "updated_by" ) lookup_field = "external_id" From f30ac26536bd1c7fe28be6b0ae717fba6a35f461 Mon Sep 17 00:00:00 2001 From: Prafful Date: Thu, 12 Dec 2024 22:30:41 +0530 Subject: [PATCH 4/6] added tests --- care/facility/tests/test_assetbed_api.py | 43 ++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/care/facility/tests/test_assetbed_api.py b/care/facility/tests/test_assetbed_api.py index 2129ef1a00..a6bd1cfc95 100644 --- a/care/facility/tests/test_assetbed_api.py +++ b/care/facility/tests/test_assetbed_api.py @@ -425,6 +425,49 @@ def setUpTestData(cls): def get_base_url(self, asset_bed_id=None): return f"/api/v1/assetbed/{asset_bed_id or self.asset_bed1.external_id}/camera_presets/" + + def test_list_bed_with_deleted_assetbed(self): + # self.asset_bed1.update(deleted=) + res=self.client.post( + self.get_base_url(self.asset_bed1.external_id), + { + "name": "Preset with proper position", + "position": { + "x": 1.0, + "y": 1.0, + "zoom": 1.0, + }, + }, + format="json", + ) + self.assertEqual(res.status_code, status.HTTP_201_CREATED) + res=self.client.post( + self.get_base_url(self.asset_bed2.external_id), + { + "name": "Preset with proper position 2", + "position": { + "x": 1.0, + "y": 1.0, + "zoom": 1.0, + }, + }, + format="json", + ) + self.assertEqual(res.status_code, status.HTTP_201_CREATED) + + res = self.client.get( + f"/api/v1/bed/{self.bed.external_id}/camera_presets/" + ) + self.assertEqual(len(res.json()["results"]),2) + + self.asset_bed1.delete() + self.asset_bed1.refresh_from_db() + res = self.client.get( + f"/api/v1/bed/{self.bed.external_id}/camera_presets/" + ) + self.assertEqual(len(res.json()["results"]),1) + + def test_create_camera_preset_without_position(self): res = self.client.post( self.get_base_url(), From e5f5edb223df429aeb72a22e200ced4083a9eede Mon Sep 17 00:00:00 2001 From: Prafful Date: Thu, 12 Dec 2024 22:41:51 +0530 Subject: [PATCH 5/6] cleaning comments --- care/facility/tests/test_assetbed_api.py | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/care/facility/tests/test_assetbed_api.py b/care/facility/tests/test_assetbed_api.py index a6bd1cfc95..2502c9bd0b 100644 --- a/care/facility/tests/test_assetbed_api.py +++ b/care/facility/tests/test_assetbed_api.py @@ -425,10 +425,8 @@ def setUpTestData(cls): def get_base_url(self, asset_bed_id=None): return f"/api/v1/assetbed/{asset_bed_id or self.asset_bed1.external_id}/camera_presets/" - def test_list_bed_with_deleted_assetbed(self): - # self.asset_bed1.update(deleted=) - res=self.client.post( + res = self.client.post( self.get_base_url(self.asset_bed1.external_id), { "name": "Preset with proper position", @@ -441,7 +439,7 @@ def test_list_bed_with_deleted_assetbed(self): format="json", ) self.assertEqual(res.status_code, status.HTTP_201_CREATED) - res=self.client.post( + res = self.client.post( self.get_base_url(self.asset_bed2.external_id), { "name": "Preset with proper position 2", @@ -455,18 +453,13 @@ def test_list_bed_with_deleted_assetbed(self): ) self.assertEqual(res.status_code, status.HTTP_201_CREATED) - res = self.client.get( - f"/api/v1/bed/{self.bed.external_id}/camera_presets/" - ) - self.assertEqual(len(res.json()["results"]),2) + res = self.client.get(f"/api/v1/bed/{self.bed.external_id}/camera_presets/") + self.assertEqual(len(res.json()["results"]), 2) self.asset_bed1.delete() self.asset_bed1.refresh_from_db() - res = self.client.get( - f"/api/v1/bed/{self.bed.external_id}/camera_presets/" - ) - self.assertEqual(len(res.json()["results"]),1) - + res = self.client.get(f"/api/v1/bed/{self.bed.external_id}/camera_presets/") + self.assertEqual(len(res.json()["results"]), 1) def test_create_camera_preset_without_position(self): res = self.client.post( From f18f77bea21e10327521fda40e98616f31d4778f Mon Sep 17 00:00:00 2001 From: Aakash Singh Date: Sun, 15 Dec 2024 23:15:22 +0530 Subject: [PATCH 6/6] Fix test workflow --- .github/workflows/reusable-test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/reusable-test.yml b/.github/workflows/reusable-test.yml index baec75ebbb..ec0259c4a8 100644 --- a/.github/workflows/reusable-test.yml +++ b/.github/workflows/reusable-test.yml @@ -29,6 +29,10 @@ jobs: restore-keys: | ${{ runner.os }}-buildx- + - name: Create new cache + run: | + mkdir -p /tmp/.buildx-cache-new + - name: Bake docker images uses: docker/bake-action@v5 with: