mirror of
https://github.com/inventree/InvenTree.git
synced 2026-09-10 06:37:17 +00:00
(cherry picked from commit 1238daa783)
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
This commit is contained in:
co-authored by
Oliver
parent
08ae4aba07
commit
2ddc615ca2
@@ -64,6 +64,7 @@ from order.status_codes import (
|
|||||||
)
|
)
|
||||||
from part.models import Part
|
from part.models import Part
|
||||||
from users.models import Owner
|
from users.models import Owner
|
||||||
|
from users.permissions import check_user_permission
|
||||||
|
|
||||||
|
|
||||||
class GeneralExtraLineListOutputOptions(OutputConfiguration):
|
class GeneralExtraLineListOutputOptions(OutputConfiguration):
|
||||||
@@ -2386,6 +2387,32 @@ class OrderCalendarExport(ICalFeed):
|
|||||||
timezone = settings.TIME_ZONE
|
timezone = settings.TIME_ZONE
|
||||||
file_name = 'calendar.ics'
|
file_name = 'calendar.ics'
|
||||||
|
|
||||||
|
# Map the URL 'ordertype' kwarg to the corresponding order model,
|
||||||
|
# so that access can be checked against the matching RuleSet
|
||||||
|
ORDER_MODELS = {
|
||||||
|
'purchase-order': models.PurchaseOrder,
|
||||||
|
'sales-order': models.SalesOrder,
|
||||||
|
'return-order': models.ReturnOrder,
|
||||||
|
'transfer-order': models.TransferOrder,
|
||||||
|
}
|
||||||
|
|
||||||
|
def check_permission(self, request, **kwargs):
|
||||||
|
"""Check that the requesting user has 'view' permission for the requested order type.
|
||||||
|
|
||||||
|
Returns a 403 JsonResponse if the user lacks the required RuleSet permission,
|
||||||
|
or None if access is permitted.
|
||||||
|
"""
|
||||||
|
model = self.ORDER_MODELS.get(kwargs.get('ordertype'))
|
||||||
|
|
||||||
|
if model is not None and not check_user_permission(request.user, model, 'view'):
|
||||||
|
response = JsonResponse({
|
||||||
|
'detail': 'You do not have permission to view this resource.'
|
||||||
|
})
|
||||||
|
response.status_code = 403
|
||||||
|
return response
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
def __call__(self, request, *args, **kwargs):
|
def __call__(self, request, *args, **kwargs):
|
||||||
"""Overload call in order to check for authentication.
|
"""Overload call in order to check for authentication.
|
||||||
|
|
||||||
@@ -2402,6 +2429,8 @@ class OrderCalendarExport(ICalFeed):
|
|||||||
|
|
||||||
if request.user.is_authenticated:
|
if request.user.is_authenticated:
|
||||||
# Authenticated on first try - maybe normal browser call?
|
# Authenticated on first try - maybe normal browser call?
|
||||||
|
if forbidden := self.check_permission(request, **kwargs):
|
||||||
|
return forbidden
|
||||||
return super().__call__(request, *args, **kwargs)
|
return super().__call__(request, *args, **kwargs)
|
||||||
|
|
||||||
# No login yet - check in headers
|
# No login yet - check in headers
|
||||||
@@ -2420,6 +2449,8 @@ class OrderCalendarExport(ICalFeed):
|
|||||||
# Check again
|
# Check again
|
||||||
if request.user.is_authenticated:
|
if request.user.is_authenticated:
|
||||||
# Authenticated after second try
|
# Authenticated after second try
|
||||||
|
if forbidden := self.check_permission(request, **kwargs):
|
||||||
|
return forbidden
|
||||||
return super().__call__(request, *args, **kwargs)
|
return super().__call__(request, *args, **kwargs)
|
||||||
|
|
||||||
# Still nothing - return Unauth. header with info on how to authenticate
|
# Still nothing - return Unauth. header with info on how to authenticate
|
||||||
|
|||||||
@@ -853,6 +853,21 @@ class PurchaseOrderTest(OrderTest):
|
|||||||
)
|
)
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
def test_po_calendar_no_permission(self):
|
||||||
|
"""Test that an authenticated user without purchase_order view permission is denied."""
|
||||||
|
self.clearRoles()
|
||||||
|
|
||||||
|
response = self.get(
|
||||||
|
reverse('api-po-so-calendar', kwargs={'ordertype': 'purchase-order'}),
|
||||||
|
expected_code=403,
|
||||||
|
format=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
resp_dict = response.json()
|
||||||
|
self.assertEqual(
|
||||||
|
resp_dict['detail'], 'You do not have permission to view this resource.'
|
||||||
|
)
|
||||||
|
|
||||||
def test_po_custom_status_query_count(self):
|
def test_po_custom_status_query_count(self):
|
||||||
"""Test that listing PurchaseOrders with custom statuses does not cause N+1 queries.
|
"""Test that listing PurchaseOrders with custom statuses does not cause N+1 queries.
|
||||||
|
|
||||||
@@ -2111,6 +2126,21 @@ class SalesOrderTest(OrderTest):
|
|||||||
self.assertGreaterEqual(n_events, 1)
|
self.assertGreaterEqual(n_events, 1)
|
||||||
self.assertEqual(number_orders_incl_complete, n_events)
|
self.assertEqual(number_orders_incl_complete, n_events)
|
||||||
|
|
||||||
|
def test_so_calendar_no_permission(self):
|
||||||
|
"""Test that an authenticated user without sales_order view permission is denied."""
|
||||||
|
self.clearRoles()
|
||||||
|
|
||||||
|
response = self.get(
|
||||||
|
reverse('api-po-so-calendar', kwargs={'ordertype': 'sales-order'}),
|
||||||
|
expected_code=403,
|
||||||
|
format=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
resp_dict = response.json()
|
||||||
|
self.assertEqual(
|
||||||
|
resp_dict['detail'], 'You do not have permission to view this resource.'
|
||||||
|
)
|
||||||
|
|
||||||
def test_export(self):
|
def test_export(self):
|
||||||
"""Test we can export the SalesOrder list."""
|
"""Test we can export the SalesOrder list."""
|
||||||
set_global_setting(models.SalesOrder.UNLOCK_SETTING, True)
|
set_global_setting(models.SalesOrder.UNLOCK_SETTING, True)
|
||||||
@@ -3564,6 +3594,21 @@ class ReturnOrderTests(InvenTreeAPITestCase):
|
|||||||
calendar = Calendar.from_ical(response.content)
|
calendar = Calendar.from_ical(response.content)
|
||||||
self.assertIsInstance(calendar, Calendar)
|
self.assertIsInstance(calendar, Calendar)
|
||||||
|
|
||||||
|
def test_ro_calendar_no_permission(self):
|
||||||
|
"""Test that an authenticated user without return_order view permission is denied."""
|
||||||
|
self.clearRoles()
|
||||||
|
|
||||||
|
response = self.get(
|
||||||
|
reverse('api-po-so-calendar', kwargs={'ordertype': 'return-order'}),
|
||||||
|
expected_code=403,
|
||||||
|
format=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
resp_dict = response.json()
|
||||||
|
self.assertEqual(
|
||||||
|
resp_dict['detail'], 'You do not have permission to view this resource.'
|
||||||
|
)
|
||||||
|
|
||||||
def test_export(self):
|
def test_export(self):
|
||||||
"""Test data export for the ReturnOrder API endpoints."""
|
"""Test data export for the ReturnOrder API endpoints."""
|
||||||
# Export return orders
|
# Export return orders
|
||||||
@@ -4114,6 +4159,21 @@ class TransferOrderTest(OrderTest):
|
|||||||
self.assertGreaterEqual(n_events, 1)
|
self.assertGreaterEqual(n_events, 1)
|
||||||
self.assertEqual(number_orders_incl_complete, n_events)
|
self.assertEqual(number_orders_incl_complete, n_events)
|
||||||
|
|
||||||
|
def test_transfer_order_calendar_no_permission(self):
|
||||||
|
"""Test that an authenticated user without transfer_order view permission is denied."""
|
||||||
|
self.clearRoles()
|
||||||
|
|
||||||
|
response = self.get(
|
||||||
|
reverse('api-po-so-calendar', kwargs={'ordertype': 'transfer-order'}),
|
||||||
|
expected_code=403,
|
||||||
|
format=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
resp_dict = response.json()
|
||||||
|
self.assertEqual(
|
||||||
|
resp_dict['detail'], 'You do not have permission to view this resource.'
|
||||||
|
)
|
||||||
|
|
||||||
def test_export(self):
|
def test_export(self):
|
||||||
"""Test we can export the TransferOrder list."""
|
"""Test we can export the TransferOrder list."""
|
||||||
n = models.TransferOrder.objects.count()
|
n = models.TransferOrder.objects.count()
|
||||||
|
|||||||
Reference in New Issue
Block a user