mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Group API (#4327)
* Add basic endpoint for group information * Add hardcoded api-url lookup function for django models * Adds JS function for rendering a 'group' * Fix typo * Add unit tests for new endpoints * Increment API version * JS linting
This commit is contained in:
parent
06605e70c5
commit
f4e8c05165
@ -2,11 +2,14 @@
|
||||
|
||||
|
||||
# InvenTree API version
|
||||
INVENTREE_API_VERSION = 93
|
||||
INVENTREE_API_VERSION = 94
|
||||
|
||||
"""
|
||||
Increment this API version number whenever there is a significant change to the API that any clients need to know about
|
||||
|
||||
v94 -> 2023-02-10 : https://github.com/inventree/InvenTree/pull/4327
|
||||
- Adds API endpoints for the "Group" auth model
|
||||
|
||||
v93 -> 2023-02-03 : https://github.com/inventree/InvenTree/pull/4300
|
||||
- Adds extra information to the currency exchange endpoint
|
||||
- Adds API endpoint for manually updating exchange rates
|
||||
|
@ -704,6 +704,17 @@ class BaseInvenTreeSetting(models.Model):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Some other model types are hard-coded
|
||||
hardcoded_models = {
|
||||
'auth.user': 'api-user-list',
|
||||
'auth.group': 'api-group-list',
|
||||
}
|
||||
|
||||
model_table = f'{model_class._meta.app_label}.{model_class._meta.model_name}'
|
||||
|
||||
if url := hardcoded_models[model_table]:
|
||||
return reverse(url)
|
||||
|
||||
return None
|
||||
|
||||
def is_bool(self):
|
||||
|
@ -11,6 +11,7 @@
|
||||
modalShowSubmitButton,
|
||||
renderBuild,
|
||||
renderCompany,
|
||||
renderGroup,
|
||||
renderManufacturerPart,
|
||||
renderOwner,
|
||||
renderPart,
|
||||
@ -2073,6 +2074,9 @@ function renderModelData(name, model, data, parameters, options) {
|
||||
case 'user':
|
||||
renderer = renderUser;
|
||||
break;
|
||||
case 'group':
|
||||
renderer = renderGroup;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
/* exported
|
||||
renderBuild,
|
||||
renderCompany,
|
||||
renderGroup,
|
||||
renderManufacturerPart,
|
||||
renderOwner,
|
||||
renderPart,
|
||||
@ -15,6 +16,7 @@
|
||||
renderStockItem,
|
||||
renderStockLocation,
|
||||
renderSupplierPart,
|
||||
renderUser,
|
||||
*/
|
||||
|
||||
|
||||
@ -216,6 +218,17 @@ function renderPart(name, data, parameters={}, options={}) {
|
||||
return html;
|
||||
}
|
||||
|
||||
|
||||
// Renderer for "Group" model
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function renderGroup(name, data, parameters={}, options={}) {
|
||||
|
||||
var html = `<span>${data.name}</span>`;
|
||||
|
||||
return html;
|
||||
|
||||
}
|
||||
|
||||
// Renderer for "User" model
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function renderUser(name, data, parameters={}, options={}) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
"""DRF API definition for the 'users' app"""
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.models import Group, User
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.urls import include, path, re_path
|
||||
|
||||
@ -13,7 +13,7 @@ from rest_framework.views import APIView
|
||||
from InvenTree.mixins import ListAPI, RetrieveAPI, RetrieveUpdateAPI
|
||||
from InvenTree.serializers import UserSerializer
|
||||
from users.models import Owner, RuleSet, check_user_role
|
||||
from users.serializers import OwnerSerializer
|
||||
from users.serializers import GroupSerializer, OwnerSerializer
|
||||
|
||||
|
||||
class OwnerList(ListAPI):
|
||||
@ -113,7 +113,9 @@ class UserDetail(RetrieveAPI):
|
||||
|
||||
queryset = User.objects.all()
|
||||
serializer_class = UserSerializer
|
||||
permission_classes = (permissions.IsAuthenticated,)
|
||||
permission_classes = [
|
||||
permissions.IsAuthenticated
|
||||
]
|
||||
|
||||
|
||||
class MeUserDetail(RetrieveUpdateAPI, UserDetail):
|
||||
@ -129,7 +131,9 @@ class UserList(ListAPI):
|
||||
|
||||
queryset = User.objects.all()
|
||||
serializer_class = UserSerializer
|
||||
permission_classes = (permissions.IsAuthenticated,)
|
||||
permission_classes = [
|
||||
permissions.IsAuthenticated,
|
||||
]
|
||||
|
||||
filter_backends = [
|
||||
DjangoFilterBackend,
|
||||
@ -143,6 +147,35 @@ class UserList(ListAPI):
|
||||
]
|
||||
|
||||
|
||||
class GroupDetail(RetrieveAPI):
|
||||
"""Detail endpoint for a particular auth group"""
|
||||
|
||||
queryset = Group.objects.all()
|
||||
serializer_class = GroupSerializer
|
||||
permission_classes = [
|
||||
permissions.IsAuthenticated,
|
||||
]
|
||||
|
||||
|
||||
class GroupList(ListAPI):
|
||||
"""List endpoint for all auth groups"""
|
||||
|
||||
queryset = Group.objects.all()
|
||||
serializer_class = GroupSerializer
|
||||
permission_classes = [
|
||||
permissions.IsAuthenticated,
|
||||
]
|
||||
|
||||
filter_backends = [
|
||||
DjangoFilterBackend,
|
||||
filters.SearchFilter,
|
||||
]
|
||||
|
||||
search_fields = [
|
||||
'name',
|
||||
]
|
||||
|
||||
|
||||
class GetAuthToken(APIView):
|
||||
"""Return authentication token for an authenticated user."""
|
||||
|
||||
@ -185,6 +218,12 @@ user_urls = [
|
||||
re_path(r'^.*$', OwnerList.as_view(), name='api-owner-list'),
|
||||
])),
|
||||
|
||||
re_path(r'^(?P<pk>[0-9]+)/?$', UserDetail.as_view(), name='user-detail'),
|
||||
path('', UserList.as_view()),
|
||||
re_path(r'^group/', include([
|
||||
re_path(r'^(?P<pk>[0-9]+)/?$', GroupDetail.as_view(), name='api-group-detail'),
|
||||
re_path(r'^.*$', GroupList.as_view(), name='api-group-list'),
|
||||
])),
|
||||
|
||||
re_path(r'^(?P<pk>[0-9]+)/?$', UserDetail.as_view(), name='api-user-detail'),
|
||||
|
||||
path('', UserList.as_view(), name='api-user-list'),
|
||||
]
|
||||
|
@ -1,5 +1,6 @@
|
||||
"""DRF API serializers for the 'users' app"""
|
||||
|
||||
from django.contrib.auth.models import Group
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
@ -24,3 +25,16 @@ class OwnerSerializer(InvenTreeModelSerializer):
|
||||
'name',
|
||||
'label',
|
||||
]
|
||||
|
||||
|
||||
class GroupSerializer(InvenTreeModelSerializer):
|
||||
"""Serializer for a 'Group'"""
|
||||
|
||||
class Meta:
|
||||
"""Metaclass defines serializer fields"""
|
||||
|
||||
model = Group
|
||||
fields = [
|
||||
'pk',
|
||||
'name',
|
||||
]
|
||||
|
55
InvenTree/users/test_api.py
Normal file
55
InvenTree/users/test_api.py
Normal file
@ -0,0 +1,55 @@
|
||||
"""API tests for various user / auth API endpoints"""
|
||||
|
||||
from django.contrib.auth.models import Group, User
|
||||
from django.urls import reverse
|
||||
|
||||
from InvenTree.api_tester import InvenTreeAPITestCase
|
||||
|
||||
|
||||
class UserAPITests(InvenTreeAPITestCase):
|
||||
"""Tests for user API endpoints"""
|
||||
|
||||
def test_user_api(self):
|
||||
"""Tests for User API endpoints"""
|
||||
|
||||
response = self.get(
|
||||
reverse('api-user-list'),
|
||||
expected_code=200
|
||||
)
|
||||
|
||||
# Check the correct number of results was returned
|
||||
self.assertEqual(len(response.data), User.objects.count())
|
||||
|
||||
for key in ['username', 'pk', 'email']:
|
||||
self.assertIn(key, response.data[0])
|
||||
|
||||
# Check detail URL
|
||||
pk = response.data[0]['pk']
|
||||
|
||||
response = self.get(
|
||||
reverse('api-user-detail', kwargs={'pk': pk}),
|
||||
expected_code=200
|
||||
)
|
||||
|
||||
self.assertIn('pk', response.data)
|
||||
self.assertIn('username', response.data)
|
||||
|
||||
def test_group_api(self):
|
||||
"""Tests for the Group API endpoints"""
|
||||
|
||||
response = self.get(
|
||||
reverse('api-group-list'),
|
||||
expected_code=200,
|
||||
)
|
||||
|
||||
self.assertIn('name', response.data[0])
|
||||
|
||||
self.assertEqual(len(response.data), Group.objects.count())
|
||||
|
||||
# Check detail URL
|
||||
response = self.get(
|
||||
reverse('api-group-detail', kwargs={'pk': response.data[0]['pk']}),
|
||||
expected_code=200,
|
||||
)
|
||||
|
||||
self.assertIn('name', response.data)
|
@ -231,7 +231,7 @@ class OwnerModelTest(InvenTreeTestCase):
|
||||
# self.assertEqual(response['owner_id'], group.pk)
|
||||
|
||||
# own user detail
|
||||
response_detail = self.do_request(reverse('user-detail', kwargs={'pk': self.user.id}), {}, 200)
|
||||
response_detail = self.do_request(reverse('api-user-detail', kwargs={'pk': self.user.id}), {}, 200)
|
||||
self.assertEqual(response_detail['username'], self.username)
|
||||
|
||||
response_me = self.do_request(reverse('api-user-me'), {}, 200)
|
||||
|
Loading…
Reference in New Issue
Block a user