From cd2135bb465cdc4a54abadecfce951a9de17c0c8 Mon Sep 17 00:00:00 2001 From: Chris Caron Date: Sun, 8 Oct 2023 10:32:03 -0400 Subject: [PATCH] Increased key length maximum size to 128 characters (#138) --- README.md | 4 +++- apprise_api/api/tests/test_add.py | 25 ++++++++++++++++++++++ apprise_api/api/tests/test_del.py | 35 +++++++++++++++++++++++++++++++ apprise_api/api/urls.py | 16 +++++++------- 4 files changed, 71 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7ae71ae..2e686ad 100644 --- a/README.md +++ b/README.md @@ -274,7 +274,8 @@ curl -X POST -d '{"tag":"leaders teamA, leaders teamB", "body":"meeting now"}' \ ### API Notes -- `{KEY}` must be 1-64 alphanumeric characters in length. In addition to this, the underscore (`_`) and dash (`-`) are also accepted. +- `{KEY}` must be 1-128 alphanumeric characters in length. In addition to this, the underscore (`_`) and dash (`-`) are also accepted. + - Consider using keys like `sha1`, `sha512`, `uuid`, etc to secure shared namespaces if you wish to open your platform to others. Or keep it simple in a controlled environment and just use the default string `apprise` as your key (and as illustrated in the examples above). - Specify the `Content-Type` of `application/json` to use the JSON support otherwise the default expected format is `application/x-www-form-urlencoded` (whether it is specified or not). - There is no authentication (or SSL encryption) required to use this API; this is by design. The intention here is to be a light-weight and fast micro-service. - There are no additional dependencies (such as database requirements, etc) should you choose to use the optional persistent store (mounted as `/config`). @@ -323,6 +324,7 @@ pip install -r dev-requirements.txt -r requirements.txt # Run a dev server (debug mode) accessible from your browser at: # -> http://localhost:8000/ ./manage.py runserver + ``` Some other useful development notes: diff --git a/apprise_api/api/tests/test_add.py b/apprise_api/api/tests/test_add.py index edc0cd2..86af29c 100644 --- a/apprise_api/api/tests/test_add.py +++ b/apprise_api/api/tests/test_add.py @@ -28,6 +28,7 @@ from django.test.utils import override_settings from ..forms import AUTO_DETECT_CONFIG_KEYWORD import json +import hashlib class AddTests(SimpleTestCase): @@ -39,6 +40,30 @@ def test_add_invalid_key_status_code(self): response = self.client.get('/add/**invalid-key**') assert response.status_code == 404 + def test_key_lengths(self): + """ + Test our key lengths + """ + + # our key to use + h = hashlib.sha512() + h.update(b'string') + key = h.hexdigest() + + # Our limit + assert len(key) == 128 + + # Add our URL + response = self.client.post( + '/add/{}'.format(key), {'urls': 'mailto://user:pass@yahoo.ca'}) + assert response.status_code == 200 + + # However adding just 1 more character exceeds our limit and the save + # will fail + response = self.client.post( + '/add/{}'.format(key + 'x'), {'urls': 'mailto://user:pass@yahoo.ca'}) + assert response.status_code == 404 + @override_settings(APPRISE_CONFIG_LOCK=True) def test_save_config_by_urls_with_lock(self): """ diff --git a/apprise_api/api/tests/test_del.py b/apprise_api/api/tests/test_del.py index 58dc5f7..2e45427 100644 --- a/apprise_api/api/tests/test_del.py +++ b/apprise_api/api/tests/test_del.py @@ -25,6 +25,7 @@ from django.test import SimpleTestCase from django.test.utils import override_settings from unittest.mock import patch +import hashlib class DelTests(SimpleTestCase): @@ -36,6 +37,36 @@ def test_del_get_invalid_key_status_code(self): response = self.client.get('/del/**invalid-key**') assert response.status_code == 404 + def test_key_lengths(self): + """ + Test our key lengths + """ + + # our key to use + h = hashlib.sha512() + h.update(b'string') + key = h.hexdigest() + + # Our limit + assert len(key) == 128 + + # Add our URL + response = self.client.post( + '/add/{}'.format(key), {'urls': 'mailto://user:pass@yahoo.ca'}) + assert response.status_code == 200 + + # remove a key that is too long + response = self.client.post('/del/{}'.format(key + 'x')) + assert response.status_code == 404 + + # remove the key + response = self.client.post('/del/{}'.format(key)) + assert response.status_code == 200 + + # Test again; key is gone + response = self.client.post('/del/{}'.format(key)) + assert response.status_code == 204 + @override_settings(APPRISE_CONFIG_LOCK=True) def test_del_with_lock(self): """ @@ -77,3 +108,7 @@ def test_del_post(self): # We can now remove the key response = self.client.post('/del/{}'.format(key)) assert response.status_code == 200 + + # Key has already been removed + response = self.client.post('/del/{}'.format(key)) + assert response.status_code == 204 diff --git a/apprise_api/api/urls.py b/apprise_api/api/urls.py index 7178e3d..aae908e 100644 --- a/apprise_api/api/urls.py +++ b/apprise_api/api/urls.py @@ -30,27 +30,27 @@ r'^$', views.WelcomeView.as_view(), name='welcome'), re_path( - r'^details/?', + r'^details/?$', views.DetailsView.as_view(), name='details'), re_path( - r'^cfg/(?P[\w_-]{1,64})/?', + r'^cfg/(?P[\w_-]{1,128})/?$', views.ConfigView.as_view(), name='config'), re_path( - r'^add/(?P[\w_-]{1,64})/?', + r'^add/(?P[\w_-]{1,128})/?$', views.AddView.as_view(), name='add'), re_path( - r'^del/(?P[\w_-]{1,64})/?', + r'^del/(?P[\w_-]{1,128})/?$', views.DelView.as_view(), name='del'), re_path( - r'^get/(?P[\w_-]{1,64})/?', + r'^get/(?P[\w_-]{1,128})/?$', views.GetView.as_view(), name='get'), re_path( - r'^notify/(?P[\w_-]{1,64})/?', + r'^notify/(?P[\w_-]{1,128})/?$', views.NotifyView.as_view(), name='notify'), re_path( - r'^notify/?', + r'^notify/?$', views.StatelessNotifyView.as_view(), name='s_notify'), re_path( - r'^json/urls/(?P[\w_-]{1,64})/?', + r'^json/urls/(?P[\w_-]{1,128})/?$', views.JsonUrlView.as_view(), name='json_urls'), ]