Add referrer hiding support (closes #26)
This commit is contained in:
parent
abe37800ec
commit
c84dac6b01
19
shynet/core/migrations/0006_service_hide_referrer_regex.py
Normal file
19
shynet/core/migrations/0006_service_hide_referrer_regex.py
Normal file
@ -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]),
|
||||||
|
),
|
||||||
|
]
|
@ -1,5 +1,6 @@
|
|||||||
import ipaddress
|
import ipaddress
|
||||||
import json
|
import json
|
||||||
|
import re
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
@ -23,6 +24,13 @@ def _validate_network_list(networks: str):
|
|||||||
raise ValidationError(str(e))
|
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):
|
def _parse_network_list(networks: str):
|
||||||
if len(networks.strip()) == 0:
|
if len(networks.strip()) == 0:
|
||||||
return []
|
return []
|
||||||
@ -61,6 +69,9 @@ class Service(models.Model):
|
|||||||
ignored_ips = models.TextField(
|
ignored_ips = models.TextField(
|
||||||
default="", blank=True, validators=[_validate_network_list]
|
default="", blank=True, validators=[_validate_network_list]
|
||||||
)
|
)
|
||||||
|
hide_referrer_regex = models.TextField(
|
||||||
|
default="", blank=True, validators=[_validate_regex]
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ["name", "uuid"]
|
ordering = ["name", "uuid"]
|
||||||
@ -71,6 +82,18 @@ class Service(models.Model):
|
|||||||
def get_ignored_networks(self):
|
def get_ignored_networks(self):
|
||||||
return _parse_network_list(self.ignored_ips)
|
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):
|
def get_daily_stats(self):
|
||||||
return self.get_core_stats(
|
return self.get_core_stats(
|
||||||
start_time=timezone.now() - timezone.timedelta(days=1)
|
start_time=timezone.now() - timezone.timedelta(days=1)
|
||||||
@ -117,12 +140,17 @@ class Service(models.Model):
|
|||||||
.order_by("-count")
|
.order_by("-count")
|
||||||
)
|
)
|
||||||
|
|
||||||
referrers = (
|
referrer_ignore = self.get_ignored_referrer_regex()
|
||||||
|
referrers = [
|
||||||
|
referrer
|
||||||
|
for referrer in (
|
||||||
hits.filter(initial=True)
|
hits.filter(initial=True)
|
||||||
.values("referrer")
|
.values("referrer")
|
||||||
.annotate(count=models.Count("referrer"))
|
.annotate(count=models.Count("referrer"))
|
||||||
.order_by("-count")
|
.order_by("-count")
|
||||||
)
|
)
|
||||||
|
if not referrer_ignore.match(referrer["referrer"])
|
||||||
|
]
|
||||||
|
|
||||||
countries = (
|
countries = (
|
||||||
sessions.values("country")
|
sessions.values("country")
|
||||||
|
@ -14,6 +14,7 @@ class ServiceForm(forms.ModelForm):
|
|||||||
"respect_dnt",
|
"respect_dnt",
|
||||||
"collect_ips",
|
"collect_ips",
|
||||||
"ignored_ips",
|
"ignored_ips",
|
||||||
|
"hide_referrer_regex",
|
||||||
"origins",
|
"origins",
|
||||||
"collaborators",
|
"collaborators",
|
||||||
]
|
]
|
||||||
@ -23,12 +24,14 @@ class ServiceForm(forms.ModelForm):
|
|||||||
"ignored_ips": forms.TextInput(),
|
"ignored_ips": forms.TextInput(),
|
||||||
"respect_dnt": forms.RadioSelect(choices=[(True, "Yes"), (False, "No")]),
|
"respect_dnt": forms.RadioSelect(choices=[(True, "Yes"), (False, "No")]),
|
||||||
"collect_ips": forms.RadioSelect(choices=[(True, "Yes"), (False, "No")]),
|
"collect_ips": forms.RadioSelect(choices=[(True, "Yes"), (False, "No")]),
|
||||||
|
"hide_referrer_regex": forms.TextInput(),
|
||||||
}
|
}
|
||||||
labels = {
|
labels = {
|
||||||
"origins": "Allowed Hostnames",
|
"origins": "Allowed Hostnames",
|
||||||
"respect_dnt": "Respect DNT",
|
"respect_dnt": "Respect DNT",
|
||||||
"collect_ips": "Collect IP addresses",
|
"collect_ips": "Collect IP addresses",
|
||||||
"ignored_ips": "Ignored IP addresses",
|
"ignored_ips": "Ignored IP addresses",
|
||||||
|
"hide_referrer_regex": "Hide specific referrers",
|
||||||
}
|
}
|
||||||
help_texts = {
|
help_texts = {
|
||||||
"name": _("What should the service be called?"),
|
"name": _("What should the service be called?"),
|
||||||
@ -39,6 +42,7 @@ class ServiceForm(forms.ModelForm):
|
|||||||
"respect_dnt": "Should visitors who have enabled <a href='https://en.wikipedia.org/wiki/Do_Not_Track'>Do Not Track</a> be excluded from all data?",
|
"respect_dnt": "Should visitors who have enabled <a href='https://en.wikipedia.org/wiki/Do_Not_Track'>Do Not Track</a> be excluded from all data?",
|
||||||
"collect_ips": "Should individual IP addresses be collected? IP metadata (location, host, etc) will still be collected.",
|
"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').",
|
"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 <a href='https://regexr.com/'>RegEx</a> will not be listed in the referrer summary. Sessions will still be tracked normally. No effect if left blank.",
|
||||||
}
|
}
|
||||||
|
|
||||||
collaborators = forms.CharField(
|
collaborators = forms.CharField(
|
||||||
|
@ -4,11 +4,12 @@
|
|||||||
{{form.link|a17t}}
|
{{form.link|a17t}}
|
||||||
{{form.collaborators|a17t}}
|
{{form.collaborators|a17t}}
|
||||||
|
|
||||||
<details class="p-4 border rounded" {% if form.errors %}open{% endif %}>
|
<details {% if form.errors %}open{% endif %}>
|
||||||
<summary class="cursor-pointer text-sm">Advanced settings</summary>
|
<summary class="cursor-pointer text-sm">Advanced settings</summary>
|
||||||
<hr class="sep h-4">
|
<hr class="sep h-4">
|
||||||
{{form.respect_dnt|a17t}}
|
{{form.respect_dnt|a17t}}
|
||||||
{{form.collect_ips|a17t}}
|
{{form.collect_ips|a17t}}
|
||||||
{{form.ignored_ips|a17t}}
|
{{form.ignored_ips|a17t}}
|
||||||
|
{{form.hide_referrer_regex|a17t}}
|
||||||
{{form.origins|a17t}}
|
{{form.origins|a17t}}
|
||||||
</details>
|
</details>
|
Loading…
Reference in New Issue
Block a user