pull/1075/head
Piero Toffanin 2021-10-19 15:51:44 -04:00
rodzic 2850571f2c
commit e706bfd17d
5 zmienionych plików z 180 dodań i 27 usunięć

Wyświetl plik

@ -86,8 +86,8 @@ class ProjectViewSet(viewsets.ModelViewSet):
try:
with transaction.atomic():
project.name = request.data.get('name')
project.description = request.data.get('description')
project.name = request.data.get('name', '')
project.description = request.data.get('description', '')
project.save()
form_perms = request.data.get('permissions')
@ -127,5 +127,7 @@ class ProjectViewSet(viewsets.ModelViewSet):
except User.DoesNotExist as e:
return Response({'error': _("Invalid user in permissions list")}, status=status.HTTP_400_BAD_REQUEST)
except AttributeError as e:
return Response({'error': _("Invalid permissions")}, status=status.HTTP_400_BAD_REQUEST)
return Response({'success': True}, status=status.HTTP_200_OK)

Wyświetl plik

@ -12,7 +12,7 @@ from rest_framework_jwt.views import obtain_jwt_token
from .tiler import TileJson, Bounds, Metadata, Tiles, Export
from .potree import Scene, CameraView
from .workers import CheckTask, GetTaskResult
from .users import UserViewSet
from .users import UsersList
from webodm import settings
router = routers.DefaultRouter()
@ -20,9 +20,6 @@ router.register(r'projects', ProjectViewSet)
router.register(r'processingnodes', ProcessingNodeViewSet)
router.register(r'presets', PresetViewSet, base_name='presets')
if settings.ENABLE_USERS_API:
router.register(r'users', UserViewSet, base_name='users')
tasks_router = routers.NestedSimpleRouter(router, r'projects', lookup='project')
tasks_router.register(r'tasks', TaskViewSet, base_name='projects-tasks')
@ -61,3 +58,7 @@ urlpatterns = [
url(r'^plugins/(?P<plugin_name>[^/.]+)/(.*)$', api_view_handler)
]
if settings.ENABLE_USERS_API:
urlpatterns.append(url(r'users', UsersList.as_view()))

Wyświetl plik

@ -1,33 +1,24 @@
from django.contrib.auth.models import User
from rest_framework import serializers, viewsets, mixins, status, exceptions, permissions
from rest_framework.views import APIView
from rest_framework import exceptions, permissions, parsers
from rest_framework.response import Response
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['username', 'email']
class UsersList(APIView):
permission_classes = (permissions.IsAuthenticated,)
parser_classes = (parsers.JSONParser, parsers.FormParser,)
class UserViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
serializer_class = UserSerializer
permission_classes = [permissions.IsAuthenticated]
# Disable pagination when not requesting any page
def paginate_queryset(self, queryset):
if self.paginator and self.request.query_params.get(self.paginator.page_query_param, None) is None:
return None
return super().paginate_queryset(queryset)
def get_queryset(self):
queryset = User.objects.all()
def get(self, request):
qs = User.objects.all()
search = self.request.query_params.get('search', None)
if search is not None:
queryset = queryset.filter(username__istartswith=search) | queryset.filter(email__istartswith=search)
qs = qs.filter(username__istartswith=search) | qs.filter(email__istartswith=search)
limit = self.request.query_params.get('limit', None)
if limit is not None:
try:
queryset = queryset[:abs(int(limit))]
qs = qs[:abs(int(limit))]
except ValueError:
raise exceptions.ValidationError(detail="Invalid query parameters")
return queryset
return Response([{'username': u.username, 'email': u.email} for u in qs])

Wyświetl plik

