Introduced a no-forms browseable API renderer; changed secrets decyption endpoint from GET to POST

This commit is contained in:
Jeremy Stretch 2016-04-12 14:03:18 -04:00
parent 3c7e5e9586
commit 0072f54c94
2 changed files with 22 additions and 14 deletions

View File

@ -8,6 +8,14 @@ AF = {
} }
class FormlessBrowsableAPIRenderer(renderers.BrowsableAPIRenderer):
"""
An instance of the browseable API with forms suppressed. Useful for POST endpoints that don't create objects.
"""
def show_form_for_method(self, *args, **kwargs):
return False
class BINDZoneRenderer(renderers.BaseRenderer): class BINDZoneRenderer(renderers.BaseRenderer):
""" """
Generate a BIND zone file from a list of DNS records. Generate a BIND zone file from a list of DNS records.

View File

@ -5,11 +5,11 @@ from django.shortcuts import get_object_or_404
from rest_framework import generics from rest_framework import generics
from rest_framework import status from rest_framework import status
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.settings import api_settings
from rest_framework.views import APIView from rest_framework.views import APIView
from extras.api.renderers import FreeRADIUSClientsRenderer from extras.api.renderers import FormlessBrowsableAPIRenderer, FreeRADIUSClientsRenderer
from secrets.filters import SecretFilter from secrets.filters import SecretFilter
from secrets.models import Secret, SecretRole, UserKey from secrets.models import Secret, SecretRole, UserKey
from .serializers import SecretRoleSerializer, SecretSerializer from .serializers import SecretRoleSerializer, SecretSerializer
@ -38,21 +38,18 @@ class SecretRoleDetailView(generics.RetrieveAPIView):
class SecretListView(generics.GenericAPIView): class SecretListView(generics.GenericAPIView):
""" """
List secrets (filterable). If a private key is provided in the GET body, attempt to decrypt each Secret. List secrets (filterable). If a private key is POSTed, attempt to decrypt each Secret.
e.g. curl -X GET http://netbox/api/secrets/secrets/ --data-binary "@/path/to/private_key"
""" """
queryset = Secret.objects.select_related('device__primary_ip', 'role')\ queryset = Secret.objects.select_related('device__primary_ip', 'role')\
.prefetch_related('role__users', 'role__groups') .prefetch_related('role__users', 'role__groups')
serializer_class = SecretSerializer serializer_class = SecretSerializer
filter_class = SecretFilter filter_class = SecretFilter
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES + [FreeRADIUSClientsRenderer] renderer_classes = [FormlessBrowsableAPIRenderer, JSONRenderer, FreeRADIUSClientsRenderer]
def get(self, request, private_key=None, *args, **kwargs): def get(self, request, private_key=None):
queryset = self.filter_queryset(self.get_queryset()) queryset = self.filter_queryset(self.get_queryset())
# Attempt to decrypt each Secret if a private key was provided. # Attempt to decrypt each Secret if a private key was provided.
private_key = request.body or None
if private_key is not None: if private_key is not None:
try: try:
uk = UserKey.objects.get(user=request.user) uk = UserKey.objects.get(user=request.user)
@ -80,23 +77,23 @@ class SecretListView(generics.GenericAPIView):
serializer = self.get_serializer(queryset, many=True) serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data) return Response(serializer.data)
def post(self, request):
return self.get(request, private_key=request.POST.get('private_key'))
class SecretDetailView(generics.GenericAPIView): class SecretDetailView(generics.GenericAPIView):
""" """
Retrieve a single Secret. If a private key is provided in the GET body, attempt to decrypt the Secret. Retrieve a single Secret. If a private key is POSTed, attempt to decrypt the Secret.
e.g. curl -X GET http://netbox/api/secrets/secrets/123/ --data-binary "@/path/to/private_key"
""" """
queryset = Secret.objects.select_related('device__primary_ip', 'role')\ queryset = Secret.objects.select_related('device__primary_ip', 'role')\
.prefetch_related('role__users', 'role__groups') .prefetch_related('role__users', 'role__groups')
serializer_class = SecretSerializer serializer_class = SecretSerializer
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES + [FreeRADIUSClientsRenderer] renderer_classes = [FormlessBrowsableAPIRenderer, JSONRenderer, FreeRADIUSClientsRenderer]
def get(self, request, pk, *args, **kwargs): def get(self, request, pk, private_key=None):
secret = get_object_or_404(Secret, pk=pk) secret = get_object_or_404(Secret, pk=pk)
# Attempt to decrypt the Secret if a private key was provided. # Attempt to decrypt the Secret if a private key was provided.
private_key = request.body or None
if private_key is not None: if private_key is not None:
try: try:
uk = UserKey.objects.get(user=request.user) uk = UserKey.objects.get(user=request.user)
@ -122,6 +119,9 @@ class SecretDetailView(generics.GenericAPIView):
serializer = self.get_serializer(secret) serializer = self.get_serializer(secret)
return Response(serializer.data) return Response(serializer.data)
def post(self, request, pk):
return self.get(request, pk, private_key=request.POST.get('private_key'))
class RSAKeyGeneratorView(APIView): class RSAKeyGeneratorView(APIView):
""" """