Make HSLan always authenticated for GET
This commit is contained in:
parent
30c3c3eb7a
commit
154e1079da
|
@ -34,7 +34,7 @@ DEBUG = not PROD
|
|||
ALLOWED_HOSTS = env(
|
||||
"ALLOWED_HOSTS",
|
||||
"devinventory,inventory.waw.hackerspace.pl,inventory.hackerspace.pl,i,inventory"
|
||||
+ (",127.0.0.1" if not PROD else ""),
|
||||
+ (",127.0.0.1,locahost,*" if not PROD else ""),
|
||||
).split(",")
|
||||
LOGIN_REDIRECT_URL = "/admin/"
|
||||
|
||||
|
@ -102,7 +102,7 @@ DATABASES = {
|
|||
"NAME": env("DB_NAME", "postgres"),
|
||||
"USER": env("DB_USER", "postgres"),
|
||||
"PASSWORD": env("DB_PASSWORD", None),
|
||||
"HOST": env("DB_HOST", "db"),
|
||||
"HOST": env("DB_HOST", "127.0.0.1"),
|
||||
"PORT": env("DB_PORT", 5432),
|
||||
}
|
||||
}
|
||||
|
@ -171,12 +171,10 @@ REST_FRAMEWORK = {
|
|||
# Use Django's standard `django.contrib.auth` permissions,
|
||||
# or allow read-only access for unauthenticated users.
|
||||
"DEFAULT_PERMISSION_CLASSES": [
|
||||
"rest_framework.permissions.IsAuthenticated",
|
||||
"rest_framework.permissions.IsAuthenticatedOrReadOnly",
|
||||
],
|
||||
"DEFAULT_AUTHENTICATION_CLASSES": [
|
||||
"rest_framework.authentication.BasicAuthentication",
|
||||
"rest_framework.authentication.SessionAuthentication",
|
||||
"rest_framework.authentication.TokenAuthentication",
|
||||
"storage.authentication.LanAuthentication",
|
||||
],
|
||||
}
|
||||
|
||||
|
@ -188,3 +186,6 @@ SOCIAL_AUTH_JSONFIELD_ENABLED = True
|
|||
|
||||
LABEL_API = env("LABEL_API", "http://label.waw.hackerspace.pl:4567")
|
||||
LOGIN_URL = "/admin/login/"
|
||||
LAN_ALLOWED_ADDRES_SPACE = "10.8.0.0/16"
|
||||
LAN_ALLOWED_HEADER = "X-LAN-ALLOWED"
|
||||
PROXY_TRUSTED_IPS = ["172.21.37.1"]
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
from rest_framework import viewsets, generics, filters
|
||||
from rest_framework import viewsets, filters
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.decorators import action
|
||||
|
||||
from rest_framework.permissions import AllowAny
|
||||
from storage.authentication import LanAuthentication
|
||||
|
||||
from storage.models import Item, Label
|
||||
from storage.serializers import ItemSerializer, LabelSerializer
|
||||
from django.http import Http404
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from storage.views import apply_smart_search
|
||||
|
||||
|
@ -40,7 +38,10 @@ class LabelViewSet(viewsets.ModelViewSet):
|
|||
queryset = Label.objects.all()
|
||||
serializer_class = LabelSerializer
|
||||
|
||||
@action(detail=True, methods=["post"], permission_classes=[AllowAny])
|
||||
@action(
|
||||
detail=True,
|
||||
methods=["post"],
|
||||
)
|
||||
def print(self, request, pk):
|
||||
return api_print(request.query_params.get("quantity", 1), self.get_object())
|
||||
|
||||
|
@ -77,40 +78,35 @@ class ItemViewSet(viewsets.ModelViewSet):
|
|||
except Label.DoesNotExist:
|
||||
raise Http404()
|
||||
|
||||
@action(detail=True, methods=["post"], permission_classes=[AllowAny])
|
||||
@action(
|
||||
detail=True,
|
||||
methods=["post"],
|
||||
)
|
||||
def print(self, request, pk):
|
||||
return api_print(request.query_params.get("quantity", 1), self.get_object())
|
||||
|
||||
@action(
|
||||
detail=True,
|
||||
)
|
||||
@action(detail=True, authentication_classes=[LanAuthentication])
|
||||
def children(self, request, pk):
|
||||
item = self.get_object()
|
||||
return Response(
|
||||
self.serializer_class(item.get_children().all(), many=True).data
|
||||
)
|
||||
|
||||
@action(
|
||||
detail=True,
|
||||
)
|
||||
@action(detail=True, authentication_classes=[LanAuthentication])
|
||||
def ancestors(self, request, pk):
|
||||
item = self.get_object()
|
||||
return Response(
|
||||
self.serializer_class(item.get_ancestors().all(), many=True).data
|
||||
)
|
||||
|
||||
@action(
|
||||
detail=True,
|
||||
)
|
||||
@action(detail=True, authentication_classes=[LanAuthentication])
|
||||
def descendants(self, request, pk):
|
||||
item = self.get_object()
|
||||
return Response(
|
||||
self.serializer_class(item.get_descendants().all(), many=True).data
|
||||
)
|
||||
|
||||
@action(
|
||||
detail=True,
|
||||
)
|
||||
@action(detail=True, authentication_classes=[LanAuthentication])
|
||||
def siblings(self, request, pk):
|
||||
item = self.get_object()
|
||||
return Response(
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
import ipaddress
|
||||
from rest_framework import exceptions
|
||||
|
||||
from rest_framework.authentication import BaseAuthentication
|
||||
from spejstore.settings import (
|
||||
LAN_ALLOWED_ADDRES_SPACE,
|
||||
LAN_ALLOWED_HEADER,
|
||||
PROD,
|
||||
PROXY_TRUSTED_IPS,
|
||||
)
|
||||
|
||||
|
||||
headers_to_check_for_ip = [
|
||||
"HTTP_X_FORWARDED_FOR",
|
||||
"X_FORWARDED_FOR",
|
||||
"HTTP_CLIENT_IP",
|
||||
"HTTP_X_REAL_IP",
|
||||
"HTTP_X_FORWARDED",
|
||||
"HTTP_X_CLUSTER_CLIENT_IP",
|
||||
"HTTP_FORWARDED_FOR",
|
||||
"HTTP_FORWARDED",
|
||||
"HTTP_VIA",
|
||||
]
|
||||
|
||||
|
||||
def get_request_meta(request, key):
|
||||
value = request.META.get(key, request).strip()
|
||||
if value == "":
|
||||
return None
|
||||
return value
|
||||
|
||||
|
||||
def get_ip_from_request(request):
|
||||
for header in headers_to_check_for_ip:
|
||||
ip = get_request_meta(request, header)
|
||||
if not ip:
|
||||
ip = get_request_meta(request, header.replace("_", "-"))
|
||||
if ip:
|
||||
return ip
|
||||
return None
|
||||
|
||||
|
||||
class LanAuthentication(BaseAuthentication):
|
||||
def authenticate(self, request):
|
||||
is_authorized = self.has_permission(request)
|
||||
if is_authorized:
|
||||
user = getattr(request._request, "user", None)
|
||||
return (user, "authorized")
|
||||
else:
|
||||
raise exceptions.AuthenticationFailed(
|
||||
"Unauthorized: not in subnet of " + LAN_ALLOWED_ADDRES_SPACE
|
||||
)
|
||||
|
||||
def authenticate_header(self, request):
|
||||
return LAN_ALLOWED_HEADER
|
||||
|
||||
def has_permission(self, request):
|
||||
if PROD:
|
||||
client_ip = get_ip_from_request(request)
|
||||
if client_ip is None:
|
||||
raise exceptions.AuthenticationFailed("Unauthorized: no ip detected?")
|
||||
# Make sure that we need to check PROXY_TRUSTED_IPS here
|
||||
if len(PROXY_TRUSTED_IPS) > 0:
|
||||
if request.META["REMOTE_ADDR"] not in PROXY_TRUSTED_IPS:
|
||||
raise exceptions.AuthenticationFailed(
|
||||
"Unauthorized: request is not coming from the PROXY_TRUSTED_IPS machine"
|
||||
)
|
||||
return ipaddress.IPv4Address(client_ip) in ipaddress.IPv4Network(
|
||||
LAN_ALLOWED_ADDRES_SPACE
|
||||
)
|
||||
else:
|
||||
return True
|
Loading…
Reference in New Issue