@ -0,0 +1,107 @@
import logging
from django.contrib.auth.models import User
from rest_framework import status
from rest_framework.test import APIClient
from app.models import Project
from .classes import BootTestCase
from guardian.shortcuts import get_perms
from webodm import settings
logger = logging.getLogger('app.logger')
class TestApiProjects(BootTestCase):
def setUp(self):
super().setUp()
def tearDown(self):
super().tearDown()
def test_project(self):
client = APIClient()
user = User.objects.get(username="testuser")
project = Project.objects.create(
owner=user,
name="test project"
)
# Cannot edit project (anonymous)
res = client.post("/api/projects/{}/edit/".format(project.id), {
'name': 'edited'
})
self.assertEqual(res.status_code, status.HTTP_403_FORBIDDEN)
client.login(username="testuser", password="test1234")
# Can edit project
res = client.post("/api/projects/{}/edit/".format(project.id), {
'name': 'edited'
})
self.assertEqual(res.status_code, status.HTTP_200_OK)
project.refresh_from_db()
self.assertEqual(project.name, 'edited')
self.assertEqual(project.description, '')
other_user = User.objects.get(username="testuser2")
other_client = APIClient()
other_client.login(username="testuser2", password="test1234")
# Other user cannot edit project
res = other_client.post("/api/projects/{}/edit/".format(project.id), {
'name': 'edited2'
})
self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND)
# Other user cannot see project
res = other_client.get("/api/projects/{}/".format(project.id))
self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND)
# Change permissions via API
res = client.post("/api/projects/{}/edit/".format(project.id), {
'permissions': [{'username': 'testuser2', 'permissions': ['view']}]
}, format="json")
self.assertEqual(res.status_code, status.HTTP_200_OK)
# Other user can see project
res = other_client.get("/api/projects/{}/".format(project.id))
self.assertEqual(res.status_code, status.HTTP_200_OK)
# Other user still cannot edit project
res = other_client.post("/api/projects/{}/edit/".format(project.id), {
'name': 'edited2'
})
self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND)
# Change permissions again
res = client.post("/api/projects/{}/edit/".format(project.id), {
'permissions': [{'username': 'testuser2', 'permissions': ['view', 'add', 'change', 'delete']}]
}, format="json")
self.assertEqual(res.status_code, status.HTTP_200_OK)
# Other user can now edit
res = other_client.post("/api/projects/{}/edit/".format(project.id), {
'name': 'edited3'
})
self.assertEqual(res.status_code, status.HTTP_200_OK)
project.refresh_from_db()
self.assertEqual(project.name, 'edited3')
# Can remove permissions
res = client.post("/api/projects/{}/edit/".format(project.id), {
'permissions': []
}, format="json")
self.assertEqual(res.status_code, status.HTTP_200_OK)
# Other user cannot see project
res = other_client.get("/api/projects/{}/".format(project.id))
self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND)
# Current user (owner) still has permissions
res = client.get("/api/projects/{}/".format(project.id))
self.assertEqual(res.status_code, status.HTTP_200_OK)
perms = get_perms(user, project)
self.assertEqual(len(perms), 4)

Wyświetl plik

@ -0,0 +1,52 @@
import logging
from django.contrib.auth.models import User
from rest_framework import status
from rest_framework.test import APIClient
from app.models import Project
from .classes import BootTestCase
from webodm import settings
logger = logging.getLogger('app.logger')
class TestApiUsers(BootTestCase):
def setUp(self):
super().setUp()
def tearDown(self):
super().tearDown()
def test_users(self):
client = APIClient()
user = User.objects.get(username="testuser")
# Cannot list users (anonymous)
res = client.get("/api/users/?limit=30")
self.assertEqual(res.status_code, status.HTTP_403_FORBIDDEN)
client.login(username="testuser", password="test1234")
# Can list users (authenticated)
res = client.get("/api/users/?limit=30")
self.assertEqual(res.status_code, status.HTTP_200_OK)
self.assertTrue([u for u in res.data if u['username'] == 'testuser'])
self.assertTrue([u for u in res.data if u['username'] == 'testsuperuser'])
# Can search for users
res = client.get("/api/users/?search=super")
self.assertEqual(res.status_code, status.HTTP_200_OK)
self.assertFalse([u for u in res.data if u['username'] == 'testuser'])
self.assertTrue([u for u in res.data if u['username'] == 'testsuperuser'])
# Can search for users and limit
res = client.get("/api/users/?search=super&limit=1")
self.assertEqual(res.status_code, status.HTTP_200_OK)
self.assertFalse([u for u in res.data if u['username'] == 'testuser'])
self.assertTrue([u for u in res.data if u['username'] == 'testsuperuser'])
# Handle invalid limits
res = client.get("/api/users/?search=super&limit=-1")
self.assertEqual(res.status_code, status.HTTP_200_OK)
self.assertEqual(len(res.data), 1)