Skip to content

Commit

Permalink
feat: Implement Hotel model with CRUD operations and integrate into v…
Browse files Browse the repository at this point in the history
…iews and serializers
  • Loading branch information
seanmorley15 committed Feb 3, 2025
1 parent da9c2ba commit df60184
Show file tree
Hide file tree
Showing 7 changed files with 451 additions and 6 deletions.
14 changes: 12 additions & 2 deletions backend/server/adventures/serializers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.utils import timezone
import os
from .models import Adventure, AdventureImage, ChecklistItem, Collection, Note, Transportation, Checklist, Visit, Category, Attachment
from .models import Adventure, AdventureImage, ChecklistItem, Collection, Note, Transportation, Checklist, Visit, Category, Attachment, Hotel
from rest_framework import serializers
from main.utils import CustomModelSerializer
from users.serializers import CustomUserDetailsSerializer
Expand Down Expand Up @@ -303,4 +303,14 @@ def to_representation(self, instance):
shared_uuids.append(str(user.uuid))
representation['shared_with'] = shared_uuids
return representation


class HotelSerializer(CustomModelSerializer):

class Meta:
model = Hotel
fields = [
'id', 'user_id', 'name', 'description', 'rating', 'link', 'check_in', 'check_out',
'reservation_number', 'price', 'latitude', 'longitude', 'location', 'is_public',
'collection', 'created_at', 'updated_at'
]
read_only_fields = ['id', 'created_at', 'updated_at', 'user_id']
1 change: 1 addition & 0 deletions backend/server/adventures/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
router.register(r'overpass', OverpassViewSet, basename='overpass')
router.register(r'search', GlobalSearchView, basename='search')
router.register(r'attachments', AttachmentViewSet, basename='attachments')
router.register(r'hotels', HotelViewSet, basename='hotels')


urlpatterns = [
Expand Down
3 changes: 2 additions & 1 deletion backend/server/adventures/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@
from .stats_view import *
from .transportation_view import *
from .global_search_view import *
from .attachment_view import *
from .attachment_view import *
from .hotel_view import *
84 changes: 84 additions & 0 deletions backend/server/adventures/views/hotel_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from django.db.models import Q
from adventures.models import Hotel
from adventures.serializers import HotelSerializer
from rest_framework.exceptions import PermissionDenied
from adventures.permissions import IsOwnerOrSharedWithFullAccess
from rest_framework.permissions import IsAuthenticated

class HotelViewSet(viewsets.ModelViewSet):
queryset = Hotel.objects.all()
serializer_class = HotelSerializer
permission_classes = [IsOwnerOrSharedWithFullAccess]

def list(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return Response(status=status.HTTP_403_FORBIDDEN)
queryset = Hotel.objects.filter(
Q(user_id=request.user.id)
)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)

def get_queryset(self):
user = self.request.user
if self.action == 'retrieve':
# For individual adventure retrieval, include public adventures, user's own adventures and shared adventures
return Hotel.objects.filter(
Q(is_public=True) | Q(user_id=user.id) | Q(collection__shared_with=user.id)
).distinct().order_by('-updated_at')
# For other actions, include user's own adventures and shared adventures
return Hotel.objects.filter(
Q(user_id=user.id) | Q(collection__shared_with=user.id)
).distinct().order_by('-updated_at')

def partial_update(self, request, *args, **kwargs):
# Retrieve the current object
instance = self.get_object()
user = request.user

# Partially update the instance with the request data
serializer = self.get_serializer(instance, data=request.data, partial=True)
serializer.is_valid(raise_exception=True)

# Retrieve the collection from the validated data
new_collection = serializer.validated_data.get('collection')

if new_collection is not None and new_collection != instance.collection:
# Check if the user is the owner of the new collection
if new_collection.user_id != user or instance.user_id != user:
raise PermissionDenied("You do not have permission to use this collection.")
elif new_collection is None:
# Handle the case where the user is trying to set the collection to None
if instance.collection is not None and instance.collection.user_id != user:
raise PermissionDenied("You cannot remove the collection as you are not the owner.")

# Perform the update
self.perform_update(serializer)

# Return the updated instance
return Response(serializer.data)

def perform_update(self, serializer):
serializer.save()

# when creating an adventure, make sure the user is the owner of the collection or shared with the collection
def perform_create(self, serializer):
# Retrieve the collection from the validated data
collection = serializer.validated_data.get('collection')

# Check if a collection is provided
if collection:
user = self.request.user
# Check if the user is the owner or is in the shared_with list
if collection.user_id != user and not collection.shared_with.filter(id=user.id).exists():
# Return an error response if the user does not have permission
raise PermissionDenied("You do not have permission to use this collection.")
# if collection the owner of the adventure is the owner of the collection
serializer.save(user_id=collection.user_id)
return

# Save the adventure with the current user as the owner
serializer.save(user_id=self.request.user)
7 changes: 4 additions & 3 deletions documentation/docs/configuration/social_auth/github.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ This configuration is done in the [Admin Panel](../../guides/admin_panel.md). Yo
- Settings: can be left blank
- Sites: move over the sites you want to enable Authentik on, usually `example.com` and `www.example.com` unless you renamed your sites.

4. Save the configuration.

Users should now be able to log in to AdventureLog using their GitHub account, and link it to existing accounts.

## Linking to Existing Account

If a user has an existing AdventureLog account and wants to link it to their Github account, they can do so by logging in to their AdventureLog account and navigating to the `Settings` page. There is a button that says `Launch Account Connections`, click that and then choose the provider to link to the existing account.
Expand All @@ -43,6 +47,3 @@ If a user has an existing AdventureLog account and wants to link it to their Git

![Authentik Social Auth Configuration](/github_settings.png)

4. Save the configuration.

Users should now be able to log in to AdventureLog using their GitHub account, and link it to existing accounts.
Loading

0 comments on commit df60184

Please sign in to comment.