Merge pull request #6272 from normanjaeckel/GetUser
Added route to get a user e. g. for third-party applications.
This commit is contained in:
commit
d4953ed81a
1
.github/workflows/run-tests.yml
vendored
1
.github/workflows/run-tests.yml
vendored
@ -2,7 +2,6 @@ name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
test-server:
|
||||
|
@ -109,7 +109,7 @@ export class VideoPlayerComponent implements AfterViewInit, OnDestroy {
|
||||
}
|
||||
|
||||
public get nanocosmosVideoUrl(): string {
|
||||
return `https://demo.nanocosmos.de/nanoplayer/embed/1.0.0/nanoplayer.html?entry.rtmp.streamname=${this.videoId}`;
|
||||
return `https://demo.nanocosmos.de/nanoplayer/embed/1.0.0/nanoplayer.html?entry.rtmp.streamname=${this.videoId}`; // tslint:disable
|
||||
}
|
||||
|
||||
public constructor(
|
||||
@ -237,7 +237,7 @@ export class VideoPlayerComponent implements AfterViewInit, OnDestroy {
|
||||
}
|
||||
|
||||
private getNanocosmosVideoId(url: string): string {
|
||||
const urlParts: Array<String> = url.split('=');
|
||||
const urlParts: String[] = url.split('=');
|
||||
if (urlParts?.length && typeof urlParts[1] === 'string') {
|
||||
return urlParts[1];
|
||||
}
|
||||
|
@ -20,4 +20,9 @@ urlpatterns = [
|
||||
views.PasswordResetConfirmView.as_view(),
|
||||
name="password_reset_confirm",
|
||||
),
|
||||
url(
|
||||
r"^get-user/$",
|
||||
views.GetUserView.as_view(),
|
||||
name="get_user",
|
||||
),
|
||||
]
|
||||
|
@ -39,6 +39,7 @@ from ..utils.autoupdate import AutoupdateElement, inform_changed_data, inform_el
|
||||
from ..utils.cache import element_cache
|
||||
from ..utils.rest_api import (
|
||||
ModelViewSet,
|
||||
NotFound,
|
||||
Response,
|
||||
SimpleMetadata,
|
||||
ValidationError,
|
||||
@ -1168,3 +1169,61 @@ class PasswordResetConfirmView(APIView):
|
||||
except (TypeError, ValueError, OverflowError, User.DoesNotExist):
|
||||
user = None
|
||||
return user
|
||||
|
||||
|
||||
class GetUserView(APIView):
|
||||
"""
|
||||
View to retrieve a single user.
|
||||
|
||||
Use query parameters "id", "username", "email" or "number" to look for
|
||||
a user and retrieve its data.
|
||||
"""
|
||||
|
||||
http_method_names = ["get"]
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
# Check permissions.
|
||||
if not request.user.is_authenticated or not has_perm(
|
||||
request.user, "users.can_manage"
|
||||
):
|
||||
self.permission_denied(request)
|
||||
|
||||
# Parse parameters
|
||||
params = request.GET
|
||||
user_id = params.get("id", "0")
|
||||
try:
|
||||
user_id = int(user_id)
|
||||
except ValueError:
|
||||
raise ValidationError({"detail": "Invalid parameter user_id."})
|
||||
email = params.get("email", "")
|
||||
username = params.get("username", "")
|
||||
number = params.get("number", "")
|
||||
|
||||
# Build queryset
|
||||
query = User.objects.all()
|
||||
if user_id:
|
||||
query = query.filter(pk=user_id)
|
||||
if username:
|
||||
query = query.filter(username=username)
|
||||
if email:
|
||||
query = query.filter(email=email)
|
||||
if number:
|
||||
query = query.filter(number=number)
|
||||
|
||||
# Execute queryset
|
||||
try:
|
||||
self.user = query.get()
|
||||
except User.DoesNotExist:
|
||||
raise NotFound({"detail": "User does not exist."})
|
||||
except User.MultipleObjectsReturned:
|
||||
raise ValidationError({"detail": "Found more than one user."})
|
||||
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **context):
|
||||
user_full_data = async_to_sync(element_cache.get_element_data)(
|
||||
self.user.get_collection_string(), self.user.pk
|
||||
)
|
||||
user_full_data.pop("session_auth_hash")
|
||||
context.update({"user": user_full_data})
|
||||
return context
|
||||
|
@ -4,7 +4,7 @@ from typing import Any, Dict, Iterable, Type
|
||||
from django.db.models import Model
|
||||
from rest_framework import status
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.exceptions import APIException
|
||||
from rest_framework.exceptions import APIException, NotFound, ValidationError
|
||||
from rest_framework.metadata import SimpleMetadata
|
||||
from rest_framework.mixins import (
|
||||
CreateModelMixin as _CreateModelMixin,
|
||||
@ -33,7 +33,6 @@ from rest_framework.serializers import (
|
||||
Serializer,
|
||||
SerializerMetaclass,
|
||||
SerializerMethodField,
|
||||
ValidationError,
|
||||
)
|
||||
from rest_framework.utils.serializer_helpers import ReturnDict
|
||||
from rest_framework.viewsets import GenericViewSet as _GenericViewSet
|
||||
@ -59,6 +58,7 @@ __all__ = [
|
||||
"RelatedField",
|
||||
"SerializerMethodField",
|
||||
"ValidationError",
|
||||
"NotFound",
|
||||
]
|
||||
|
||||
|
||||
|
@ -162,3 +162,70 @@ class TestUserLoginView(TestCase):
|
||||
self.assertEqual(
|
||||
content.get("detail"), "Cookies have to be enabled to use OpenSlides."
|
||||
)
|
||||
|
||||
|
||||
class TestGetUserView(TestCase):
|
||||
url = reverse("get_user")
|
||||
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def test_get_anonymous(self):
|
||||
response = self.client.get(self.url)
|
||||
|
||||
self.assertEqual(response.status_code, 403)
|
||||
content = json.loads(response.content.decode())
|
||||
self.assertEqual(
|
||||
content.get("detail"), "Authentication credentials were not provided."
|
||||
)
|
||||
|
||||
def test_get_authenticated_user(self):
|
||||
self.client.login(username="admin", password="admin")
|
||||
|
||||
response = self.client.get(self.url, {"username": "admin"})
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
user = json.loads(response.content.decode()).get("user")
|
||||
self.assertEqual(user["username"], "admin")
|
||||
self.assertEqual(user["last_name"], "Administrator")
|
||||
|
||||
def test_post(self):
|
||||
response = self.client.post(self.url)
|
||||
|
||||
self.assertEqual(response.status_code, 405)
|
||||
|
||||
def test_not_found(self):
|
||||
self.client.login(username="admin", password="admin")
|
||||
|
||||
response = self.client.get(self.url, {"username": "not-existing-username"})
|
||||
|
||||
self.assertEqual(response.status_code, 404)
|
||||
content = json.loads(response.content.decode())
|
||||
self.assertEqual(content.get("detail"), "User does not exist.")
|
||||
|
||||
def test_multiple_objects(self):
|
||||
self.client.login(username="admin", password="admin")
|
||||
u1, p1 = self.create_user()
|
||||
u1.number = "Number#1234567890"
|
||||
u1.save()
|
||||
u2, p2 = self.create_user()
|
||||
u2.number = "Number#1234567890"
|
||||
u2.save()
|
||||
|
||||
response = self.client.get(self.url, {"number": "Number#1234567890"})
|
||||
|
||||
self.assertEqual(response.status_code, 400)
|
||||
content = json.loads(response.content.decode())
|
||||
self.assertEqual(content.get("detail"), "Found more than one user.")
|
||||
|
||||
def test_delegate(self):
|
||||
self.make_admin_delegate()
|
||||
self.client.login(username="admin", password="admin")
|
||||
|
||||
response = self.client.get(self.url, {"username": "admin"})
|
||||
|
||||
self.assertEqual(response.status_code, 403)
|
||||
content = json.loads(response.content.decode())
|
||||
self.assertEqual(
|
||||
content.get("detail"), "You do not have permission to perform this action."
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user