mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-15 19:45:46 +00:00
Check user permissions before linking or un-linking barcodes (#3772)
* Check user permissions before linking or un-linking barcodse * Bump API version * Permission fixes for unit tests * Fix permission issues * Unit test fixes
This commit is contained in:
@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
|
|
||||||
# InvenTree API version
|
# InvenTree API version
|
||||||
INVENTREE_API_VERSION = 76
|
INVENTREE_API_VERSION = 77
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Increment this API version number whenever there is a significant change to the API that any clients need to know about
|
Increment this API version number whenever there is a significant change to the API that any clients need to know about
|
||||||
|
|
||||||
|
v77 -> 2022-10-12 : https://github.com/inventree/InvenTree/pull/3772
|
||||||
|
- Adds model permission checks for barcode assignment actions
|
||||||
|
|
||||||
v76 -> 2022-09-10 : https://github.com/inventree/InvenTree/pull/3640
|
v76 -> 2022-09-10 : https://github.com/inventree/InvenTree/pull/3640
|
||||||
- Refactor of barcode data on the API
|
- Refactor of barcode data on the API
|
||||||
- StockItem.uid renamed to StockItem.barcode_hash
|
- StockItem.uid renamed to StockItem.barcode_hash
|
||||||
|
@ -5,7 +5,7 @@ from django.urls import path, re_path
|
|||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from rest_framework import permissions
|
from rest_framework import permissions
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import PermissionDenied, ValidationError
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
@ -13,6 +13,7 @@ from InvenTree.helpers import hash_barcode
|
|||||||
from plugin import registry
|
from plugin import registry
|
||||||
from plugin.builtin.barcodes.inventree_barcode import (
|
from plugin.builtin.barcodes.inventree_barcode import (
|
||||||
InvenTreeExternalBarcodePlugin, InvenTreeInternalBarcodePlugin)
|
InvenTreeExternalBarcodePlugin, InvenTreeInternalBarcodePlugin)
|
||||||
|
from users.models import RuleSet
|
||||||
|
|
||||||
|
|
||||||
class BarcodeScan(APIView):
|
class BarcodeScan(APIView):
|
||||||
@ -139,6 +140,17 @@ class BarcodeAssign(APIView):
|
|||||||
try:
|
try:
|
||||||
instance = model.objects.get(pk=data[label])
|
instance = model.objects.get(pk=data[label])
|
||||||
|
|
||||||
|
# Check that the user has the required permission
|
||||||
|
app_label = model._meta.app_label
|
||||||
|
model_name = model._meta.model_name
|
||||||
|
|
||||||
|
table = f"{app_label}_{model_name}"
|
||||||
|
|
||||||
|
if not RuleSet.check_table_permission(request.user, table, "change"):
|
||||||
|
raise PermissionDenied({
|
||||||
|
"error": f"You do not have the required permissions for {table}"
|
||||||
|
})
|
||||||
|
|
||||||
instance.assign_barcode(
|
instance.assign_barcode(
|
||||||
barcode_data=barcode_data,
|
barcode_data=barcode_data,
|
||||||
barcode_hash=barcode_hash,
|
barcode_hash=barcode_hash,
|
||||||
@ -210,6 +222,17 @@ class BarcodeUnassign(APIView):
|
|||||||
label: _('No match found for provided value')
|
label: _('No match found for provided value')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# Check that the user has the required permission
|
||||||
|
app_label = model._meta.app_label
|
||||||
|
model_name = model._meta.model_name
|
||||||
|
|
||||||
|
table = f"{app_label}_{model_name}"
|
||||||
|
|
||||||
|
if not RuleSet.check_table_permission(request.user, table, "change"):
|
||||||
|
raise PermissionDenied({
|
||||||
|
"error": f"You do not have the required permissions for {table}"
|
||||||
|
})
|
||||||
|
|
||||||
# Unassign the barcode data from the model instance
|
# Unassign the barcode data from the model instance
|
||||||
instance.unassign_barcode()
|
instance.unassign_barcode()
|
||||||
|
|
||||||
|
@ -190,6 +190,8 @@ class BarcodeAPITest(InvenTreeAPITestCase):
|
|||||||
"""Test that a barcode can be associated with a StockItem."""
|
"""Test that a barcode can be associated with a StockItem."""
|
||||||
item = StockItem.objects.get(pk=522)
|
item = StockItem.objects.get(pk=522)
|
||||||
|
|
||||||
|
self.assignRole('stock.change')
|
||||||
|
|
||||||
self.assertEqual(len(item.barcode_hash), 0)
|
self.assertEqual(len(item.barcode_hash), 0)
|
||||||
|
|
||||||
barcode_data = 'A-TEST-BARCODE-STRING'
|
barcode_data = 'A-TEST-BARCODE-STRING'
|
||||||
|
@ -125,6 +125,19 @@ class TestInvenTreeBarcode(InvenTreeAPITestCase):
|
|||||||
|
|
||||||
self.assertIn('Missing data:', str(response.data))
|
self.assertIn('Missing data:', str(response.data))
|
||||||
|
|
||||||
|
# Permission error check
|
||||||
|
response = self.assign(
|
||||||
|
{
|
||||||
|
'barcode': 'abcdefg',
|
||||||
|
'part': 1,
|
||||||
|
'stockitem': 1,
|
||||||
|
},
|
||||||
|
expected_code=403
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assignRole('part.change')
|
||||||
|
self.assignRole('stock.change')
|
||||||
|
|
||||||
# Provide too many fields
|
# Provide too many fields
|
||||||
response = self.assign(
|
response = self.assign(
|
||||||
{
|
{
|
||||||
@ -188,6 +201,8 @@ class TestInvenTreeBarcode(InvenTreeAPITestCase):
|
|||||||
|
|
||||||
barcode = 'xyz-123'
|
barcode = 'xyz-123'
|
||||||
|
|
||||||
|
self.assignRole('part.change')
|
||||||
|
|
||||||
# Test that an initial scan yields no results
|
# Test that an initial scan yields no results
|
||||||
response = self.scan(
|
response = self.scan(
|
||||||
{
|
{
|
||||||
@ -196,6 +211,8 @@ class TestInvenTreeBarcode(InvenTreeAPITestCase):
|
|||||||
expected_code=400
|
expected_code=400
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.assignRole('part.change')
|
||||||
|
|
||||||
# Attempt to assign to an invalid part ID
|
# Attempt to assign to an invalid part ID
|
||||||
response = self.assign(
|
response = self.assign(
|
||||||
{
|
{
|
||||||
@ -247,6 +264,8 @@ class TestInvenTreeBarcode(InvenTreeAPITestCase):
|
|||||||
|
|
||||||
self.assertIn('Barcode matches existing item', str(response.data['error']))
|
self.assertIn('Barcode matches existing item', str(response.data['error']))
|
||||||
|
|
||||||
|
self.assignRole('part.change')
|
||||||
|
|
||||||
# Now test that we can unassign the barcode data also
|
# Now test that we can unassign the barcode data also
|
||||||
response = self.unassign(
|
response = self.unassign(
|
||||||
{
|
{
|
||||||
@ -265,6 +284,17 @@ class TestInvenTreeBarcode(InvenTreeAPITestCase):
|
|||||||
|
|
||||||
barcode = '555555555555555555555555'
|
barcode = '555555555555555555555555'
|
||||||
|
|
||||||
|
# Assign random barcode data to a StockLocation instance
|
||||||
|
response = self.assign(
|
||||||
|
data={
|
||||||
|
'barcode': barcode,
|
||||||
|
'stocklocation': 1,
|
||||||
|
},
|
||||||
|
expected_code=403,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assignRole('stock_location.change')
|
||||||
|
|
||||||
# Assign random barcode data to a StockLocation instance
|
# Assign random barcode data to a StockLocation instance
|
||||||
response = self.assign(
|
response = self.assign(
|
||||||
data={
|
data={
|
||||||
|
Reference in New Issue
Block a user