toolshed/backend/toolshed/api/idmap.py
2026-08-27 03:04:50 +02:00

69 lines
3 KiB
Python

from django.urls import path
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ViewSetMixin
from authentication.models import KnownIdentity, ToolshedUser, Group
from authentication.signature_auth import SignatureAuthentication
from toolshed.models import InventoryItem, StorageLocation
from toolshed.serializers import FriendSerializer, GroupIdMapSerializer
class IdMap(APIView, ViewSetMixin):
authentication_classes = [SignatureAuthentication]
permission_classes = [IsAuthenticated]
def get(self, request, format=None): # /api/idmap/
identity = request.user
identities = identity.friends.all() | KnownIdentity.objects.filter(pk=identity.pk)
groups = identity.member_of_groups.all()
return Response({
'identities': FriendSerializer(identities, many=True).data,
'groups': GroupIdMapSerializer(groups, many=True).data,
})
@api_view(['GET'])
@authentication_classes([SignatureAuthentication])
@permission_classes([IsAuthenticated])
def resolve_short_id(request, kind, owner_id, local_id):
"""Resolves a short id's (kind, owner_id, local_id) against this backend's own numbering. See docs/implementation.md#domain-qualified-short-id-resolution."""
if kind in ('item', 'storage_location'):
try:
owner = KnownIdentity.objects.get(pk=owner_id).user.get()
except (KnownIdentity.DoesNotExist, ToolshedUser.DoesNotExist):
return Response(status=404)
if owner not in request.user.friends_or_self():
return Response(status=403)
model = InventoryItem if kind == 'item' else StorageLocation
try:
obj = model.objects.get(owner=owner, id=local_id)
except model.DoesNotExist:
return Response(status=404)
is_owner = request.user.user.filter(pk=owner.pk).exists()
if getattr(obj, 'availability_policy', 'share') == 'private' and not is_owner:
return Response(status=403)
return Response({'handle': f'{owner.username}@{owner.domain}', 'id': obj.id})
if kind in ('group_item', 'group_storage_location'):
try:
group = Group.objects.get(pk=owner_id)
except Group.DoesNotExist:
return Response(status=404)
if not group.is_member(request.user):
return Response(status=403)
model = InventoryItem if kind == 'group_item' else StorageLocation
try:
obj = model.objects.get(owner_group=group, id=local_id)
except model.DoesNotExist:
return Response(status=404)
return Response({'handle': str(group), 'id': obj.id})
return Response(status=400)
urlpatterns = [
path('idmap/', IdMap.as_view(), name='idmap'),
path('resolve_short_id/<str:kind>/<int:owner_id>/<int:local_id>/', resolve_short_id,
name='resolve_short_id'),
]