mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2026-08-02 17:01:58 -04:00
- Added permissions for GitHub Actions workflows to manage contents, packages, and actions. - Refactored SearchValidationError and IntegrationError classes to include custom messages and status codes. - Improved logging in GlobalSearchView and WandererIntegrationViewSet to capture validation errors and exceptions more effectively. - Updated error responses in billing views to provide user-friendly messages while logging detailed exceptions.
123 lines
4.5 KiB
Python
123 lines
4.5 KiB
Python
import logging
|
|
|
|
from rest_framework import viewsets, status
|
|
from rest_framework.decorators import action
|
|
from rest_framework.permissions import IsAuthenticated
|
|
from rest_framework.response import Response
|
|
from rest_framework.exceptions import ValidationError, NotFound
|
|
|
|
from integrations.models import WandererIntegration
|
|
from integrations.serializers import WandererIntegrationSerializer
|
|
from integrations.wanderer_services import (
|
|
IntegrationError,
|
|
TRAIL_EXPAND_AUTHOR,
|
|
TRAILS_LIST_PATHS,
|
|
make_wanderer_request,
|
|
validate_wanderer_connection,
|
|
)
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class WandererIntegrationViewSet(viewsets.ViewSet):
|
|
permission_classes = [IsAuthenticated]
|
|
serializer_class = WandererIntegrationSerializer
|
|
|
|
def _get_obj(self):
|
|
return WandererIntegration.objects.filter(user=self.request.user).first()
|
|
|
|
def list(self, request):
|
|
inst = self._get_obj()
|
|
if not inst:
|
|
return Response(status=status.HTTP_404_NOT_FOUND)
|
|
serializer = self.serializer_class(inst)
|
|
return Response(serializer.data)
|
|
|
|
def create(self, request):
|
|
if WandererIntegration.objects.filter(user=request.user).exists():
|
|
raise ValidationError('Wanderer integration already exists. Use UPDATE instead.')
|
|
|
|
server_url = request.data.get('server_url')
|
|
api_key = request.data.get('api_key')
|
|
if not server_url or not api_key:
|
|
raise ValidationError('Must provide server_url and api_key in request data.')
|
|
|
|
try:
|
|
normalized_url = validate_wanderer_connection(server_url, api_key)
|
|
except IntegrationError as exc:
|
|
logger.warning('Wanderer connection validation failed during create: %s', exc.user_message)
|
|
raise ValidationError({'error': exc.user_message})
|
|
|
|
inst = WandererIntegration.objects.create(
|
|
user=request.user,
|
|
server_url=normalized_url,
|
|
api_key=api_key.strip(),
|
|
)
|
|
return Response(
|
|
self.serializer_class(inst).data,
|
|
status=status.HTTP_201_CREATED,
|
|
)
|
|
|
|
def update(self, request, pk=None):
|
|
inst = self._get_obj()
|
|
if not inst:
|
|
raise NotFound('Wanderer integration not found.')
|
|
if pk and str(inst.id) != str(pk):
|
|
raise NotFound('Wanderer integration not found.')
|
|
|
|
server_url = request.data.get('server_url', inst.server_url)
|
|
api_key = (request.data.get('api_key') or '').strip() or inst.api_key
|
|
|
|
if not server_url:
|
|
raise ValidationError('server_url is required.')
|
|
|
|
try:
|
|
normalized_url = validate_wanderer_connection(server_url, api_key)
|
|
except IntegrationError as exc:
|
|
logger.warning('Wanderer connection validation failed during update: %s', exc.user_message)
|
|
raise ValidationError({'error': exc.user_message})
|
|
|
|
inst.server_url = normalized_url
|
|
inst.api_key = api_key.strip()
|
|
inst.save(update_fields=['server_url', 'api_key'])
|
|
|
|
return Response(self.serializer_class(inst).data)
|
|
|
|
@action(detail=False, methods=['post'])
|
|
def disable(self, request):
|
|
inst = self._get_obj()
|
|
if not inst:
|
|
raise NotFound('Wanderer integration not found.')
|
|
inst.delete()
|
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
|
|
|
@action(detail=False, methods=['get'], url_path='trails')
|
|
def trails(self, request):
|
|
inst = self._get_obj()
|
|
if not inst:
|
|
raise NotFound('Wanderer integration not found.')
|
|
|
|
params = dict(request.query_params)
|
|
params.setdefault('expand', TRAIL_EXPAND_AUTHOR['expand'])
|
|
last_error = None
|
|
for path in TRAILS_LIST_PATHS:
|
|
try:
|
|
response = make_wanderer_request(
|
|
inst,
|
|
path,
|
|
params=params,
|
|
)
|
|
return Response(response.json())
|
|
except IntegrationError as exc:
|
|
last_error = exc
|
|
if exc.status_code == 404:
|
|
continue
|
|
logger.warning('Wanderer trails request failed: %s', exc.user_message)
|
|
raise ValidationError({'detail': 'Unable to fetch trails from Wanderer at this time.'})
|
|
|
|
logger.warning(
|
|
'Wanderer trails request failed for all known paths',
|
|
exc_info=last_error,
|
|
)
|
|
raise ValidationError({'detail': 'Unable to fetch trails from Wanderer at this time.'})
|