diff --git a/.gitignore b/.gitignore
index e9a4f5e..cb71bff 100644
--- a/.gitignore
+++ b/.gitignore
@@ -138,4 +138,7 @@ dmypy.json
secrets.yml
.vscode
.DS_Store
-compiledstatic/
\ No newline at end of file
+compiledstatic/
+
+# Pycharm
+.idea
diff --git a/TEMPLATE.env b/TEMPLATE.env
index c7e66ba..7a620bb 100644
--- a/TEMPLATE.env
+++ b/TEMPLATE.env
@@ -72,4 +72,7 @@ SHOW_SHYNET_VERSION=True
# CELERY_BROKER_URL=redis://redis.default.svc.cluster.local/1
# Should Shynet show third-party icons in the dashboard?
-SHOW_THIRD_PARTY_ICONS=True
\ No newline at end of file
+SHOW_THIRD_PARTY_ICONS=True
+
+# Should Shynet block collection of IP addresses globally?
+BLOCK_ALL_IPS=False
\ No newline at end of file
diff --git a/shynet/analytics/tasks.py b/shynet/analytics/tasks.py
index 75b8524..27f7c3f 100644
--- a/shynet/analytics/tasks.py
+++ b/shynet/analytics/tasks.py
@@ -116,7 +116,7 @@ def ingress_request(
return
session = Session.objects.create(
service=service,
- ip=ip if service.collect_ips else None,
+ ip=ip if service.collect_ips and not settings.BLOCK_ALL_IPS else None,
user_agent=user_agent,
identifier=identifier.strip(),
browser=ua.browser.family or "",
diff --git a/shynet/dashboard/forms.py b/shynet/dashboard/forms.py
index 9a926e0..d07ea5f 100644
--- a/shynet/dashboard/forms.py
+++ b/shynet/dashboard/forms.py
@@ -1,5 +1,6 @@
from allauth.account.admin import EmailAddress
from django import forms
+from django.conf import settings
from django.utils.translation import gettext_lazy as _
from core.models import Service, User
@@ -33,7 +34,6 @@ class ServiceForm(forms.ModelForm):
labels = {
"origins": "Allowed origins",
"respect_dnt": "Respect DNT",
- "collect_ips": "Collect IP addresses",
"ignored_ips": "Ignored IP addresses",
"ignore_robots": "Ignore robots",
"hide_referrer_regex": "Hide specific referrers",
@@ -46,13 +46,25 @@ class ServiceForm(forms.ModelForm):
"At what origins does the service operate? Use commas to separate multiple values. This sets CORS headers, so use '*' if you're not sure (or don't care)."
),
"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').",
"ignore_robots": "Should sessions generated by bots be excluded from tracking?",
"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.",
"script_inject": "Optional additional JavaScript to inject at the end of the Shynet script. This code will be injected on every page where this service is installed.",
}
+ collect_ips = forms.BooleanField(
+ help_text="IP address collection is disabled globally by your administrator." if settings.BLOCK_ALL_IPS else "Should individual IP addresses be collected? IP metadata (location, host, etc) will still be collected.",
+ widget=forms.RadioSelect(choices=[(True, "Yes"), (False, "No")]),
+ initial=False if settings.BLOCK_ALL_IPS else True,
+ required=False,
+ disabled=settings.BLOCK_ALL_IPS
+ )
+
+ def clean_collect_ips(self):
+ collect_ips = self.cleaned_data["collect_ips"]
+ # Forces collect IPs to be false if it is disabled globally
+ return False if settings.BLOCK_ALL_IPS else collect_ips
+
collaborators = forms.CharField(
help_text="Which users on this Shynet instance should have read-only access to this service? (Comma separated list of emails.)",
required=False,
diff --git a/shynet/shynet/settings.py b/shynet/shynet/settings.py
index e9aa568..c467e9c 100644
--- a/shynet/shynet/settings.py
+++ b/shynet/shynet/settings.py
@@ -321,3 +321,6 @@ SHOW_SHYNET_VERSION = os.getenv("SHOW_SHYNET_VERSION", "True") == "True"
# Should Shynet show third-party icons in the dashboard?
SHOW_THIRD_PARTY_ICONS = os.getenv("SHOW_THIRD_PARTY_ICONS", "True") == "True"
+
+# Should Shynet never collect any IP?
+BLOCK_ALL_IPS = os.getenv("BLOCK_ALL_IPS", "False") == "True"