arthexis 0.1.24__py3-none-any.whl → 0.1.25__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of arthexis might be problematic. Click here for more details.
- {arthexis-0.1.24.dist-info → arthexis-0.1.25.dist-info}/METADATA +35 -14
- {arthexis-0.1.24.dist-info → arthexis-0.1.25.dist-info}/RECORD +30 -29
- config/settings.py +6 -3
- config/urls.py +2 -0
- core/admin.py +1 -186
- core/backends.py +3 -1
- core/models.py +74 -8
- core/system.py +67 -2
- core/views.py +0 -3
- nodes/admin.py +444 -251
- nodes/models.py +299 -23
- nodes/tasks.py +13 -16
- nodes/tests.py +211 -1
- nodes/urls.py +5 -0
- nodes/utils.py +9 -2
- nodes/views.py +128 -80
- ocpp/admin.py +190 -2
- ocpp/consumers.py +98 -0
- ocpp/models.py +271 -0
- ocpp/network.py +398 -0
- ocpp/tasks.py +108 -267
- ocpp/tests.py +179 -0
- ocpp/views.py +2 -0
- pages/middleware.py +3 -2
- pages/tests.py +40 -0
- pages/utils.py +70 -0
- pages/views.py +4 -2
- {arthexis-0.1.24.dist-info → arthexis-0.1.25.dist-info}/WHEEL +0 -0
- {arthexis-0.1.24.dist-info → arthexis-0.1.25.dist-info}/licenses/LICENSE +0 -0
- {arthexis-0.1.24.dist-info → arthexis-0.1.25.dist-info}/top_level.txt +0 -0
pages/tests.py
CHANGED
|
@@ -515,6 +515,23 @@ class InvitationTests(TestCase):
|
|
|
515
515
|
self.assertEqual(lead.mac_address, "")
|
|
516
516
|
self.assertEqual(len(mail.outbox), 0)
|
|
517
517
|
|
|
518
|
+
def test_request_invite_uses_original_referer(self):
|
|
519
|
+
InviteLead.objects.all().delete()
|
|
520
|
+
self.client.get(
|
|
521
|
+
reverse("pages:index"),
|
|
522
|
+
HTTP_REFERER="https://campaign.example/landing",
|
|
523
|
+
)
|
|
524
|
+
|
|
525
|
+
resp = self.client.post(
|
|
526
|
+
reverse("pages:request-invite"),
|
|
527
|
+
{"email": "origin@example.com"},
|
|
528
|
+
HTTP_REFERER="http://testserver/pages/request-invite/",
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
self.assertEqual(resp.status_code, 200)
|
|
532
|
+
lead = InviteLead.objects.get()
|
|
533
|
+
self.assertEqual(lead.referer, "https://campaign.example/landing")
|
|
534
|
+
|
|
518
535
|
def test_request_invite_falls_back_to_send_mail(self):
|
|
519
536
|
node = Node.objects.create(
|
|
520
537
|
hostname="local", address="127.0.0.1", mac_address="00:11:22:33:44:55"
|
|
@@ -3531,6 +3548,28 @@ class UserStorySubmissionTests(TestCase):
|
|
|
3531
3548
|
story = UserStory.objects.get()
|
|
3532
3549
|
self.assertEqual(story.language_code, "es")
|
|
3533
3550
|
|
|
3551
|
+
def test_submission_prefers_original_referer(self):
|
|
3552
|
+
self.client.get(
|
|
3553
|
+
reverse("pages:index"),
|
|
3554
|
+
HTTP_REFERER="https://ads.example/original",
|
|
3555
|
+
)
|
|
3556
|
+
response = self.client.post(
|
|
3557
|
+
self.url,
|
|
3558
|
+
{
|
|
3559
|
+
"rating": 3,
|
|
3560
|
+
"comments": "Works well",
|
|
3561
|
+
"path": "/wizard/step-2/",
|
|
3562
|
+
"name": "visitor@example.com",
|
|
3563
|
+
"take_screenshot": "0",
|
|
3564
|
+
},
|
|
3565
|
+
HTTP_REFERER="http://testserver/wizard/step-2/",
|
|
3566
|
+
HTTP_USER_AGENT="FeedbackBot/2.0",
|
|
3567
|
+
)
|
|
3568
|
+
|
|
3569
|
+
self.assertEqual(response.status_code, 200)
|
|
3570
|
+
story = UserStory.objects.get()
|
|
3571
|
+
self.assertEqual(story.referer, "https://ads.example/original")
|
|
3572
|
+
|
|
3534
3573
|
def test_superuser_submission_creates_triage_todo(self):
|
|
3535
3574
|
Todo.objects.all().delete()
|
|
3536
3575
|
superuser = get_user_model().objects.create_superuser(
|
|
@@ -3591,6 +3630,7 @@ class UserStorySubmissionTests(TestCase):
|
|
|
3591
3630
|
screenshot_file,
|
|
3592
3631
|
method="USER_STORY",
|
|
3593
3632
|
user=self.user,
|
|
3633
|
+
link_duplicates=True,
|
|
3594
3634
|
)
|
|
3595
3635
|
|
|
3596
3636
|
def test_anonymous_submission_uses_provided_email(self):
|
pages/utils.py
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from urllib.parse import urlsplit
|
|
4
|
+
|
|
5
|
+
from django.core.exceptions import DisallowedHost
|
|
6
|
+
from django.http.request import split_domain_port
|
|
1
7
|
from django.urls import path as django_path
|
|
2
8
|
|
|
3
9
|
|
|
10
|
+
ORIGINAL_REFERER_SESSION_KEY = "pages:original_referer"
|
|
11
|
+
|
|
12
|
+
|
|
4
13
|
def landing(label=None):
|
|
5
14
|
"""Decorator to mark a view as a landing page."""
|
|
6
15
|
|
|
@@ -12,6 +21,67 @@ def landing(label=None):
|
|
|
12
21
|
return decorator
|
|
13
22
|
|
|
14
23
|
|
|
24
|
+
def cache_original_referer(request) -> None:
|
|
25
|
+
"""Persist the first external referer observed for the session."""
|
|
26
|
+
|
|
27
|
+
session = getattr(request, "session", None)
|
|
28
|
+
if not hasattr(session, "get"):
|
|
29
|
+
return
|
|
30
|
+
|
|
31
|
+
original = session.get(ORIGINAL_REFERER_SESSION_KEY)
|
|
32
|
+
if original:
|
|
33
|
+
request.original_referer = original
|
|
34
|
+
return
|
|
35
|
+
|
|
36
|
+
referer = (request.META.get("HTTP_REFERER") or "").strip()
|
|
37
|
+
if not referer:
|
|
38
|
+
return
|
|
39
|
+
|
|
40
|
+
try:
|
|
41
|
+
parsed = urlsplit(referer)
|
|
42
|
+
except ValueError:
|
|
43
|
+
return
|
|
44
|
+
|
|
45
|
+
if parsed.scheme not in {"http", "https"} or not parsed.netloc:
|
|
46
|
+
return
|
|
47
|
+
|
|
48
|
+
try:
|
|
49
|
+
host = request.get_host()
|
|
50
|
+
except DisallowedHost:
|
|
51
|
+
host = ""
|
|
52
|
+
|
|
53
|
+
referer_host, _ = split_domain_port(parsed.netloc)
|
|
54
|
+
request_host, _ = split_domain_port(host)
|
|
55
|
+
|
|
56
|
+
if referer_host and request_host:
|
|
57
|
+
if referer_host.lower() == request_host.lower():
|
|
58
|
+
return
|
|
59
|
+
|
|
60
|
+
referer_value = referer[:1000]
|
|
61
|
+
session[ORIGINAL_REFERER_SESSION_KEY] = referer_value
|
|
62
|
+
request.original_referer = referer_value
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def get_original_referer(request) -> str:
|
|
66
|
+
"""Return the original external referer recorded for the session."""
|
|
67
|
+
|
|
68
|
+
if hasattr(request, "original_referer"):
|
|
69
|
+
return request.original_referer or ""
|
|
70
|
+
|
|
71
|
+
session = getattr(request, "session", None)
|
|
72
|
+
if hasattr(session, "get"):
|
|
73
|
+
referer = session.get(ORIGINAL_REFERER_SESSION_KEY)
|
|
74
|
+
if referer:
|
|
75
|
+
request.original_referer = referer
|
|
76
|
+
return referer
|
|
77
|
+
|
|
78
|
+
referer = (request.META.get("HTTP_REFERER") or "").strip()
|
|
79
|
+
if referer:
|
|
80
|
+
referer = referer[:1000]
|
|
81
|
+
request.original_referer = referer
|
|
82
|
+
return referer
|
|
83
|
+
|
|
84
|
+
|
|
15
85
|
def landing_leads_supported() -> bool:
|
|
16
86
|
"""Return ``True`` when the local node supports landing lead tracking."""
|
|
17
87
|
|
pages/views.py
CHANGED
|
@@ -67,6 +67,7 @@ from core.models import (
|
|
|
67
67
|
Todo,
|
|
68
68
|
)
|
|
69
69
|
from ocpp.models import Charger
|
|
70
|
+
from .utils import get_original_referer
|
|
70
71
|
|
|
71
72
|
try: # pragma: no cover - optional dependency guard
|
|
72
73
|
from graphviz import Digraph
|
|
@@ -1114,7 +1115,7 @@ def request_invite(request):
|
|
|
1114
1115
|
comment=comment,
|
|
1115
1116
|
user=request.user if request.user.is_authenticated else None,
|
|
1116
1117
|
path=request.path,
|
|
1117
|
-
referer=request
|
|
1118
|
+
referer=get_original_referer(request),
|
|
1118
1119
|
user_agent=request.META.get("HTTP_USER_AGENT", ""),
|
|
1119
1120
|
ip_address=ip_address,
|
|
1120
1121
|
mac_address=mac_address or "",
|
|
@@ -1592,7 +1593,7 @@ def submit_user_story(request):
|
|
|
1592
1593
|
if not story.name:
|
|
1593
1594
|
story.name = str(_("Anonymous"))[:40]
|
|
1594
1595
|
story.path = (story.path or request.get_full_path())[:500]
|
|
1595
|
-
story.referer = request
|
|
1596
|
+
story.referer = get_original_referer(request)
|
|
1596
1597
|
story.user_agent = request.META.get("HTTP_USER_AGENT", "")
|
|
1597
1598
|
story.ip_address = client_ip or None
|
|
1598
1599
|
story.is_user_data = True
|
|
@@ -1664,6 +1665,7 @@ def submit_user_story(request):
|
|
|
1664
1665
|
screenshot_path,
|
|
1665
1666
|
method="USER_STORY",
|
|
1666
1667
|
user=story.user if story.user_id else None,
|
|
1668
|
+
link_duplicates=True,
|
|
1667
1669
|
)
|
|
1668
1670
|
except Exception: # pragma: no cover - best effort persistence
|
|
1669
1671
|
logger.exception(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|