from __future__ import annotations import json from django.contrib.auth.models import Permission from django.contrib.sessions.middleware import SessionMiddleware from django.http import HttpResponse from django.test import RequestFactory, TestCase, override_settings from labs.admin.sudo import grant_sudo from labs.admin.views.site_settings import SiteSettingOverrideForm, SiteSettingUpdateView from labs.models import AdminOTPDevice, SiteSetting, User from labs.site_settings.types import SettingType def _attach_session(request) -> None: middleware = SessionMiddleware(lambda _request: HttpResponse()) middleware.process_request(request) request.session.save() def _build_admin_request( factory: RequestFactory, *, method: str, path: str, user: User, data: dict | None = None, remote_addr: str = "127.0.0.1", ): if method.upper() == "POST": request = factory.post(path, data=data or {}) else: request = factory.get(path) request.user = user request.META["REMOTE_ADDR"] = remote_addr _attach_session(request) grant_sudo(request) return request @override_settings( CACHES={ "default": {"BACKEND": "django.core.cache.backends.locmem.LocMemCache"}, } ) class AdminSiteSettingsTests(TestCase): def setUp(self) -> None: super().setUp() self.factory = RequestFactory() self.user = User.objects.create_user( email="admin@example.com", password="password", is_staff=True, ) AdminOTPDevice.objects.create( user=self.user, secret_encrypted="JBSWY3DPEHPK3PXP", is_confirmed=True, ) view_perm = Permission.objects.get( content_type__app_label="labs", codename="view_sitesetting", ) change_perm = Permission.objects.get( content_type__app_label="labs", codename="change_sitesetting", ) self.user.user_permissions.add(view_perm, change_perm) def test_override_string_setting_creates_db_row_with_json_storage(self) -> None: key = "credit_voucher_notification_lark_app_id" request = _build_admin_request( self.factory, method="POST", path=f"/admin/site-settings/{key}/", user=self.user, data={"value": "app_id_123"}, ) response = SiteSettingUpdateView.as_view()(request, key=key) self.assertEqual(response.status_code, 302) obj = SiteSetting.objects.get(key=key) self.assertEqual(obj.key_type, "string") self.assertEqual(obj.value, json.dumps("app_id_123")) def test_override_equal_to_default_deletes_db_row(self) -> None: key = "credit_voucher_notification_lark_app_id" SiteSetting.objects.create( key=key, key_type="string", value=json.dumps("will_be_deleted"), ) request = _build_admin_request( self.factory, method="POST", path=f"/admin/site-settings/{key}/", user=self.user, data={"value": ""}, ) response = SiteSettingUpdateView.as_view()(request, key=key) self.assertEqual(response.status_code, 302) self.assertFalse(SiteSetting.objects.filter(key=key).exists()) def test_masked_setting_empty_value_keeps_current_override(self) -> None: key = "credit_voucher_notification_lark_app_secret" SiteSetting.objects.create( key=key, key_type="string", value=json.dumps("secret_123"), ) request = _build_admin_request( self.factory, method="POST", path=f"/admin/site-settings/{key}/", user=self.user, data={"value": ""}, ) response = SiteSettingUpdateView.as_view()(request, key=key) self.assertEqual(response.status_code, 302) obj = SiteSetting.objects.get(key=key) self.assertEqual(obj.value, json.dumps("secret_123")) def test_masked_setting_requires_value_when_no_override_exists(self) -> None: form = SiteSettingOverrideForm( data={"value": ""}, setting_key="credit_voucher_notification_lark_app_secret", setting_type=SettingType.STRING, masked=True, override_exists=False, ) self.assertFalse(form.is_valid()) self.assertIn("value", form.errors)