# (c) cavaliba.com - tests / data / exporter form hides a schema the caller cannot read

from django.test import TestCase, override_settings
from django.urls import reverse

import app_home.cache as cache
from tests import helper


class ViewExporterSchemaPermissionTest(TestCase):
    def setUp(self):
        cache.clear()

        # p_read names a permission nobody in these tests holds
        helper.add_schema(
            classname="vexpsecret",
            options={"p_read": "p_not_granted_here"},
            field_definition={
                "salary": {"dataformat": "string", "displayname": "Salary"},
            },
        )
        helper.add_instance(classname="vexpsecret", keyname="vexpsecret-01")

        helper.add_schema(
            classname="vexpopen",
            field_definition={
                "mystring": {"dataformat": "string", "displayname": "MyString"},
            },
        )
        helper.add_instance(classname="vexpopen", keyname="vexpopen-01")

        helper.add_user_with_perm(login="unittest", perms=["p_data_export", "p_data_read"])

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_unreadable_schema_not_in_the_selector(self):
        response = self.client.get(reverse("app_data:data_exporter"))

        self.assertNotIn("vexpsecret", [s.classname for s in response.context["schemas"]])

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_schema_param_does_not_leak_the_column_catalog(self):
        response = self.client.get(reverse("app_data:data_exporter"), {"schema": "vexpsecret"})

        self.assertEqual(response.context["catalog"], [])
        self.assertEqual(response.context["schema_name"], "")
        self.assertNotContains(response, "salary")
        self.assertNotContains(response, "Salary")

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_htmx_partial_does_not_leak_the_column_catalog(self):
        response = self.client.get(
            reverse("app_data:data_exporter_fields"), {"schema": "vexpsecret"}
        )

        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.context["catalog"], [])
        self.assertNotContains(response, "salary")

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_unknown_schema_leaks_nothing_either(self):
        response = self.client.get(reverse("app_data:data_exporter"), {"schema": "nosuchschema"})

        self.assertEqual(response.context["catalog"], [])
        self.assertEqual(response.context["schema_name"], "")

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_a_readable_schema_still_works(self):
        response = self.client.get(reverse("app_data:data_exporter"), {"schema": "vexpopen"})

        self.assertEqual(response.context["schema_name"], "vexpopen")
        self.assertIn("mystring", [e["name"] for e in response.context["catalog"]])

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_post_on_an_unreadable_schema_exports_nothing(self):
        response = self.client.post(
            reverse("app_data:data_exporter"),
            {
                "schema": "vexpsecret",
                "format": "csv",
                "columns": ["_schema", "keyname", "salary"],
            },
        )

        # stays on the form instead of streaming a file back
        self.assertEqual(response.status_code, 200)
        self.assertIn("text/html", response["Content-Type"])
        self.assertEqual(response.context["catalog"], [])
