diff --git a/shynet/core/migrations/0006_service_hide_referrer_regex.py b/shynet/core/migrations/0006_service_hide_referrer_regex.py
new file mode 100644
index 0000000..5aca80e
--- /dev/null
+++ b/shynet/core/migrations/0006_service_hide_referrer_regex.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.0.6 on 2020-05-07 21:23
+
+import core.models
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('core', '0005_service_ignored_ips'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='service',
+ name='hide_referrer_regex',
+ field=models.TextField(blank=True, default='', validators=[core.models._validate_regex]),
+ ),
+ ]
diff --git a/shynet/core/models.py b/shynet/core/models.py
index 775f1f3..74b8b64 100644
--- a/shynet/core/models.py
+++ b/shynet/core/models.py
@@ -1,5 +1,6 @@
import ipaddress
import json
+import re
import uuid
from django.apps import apps
@@ -23,6 +24,13 @@ def _validate_network_list(networks: str):
raise ValidationError(str(e))
+def _validate_regex(regex: str):
+ try:
+ re.compile(regex)
+ except re.error:
+ raise ValidationError(f"'{regex}' is not valid RegEx")
+
+
def _parse_network_list(networks: str):
if len(networks.strip()) == 0:
return []
@@ -61,6 +69,9 @@ class Service(models.Model):
ignored_ips = models.TextField(
default="", blank=True, validators=[_validate_network_list]
)
+ hide_referrer_regex = models.TextField(
+ default="", blank=True, validators=[_validate_regex]
+ )
class Meta:
ordering = ["name", "uuid"]
@@ -71,6 +82,18 @@ class Service(models.Model):
def get_ignored_networks(self):
return _parse_network_list(self.ignored_ips)
+ def get_ignored_referrer_regex(self):
+ if len(self.hide_referrer_regex.strip()) == 0:
+ return re.compile(r".^") # matches nothing
+ else:
+ try:
+ return re.compile(self.hide_referrer_regex)
+ except re.error:
+ # Regexes are validated in the form, but this is an important
+ # fallback to prevent form validation and malformed source
+ # data from causing all service pages to error
+ return re.compile(r".^")
+
def get_daily_stats(self):
return self.get_core_stats(
start_time=timezone.now() - timezone.timedelta(days=1)
@@ -117,12 +140,17 @@ class Service(models.Model):
.order_by("-count")
)
- referrers = (
- hits.filter(initial=True)
- .values("referrer")
- .annotate(count=models.Count("referrer"))
- .order_by("-count")
- )
+ referrer_ignore = self.get_ignored_referrer_regex()
+ referrers = [
+ referrer
+ for referrer in (
+ hits.filter(initial=True)
+ .values("referrer")
+ .annotate(count=models.Count("referrer"))
+ .order_by("-count")
+ )
+ if not referrer_ignore.match(referrer["referrer"])
+ ]
countries = (
sessions.values("country")
diff --git a/shynet/dashboard/forms.py b/shynet/dashboard/forms.py
index d0f4163..d402f1b 100644
--- a/shynet/dashboard/forms.py
+++ b/shynet/dashboard/forms.py
@@ -14,6 +14,7 @@ class ServiceForm(forms.ModelForm):
"respect_dnt",
"collect_ips",
"ignored_ips",
+ "hide_referrer_regex",
"origins",
"collaborators",
]
@@ -23,12 +24,14 @@ class ServiceForm(forms.ModelForm):
"ignored_ips": forms.TextInput(),
"respect_dnt": forms.RadioSelect(choices=[(True, "Yes"), (False, "No")]),
"collect_ips": forms.RadioSelect(choices=[(True, "Yes"), (False, "No")]),
+ "hide_referrer_regex": forms.TextInput(),
}
labels = {
"origins": "Allowed Hostnames",
"respect_dnt": "Respect DNT",
"collect_ips": "Collect IP addresses",
"ignored_ips": "Ignored IP addresses",
+ "hide_referrer_regex": "Hide specific referrers",
}
help_texts = {
"name": _("What should the service be called?"),
@@ -39,6 +42,7 @@ class ServiceForm(forms.ModelForm):
"respect_dnt": "Should visitors who have enabled Do Not Track be excluded from all data?",
"collect_ips": "Should individual IP addresses be collected? IP metadata (location, host, etc) will still be collected.",
"ignored_ips": "A comma-separated list of IP addresses or IP ranges (IPv4 and IPv6) to exclude from tracking (e.g., '192.168.0.2, 127.0.0.1/32').",
+ "hide_referrer_regex": "Any referrers that match this RegEx will not be listed in the referrer summary. Sessions will still be tracked normally. No effect if left blank.",
}
collaborators = forms.CharField(
diff --git a/shynet/dashboard/templates/dashboard/includes/service_form.html b/shynet/dashboard/templates/dashboard/includes/service_form.html
index 2413dd7..0af3f60 100644
--- a/shynet/dashboard/templates/dashboard/includes/service_form.html
+++ b/shynet/dashboard/templates/dashboard/includes/service_form.html
@@ -4,11 +4,12 @@
{{form.link|a17t}}
{{form.collaborators|a17t}}
-
+
Advanced settings
{{form.respect_dnt|a17t}}
{{form.collect_ips|a17t}}
{{form.ignored_ips|a17t}}
+ {{form.hide_referrer_regex|a17t}}
{{form.origins|a17t}}
\ No newline at end of file