Add Do Not Track support
This commit is contained in:
parent
3d10ddf711
commit
c2f4724b11
@ -131,9 +131,9 @@ SERVER_EMAIL="Shynet <noreply@shynet.example.com>"
|
|||||||
|
|
||||||
## FAQ
|
## 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
|
## Roadmap
|
||||||
|
|
||||||
@ -145,7 +145,6 @@ The following features are planned:
|
|||||||
* **Better collaboration interface** (the current interface is... a draft)
|
* **Better collaboration interface** (the current interface is... a draft)
|
||||||
* **Data deletion tool** (easily prune user data by specifying an ID or IP)
|
* **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)
|
* **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
|
## In the Wild
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% elif field|is_radio %}
|
{% elif field|is_radio %}
|
||||||
{% if field.auto_id %}
|
{% 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 %}
|
{% endif %}
|
||||||
{% for choice in field %}
|
{% for choice in field %}
|
||||||
<label class="switch my-1">
|
<label class="switch my-1">
|
||||||
|
@ -42,12 +42,15 @@ def _geoip2_lookup(ip):
|
|||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
def ingress_request(
|
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:
|
try:
|
||||||
service = Service.objects.get(pk=service_uuid, status=Service.ACTIVE)
|
service = Service.objects.get(pk=service_uuid, status=Service.ACTIVE)
|
||||||
log.debug(f"Linked to service {service}")
|
log.debug(f"Linked to service {service}")
|
||||||
|
|
||||||
|
if dnt and service.respect_dnt:
|
||||||
|
return
|
||||||
|
|
||||||
ip_data = _geoip2_lookup(ip)
|
ip_data = _geoip2_lookup(ip)
|
||||||
log.debug(f"Found geoip2 data")
|
log.debug(f"Found geoip2 data")
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ def ingress(request, service_uuid, identifier, tracker, payload):
|
|||||||
client_ip, is_routable = get_client_ip(request)
|
client_ip, is_routable = get_client_ip(request)
|
||||||
location = request.META.get("HTTP_REFERER", "").strip()
|
location = request.META.get("HTTP_REFERER", "").strip()
|
||||||
user_agent = request.META.get("HTTP_USER_AGENT", "").strip()
|
user_agent = request.META.get("HTTP_USER_AGENT", "").strip()
|
||||||
|
dnt = request.META.get("HTTP_DNT", "0").strip() == "1"
|
||||||
|
|
||||||
ingress_request.delay(
|
ingress_request.delay(
|
||||||
service_uuid,
|
service_uuid,
|
||||||
@ -27,7 +28,8 @@ def ingress(request, service_uuid, identifier, tracker, payload):
|
|||||||
client_ip,
|
client_ip,
|
||||||
location,
|
location,
|
||||||
user_agent,
|
user_agent,
|
||||||
identifier,
|
dnt=dnt,
|
||||||
|
identifier=identifier,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
18
shynet/core/migrations/0003_service_respect_dnt.py
Normal file
18
shynet/core/migrations/0003_service_respect_dnt.py
Normal 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),
|
||||||
|
),
|
||||||
|
]
|
@ -41,6 +41,7 @@ class Service(models.Model):
|
|||||||
status = models.CharField(
|
status = models.CharField(
|
||||||
max_length=2, choices=SERVICE_STATUSES, default=ACTIVE, db_index=True
|
max_length=2, choices=SERVICE_STATUSES, default=ACTIVE, db_index=True
|
||||||
)
|
)
|
||||||
|
respect_dnt = models.BooleanField(default=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ["name", "uuid"]
|
ordering = ["name", "uuid"]
|
||||||
@ -60,7 +61,9 @@ class Service(models.Model):
|
|||||||
end_time = timezone.now()
|
end_time = timezone.now()
|
||||||
|
|
||||||
main_data = self.get_relative_stats(start_time, end_time)
|
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
|
main_data["compare"] = comparison_data
|
||||||
|
|
||||||
return main_data
|
return main_data
|
||||||
|
@ -7,14 +7,16 @@ from core.models import Service
|
|||||||
class ServiceForm(forms.ModelForm):
|
class ServiceForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Service
|
model = Service
|
||||||
fields = ["name", "link", "origins", "collaborators"]
|
fields = ["name", "link", "origins", "respect_dnt", "collaborators"]
|
||||||
widgets = {
|
widgets = {
|
||||||
"name": forms.TextInput(),
|
"name": forms.TextInput(),
|
||||||
"origins": forms.TextInput(),
|
"origins": forms.TextInput(),
|
||||||
"collaborators": forms.CheckboxSelectMultiple(),
|
"collaborators": forms.CheckboxSelectMultiple(),
|
||||||
|
"respect_dnt": forms.RadioSelect(choices=[(True, "Yes"), (False, "No")])
|
||||||
}
|
}
|
||||||
labels = {
|
labels = {
|
||||||
"origins": "Allowed Hostnames",
|
"origins": "Allowed Hostnames",
|
||||||
|
"respect_dnt": "Respect DNT",
|
||||||
}
|
}
|
||||||
help_texts = {
|
help_texts = {
|
||||||
"name": _("What should the service be called?"),
|
"name": _("What should the service be called?"),
|
||||||
@ -22,4 +24,5 @@ class ServiceForm(forms.ModelForm):
|
|||||||
"origins": _(
|
"origins": _(
|
||||||
"At what hostnames does the service operate? This sets CORS headers, so use '*' if you're not sure (or don't care)."
|
"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?"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user