mirror of
https://github.com/caronc/apprise-api.git
synced 2025-08-16 01:27:47 +02:00
Server-side handling of new apprise:// schema (#56)
This commit is contained in:
@ -492,3 +492,99 @@ class NotifyTests(SimpleTestCase):
|
||||
|
||||
# nothing was changed
|
||||
assert apprise.plugins.SCHEMA_MAP['mailto'].enabled is True
|
||||
|
||||
@override_settings(APPRISE_RECURSION_MAX=1)
|
||||
@patch('apprise.Apprise.notify')
|
||||
def test_stateful_notify_recursion(self, mock_notify):
|
||||
"""
|
||||
Test recursion an id header details as part of post
|
||||
"""
|
||||
|
||||
# Set our return value
|
||||
mock_notify.return_value = True
|
||||
|
||||
# our key to use
|
||||
key = 'test_stateful_notify_recursion'
|
||||
|
||||
# Add some content
|
||||
response = self.client.post(
|
||||
'/add/{}'.format(key),
|
||||
{'urls': 'mailto://user:pass@yahoo.ca'})
|
||||
assert response.status_code == 200
|
||||
|
||||
# Form data
|
||||
form_data = {
|
||||
'body': 'test notifiction',
|
||||
}
|
||||
|
||||
# Define our headers we plan to pass along with our request
|
||||
headers = {
|
||||
'HTTP_X-APPRISE-ID': 'abc123',
|
||||
'HTTP_X-APPRISE-RECURSION-COUNT': str(1),
|
||||
}
|
||||
|
||||
# Send our notification
|
||||
response = self.client.post(
|
||||
'/notify/{}'.format(key), data=form_data, **headers)
|
||||
assert response.status_code == 200
|
||||
assert mock_notify.call_count == 1
|
||||
|
||||
headers = {
|
||||
# Header specified but with whitespace
|
||||
'HTTP_X-APPRISE-ID': ' ',
|
||||
# No Recursion value specified
|
||||
}
|
||||
|
||||
# Reset our count
|
||||
mock_notify.reset_mock()
|
||||
|
||||
# Recursion limit reached
|
||||
response = self.client.post(
|
||||
'/notify/{}'.format(key), data=form_data, **headers)
|
||||
assert response.status_code == 200
|
||||
assert mock_notify.call_count == 1
|
||||
|
||||
headers = {
|
||||
'HTTP_X-APPRISE-ID': 'abc123',
|
||||
# Recursion Limit hit
|
||||
'HTTP_X-APPRISE-RECURSION-COUNT': str(2),
|
||||
}
|
||||
|
||||
# Reset our count
|
||||
mock_notify.reset_mock()
|
||||
|
||||
# Recursion limit reached
|
||||
response = self.client.post(
|
||||
'/notify/{}'.format(key), data=form_data, **headers)
|
||||
assert response.status_code == 406
|
||||
assert mock_notify.call_count == 0
|
||||
|
||||
headers = {
|
||||
'HTTP_X-APPRISE-ID': 'abc123',
|
||||
# Negative recursion value (bad request)
|
||||
'HTTP_X-APPRISE-RECURSION-COUNT': str(-1),
|
||||
}
|
||||
|
||||
# Reset our count
|
||||
mock_notify.reset_mock()
|
||||
|
||||
# invalid recursion specified
|
||||
response = self.client.post(
|
||||
'/notify/{}'.format(key), data=form_data, **headers)
|
||||
assert response.status_code == 400
|
||||
assert mock_notify.call_count == 0
|
||||
|
||||
headers = {
|
||||
'HTTP_X-APPRISE-ID': 'abc123',
|
||||
# Invalid recursion value (bad request)
|
||||
'HTTP_X-APPRISE-RECURSION-COUNT': 'invalid',
|
||||
}
|
||||
|
||||
# Reset our count
|
||||
mock_notify.reset_mock()
|
||||
|
||||
# invalid recursion specified
|
||||
response = self.client.post(
|
||||
'/notify/{}'.format(key), data=form_data, **headers)
|
||||
assert response.status_code == 400
|
||||
assert mock_notify.call_count == 0
|
||||
|
@ -113,6 +113,93 @@ class StatelessNotifyTests(SimpleTestCase):
|
||||
assert response.status_code == 424
|
||||
assert mock_notify.call_count == 2
|
||||
|
||||
@override_settings(APPRISE_RECURSION_MAX=1)
|
||||
@patch('apprise.Apprise.notify')
|
||||
def test_stateless_notify_recursion(self, mock_notify):
|
||||
"""
|
||||
Test recursion an id header details as part of post
|
||||
"""
|
||||
|
||||
# Set our return value
|
||||
mock_notify.return_value = True
|
||||
|
||||
headers = {
|
||||
'HTTP_X-APPRISE-ID': 'abc123',
|
||||
'HTTP_X-APPRISE-RECURSION-COUNT': str(1),
|
||||
}
|
||||
|
||||
# Preare our form data (without url specified)
|
||||
# content will fall back to default configuration
|
||||
form_data = {
|
||||
'urls': 'mailto://user:pass@hotmail.com',
|
||||
'body': 'test notifiction',
|
||||
}
|
||||
|
||||
# At a minimum 'body' is requred
|
||||
form = NotifyByUrlForm(data=form_data)
|
||||
assert form.is_valid()
|
||||
|
||||
# recursion value is within correct limits
|
||||
response = self.client.post('/notify', form.cleaned_data, **headers)
|
||||
assert response.status_code == 200
|
||||
assert mock_notify.call_count == 1
|
||||
|
||||
headers = {
|
||||
# Header specified but with whitespace
|
||||
'HTTP_X-APPRISE-ID': ' ',
|
||||
# No Recursion value specified
|
||||
}
|
||||
|
||||
# Reset our count
|
||||
mock_notify.reset_mock()
|
||||
|
||||
# Recursion limit reached
|
||||
response = self.client.post('/notify', form.cleaned_data, **headers)
|
||||
assert response.status_code == 200
|
||||
assert mock_notify.call_count == 1
|
||||
|
||||
headers = {
|
||||
'HTTP_X-APPRISE-ID': 'abc123',
|
||||
# Recursion Limit hit
|
||||
'HTTP_X-APPRISE-RECURSION-COUNT': str(2),
|
||||
}
|
||||
|
||||
# Reset our count
|
||||
mock_notify.reset_mock()
|
||||
|
||||
# Recursion limit reached
|
||||
response = self.client.post('/notify', form.cleaned_data, **headers)
|
||||
assert response.status_code == 406
|
||||
assert mock_notify.call_count == 0
|
||||
|
||||
headers = {
|
||||
'HTTP_X-APPRISE-ID': 'abc123',
|
||||
# Negative recursion value (bad request)
|
||||
'HTTP_X-APPRISE-RECURSION-COUNT': str(-1),
|
||||
}
|
||||
|
||||
# Reset our count
|
||||
mock_notify.reset_mock()
|
||||
|
||||
# invalid recursion specified
|
||||
response = self.client.post('/notify', form.cleaned_data, **headers)
|
||||
assert response.status_code == 400
|
||||
assert mock_notify.call_count == 0
|
||||
|
||||
headers = {
|
||||
'HTTP_X-APPRISE-ID': 'abc123',
|
||||
# Invalid recursion value (bad request)
|
||||
'HTTP_X-APPRISE-RECURSION-COUNT': 'invalid',
|
||||
}
|
||||
|
||||
# Reset our count
|
||||
mock_notify.reset_mock()
|
||||
|
||||
# invalid recursion specified
|
||||
response = self.client.post('/notify', form.cleaned_data, **headers)
|
||||
assert response.status_code == 400
|
||||
assert mock_notify.call_count == 0
|
||||
|
||||
@override_settings(APPRISE_STATELESS_URLS="mailto://user:pass@localhost")
|
||||
@patch('apprise.Apprise.notify')
|
||||
def test_notify_default_urls(self, mock_notify):
|
||||
|
@ -89,6 +89,7 @@ class ResponseCode(object):
|
||||
no_access = 403
|
||||
not_found = 404
|
||||
method_not_allowed = 405
|
||||
method_not_accepted = 406
|
||||
failed_dependency = 424
|
||||
internal_server_error = 500
|
||||
|
||||
@ -623,6 +624,41 @@ class NotifyView(View):
|
||||
'APPRISE_DENY_SERVICES plugin %s:// was not found -'
|
||||
' ignoring.', name)
|
||||
|
||||
# Prepare our keyword arguments (to be passed into an AppriseAsset
|
||||
# object)
|
||||
kwargs = {}
|
||||
|
||||
if body_format:
|
||||
# Store our defined body format
|
||||
kwargs['body_format'] = body_format
|
||||
|
||||
# Acquire our recursion count (if defined)
|
||||
try:
|
||||
recursion = \
|
||||
int(request.headers.get('X-Apprise-Recursion-Count', 0))
|
||||
|
||||
if recursion < 0:
|
||||
# We do not accept negative numbers
|
||||
raise TypeError("Invalid Recursion Value")
|
||||
|
||||
if recursion > settings.APPRISE_RECURSION_MAX:
|
||||
return HttpResponse(
|
||||
_('The recursion limit has been reached.'),
|
||||
status=ResponseCode.method_not_accepted)
|
||||
|
||||
# Store our recursion value for our AppriseAsset() initialization
|
||||
kwargs['_recursion'] = recursion
|
||||
|
||||
except (TypeError, ValueError):
|
||||
return HttpResponse(
|
||||
_('An invalid recursion value was specified.'),
|
||||
status=ResponseCode.bad_request)
|
||||
|
||||
# Acquire our unique identifier (if defined)
|
||||
uid = request.headers.get('X-Apprise-ID', '').strip()
|
||||
if uid:
|
||||
kwargs['_uid'] = uid
|
||||
|
||||
# Prepare ourselves a default Asset
|
||||
asset = None if not body_format else \
|
||||
apprise.AppriseAsset(body_format=body_format)
|
||||
@ -785,6 +821,41 @@ class StatelessNotifyView(View):
|
||||
_('An invalid (body) format was specified.'),
|
||||
status=ResponseCode.bad_request)
|
||||
|
||||
# Prepare our keyword arguments (to be passed into an AppriseAsset
|
||||
# object)
|
||||
kwargs = {}
|
||||
|
||||
if body_format:
|
||||
# Store our defined body format
|
||||
kwargs['body_format'] = body_format
|
||||
|
||||
# Acquire our recursion count (if defined)
|
||||
try:
|
||||
recursion = \
|
||||
int(request.headers.get('X-Apprise-Recursion-Count', 0))
|
||||
|
||||
if recursion < 0:
|
||||
# We do not accept negative numbers
|
||||
raise TypeError("Invalid Recursion Value")
|
||||
|
||||
if recursion > settings.APPRISE_RECURSION_MAX:
|
||||
return HttpResponse(
|
||||
_('The recursion limit has been reached.'),
|
||||
status=ResponseCode.method_not_accepted)
|
||||
|
||||
# Store our recursion value for our AppriseAsset() initialization
|
||||
kwargs['_recursion'] = recursion
|
||||
|
||||
except (TypeError, ValueError):
|
||||
return HttpResponse(
|
||||
_('An invalid recursion value was specified.'),
|
||||
status=ResponseCode.bad_request)
|
||||
|
||||
# Acquire our unique identifier (if defined)
|
||||
uid = request.headers.get('X-Apprise-ID', '').strip()
|
||||
if uid:
|
||||
kwargs['_uid'] = uid
|
||||
|
||||
# Prepare ourselves a default Asset
|
||||
asset = None if not body_format else \
|
||||
apprise.AppriseAsset(body_format=body_format)
|
||||
|
Reference in New Issue
Block a user