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 = env(
|
||||||
"ALLOWED_HOSTS",
|
"ALLOWED_HOSTS",
|
||||||
"devinventory,inventory.waw.hackerspace.pl,inventory.hackerspace.pl,i,inventory"
|
"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(",")
|
).split(",")
|
||||||
LOGIN_REDIRECT_URL = "/admin/"
|
LOGIN_REDIRECT_URL = "/admin/"
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ DATABASES = {
|
||||||
"NAME": env("DB_NAME", "postgres"),
|
"NAME": env("DB_NAME", "postgres"),
|
||||||
"USER": env("DB_USER", "postgres"),
|
"USER": env("DB_USER", "postgres"),
|
||||||
"PASSWORD": env("DB_PASSWORD", None),
|
"PASSWORD": env("DB_PASSWORD", None),
|
||||||
"HOST": env("DB_HOST", "db"),
|
"HOST": env("DB_HOST", "127.0.0.1"),
|
||||||
"PORT": env("DB_PORT", 5432),
|
"PORT": env("DB_PORT", 5432),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,12 +171,10 @@ REST_FRAMEWORK = {
|
||||||
# Use Django's standard `django.contrib.auth` permissions,
|
# Use Django's standard `django.contrib.auth` permissions,
|
||||||
# or allow read-only access for unauthenticated users.
|
# or allow read-only access for unauthenticated users.
|
||||||
"DEFAULT_PERMISSION_CLASSES": [
|
"DEFAULT_PERMISSION_CLASSES": [
|
||||||
"rest_framework.permissions.IsAuthenticated",
|
"rest_framework.permissions.IsAuthenticatedOrReadOnly",
|
||||||
],
|
],
|
||||||
"DEFAULT_AUTHENTICATION_CLASSES": [
|
"DEFAULT_AUTHENTICATION_CLASSES": [
|
||||||
"rest_framework.authentication.BasicAuthentication",
|
"storage.authentication.LanAuthentication",
|
||||||
"rest_framework.authentication.SessionAuthentication",
|
|
||||||
"rest_framework.authentication.TokenAuthentication",
|
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,3 +186,6 @@ SOCIAL_AUTH_JSONFIELD_ENABLED = True
|
||||||
|
|
||||||
LABEL_API = env("LABEL_API", "http://label.waw.hackerspace.pl:4567")
|
LABEL_API = env("LABEL_API", "http://label.waw.hackerspace.pl:4567")
|
||||||
LOGIN_URL = "/admin/login/"
|
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.response import Response
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
|
from storage.authentication import LanAuthentication
|
||||||
from rest_framework.permissions import AllowAny
|
|
||||||
|
|
||||||
from storage.models import Item, Label
|
from storage.models import Item, Label
|
||||||
from storage.serializers import ItemSerializer, LabelSerializer
|
from storage.serializers import ItemSerializer, LabelSerializer
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.shortcuts import get_object_or_404
|
|
||||||
|
|
||||||
from storage.views import apply_smart_search
|
from storage.views import apply_smart_search
|
||||||
|
|
||||||
|
@ -40,7 +38,10 @@ class LabelViewSet(viewsets.ModelViewSet):
|
||||||
queryset = Label.objects.all()
|
queryset = Label.objects.all()
|
||||||
serializer_class = LabelSerializer
|
serializer_class = LabelSerializer
|
||||||
|
|
||||||
@action(detail=True, methods=["post"], permission_classes=[AllowAny])
|
@action(
|
||||||
|
detail=True,
|
||||||
|
methods=["post"],
|
||||||
|
)
|
||||||
def print(self, request, pk):
|
def print(self, request, pk):
|
||||||
return api_print(request.query_params.get("quantity", 1), self.get_object())
|
return api_print(request.query_params.get("quantity", 1), self.get_object())
|
||||||
|
|
||||||
|
@ -77,40 +78,35 @@ class ItemViewSet(viewsets.ModelViewSet):
|
||||||
except Label.DoesNotExist:
|
except Label.DoesNotExist:
|
||||||
raise Http404()
|
raise Http404()
|
||||||
|
|
||||||
@action(detail=True, methods=["post"], permission_classes=[AllowAny])
|
@action(
|
||||||
|
detail=True,
|
||||||
|
methods=["post"],
|
||||||
|
)
|
||||||
def print(self, request, pk):
|
def print(self, request, pk):
|
||||||
return api_print(request.query_params.get("quantity", 1), self.get_object())
|
return api_print(request.query_params.get("quantity", 1), self.get_object())
|
||||||
|
|
||||||
@action(
|
@action(detail=True, authentication_classes=[LanAuthentication])
|
||||||
detail=True,
|
|
||||||
)
|
|
||||||
def children(self, request, pk):
|
def children(self, request, pk):
|
||||||
item = self.get_object()
|
item = self.get_object()
|
||||||
return Response(
|
return Response(
|
||||||
self.serializer_class(item.get_children().all(), many=True).data
|
self.serializer_class(item.get_children().all(), many=True).data
|
||||||
)
|
)
|
||||||
|
|
||||||
@action(
|
@action(detail=True, authentication_classes=[LanAuthentication])
|
||||||
detail=True,
|
|
||||||
)
|
|
||||||
def ancestors(self, request, pk):
|
def ancestors(self, request, pk):
|
||||||
item = self.get_object()
|
item = self.get_object()
|
||||||
return Response(
|
return Response(
|
||||||
self.serializer_class(item.get_ancestors().all(), many=True).data
|
self.serializer_class(item.get_ancestors().all(), many=True).data
|
||||||
)
|
)
|
||||||
|
|
||||||
@action(
|
@action(detail=True, authentication_classes=[LanAuthentication])
|
||||||
detail=True,
|
|
||||||
)
|
|
||||||
def descendants(self, request, pk):
|
def descendants(self, request, pk):
|
||||||
item = self.get_object()
|
item = self.get_object()
|
||||||
return Response(
|
return Response(
|
||||||
self.serializer_class(item.get_descendants().all(), many=True).data
|
self.serializer_class(item.get_descendants().all(), many=True).data
|
||||||
)
|
)
|
||||||
|
|
||||||
@action(
|
@action(detail=True, authentication_classes=[LanAuthentication])
|
||||||
detail=True,
|
|
||||||
)
|
|
||||||
def siblings(self, request, pk):
|
def siblings(self, request, pk):
|
||||||
item = self.get_object()
|
item = self.get_object()
|
||||||
return Response(
|
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