Add Do Not Track support

This commit is contained in:
R. Miles McCain 2020-04-22 13:18:25 -04:00
parent 3d10ddf711
commit c2f4724b11
No known key found for this signature in database
GPG Key ID: 91CB47BDDF2671A5
7 changed files with 36 additions and 8 deletions

View File

@ -131,9 +131,9 @@ SERVER_EMAIL="Shynet <noreply@shynet.example.com>"
## FAQ
**Does Shynet respond to Do Not Track (DNT) signals?** It's on the [roadmap](#roadmap). While there isn't any standardized way to handle DNT requests, the plan is to give services the option of ignoring DNT signals entirely, limiting collected data (i.e. not collecting any visitor-related details such as browser, IP, etc.), or excluding DNT requests from analytics entirely.
**Does Shynet respond to Do Not Track (DNT) signals?** Yes. While there isn't any standardized way to handle DNT requests, Shynet allows you to specify whether you want to collect any data from users with DNT enabled on a per-service basis. (By default, Shynet will _not_ collect any data from users who specify DNT.)
**Is this GDPR compliant?** I think so, but it also depends on how you use it. If you're worried about GDPR, you should talk to a lawyer about your particular data collection practices. I am not a lawyer.
**Is this GDPR compliant?** I think so, but it also depends on how you use it. If you're worried about GDPR, you should talk to a lawyer about your particular data collection practices. I'm not a lawyer. (And this isn't legal advice.)
## Roadmap
@ -145,7 +145,6 @@ The following features are planned:
* **Better collaboration interface** (the current interface is... a draft)
* **Data deletion tool** (easily prune user data by specifying an ID or IP)
* **Differential privacy** (explore and share your data without revealing any personal information)
* **Do Not Track support** (change tracking behavior in response to DNT signals)
## In the Wild

View File

@ -18,7 +18,7 @@
{% endfor %}
{% elif field|is_radio %}
{% if field.auto_id %}
<label class="label my-1" for="{{field.auto_id}}">{{ field.label }}</label>
<label class="label block" for="{{field.auto_id}}">{{ field.label }}</label>
{% endif %}
{% for choice in field %}
<label class="switch my-1">

View File

@ -42,12 +42,15 @@ def _geoip2_lookup(ip):
@shared_task
def ingress_request(
service_uuid, tracker, time, payload, ip, location, user_agent, identifier=""
service_uuid, tracker, time, payload, ip, location, user_agent, dnt=False, identifier=""
):
try:
service = Service.objects.get(pk=service_uuid, status=Service.ACTIVE)
log.debug(f"Linked to service {service}")
if dnt and service.respect_dnt:
return
ip_data = _geoip2_lookup(ip)
log.debug(f"Found geoip2 data")

View File

@ -18,6 +18,7 @@ def ingress(request, service_uuid, identifier, tracker, payload):
client_ip, is_routable = get_client_ip(request)
location = request.META.get("HTTP_REFERER", "").strip()
user_agent = request.META.get("HTTP_USER_AGENT", "").strip()
dnt = request.META.get("HTTP_DNT", "0").strip() == "1"
ingress_request.delay(
service_uuid,
@ -27,7 +28,8 @@ def ingress(request, service_uuid, identifier, tracker, payload):
client_ip,
location,
user_agent,
identifier,
dnt=dnt,
identifier=identifier,
)

View File

@ -0,0 +1,18 @@
# Generated by Django 3.0.5 on 2020-04-22 17:03
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0002_auto_20200415_1742'),
]
operations = [
migrations.AddField(
model_name='service',
name='respect_dnt',
field=models.BooleanField(default=True),
),
]

View File

@ -41,6 +41,7 @@ class Service(models.Model):
status = models.CharField(
max_length=2, choices=SERVICE_STATUSES, default=ACTIVE, db_index=True
)
respect_dnt = models.BooleanField(default=True)
class Meta:
ordering = ["name", "uuid"]
@ -60,7 +61,9 @@ class Service(models.Model):
end_time = timezone.now()
main_data = self.get_relative_stats(start_time, end_time)
comparison_data = self.get_relative_stats(start_time - (end_time - start_time), start_time)
comparison_data = self.get_relative_stats(
start_time - (end_time - start_time), start_time
)
main_data["compare"] = comparison_data
return main_data

View File

@ -7,14 +7,16 @@ from core.models import Service
class ServiceForm(forms.ModelForm):
class Meta:
model = Service
fields = ["name", "link", "origins", "collaborators"]
fields = ["name", "link", "origins", "respect_dnt", "collaborators"]
widgets = {
"name": forms.TextInput(),
"origins": forms.TextInput(),
"collaborators": forms.CheckboxSelectMultiple(),
"respect_dnt": forms.RadioSelect(choices=[(True, "Yes"), (False, "No")])
}
labels = {
"origins": "Allowed Hostnames",
"respect_dnt": "Respect DNT",
}
help_texts = {
"name": _("What should the service be called?"),
@ -22,4 +24,5 @@ class ServiceForm(forms.ModelForm):
"origins": _(
"At what hostnames does the service operate? This sets CORS headers, so use '*' if you're not sure (or don't care)."
),
"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?"
}