feat: ship MVP itinerary optimization, weather, AI key prefs, and MCP tools
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
from .immich_view import ImmichIntegrationView, ImmichIntegrationViewSet
|
||||
from .integration_view import IntegrationView
|
||||
from .strava_view import StravaIntegrationView
|
||||
from .wanderer_view import WandererIntegrationViewSet
|
||||
from .wanderer_view import WandererIntegrationViewSet
|
||||
from .user_api_key_view import UserAPIKeyViewSet
|
||||
from .recommendation_profile_view import UserRecommendationPreferenceProfileViewSet
|
||||
|
||||
@@ -3,40 +3,77 @@ from rest_framework.response import Response
|
||||
from rest_framework import viewsets, status
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from django.utils import timezone
|
||||
from integrations.models import ImmichIntegration, StravaToken, WandererIntegration
|
||||
from integrations.models import (
|
||||
EncryptionConfigurationError,
|
||||
ImmichIntegration,
|
||||
StravaToken,
|
||||
WandererIntegration,
|
||||
UserAPIKey,
|
||||
get_field_fernet,
|
||||
)
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class IntegrationView(viewsets.ViewSet):
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def list(self, request):
|
||||
"""
|
||||
RESTful GET method for listing all integrations.
|
||||
"""
|
||||
immich_integrations = ImmichIntegration.objects.filter(user=request.user)
|
||||
google_map_integration = settings.GOOGLE_MAPS_API_KEY != ''
|
||||
strava_integration_global = settings.STRAVA_CLIENT_ID != '' and settings.STRAVA_CLIENT_SECRET != ''
|
||||
google_map_integration = (
|
||||
settings.GOOGLE_MAPS_API_KEY != ""
|
||||
or UserAPIKey.objects.filter(
|
||||
user=request.user,
|
||||
provider="google_maps",
|
||||
).exists()
|
||||
)
|
||||
strava_integration_global = (
|
||||
settings.STRAVA_CLIENT_ID != "" and settings.STRAVA_CLIENT_SECRET != ""
|
||||
)
|
||||
strava_integration_user = StravaToken.objects.filter(user=request.user).exists()
|
||||
wanderer_integration = WandererIntegration.objects.filter(user=request.user).exists()
|
||||
wanderer_integration = WandererIntegration.objects.filter(
|
||||
user=request.user
|
||||
).exists()
|
||||
is_wanderer_expired = False
|
||||
|
||||
if wanderer_integration:
|
||||
token_expiry = WandererIntegration.objects.filter(user=request.user).first().token_expiry
|
||||
token_expiry = (
|
||||
WandererIntegration.objects.filter(user=request.user)
|
||||
.first()
|
||||
.token_expiry
|
||||
)
|
||||
if token_expiry and token_expiry < timezone.now():
|
||||
is_wanderer_expired = True
|
||||
|
||||
api_key_status = {
|
||||
"enabled": UserAPIKey.objects.filter(user=request.user).exists(),
|
||||
"available": True,
|
||||
"error": None,
|
||||
}
|
||||
try:
|
||||
get_field_fernet()
|
||||
except EncryptionConfigurationError as exc:
|
||||
api_key_status = {
|
||||
"enabled": False,
|
||||
"available": False,
|
||||
"error": str(exc),
|
||||
}
|
||||
|
||||
return Response(
|
||||
{
|
||||
'immich': immich_integrations.exists(),
|
||||
'google_maps': google_map_integration,
|
||||
'strava': {
|
||||
'global': strava_integration_global,
|
||||
'user': strava_integration_user
|
||||
"immich": immich_integrations.exists(),
|
||||
"google_maps": google_map_integration,
|
||||
"api_keys": api_key_status,
|
||||
"strava": {
|
||||
"global": strava_integration_global,
|
||||
"user": strava_integration_user,
|
||||
},
|
||||
"wanderer": {
|
||||
"exists": wanderer_integration,
|
||||
"expired": is_wanderer_expired,
|
||||
},
|
||||
'wanderer': {
|
||||
'exists': wanderer_integration,
|
||||
'expired': is_wanderer_expired
|
||||
}
|
||||
},
|
||||
status=status.HTTP_200_OK
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
from rest_framework import status, viewsets
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
|
||||
from integrations.models import UserRecommendationPreferenceProfile
|
||||
from integrations.serializers import UserRecommendationPreferenceProfileSerializer
|
||||
|
||||
|
||||
class UserRecommendationPreferenceProfileViewSet(viewsets.ModelViewSet):
|
||||
serializer_class = UserRecommendationPreferenceProfileSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get_queryset(self):
|
||||
return UserRecommendationPreferenceProfile.objects.filter(
|
||||
user=self.request.user
|
||||
)
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
instance = self.get_queryset().first()
|
||||
if not instance:
|
||||
return Response([], status=status.HTTP_200_OK)
|
||||
serializer = self.get_serializer(instance)
|
||||
return Response([serializer.data], status=status.HTTP_200_OK)
|
||||
|
||||
def perform_create(self, serializer):
|
||||
existing = UserRecommendationPreferenceProfile.objects.filter(
|
||||
user=self.request.user
|
||||
).first()
|
||||
if existing:
|
||||
for field, value in serializer.validated_data.items():
|
||||
setattr(existing, field, value)
|
||||
existing.save()
|
||||
self._upserted_instance = existing
|
||||
return
|
||||
|
||||
self._upserted_instance = serializer.save(user=self.request.user)
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
self.perform_create(serializer)
|
||||
output = self.get_serializer(self._upserted_instance)
|
||||
return Response(output.data, status=status.HTTP_200_OK)
|
||||
33
backend/server/integrations/views/user_api_key_view.py
Normal file
33
backend/server/integrations/views/user_api_key_view.py
Normal file
@@ -0,0 +1,33 @@
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.exceptions import APIException
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
|
||||
from integrations.models import (
|
||||
EncryptionConfigurationError,
|
||||
UserAPIKey,
|
||||
get_field_fernet,
|
||||
)
|
||||
from integrations.serializers import UserAPIKeySerializer
|
||||
|
||||
|
||||
class APIKeyConfigurationError(APIException):
|
||||
status_code = 503
|
||||
default_detail = (
|
||||
"API key storage is unavailable due to server encryption configuration."
|
||||
)
|
||||
default_code = "api_key_encryption_unavailable"
|
||||
|
||||
|
||||
class UserAPIKeyViewSet(viewsets.ModelViewSet):
|
||||
serializer_class = UserAPIKeySerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def initial(self, request, *args, **kwargs):
|
||||
try:
|
||||
get_field_fernet()
|
||||
except EncryptionConfigurationError as exc:
|
||||
raise APIKeyConfigurationError(detail=str(exc)) from exc
|
||||
return super().initial(request, *args, **kwargs)
|
||||
|
||||
def get_queryset(self):
|
||||
return UserAPIKey.objects.filter(user=self.request.user).order_by("provider")
|
||||
Reference in New Issue
Block a user