mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
226 lines
7.0 KiB
Python
226 lines
7.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
from __future__ import unicode_literals
|
|
from http import HTTPStatus
|
|
import json
|
|
from datetime import timedelta
|
|
|
|
from django.test import TestCase, Client
|
|
from django.contrib.auth import get_user_model
|
|
|
|
from .models import InvenTreeSetting, WebhookEndpoint, WebhookMessage, NotificationEntry
|
|
from .api import WebhookView
|
|
|
|
CONTENT_TYPE_JSON = 'application/json'
|
|
|
|
|
|
class SettingsTest(TestCase):
|
|
"""
|
|
Tests for the 'settings' model
|
|
"""
|
|
|
|
fixtures = [
|
|
'settings',
|
|
]
|
|
|
|
def setUp(self):
|
|
|
|
user = get_user_model()
|
|
|
|
self.user = user.objects.create_user('username', 'user@email.com', 'password')
|
|
self.user.is_staff = True
|
|
self.user.save()
|
|
|
|
self.client.login(username='username', password='password')
|
|
|
|
def test_settings_objects(self):
|
|
|
|
# There should be two settings objects in the database
|
|
settings = InvenTreeSetting.objects.all()
|
|
|
|
self.assertTrue(settings.count() >= 2)
|
|
|
|
instance_name = InvenTreeSetting.objects.get(pk=1)
|
|
self.assertEqual(instance_name.key, 'INVENTREE_INSTANCE')
|
|
self.assertEqual(instance_name.value, 'My very first InvenTree Instance')
|
|
|
|
# Check object lookup (case insensitive)
|
|
self.assertEqual(InvenTreeSetting.get_setting_object('iNvEnTrEE_inSTanCE').pk, 1)
|
|
|
|
def test_required_values(self):
|
|
"""
|
|
- Ensure that every global setting has a name.
|
|
- Ensure that every global setting has a description.
|
|
"""
|
|
|
|
for key in InvenTreeSetting.SETTINGS.keys():
|
|
|
|
setting = InvenTreeSetting.SETTINGS[key]
|
|
|
|
name = setting.get('name', None)
|
|
|
|
if name is None:
|
|
raise ValueError(f'Missing GLOBAL_SETTING name for {key}') # pragma: no cover
|
|
|
|
description = setting.get('description', None)
|
|
|
|
if description is None:
|
|
raise ValueError(f'Missing GLOBAL_SETTING description for {key}') # pragma: no cover
|
|
|
|
if not key == key.upper():
|
|
raise ValueError(f"SETTINGS key '{key}' is not uppercase") # pragma: no cover
|
|
|
|
def test_defaults(self):
|
|
"""
|
|
Populate the settings with default values
|
|
"""
|
|
|
|
for key in InvenTreeSetting.SETTINGS.keys():
|
|
|
|
value = InvenTreeSetting.get_setting_default(key)
|
|
|
|
InvenTreeSetting.set_setting(key, value, self.user)
|
|
|
|
self.assertEqual(value, InvenTreeSetting.get_setting(key))
|
|
|
|
# Any fields marked as 'boolean' must have a default value specified
|
|
setting = InvenTreeSetting.get_setting_object(key)
|
|
|
|
if setting.is_bool():
|
|
if setting.default_value in ['', None]:
|
|
raise ValueError(f'Default value for boolean setting {key} not provided') # pragma: no cover
|
|
|
|
if setting.default_value not in [True, False]:
|
|
raise ValueError(f'Non-boolean default value specified for {key}') # pragma: no cover
|
|
|
|
|
|
class WebhookMessageTests(TestCase):
|
|
def setUp(self):
|
|
self.endpoint_def = WebhookEndpoint.objects.create()
|
|
self.url = f'/api/webhook/{self.endpoint_def.endpoint_id}/'
|
|
self.client = Client(enforce_csrf_checks=True)
|
|
|
|
def test_bad_method(self):
|
|
response = self.client.get(self.url)
|
|
|
|
assert response.status_code == HTTPStatus.METHOD_NOT_ALLOWED
|
|
|
|
def test_missing_token(self):
|
|
response = self.client.post(
|
|
self.url,
|
|
content_type=CONTENT_TYPE_JSON,
|
|
)
|
|
|
|
assert response.status_code == HTTPStatus.FORBIDDEN
|
|
assert (
|
|
json.loads(response.content)['detail'] == WebhookView.model_class.MESSAGE_TOKEN_ERROR
|
|
)
|
|
|
|
def test_bad_token(self):
|
|
response = self.client.post(
|
|
self.url,
|
|
content_type=CONTENT_TYPE_JSON,
|
|
**{'HTTP_TOKEN': '1234567fghj'},
|
|
)
|
|
|
|
assert response.status_code == HTTPStatus.FORBIDDEN
|
|
assert (json.loads(response.content)['detail'] == WebhookView.model_class.MESSAGE_TOKEN_ERROR)
|
|
|
|
def test_bad_url(self):
|
|
response = self.client.post(
|
|
'/api/webhook/1234/',
|
|
content_type=CONTENT_TYPE_JSON,
|
|
)
|
|
|
|
assert response.status_code == HTTPStatus.NOT_FOUND
|
|
|
|
def test_bad_json(self):
|
|
response = self.client.post(
|
|
self.url,
|
|
data="{'this': 123}",
|
|
content_type=CONTENT_TYPE_JSON,
|
|
**{'HTTP_TOKEN': str(self.endpoint_def.token)},
|
|
)
|
|
|
|
assert response.status_code == HTTPStatus.NOT_ACCEPTABLE
|
|
assert (
|
|
json.loads(response.content)['detail'] == 'Expecting property name enclosed in double quotes'
|
|
)
|
|
|
|
def test_success_no_token_check(self):
|
|
# delete token
|
|
self.endpoint_def.token = ''
|
|
self.endpoint_def.save()
|
|
|
|
# check
|
|
response = self.client.post(
|
|
self.url,
|
|
content_type=CONTENT_TYPE_JSON,
|
|
)
|
|
|
|
assert response.status_code == HTTPStatus.OK
|
|
assert str(response.content, 'utf-8') == WebhookView.model_class.MESSAGE_OK
|
|
|
|
def test_bad_hmac(self):
|
|
# delete token
|
|
self.endpoint_def.token = ''
|
|
self.endpoint_def.secret = '123abc'
|
|
self.endpoint_def.save()
|
|
|
|
# check
|
|
response = self.client.post(
|
|
self.url,
|
|
content_type=CONTENT_TYPE_JSON,
|
|
)
|
|
|
|
assert response.status_code == HTTPStatus.FORBIDDEN
|
|
assert (json.loads(response.content)['detail'] == WebhookView.model_class.MESSAGE_TOKEN_ERROR)
|
|
|
|
def test_success_hmac(self):
|
|
# delete token
|
|
self.endpoint_def.token = ''
|
|
self.endpoint_def.secret = '123abc'
|
|
self.endpoint_def.save()
|
|
|
|
# check
|
|
response = self.client.post(
|
|
self.url,
|
|
content_type=CONTENT_TYPE_JSON,
|
|
**{'HTTP_TOKEN': str('68MXtc/OiXdA5e2Nq9hATEVrZFpLb3Zb0oau7n8s31I=')},
|
|
)
|
|
|
|
assert response.status_code == HTTPStatus.OK
|
|
assert str(response.content, 'utf-8') == WebhookView.model_class.MESSAGE_OK
|
|
|
|
def test_success(self):
|
|
response = self.client.post(
|
|
self.url,
|
|
data={"this": "is a message"},
|
|
content_type=CONTENT_TYPE_JSON,
|
|
**{'HTTP_TOKEN': str(self.endpoint_def.token)},
|
|
)
|
|
|
|
assert response.status_code == HTTPStatus.OK
|
|
assert str(response.content, 'utf-8') == WebhookView.model_class.MESSAGE_OK
|
|
message = WebhookMessage.objects.get()
|
|
assert message.body == {"this": "is a message"}
|
|
|
|
|
|
class NotificationTest(TestCase):
|
|
|
|
def test_check_notification_entries(self):
|
|
|
|
# Create some notification entries
|
|
|
|
self.assertEqual(NotificationEntry.objects.count(), 0)
|
|
|
|
NotificationEntry.notify('test.notification', 1)
|
|
|
|
self.assertEqual(NotificationEntry.objects.count(), 1)
|
|
|
|
delta = timedelta(days=1)
|
|
|
|
self.assertFalse(NotificationEntry.check_recent('test.notification', 2, delta))
|
|
self.assertFalse(NotificationEntry.check_recent('test.notification2', 1, delta))
|
|
|
|
self.assertTrue(NotificationEntry.check_recent('test.notification', 1, delta))
|