From 29b8ed91d22e7471a75c1197cd8f45a13ad40fdd Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 18 Jun 2026 22:18:14 +1000 Subject: [PATCH] [API] Adjust permissions for machine restart (#12197) * [API] Adjust permissions for machine restart Can only be actioned by a staff user * Fix import * Wrong class * Extend unit test * Bump API version * Update CHANGELOG --- CHANGELOG.md | 1 + src/backend/InvenTree/InvenTree/api_version.py | 5 ++++- src/backend/InvenTree/machine/api.py | 6 +++++- src/backend/InvenTree/machine/test_api.py | 15 ++++++++++++--- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2abba4e75e..4c441b199c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- [#12197](https://github.com/inventree/InvenTree/pull/12197) requires staff permissions to restart machines via the API. - [#12142](https://github.com/inventree/InvenTree/pull/12142) prevents users from printing reports or labels against models for which they do not have adequate permissions. This change improves the security of the system by ensuring that users cannot access or print reports or labels for models they do not have permission to view. - [#11990](https://github.com/inventree/InvenTree/pull/11990) build output operations performed via the API now offload the work to a background task, and now return a task ID which can be used to monitor the progress of the task. This allows for better performance and responsiveness when performing build output operations, as the work is performed asynchronously in the background. - [#11825](https://github.com/inventree/InvenTree/pull/11825) adds a new "bom" ruleset and associated permissions for BOM management, separate from the "part" ruleset which remains focused on part management. This allows for more granular control over user permissions, allowing users to have different levels of access to part management and BOM management functionality. diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index 2b522c0987..fff7f52f77 100644 --- a/src/backend/InvenTree/InvenTree/api_version.py +++ b/src/backend/InvenTree/InvenTree/api_version.py @@ -1,11 +1,14 @@ """InvenTree API version information.""" # InvenTree API version -INVENTREE_API_VERSION = 509 +INVENTREE_API_VERSION = 510 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ +v510 -> 2026-06-18 : https://github.com/inventree/InvenTree/pull/12197 + - Require "staff" access permissions for the machine restart API endpoint + v509 -> 2026-06-17 : https://github.com/inventree/InvenTree/pull/12184 - Adds "completed_row_count_history" and "row_count_history" fields to the DataImportSession model, which store the historic count of completed rows and total rows for a data import session. diff --git a/src/backend/InvenTree/machine/api.py b/src/backend/InvenTree/machine/api.py index bea28dfcfd..bc78c7737c 100644 --- a/src/backend/InvenTree/machine/api.py +++ b/src/backend/InvenTree/machine/api.py @@ -3,6 +3,7 @@ from django.urls import include, path, re_path from drf_spectacular.utils import extend_schema +from rest_framework import permissions from rest_framework.exceptions import NotFound from rest_framework.response import Response from rest_framework.views import APIView @@ -142,7 +143,10 @@ class MachineRestart(APIView): - POST: restart machine by pk """ - permission_classes = [InvenTree.permissions.IsAuthenticatedOrReadScope] + permission_classes = [ + permissions.IsAuthenticated, + InvenTree.permissions.IsStaffOrReadOnlyScope, + ] @extend_schema( request=None, responses={200: MachineSerializers.MachineRestartSerializer()} diff --git a/src/backend/InvenTree/machine/test_api.py b/src/backend/InvenTree/machine/test_api.py index 32a2809d2f..eb2e7584a9 100644 --- a/src/backend/InvenTree/machine/test_api.py +++ b/src/backend/InvenTree/machine/test_api.py @@ -287,14 +287,23 @@ class MachineAPITest(TestMachineRegistryMixin, InvenTreeAPITestCase): active=True, ) + restart_url = reverse('api-machine-restart', kwargs={'pk': machine.pk}) + + # Non-staff users must not be able to restart a machine + self.user.is_staff = False + self.user.save() + self.post(restart_url, expected_code=403) + + # Restore staff access + self.user.is_staff = True + self.user.save() + # verify machine status before restart response = self.get(reverse('api-machine-detail', kwargs={'pk': machine.pk})) self.assertEqual(response.data['status_text'], '') # restart the machine - response = self.post( - reverse('api-machine-restart', kwargs={'pk': machine.pk}), expected_code=200 - ) + self.post(restart_url, expected_code=200) # verify machine status after restart response = self.get(reverse('api-machine-detail', kwargs={'pk': machine.pk}))