arthexis 0.1.10__py3-none-any.whl → 0.1.12__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.10.dist-info → arthexis-0.1.12.dist-info}/METADATA +36 -26
- arthexis-0.1.12.dist-info/RECORD +102 -0
- config/context_processors.py +1 -0
- config/settings.py +31 -5
- config/urls.py +5 -4
- core/admin.py +430 -90
- core/apps.py +48 -2
- core/backends.py +38 -0
- core/environment.py +23 -5
- core/mailer.py +3 -1
- core/models.py +303 -31
- core/reference_utils.py +20 -9
- core/release.py +4 -0
- core/sigil_builder.py +7 -2
- core/sigil_resolver.py +35 -4
- core/system.py +250 -1
- core/tasks.py +92 -40
- core/temp_passwords.py +181 -0
- core/test_system_info.py +62 -2
- core/tests.py +169 -3
- core/user_data.py +51 -8
- core/views.py +371 -20
- nodes/admin.py +453 -8
- nodes/backends.py +21 -6
- nodes/dns.py +203 -0
- nodes/feature_checks.py +133 -0
- nodes/models.py +374 -31
- nodes/reports.py +411 -0
- nodes/tests.py +677 -38
- nodes/utils.py +32 -0
- nodes/views.py +14 -0
- ocpp/admin.py +278 -15
- ocpp/consumers.py +517 -16
- ocpp/evcs_discovery.py +158 -0
- ocpp/models.py +237 -4
- ocpp/reference_utils.py +42 -0
- ocpp/simulator.py +321 -22
- ocpp/store.py +110 -2
- ocpp/test_rfid.py +169 -7
- ocpp/tests.py +819 -6
- ocpp/transactions_io.py +17 -3
- ocpp/views.py +233 -19
- pages/admin.py +144 -4
- pages/context_processors.py +21 -7
- pages/defaults.py +13 -0
- pages/forms.py +38 -0
- pages/models.py +189 -15
- pages/tests.py +281 -8
- pages/urls.py +4 -0
- pages/views.py +137 -21
- arthexis-0.1.10.dist-info/RECORD +0 -95
- {arthexis-0.1.10.dist-info → arthexis-0.1.12.dist-info}/WHEEL +0 -0
- {arthexis-0.1.10.dist-info → arthexis-0.1.12.dist-info}/licenses/LICENSE +0 -0
- {arthexis-0.1.10.dist-info → arthexis-0.1.12.dist-info}/top_level.txt +0 -0
ocpp/test_rfid.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import io
|
|
2
|
+
import json
|
|
2
3
|
import os
|
|
3
4
|
import sys
|
|
4
5
|
import types
|
|
@@ -17,12 +18,13 @@ from django.test import SimpleTestCase, TestCase
|
|
|
17
18
|
from django.urls import reverse
|
|
18
19
|
from django.contrib.auth import get_user_model
|
|
19
20
|
from django.contrib.sites.models import Site
|
|
21
|
+
from django.utils import timezone
|
|
20
22
|
|
|
21
23
|
from pages.models import Application, Module
|
|
22
24
|
from nodes.models import Node, NodeRole
|
|
23
25
|
|
|
24
26
|
from core.models import RFID
|
|
25
|
-
from ocpp.rfid.reader import read_rfid, enable_deep_read
|
|
27
|
+
from ocpp.rfid.reader import read_rfid, enable_deep_read, validate_rfid_value
|
|
26
28
|
from ocpp.rfid.detect import detect_scanner, main as detect_main
|
|
27
29
|
from ocpp.rfid import background_reader
|
|
28
30
|
from ocpp.rfid.constants import (
|
|
@@ -71,6 +73,11 @@ class BackgroundReaderConfigurationTests(SimpleTestCase):
|
|
|
71
73
|
|
|
72
74
|
|
|
73
75
|
class ScanNextViewTests(TestCase):
|
|
76
|
+
def setUp(self):
|
|
77
|
+
User = get_user_model()
|
|
78
|
+
self.user = User.objects.create_user("rfid-user", password="pwd")
|
|
79
|
+
self.client.force_login(self.user)
|
|
80
|
+
|
|
74
81
|
@patch("config.middleware.Node.get_local", return_value=None)
|
|
75
82
|
@patch("config.middleware.get_site")
|
|
76
83
|
@patch(
|
|
@@ -103,6 +110,62 @@ class ScanNextViewTests(TestCase):
|
|
|
103
110
|
self.assertEqual(resp.status_code, 500)
|
|
104
111
|
self.assertEqual(resp.json(), {"error": "boom"})
|
|
105
112
|
|
|
113
|
+
@patch("config.middleware.Node.get_local", return_value=None)
|
|
114
|
+
@patch("config.middleware.get_site")
|
|
115
|
+
@patch(
|
|
116
|
+
"ocpp.rfid.views.validate_rfid_value",
|
|
117
|
+
return_value={"rfid": "ABCD1234", "label_id": 1, "created": False},
|
|
118
|
+
)
|
|
119
|
+
def test_scan_next_post_validates(self, mock_validate, mock_site, mock_node):
|
|
120
|
+
User = get_user_model()
|
|
121
|
+
user = User.objects.create_user("scanner", password="pwd")
|
|
122
|
+
self.client.force_login(user)
|
|
123
|
+
resp = self.client.post(
|
|
124
|
+
reverse("rfid-scan-next"),
|
|
125
|
+
data=json.dumps({"rfid": "ABCD1234"}),
|
|
126
|
+
content_type="application/json",
|
|
127
|
+
)
|
|
128
|
+
self.assertEqual(resp.status_code, 200)
|
|
129
|
+
self.assertEqual(
|
|
130
|
+
resp.json(), {"rfid": "ABCD1234", "label_id": 1, "created": False}
|
|
131
|
+
)
|
|
132
|
+
mock_validate.assert_called_once_with("ABCD1234", kind=None)
|
|
133
|
+
|
|
134
|
+
@patch("config.middleware.Node.get_local", return_value=None)
|
|
135
|
+
@patch("config.middleware.get_site")
|
|
136
|
+
@patch("ocpp.rfid.views.validate_rfid_value")
|
|
137
|
+
def test_scan_next_post_requires_authentication(
|
|
138
|
+
self, mock_validate, mock_site, mock_node
|
|
139
|
+
):
|
|
140
|
+
resp = self.client.post(
|
|
141
|
+
reverse("rfid-scan-next"),
|
|
142
|
+
data=json.dumps({"rfid": "ABCD1234"}),
|
|
143
|
+
content_type="application/json",
|
|
144
|
+
)
|
|
145
|
+
self.assertEqual(resp.status_code, 401)
|
|
146
|
+
self.assertEqual(resp.json(), {"error": "Authentication required"})
|
|
147
|
+
mock_validate.assert_not_called()
|
|
148
|
+
|
|
149
|
+
@patch("config.middleware.Node.get_local", return_value=None)
|
|
150
|
+
@patch("config.middleware.get_site")
|
|
151
|
+
def test_scan_next_post_invalid_json(self, mock_site, mock_node):
|
|
152
|
+
User = get_user_model()
|
|
153
|
+
user = User.objects.create_user("invalid-json", password="pwd")
|
|
154
|
+
self.client.force_login(user)
|
|
155
|
+
resp = self.client.post(
|
|
156
|
+
reverse("rfid-scan-next"),
|
|
157
|
+
data="{",
|
|
158
|
+
content_type="application/json",
|
|
159
|
+
)
|
|
160
|
+
self.assertEqual(resp.status_code, 400)
|
|
161
|
+
self.assertEqual(resp.json(), {"error": "Invalid JSON payload"})
|
|
162
|
+
|
|
163
|
+
def test_scan_next_requires_authentication(self):
|
|
164
|
+
self.client.logout()
|
|
165
|
+
resp = self.client.get(reverse("rfid-scan-next"))
|
|
166
|
+
self.assertEqual(resp.status_code, 302)
|
|
167
|
+
self.assertIn(reverse("pages:login"), resp.url)
|
|
168
|
+
|
|
106
169
|
|
|
107
170
|
class ReaderNotificationTests(TestCase):
|
|
108
171
|
def _mock_reader(self):
|
|
@@ -171,6 +234,74 @@ class ReaderNotificationTests(TestCase):
|
|
|
171
234
|
self.assertTrue(getattr(reader, "stop_called", False))
|
|
172
235
|
|
|
173
236
|
|
|
237
|
+
class ValidateRfidValueTests(SimpleTestCase):
|
|
238
|
+
@patch("ocpp.rfid.reader.timezone.now")
|
|
239
|
+
@patch("ocpp.rfid.reader.notify_async")
|
|
240
|
+
@patch("ocpp.rfid.reader.RFID.objects.get_or_create")
|
|
241
|
+
def test_creates_new_tag(self, mock_get, mock_notify, mock_now):
|
|
242
|
+
fake_now = object()
|
|
243
|
+
mock_now.return_value = fake_now
|
|
244
|
+
tag = MagicMock()
|
|
245
|
+
tag.pk = 1
|
|
246
|
+
tag.label_id = 1
|
|
247
|
+
tag.allowed = True
|
|
248
|
+
tag.color = "B"
|
|
249
|
+
tag.released = False
|
|
250
|
+
tag.reference = None
|
|
251
|
+
tag.kind = RFID.CLASSIC
|
|
252
|
+
mock_get.return_value = (tag, True)
|
|
253
|
+
|
|
254
|
+
result = validate_rfid_value("abcd1234")
|
|
255
|
+
|
|
256
|
+
mock_get.assert_called_once_with(rfid="ABCD1234", defaults={})
|
|
257
|
+
tag.save.assert_called_once_with(update_fields=["last_seen_on"])
|
|
258
|
+
self.assertIs(tag.last_seen_on, fake_now)
|
|
259
|
+
mock_notify.assert_called_once_with("RFID 1 OK", "ABCD1234 B")
|
|
260
|
+
self.assertTrue(result["created"])
|
|
261
|
+
self.assertEqual(result["rfid"], "ABCD1234")
|
|
262
|
+
|
|
263
|
+
@patch("ocpp.rfid.reader.timezone.now")
|
|
264
|
+
@patch("ocpp.rfid.reader.notify_async")
|
|
265
|
+
@patch("ocpp.rfid.reader.RFID.objects.get_or_create")
|
|
266
|
+
def test_updates_existing_tag_kind(self, mock_get, mock_notify, mock_now):
|
|
267
|
+
fake_now = object()
|
|
268
|
+
mock_now.return_value = fake_now
|
|
269
|
+
tag = MagicMock()
|
|
270
|
+
tag.pk = 5
|
|
271
|
+
tag.label_id = 5
|
|
272
|
+
tag.allowed = False
|
|
273
|
+
tag.color = "G"
|
|
274
|
+
tag.released = True
|
|
275
|
+
tag.reference = None
|
|
276
|
+
tag.kind = RFID.CLASSIC
|
|
277
|
+
mock_get.return_value = (tag, False)
|
|
278
|
+
|
|
279
|
+
result = validate_rfid_value("abcd", kind=RFID.NTAG215)
|
|
280
|
+
|
|
281
|
+
mock_get.assert_called_once_with(
|
|
282
|
+
rfid="ABCD", defaults={"kind": RFID.NTAG215}
|
|
283
|
+
)
|
|
284
|
+
tag.save.assert_called_once_with(update_fields=["kind", "last_seen_on"])
|
|
285
|
+
self.assertIs(tag.last_seen_on, fake_now)
|
|
286
|
+
self.assertEqual(tag.kind, RFID.NTAG215)
|
|
287
|
+
mock_notify.assert_called_once_with("RFID 5 BAD", "ABCD G")
|
|
288
|
+
self.assertFalse(result["allowed"])
|
|
289
|
+
self.assertFalse(result["created"])
|
|
290
|
+
self.assertEqual(result["kind"], RFID.NTAG215)
|
|
291
|
+
|
|
292
|
+
def test_rejects_invalid_value(self):
|
|
293
|
+
result = validate_rfid_value("invalid!")
|
|
294
|
+
self.assertEqual(result, {"error": "RFID must be hexadecimal digits"})
|
|
295
|
+
|
|
296
|
+
def test_rejects_non_string_values(self):
|
|
297
|
+
result = validate_rfid_value(12345)
|
|
298
|
+
self.assertEqual(result, {"error": "RFID must be a string"})
|
|
299
|
+
|
|
300
|
+
def test_rejects_missing_value(self):
|
|
301
|
+
result = validate_rfid_value(None)
|
|
302
|
+
self.assertEqual(result, {"error": "RFID value is required"})
|
|
303
|
+
|
|
304
|
+
|
|
174
305
|
class CardTypeDetectionTests(TestCase):
|
|
175
306
|
def _mock_ntag_reader(self):
|
|
176
307
|
class MockReader:
|
|
@@ -301,7 +432,12 @@ class RFIDDetectionScriptTests(SimpleTestCase):
|
|
|
301
432
|
mock_detect.assert_called_once()
|
|
302
433
|
|
|
303
434
|
|
|
304
|
-
class RestartViewTests(
|
|
435
|
+
class RestartViewTests(TestCase):
|
|
436
|
+
def setUp(self):
|
|
437
|
+
User = get_user_model()
|
|
438
|
+
self.user = User.objects.create_user("restart-user", password="pwd")
|
|
439
|
+
self.client.force_login(self.user)
|
|
440
|
+
|
|
305
441
|
@patch("config.middleware.Node.get_local", return_value=None)
|
|
306
442
|
@patch("config.middleware.get_site")
|
|
307
443
|
@patch("ocpp.rfid.views.restart_sources", return_value={"status": "restarted"})
|
|
@@ -311,8 +447,19 @@ class RestartViewTests(SimpleTestCase):
|
|
|
311
447
|
self.assertEqual(resp.json(), {"status": "restarted"})
|
|
312
448
|
mock_restart.assert_called_once()
|
|
313
449
|
|
|
450
|
+
def test_restart_requires_authentication(self):
|
|
451
|
+
self.client.logout()
|
|
452
|
+
resp = self.client.post(reverse("rfid-scan-restart"))
|
|
453
|
+
self.assertEqual(resp.status_code, 302)
|
|
454
|
+
self.assertIn(reverse("pages:login"), resp.url)
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
class ScanTestViewTests(TestCase):
|
|
458
|
+
def setUp(self):
|
|
459
|
+
User = get_user_model()
|
|
460
|
+
self.user = User.objects.create_user("scan-test-user", password="pwd")
|
|
461
|
+
self.client.force_login(self.user)
|
|
314
462
|
|
|
315
|
-
class ScanTestViewTests(SimpleTestCase):
|
|
316
463
|
@patch("config.middleware.Node.get_local", return_value=None)
|
|
317
464
|
@patch("config.middleware.get_site")
|
|
318
465
|
@patch("ocpp.rfid.views.test_sources", return_value={"irq_pin": 7})
|
|
@@ -332,6 +479,12 @@ class ScanTestViewTests(SimpleTestCase):
|
|
|
332
479
|
self.assertEqual(resp.status_code, 500)
|
|
333
480
|
self.assertEqual(resp.json(), {"error": "no scanner detected"})
|
|
334
481
|
|
|
482
|
+
def test_scan_test_requires_authentication(self):
|
|
483
|
+
self.client.logout()
|
|
484
|
+
resp = self.client.get(reverse("rfid-scan-test"))
|
|
485
|
+
self.assertEqual(resp.status_code, 302)
|
|
486
|
+
self.assertIn(reverse("pages:login"), resp.url)
|
|
487
|
+
|
|
335
488
|
|
|
336
489
|
class RFIDLandingTests(TestCase):
|
|
337
490
|
def test_scanner_view_registered_as_landing(self):
|
|
@@ -352,6 +505,8 @@ class RFIDLandingTests(TestCase):
|
|
|
352
505
|
class ScannerTemplateTests(TestCase):
|
|
353
506
|
def setUp(self):
|
|
354
507
|
self.url = reverse("rfid-reader")
|
|
508
|
+
User = get_user_model()
|
|
509
|
+
self.user = User.objects.create_user("scanner-user", password="pwd")
|
|
355
510
|
|
|
356
511
|
def test_configure_link_for_staff(self):
|
|
357
512
|
User = get_user_model()
|
|
@@ -360,9 +515,11 @@ class ScannerTemplateTests(TestCase):
|
|
|
360
515
|
resp = self.client.get(self.url)
|
|
361
516
|
self.assertContains(resp, 'id="rfid-configure"')
|
|
362
517
|
|
|
363
|
-
def
|
|
518
|
+
def test_redirect_for_anonymous(self):
|
|
519
|
+
self.client.logout()
|
|
364
520
|
resp = self.client.get(self.url)
|
|
365
|
-
self.
|
|
521
|
+
self.assertEqual(resp.status_code, 302)
|
|
522
|
+
self.assertIn(reverse("pages:login"), resp.url)
|
|
366
523
|
|
|
367
524
|
def test_advanced_fields_for_staff(self):
|
|
368
525
|
User = get_user_model()
|
|
@@ -374,9 +531,12 @@ class ScannerTemplateTests(TestCase):
|
|
|
374
531
|
self.assertContains(resp, 'id="rfid-released"')
|
|
375
532
|
self.assertContains(resp, 'id="rfid-reference"')
|
|
376
533
|
|
|
377
|
-
def
|
|
534
|
+
def test_basic_fields_for_authenticated_user(self):
|
|
535
|
+
self.client.logout()
|
|
536
|
+
self.client.force_login(self.user)
|
|
378
537
|
resp = self.client.get(self.url)
|
|
379
538
|
self.assertContains(resp, 'id="rfid-kind"')
|
|
539
|
+
self.assertNotContains(resp, 'id="rfid-connect-local"')
|
|
380
540
|
self.assertNotContains(resp, 'id="rfid-rfid"')
|
|
381
541
|
self.assertNotContains(resp, 'id="rfid-released"')
|
|
382
542
|
self.assertNotContains(resp, 'id="rfid-reference"')
|
|
@@ -388,7 +548,9 @@ class ScannerTemplateTests(TestCase):
|
|
|
388
548
|
resp = self.client.get(self.url)
|
|
389
549
|
self.assertContains(resp, 'id="rfid-deep-read"')
|
|
390
550
|
|
|
391
|
-
def
|
|
551
|
+
def test_no_deep_read_button_for_authenticated_user(self):
|
|
552
|
+
self.client.logout()
|
|
553
|
+
self.client.force_login(self.user)
|
|
392
554
|
resp = self.client.get(self.url)
|
|
393
555
|
self.assertNotContains(resp, 'id="rfid-deep-read"')
|
|
394
556
|
|