replace DRF with django-ninja
This commit is contained in:
		
							parent
							
								
									4299d46b7b
								
							
						
					
					
						commit
						813780a18b
					
				| 
						 | 
					@ -0,0 +1,112 @@
 | 
				
			||||||
 | 
					from ninja import Router, Schema
 | 
				
			||||||
 | 
					from ninja.errors import HttpError
 | 
				
			||||||
 | 
					from concierge import models
 | 
				
			||||||
 | 
					from typing import List
 | 
				
			||||||
 | 
					from django.db import transaction
 | 
				
			||||||
 | 
					from django.shortcuts import get_object_or_404
 | 
				
			||||||
 | 
					from django.utils.timezone import now
 | 
				
			||||||
 | 
					from django.views.decorators.csrf import csrf_exempt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					router = Router()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ClaimReference(Schema):
 | 
				
			||||||
 | 
					  uuid: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AvailableTask(Schema):
 | 
				
			||||||
 | 
					  uuid: str
 | 
				
			||||||
 | 
					  type: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class HeartbeatResponse(Schema):
 | 
				
			||||||
 | 
					  success: bool = True
 | 
				
			||||||
 | 
					  claims: List[ClaimReference]
 | 
				
			||||||
 | 
					  available: List[AvailableTask]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ClaimResponse(Schema):
 | 
				
			||||||
 | 
					  uuid: str
 | 
				
			||||||
 | 
					  type: str
 | 
				
			||||||
 | 
					  configuration: dict
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ReleaseResponse(Schema):
 | 
				
			||||||
 | 
					  success: bool = True
 | 
				
			||||||
 | 
					  uuid: str
 | 
				
			||||||
 | 
					  type: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@router.post('/heartbeat/{identity}', response=HeartbeatResponse)
 | 
				
			||||||
 | 
					@csrf_exempt
 | 
				
			||||||
 | 
					def receive_heartbeat(request, identity: str):
 | 
				
			||||||
 | 
					  try:
 | 
				
			||||||
 | 
					    id = models.Identity.objects.get(identity=identity)
 | 
				
			||||||
 | 
					  except models.Identity.DoesNotExist:
 | 
				
			||||||
 | 
					    raise HttpError(403, "identity unknown")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # update heartbeat
 | 
				
			||||||
 | 
					  id.heartbeat = now()
 | 
				
			||||||
 | 
					  id.save()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # get current claims and available tasks
 | 
				
			||||||
 | 
					  claims = models.Task.objects.filter(claimed_by=id).all()
 | 
				
			||||||
 | 
					  available = models.Task.objects.filter(claimed_by=None).all()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					      'success': True,
 | 
				
			||||||
 | 
					      'claims': [{'uuid': str(o.uuid)} for o in list(claims)],
 | 
				
			||||||
 | 
					      'available': [{'uuid': str(o.uuid), 'type': o.type} for o in list(available)],
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@router.post('/claim/{identity}/{task_uuid}', response=ClaimResponse)
 | 
				
			||||||
 | 
					@csrf_exempt
 | 
				
			||||||
 | 
					def claim_task(request, identity: str, task_uuid: str):
 | 
				
			||||||
 | 
					  try:
 | 
				
			||||||
 | 
					    id = models.Identity.objects.get(identity=identity)
 | 
				
			||||||
 | 
					  except models.Identity.DoesNotExist:
 | 
				
			||||||
 | 
					    raise HttpError(403, "identity unknown")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  with transaction.atomic():
 | 
				
			||||||
 | 
					    task = get_object_or_404(models.Task, uuid=task_uuid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if task.claimed_by:
 | 
				
			||||||
 | 
					      raise HttpError(423, "task already claimed")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    task.claimed_by = id
 | 
				
			||||||
 | 
					    task.save()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        'success': True,
 | 
				
			||||||
 | 
					        'uuid': task.uuid,
 | 
				
			||||||
 | 
					        'type': task.type,
 | 
				
			||||||
 | 
					        'configuration': json.loads(task.configuration)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@router.post('/release/{identity}/{task_uuid}')
 | 
				
			||||||
 | 
					@csrf_exempt
 | 
				
			||||||
 | 
					def release_task(request, identity: str, task_uuid: str):
 | 
				
			||||||
 | 
					  try:
 | 
				
			||||||
 | 
					    id = models.Identity.objects.get(identity=identity)
 | 
				
			||||||
 | 
					  except models.Identity.DoesNotExist:
 | 
				
			||||||
 | 
					    raise HttpError(403, "identity unknown")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  with transaction.atomic():
 | 
				
			||||||
 | 
					    task = get_object_or_404(models.Task, uuid=task_uuid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if task.claimed_by != id:
 | 
				
			||||||
 | 
					      raise HttpError(403, "task not claimed by this identity")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    task.claimed_by = None
 | 
				
			||||||
 | 
					    task.save()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      'success': True,
 | 
				
			||||||
 | 
					      'uuid': task.uuid,
 | 
				
			||||||
 | 
					      'type': task.type,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -1,8 +0,0 @@
 | 
				
			||||||
from django.urls import path
 | 
					 | 
				
			||||||
from . import views
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
urlpatterns = [
 | 
					 | 
				
			||||||
    path('api/<uuid:identity>/heartbeat', views.heartbeat, name='heartbeat'),
 | 
					 | 
				
			||||||
    path('api/<uuid:identity>/claim/<uuid:task_uuid>', views.claim, name='claim'),
 | 
					 | 
				
			||||||
    path('api/<uuid:identity>/release/<uuid:task_uuid>', views.release, name='release'),
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,94 +0,0 @@
 | 
				
			||||||
import json
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from django.db import transaction
 | 
					 | 
				
			||||||
from django.http import JsonResponse
 | 
					 | 
				
			||||||
from django.views.decorators.csrf import csrf_exempt
 | 
					 | 
				
			||||||
from django.views.decorators.http import require_POST
 | 
					 | 
				
			||||||
from django.core.exceptions import ObjectDoesNotExist
 | 
					 | 
				
			||||||
from django.utils.timezone import now
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from .models import Identity, Task
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@csrf_exempt
 | 
					 | 
				
			||||||
@require_POST
 | 
					 | 
				
			||||||
def heartbeat(request, identity):
 | 
					 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        id = Identity.objects.get(identity=identity)
 | 
					 | 
				
			||||||
    except ObjectDoesNotExist:
 | 
					 | 
				
			||||||
        return JsonResponse({'error': 'identity unknown'}, status=403)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # update heartbeat
 | 
					 | 
				
			||||||
    id.heartbeat = now()
 | 
					 | 
				
			||||||
    id.save()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # get current claims and available tasks
 | 
					 | 
				
			||||||
    claims = Task.objects.filter(claimed_by=id).all()
 | 
					 | 
				
			||||||
    available = Task.objects.filter(claimed_by=None).all()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    data = {
 | 
					 | 
				
			||||||
        'success': True,
 | 
					 | 
				
			||||||
        'claims': [{'uuid': str(o.uuid)} for o in list(claims)],
 | 
					 | 
				
			||||||
        'available': [{'uuid': str(o.uuid), 'type': o.type} for o in list(available)],
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return JsonResponse(data)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@csrf_exempt
 | 
					 | 
				
			||||||
@require_POST
 | 
					 | 
				
			||||||
def claim(request, identity, task_uuid):
 | 
					 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        id = Identity.objects.get(identity=identity)
 | 
					 | 
				
			||||||
    except ObjectDoesNotExist:
 | 
					 | 
				
			||||||
        return JsonResponse({'error': 'identity unknown'}, status=403)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    with transaction.atomic():
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            task = Task.objects.get(uuid=task_uuid)
 | 
					 | 
				
			||||||
        except ObjectDoesNotExist:
 | 
					 | 
				
			||||||
            return JsonResponse({'error': 'task unknown'}, status=404)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if task.claimed_by:
 | 
					 | 
				
			||||||
            return JsonResponse({'error': 'task already claimed'}, status=423)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        task.claimed_by = id
 | 
					 | 
				
			||||||
        task.save()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        data = {
 | 
					 | 
				
			||||||
            'success': True,
 | 
					 | 
				
			||||||
            'uuid': task.uuid,
 | 
					 | 
				
			||||||
            'type': task.type,
 | 
					 | 
				
			||||||
            'configuration': json.loads(task.configuration)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return JsonResponse(data)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@csrf_exempt
 | 
					 | 
				
			||||||
@require_POST
 | 
					 | 
				
			||||||
def release(request, identity, task_uuid):
 | 
					 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        id = Identity.objects.get(identity=identity)
 | 
					 | 
				
			||||||
    except ObjectDoesNotExist:
 | 
					 | 
				
			||||||
        return JsonResponse({'error': 'identity unknown'}, status=403)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    with transaction.atomic():
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            task = Task.objects.get(uuid=task_uuid)
 | 
					 | 
				
			||||||
        except ObjectDoesNotExist:
 | 
					 | 
				
			||||||
            return JsonResponse({'error': 'task unknown'}, status=404)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if task.claimed_by != id:
 | 
					 | 
				
			||||||
            return JsonResponse({'error': 'task claimed by other identity'}, status=403)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        task.claimed_by = None
 | 
					 | 
				
			||||||
        task.save()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        data = {
 | 
					 | 
				
			||||||
            'success': True,
 | 
					 | 
				
			||||||
            'uuid': task.uuid,
 | 
					 | 
				
			||||||
            'type': task.type,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return JsonResponse(data)
 | 
					 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,144 @@
 | 
				
			||||||
 | 
					from ninja import Router, ModelSchema, Schema
 | 
				
			||||||
 | 
					from ninja.errors import HttpError
 | 
				
			||||||
 | 
					from config import models
 | 
				
			||||||
 | 
					from typing import List
 | 
				
			||||||
 | 
					from guardian.shortcuts import get_objects_for_user, assign_perm
 | 
				
			||||||
 | 
					from django.shortcuts import get_object_or_404
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					router = Router()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Restream(ModelSchema):
 | 
				
			||||||
 | 
					  class Meta:
 | 
				
			||||||
 | 
					    model = models.Restream
 | 
				
			||||||
 | 
					    fields = "__all__"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RestreamPatch(ModelSchema):
 | 
				
			||||||
 | 
					  class Meta:
 | 
				
			||||||
 | 
					    model = models.Restream
 | 
				
			||||||
 | 
					    exclude = ["id"]
 | 
				
			||||||
 | 
					    fields_optional = "__all__"
 | 
				
			||||||
 | 
					    extra = "forbid"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Stream(ModelSchema):
 | 
				
			||||||
 | 
					  class Meta:
 | 
				
			||||||
 | 
					    model = models.Stream
 | 
				
			||||||
 | 
					    fields = "__all__"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class StreamPatch(ModelSchema):
 | 
				
			||||||
 | 
					  class Meta:
 | 
				
			||||||
 | 
					    model = models.Stream
 | 
				
			||||||
 | 
					    fields = ["name"]
 | 
				
			||||||
 | 
					    fields_optional = "__all__"
 | 
				
			||||||
 | 
					    extra = "forbid"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class StreamCreate(ModelSchema):
 | 
				
			||||||
 | 
					  class Meta:
 | 
				
			||||||
 | 
					    model = models.Stream
 | 
				
			||||||
 | 
					    fields = ["name"]
 | 
				
			||||||
 | 
					    extra = "forbid"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@router.get('/streams', response=List[Stream])
 | 
				
			||||||
 | 
					def list_streams(request):
 | 
				
			||||||
 | 
					  return get_objects_for_user(request.user, 'view_stream', models.Stream.objects.all())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@router.post('/streams', response=Stream)
 | 
				
			||||||
 | 
					def create_stream(request, payload: StreamCreate):
 | 
				
			||||||
 | 
					  stream = models.Stream.objects.create(**payload.dict())
 | 
				
			||||||
 | 
					  assign_perm('view_stream', request.user, stream)
 | 
				
			||||||
 | 
					  assign_perm('change_stream', request.user, stream)
 | 
				
			||||||
 | 
					  assign_perm('delete_stream', request.user, stream)
 | 
				
			||||||
 | 
					  return stream
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@router.get('/streams/{id}', response=Stream)
 | 
				
			||||||
 | 
					def get_stream(request, id: int):
 | 
				
			||||||
 | 
					  stream = get_object_or_404(models.Stream, id=id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if not request.user.has_perm('view_stream', stream):
 | 
				
			||||||
 | 
					    raise HttpError(401, "unauthorized")
 | 
				
			||||||
 | 
					  return stream
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@router.patch('/streams/{id}', response=Stream)
 | 
				
			||||||
 | 
					def update_stream(request, id: int, payload: StreamPatch):
 | 
				
			||||||
 | 
					  stream = get_object_or_404(models.Stream, id=id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if not request.user.has_perm('change_stream', stream):
 | 
				
			||||||
 | 
					    raise HttpError(401, "unauthorized")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  stream.name = payload.name
 | 
				
			||||||
 | 
					  stream.save()
 | 
				
			||||||
 | 
					  return stream
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@router.delete('/streams/{id}', response=None)
 | 
				
			||||||
 | 
					def delete_stream(request, id: int):
 | 
				
			||||||
 | 
					  stream = get_object_or_404(models.Stream, id=id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if not request.user.has_perm('delete_stream', stream):
 | 
				
			||||||
 | 
					    raise HttpError(401, "unauthorized")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  stream.delete()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@router.get('/restreams', response=List[Restream])
 | 
				
			||||||
 | 
					def list_restreams(request):
 | 
				
			||||||
 | 
					  return get_objects_for_user(request.user, 'view_restream', models.Restream.objects.all())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@router.post('/restreams', response=Restream)
 | 
				
			||||||
 | 
					def create_restream(request, payload: Restream):
 | 
				
			||||||
 | 
					  if not request.user.has_perm('view_stream', payload.stream):
 | 
				
			||||||
 | 
					    raise HttpError(401, "unauthorized")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  restream = models.Restream.objects.create(**payload.dict())
 | 
				
			||||||
 | 
					  assign_perm('view_restream', request.user, restream)
 | 
				
			||||||
 | 
					  assign_perm('change_restream', request.user, restream)
 | 
				
			||||||
 | 
					  assign_perm('delete_restream', request.user, restream)
 | 
				
			||||||
 | 
					  return restream
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@router.get('/restreams/{id}', response=Restream)
 | 
				
			||||||
 | 
					def get_restream(request, id: int):
 | 
				
			||||||
 | 
					  restream = get_object_or_404(models.Restream, id=id)
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if not request.user.has_perm('view_restream', restream):
 | 
				
			||||||
 | 
					    raise HttpError(401, "unauthorized")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return restream
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@router.patch('/restreams/{id}', response=Restream)
 | 
				
			||||||
 | 
					def update_restream(request, id: int, payload: RestreamPatch):
 | 
				
			||||||
 | 
					  restream = get_object_or_404(models.Restream, id=id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if not request.user.has_perm('change_restream', restream):
 | 
				
			||||||
 | 
					    raise HttpError(401, "unauthorized")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if payload.stream:
 | 
				
			||||||
 | 
					    payload.stream = get_object_or_404(models.Stream, id=payload.stream)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if not request.user.has_perm('view_stream', payload.stream):
 | 
				
			||||||
 | 
					      raise HttpError(401, "unauthorized")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for key, value in payload.dict(exclude_unset=True).items():
 | 
				
			||||||
 | 
					    setattr(restream, key, value)
 | 
				
			||||||
 | 
					  restream.save()
 | 
				
			||||||
 | 
					  return restream
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@router.delete('/restreams/{id}', response=None)
 | 
				
			||||||
 | 
					def delete_restream(request, id: int):
 | 
				
			||||||
 | 
					  restream = get_object_or_404(models.Restream, id=id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if not request.user.has_perm('delete_restream', restream):
 | 
				
			||||||
 | 
					    raise HttpError(401, "unauthorized")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  restream.delete()
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,30 @@
 | 
				
			||||||
 | 
					from ninja import NinjaAPI, ModelSchema, Router
 | 
				
			||||||
 | 
					from ninja.security import django_auth
 | 
				
			||||||
 | 
					from django.contrib.auth.models import User
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from config.api import router as config_router
 | 
				
			||||||
 | 
					from concierge.api import router as concierge_router
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					core_router = Router()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UserSchema(ModelSchema):
 | 
				
			||||||
 | 
					  class Meta:
 | 
				
			||||||
 | 
					    model = User
 | 
				
			||||||
 | 
					    fields = ["id", "username", "email"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@core_router.get("/me", response=UserSchema)
 | 
				
			||||||
 | 
					def me(request):
 | 
				
			||||||
 | 
					  return request.user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					api = NinjaAPI(
 | 
				
			||||||
 | 
					  title="Portier API",
 | 
				
			||||||
 | 
					  version="2.0.0",
 | 
				
			||||||
 | 
					  description="HTTP API for Portier. Use this to interact with the Portier backend.",
 | 
				
			||||||
 | 
					  csrf=True,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					api.add_router("/", core_router, auth=django_auth, tags=["Core"])
 | 
				
			||||||
 | 
					api.add_router("/config/", config_router, auth=django_auth, tags=["Configuration"])
 | 
				
			||||||
 | 
					api.add_router("/concierge/", concierge_router, auth=None, tags=["Concierge"])
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,8 @@ INSTALLED_APPS = [
 | 
				
			||||||
    'django.contrib.sessions',
 | 
					    'django.contrib.sessions',
 | 
				
			||||||
    'django.contrib.messages',
 | 
					    'django.contrib.messages',
 | 
				
			||||||
    'django.contrib.staticfiles',
 | 
					    'django.contrib.staticfiles',
 | 
				
			||||||
    'rest_framework',
 | 
					    'ninja',
 | 
				
			||||||
 | 
					    #'rest_framework',
 | 
				
			||||||
    'guardian',
 | 
					    'guardian',
 | 
				
			||||||
    'django_registration',
 | 
					    'django_registration',
 | 
				
			||||||
    'bootstrap4',
 | 
					    'bootstrap4',
 | 
				
			||||||
| 
						 | 
					@ -194,7 +195,7 @@ DJANGO_CELERY_BEAT_TZ_AWARE = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
 | 
					DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if DEBUG:
 | 
					if DEBUG == "LOLOLOL":
 | 
				
			||||||
    LOGGING = {
 | 
					    LOGGING = {
 | 
				
			||||||
        'version': 1,
 | 
					        'version': 1,
 | 
				
			||||||
        'disable_existing_loggers': False,
 | 
					        'disable_existing_loggers': False,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,13 +1,14 @@
 | 
				
			||||||
from django.contrib import admin
 | 
					from django.contrib import admin
 | 
				
			||||||
from django.urls import include, path
 | 
					from django.urls import include, path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from .api import api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
urlpatterns = [
 | 
					urlpatterns = [
 | 
				
			||||||
    path('accounts/', include('django_registration.backends.activation.urls')),
 | 
					    path('accounts/', include('django_registration.backends.activation.urls')),
 | 
				
			||||||
    path('accounts/', include('django.contrib.auth.urls')),
 | 
					    path('accounts/', include('django.contrib.auth.urls')),
 | 
				
			||||||
    path('i18n/', include('django.conf.urls.i18n')),
 | 
					    path('i18n/', include('django.conf.urls.i18n')),
 | 
				
			||||||
    path('admin/', admin.site.urls),
 | 
					    path('admin/', admin.site.urls),
 | 
				
			||||||
    path('config/', include('config.urls')),
 | 
					    path('config/', include('config.urls')),
 | 
				
			||||||
    path('concierge/', include('concierge.urls')),
 | 
					    path('api/v2/', api.urls),
 | 
				
			||||||
    path('api/v1/', include('restapi.urls')),
 | 
					 | 
				
			||||||
    path('', include('core.urls')),
 | 
					    path('', include('core.urls')),
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,8 +5,7 @@ django-guardian
 | 
				
			||||||
django-fontawesome-5
 | 
					django-fontawesome-5
 | 
				
			||||||
django-celery-beat
 | 
					django-celery-beat
 | 
				
			||||||
django-filter
 | 
					django-filter
 | 
				
			||||||
djangorestframework
 | 
					django-ninja
 | 
				
			||||||
djangorestframework-guardian
 | 
					 | 
				
			||||||
celery>=5.3
 | 
					celery>=5.3
 | 
				
			||||||
gunicorn>=20
 | 
					gunicorn>=20
 | 
				
			||||||
psycopg2-binary
 | 
					psycopg2-binary
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +0,0 @@
 | 
				
			||||||
from django.apps import AppConfig
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class RestapiConfig(AppConfig):
 | 
					 | 
				
			||||||
    name = 'restapi'
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,16 +0,0 @@
 | 
				
			||||||
from django.urls import path, include
 | 
					 | 
				
			||||||
from rest_framework import routers
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from .views import StreamViewSet, RestreamViewSet
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
router = routers.DefaultRouter()
 | 
					 | 
				
			||||||
router.register(r'stream', StreamViewSet)
 | 
					 | 
				
			||||||
router.register(r'restream', RestreamViewSet)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
app_name = 'restapi'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
urlpatterns = [
 | 
					 | 
				
			||||||
    path('', include(router.urls)),
 | 
					 | 
				
			||||||
    path('auth/', include('rest_framework.urls', namespace='rest_framework'))
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,51 +0,0 @@
 | 
				
			||||||
from rest_framework_guardian.serializers import ObjectPermissionsAssignmentMixin
 | 
					 | 
				
			||||||
from rest_framework import serializers, viewsets
 | 
					 | 
				
			||||||
from rest_framework_guardian import filters
 | 
					 | 
				
			||||||
from config.models import Stream, Restream
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class StreamSerializer(ObjectPermissionsAssignmentMixin, serializers.ModelSerializer):
 | 
					 | 
				
			||||||
    class Meta:
 | 
					 | 
				
			||||||
        model = Stream
 | 
					 | 
				
			||||||
        fields = '__all__'
 | 
					 | 
				
			||||||
        read_only_fields = ['publish_counter']
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_permissions_map(self, created):
 | 
					 | 
				
			||||||
        current_user = self.context['request'].user
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            'view_stream': [current_user],
 | 
					 | 
				
			||||||
            'change_stream': [current_user],
 | 
					 | 
				
			||||||
            'delete_stream': [current_user]
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class StreamViewSet(viewsets.ModelViewSet):
 | 
					 | 
				
			||||||
    queryset = Stream.objects.all()
 | 
					 | 
				
			||||||
    serializer_class = StreamSerializer
 | 
					 | 
				
			||||||
    filter_backends = [filters.ObjectPermissionsFilter]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class RestreamSerializer(ObjectPermissionsAssignmentMixin, serializers.ModelSerializer):
 | 
					 | 
				
			||||||
    class Meta:
 | 
					 | 
				
			||||||
        model = Restream
 | 
					 | 
				
			||||||
        fields = '__all__'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_permissions_map(self, created):
 | 
					 | 
				
			||||||
        current_user = self.context['request'].user
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            'view_restream': [current_user],
 | 
					 | 
				
			||||||
            'change_restream': [current_user],
 | 
					 | 
				
			||||||
            'delete_restream': [current_user]
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def validate_stream(self, value):
 | 
					 | 
				
			||||||
        request = self.context['request']
 | 
					 | 
				
			||||||
        if not request.user.has_perm('config.view_stream', value):
 | 
					 | 
				
			||||||
            raise serializers.ValidationError('Access to stream is not authorized')
 | 
					 | 
				
			||||||
        return value
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class RestreamViewSet(viewsets.ModelViewSet):
 | 
					 | 
				
			||||||
    queryset = Restream.objects.all()
 | 
					 | 
				
			||||||
    serializer_class = RestreamSerializer
 | 
					 | 
				
			||||||
    filter_backends = [filters.ObjectPermissionsFilter]
 | 
					 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,7 @@ var app = new Vue({
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    toggleActive(cfg) {
 | 
					    toggleActive(cfg) {
 | 
				
			||||||
      axios
 | 
					      axios
 | 
				
			||||||
        .patch('/api/v1/restream/' + cfg.id + '/', { active: !cfg.active })
 | 
					        .patch('/api/v2/config/restreams/' + cfg.id, { active: !cfg.active })
 | 
				
			||||||
        .then(response => {
 | 
					        .then(response => {
 | 
				
			||||||
            i = this.cfgs.findIndex((obj => obj.id == cfg.id))
 | 
					            i = this.cfgs.findIndex((obj => obj.id == cfg.id))
 | 
				
			||||||
            Vue.set(this.cfgs, i, response.data)
 | 
					            Vue.set(this.cfgs, i, response.data)
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,7 @@ var app = new Vue({
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    fetchData() {
 | 
					    fetchData() {
 | 
				
			||||||
      axios
 | 
					      axios
 | 
				
			||||||
        .get('/api/v1/restream/')
 | 
					        .get('/api/v2/config/restreams')
 | 
				
			||||||
        .then(response => {
 | 
					        .then(response => {
 | 
				
			||||||
          this.cfgs = response.data
 | 
					          this.cfgs = response.data
 | 
				
			||||||
          this.isLoading = false
 | 
					          this.isLoading = false
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,7 @@ var app = new Vue({
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    fetchData() {
 | 
					    fetchData() {
 | 
				
			||||||
      axios
 | 
					      axios
 | 
				
			||||||
        .get('/api/v1/stream/')
 | 
					        .get('/api/v2/config/streams')
 | 
				
			||||||
        .then(response => {
 | 
					        .then(response => {
 | 
				
			||||||
          this.streams = response.data
 | 
					          this.streams = response.data
 | 
				
			||||||
          this.isLoading = false
 | 
					          this.isLoading = false
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue