Skip to content

Commit

Permalink
[#3558] Add test for migration, set content object
Browse files Browse the repository at this point in the history
  • Loading branch information
Viicos committed Nov 23, 2023
1 parent c894a1e commit 0819de5
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,37 @@ def set_identifier(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) ->
AnalyticsToolsConfiguration = apps.get_model(
"analytics_tools", "AnalyticsToolsConfiguration"
)
analytics_conf = AnalyticsToolsConfiguration.get_solo()
try:
analytics_conf = AnalyticsToolsConfiguration.objects.get()
except AnalyticsToolsConfiguration.DoesNotExist:
return

ContentType = apps.get_model("contenttypes", "ContentType")
analytics_content_type = ContentType.objects.get_for_model(
AnalyticsToolsConfiguration
)

CSPSetting = apps.get_model("config", "CSPSetting")

set_content_type = False
for csp_setting in CSPSetting.objects.filter(identifier="").iterator():
if csp_setting.value in SITEIMPROVE_VALUES:
csp_setting.identifier = AnalyticsTools.siteimprove
set_content_type = True
elif csp_setting.value in GA_VALUES:
csp_setting.identifier = AnalyticsTools.google_analytics
set_content_type = True
else:
for field, identifier in FIELD_TO_IDENTIFIER.items():
if getattr(analytics_conf, field) == csp_setting.value:
if getattr(analytics_conf, field, None) == csp_setting.value:
csp_setting.identifier = identifier
set_content_type = True

if set_content_type:
# `content_object` is not available in migrations,
# so we set `content_type` and `object_id` instead:
csp_setting.content_type = analytics_content_type
csp_setting.object_id = analytics_conf.id

csp_setting.save()

Expand All @@ -51,6 +70,7 @@ class Migration(migrations.Migration):

dependencies = [
("analytics_tools", "0002_auto_20230119_1500"),
("config", "0063_auto_20231122_1816"),
]

operations = [
Expand Down
15 changes: 11 additions & 4 deletions src/openforms/analytics_tools/tests/test_cspsettings_identifier.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.contrib.admin.options import get_content_type_for_model
from django.test import TestCase, override_settings

from openforms.config.models import CSPSetting
Expand All @@ -8,7 +9,7 @@

@override_settings(SOLO_CACHE=None)
class CSPIdentifierTests(AnalyticsMixin, TestCase):
def disabling_analytics_does_not_delete_unrelated_csp_settings(self):
def test_disabling_analytics_does_not_delete_unrelated_csp_settings(self):
self.config.gtm_code = "GTM-XXXX"
self.config.ga_code = "UA-XXXXX-Y"
self.config.enable_google_analytics = True
Expand All @@ -19,9 +20,13 @@ def disabling_analytics_does_not_delete_unrelated_csp_settings(self):
self.config.clean()
self.config.save()

csp_settings = CSPSetting.objects.filter(content_object=self.config)
csp_settings = CSPSetting.objects.filter(
content_type=get_content_type_for_model(self.config),
object_id=str(self.config.pk),
)

assert csp_settings.count() == 2
# GA sets two CSPSettings
assert csp_settings.count() == 3

self.config.enable_google_analytics = False
self.config.save()
Expand All @@ -32,6 +37,8 @@ def disabling_analytics_does_not_delete_unrelated_csp_settings(self):
self.fail("CSPSetting instance should exist")

other_settings = CSPSetting.objects.filter(
content_object=self.config, identifier=AnalyticsTools.google_analytics
content_type=get_content_type_for_model(self.config),
object_id=str(self.config.pk),
identifier=AnalyticsTools.google_analytics,
)
self.assertFalse(other_settings.exists())
78 changes: 78 additions & 0 deletions src/openforms/analytics_tools/tests/test_migrations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from django.contrib.admin.options import get_content_type_for_model
from django.db.migrations.state import StateApps

from openforms.analytics_tools.constants import AnalyticsTools
from openforms.config.constants import CSPDirective
from openforms.utils.tests.test_migrations import TestMigrations


class CSPSettingIdentifierMigrationTests(TestMigrations):
app = "analytics_tools"
migrate_from = "0002_auto_20230119_1500"
migrate_to = "0003_cspsetting_identifier"

def setUpBeforeMigration(self, apps: StateApps):
CSPSetting = apps.get_model("config", "CSPSetting")
AnalyticsToolsConfiguration = apps.get_model(
"analytics_tools", "AnalyticsToolsConfiguration"
)

AnalyticsToolsConfiguration.objects.create(
matomo_url="https://matomo.example.com",
piwik_url="https://piwik.example.com",
piwik_pro_url="https://your-instance-name.piwik.pro",
)

CSPSetting.objects.create(
directive=CSPDirective.DEFAULT_SRC, value="https://matomo.example.com"
)
CSPSetting.objects.create(
directive=CSPDirective.DEFAULT_SRC, value="https://piwik.example.com"
)
CSPSetting.objects.create(
directive=CSPDirective.DEFAULT_SRC,
value="https://your-instance-name.piwik.pro",
)
CSPSetting.objects.create(
directive=CSPDirective.DEFAULT_SRC, value="https://siteimproveanalytics.com"
)
CSPSetting.objects.create(
directive=CSPDirective.DEFAULT_SRC, value="https://www.googleanalytics.com"
)

def test_migration_sets_identifier_and_gfk(self):
CSPSetting = self.apps.get_model("config", "CSPSetting")
AnalyticsToolsConfiguration = self.apps.get_model(
"analytics_tools", "AnalyticsToolsConfiguration"
)
analytics_conf = AnalyticsToolsConfiguration.objects.get()

value_to_identifier = {
"https://matomo.example.com": AnalyticsTools.matomo,
"https://piwik.example.com": AnalyticsTools.piwik,
"https://your-instance-name.piwik.pro": AnalyticsTools.piwik_pro,
"https://siteimproveanalytics.com": AnalyticsTools.siteimprove,
"https://www.googleanalytics.com": AnalyticsTools.google_analytics,
}

self.assertFalse(CSPSetting.objects.filter(identifier="").exists())
breakpoint()
print(type(get_content_type_for_model(analytics_conf)))

# We avoid using django.contrib.admin.options.get_content_type_for_model
# as it uses the "real" `ContentType` model. See:
# https://stackoverflow.com/q/51670468/#comment110467392_54357872
content_type = self.apps.get_model(
"contenttypes", "ContentType"
).objects.get_for_model(analytics_conf)

for value, identifier in value_to_identifier.items():
self.assertEqual(
CSPSetting.objects.filter(
value=value,
identifier=identifier,
content_type=content_type,
object_id=str(analytics_conf.pk),
).count(),
1,
)
5 changes: 3 additions & 2 deletions src/openforms/analytics_tools/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,16 @@ def update_analytics_tool(
CSPEntry(**data) for data in load_asset("csp_headers.json", analytics_tool)
]
)

for csp in csps:
for replacement in tool_config.replacements:
if not (field_name := replacement.field_name):
continue # we do not support callables for CSP
replacement_value = getattr(config, field_name)
csp.value = csp.value.replace(replacement.needle, str(replacement_value))

CSPSetting.objects.set_for(config, csps, identifier=analytics_tool)

# process the cookies
cookies = cast(list[CookieDict], load_asset("cookies.json", analytics_tool))
for cookie in cookies:
Expand All @@ -72,8 +75,6 @@ def update_analytics_tool(
cookie_consent_group_id=config.analytics_cookie_consent_group.id,
)

CSPSetting.objects.set_for(config, csps, identifier=analytics_tool)


def load_asset(
asset: Literal["cookies.json", "csp_headers.json"],
Expand Down

0 comments on commit 0819de5

Please sign in to comment.