2024-07-09 13:26:39 -04:00
|
|
|
from rest_framework import permissions
|
|
|
|
|
|
|
|
class IsOwnerOrReadOnly(permissions.BasePermission):
|
|
|
|
"""
|
2025-06-12 15:54:01 -04:00
|
|
|
Owners can edit, others have read-only access.
|
2024-07-09 13:26:39 -04:00
|
|
|
"""
|
|
|
|
def has_object_permission(self, request, view, obj):
|
|
|
|
if request.method in permissions.SAFE_METHODS:
|
|
|
|
return True
|
Rename Adventures to Locations (#696)
* Refactor user_id to user in adventures and related models, views, and components
- Updated all instances of user_id to user in the adventures app, including models, serializers, views, and frontend components.
- Adjusted queries and filters to reflect the new user field naming convention.
- Ensured consistency across the codebase for user identification in adventures, collections, notes, and transportation entities.
- Modified frontend components to align with the updated data structure, ensuring proper access control and rendering based on user ownership.
* Refactor adventure-related views and components to use "Location" terminology
- Updated GlobalSearchView to replace AdventureSerializer with LocationSerializer.
- Modified IcsCalendarGeneratorViewSet to use LocationSerializer instead of AdventureSerializer.
- Created new LocationImageViewSet for managing location images, including primary image toggling and image deletion.
- Introduced LocationViewSet for managing locations with enhanced filtering, sorting, and sharing capabilities.
- Updated ReverseGeocodeViewSet to utilize LocationSerializer.
- Added ActivityTypesView to retrieve distinct activity types from locations.
- Refactored user views to replace AdventureSerializer with LocationSerializer.
- Updated frontend components to reflect changes from "adventure" to "location", including AdventureCard, AdventureLink, AdventureModal, and others.
- Adjusted API endpoints in frontend routes to align with new location-based structure.
- Ensured all references to adventures are replaced with locations across the codebase.
* refactor: rename adventures to locations across the application
- Updated localization files to replace adventure-related terms with location-related terms.
- Refactored TypeScript types and variables from Adventure to Location in various routes and components.
- Adjusted UI elements and labels to reflect the change from adventures to locations.
- Ensured all references to adventures in the codebase are consistent with the new location terminology.
* Refactor code structure for improved readability and maintainability
* feat: Implement location details page with server-side loading and deletion functionality
- Added +page.server.ts to handle server-side loading of additional location info.
- Created +page.svelte for displaying location details, including images, visits, and maps.
- Integrated GPX file handling and rendering on the map.
- Updated map route to link to locations instead of adventures.
- Refactored profile and search routes to use LocationCard instead of AdventureCard.
* docs: Update terminology from "Adventure" to "Location" and enhance project overview
* docs: Clarify collection examples in usage documentation
* feat: Enable credentials for GPX file fetch and add CORS_ALLOW_CREDENTIALS setting
* Refactor adventure references to locations across the backend and frontend
- Updated CategoryViewSet to reflect location context instead of adventures.
- Modified ChecklistViewSet to include locations in retrieval logic.
- Changed GlobalSearchView to search for locations instead of adventures.
- Adjusted IcsCalendarGeneratorViewSet to handle locations instead of adventures.
- Refactored LocationImageViewSet to remove unused import.
- Updated LocationViewSet to clarify public access for locations.
- Changed LodgingViewSet to reference locations instead of adventures.
- Modified NoteViewSet to prevent listing all locations.
- Updated RecommendationsViewSet to handle locations in parsing and response.
- Adjusted ReverseGeocodeViewSet to search through user locations.
- Updated StatsViewSet to count locations instead of adventures.
- Changed TagsView to reflect activity types for locations.
- Updated TransportationViewSet to reference locations instead of adventures.
- Added new translations for search results related to locations in multiple languages.
- Updated dashboard and profile pages to reflect location counts instead of adventure counts.
- Adjusted search routes to handle locations instead of adventures.
* Update banner image
* style: Update stats component background and border for improved visibility
* refactor: Rename AdventureCard and AdventureModal to LocationCard and LocationModal for consistency
2025-06-25 11:49:34 -04:00
|
|
|
# obj.user is FK to User, compare with request.user
|
|
|
|
return obj.user == request.user
|
2024-07-09 16:48:52 -04:00
|
|
|
|
|
|
|
|
|
|
|
class IsPublicReadOnly(permissions.BasePermission):
|
|
|
|
"""
|
2025-06-12 15:54:01 -04:00
|
|
|
Read-only if public or owner, write only for owner.
|
2024-07-09 16:48:52 -04:00
|
|
|
"""
|
|
|
|
def has_object_permission(self, request, view, obj):
|
|
|
|
if request.method in permissions.SAFE_METHODS:
|
Rename Adventures to Locations (#696)
* Refactor user_id to user in adventures and related models, views, and components
- Updated all instances of user_id to user in the adventures app, including models, serializers, views, and frontend components.
- Adjusted queries and filters to reflect the new user field naming convention.
- Ensured consistency across the codebase for user identification in adventures, collections, notes, and transportation entities.
- Modified frontend components to align with the updated data structure, ensuring proper access control and rendering based on user ownership.
* Refactor adventure-related views and components to use "Location" terminology
- Updated GlobalSearchView to replace AdventureSerializer with LocationSerializer.
- Modified IcsCalendarGeneratorViewSet to use LocationSerializer instead of AdventureSerializer.
- Created new LocationImageViewSet for managing location images, including primary image toggling and image deletion.
- Introduced LocationViewSet for managing locations with enhanced filtering, sorting, and sharing capabilities.
- Updated ReverseGeocodeViewSet to utilize LocationSerializer.
- Added ActivityTypesView to retrieve distinct activity types from locations.
- Refactored user views to replace AdventureSerializer with LocationSerializer.
- Updated frontend components to reflect changes from "adventure" to "location", including AdventureCard, AdventureLink, AdventureModal, and others.
- Adjusted API endpoints in frontend routes to align with new location-based structure.
- Ensured all references to adventures are replaced with locations across the codebase.
* refactor: rename adventures to locations across the application
- Updated localization files to replace adventure-related terms with location-related terms.
- Refactored TypeScript types and variables from Adventure to Location in various routes and components.
- Adjusted UI elements and labels to reflect the change from adventures to locations.
- Ensured all references to adventures in the codebase are consistent with the new location terminology.
* Refactor code structure for improved readability and maintainability
* feat: Implement location details page with server-side loading and deletion functionality
- Added +page.server.ts to handle server-side loading of additional location info.
- Created +page.svelte for displaying location details, including images, visits, and maps.
- Integrated GPX file handling and rendering on the map.
- Updated map route to link to locations instead of adventures.
- Refactored profile and search routes to use LocationCard instead of AdventureCard.
* docs: Update terminology from "Adventure" to "Location" and enhance project overview
* docs: Clarify collection examples in usage documentation
* feat: Enable credentials for GPX file fetch and add CORS_ALLOW_CREDENTIALS setting
* Refactor adventure references to locations across the backend and frontend
- Updated CategoryViewSet to reflect location context instead of adventures.
- Modified ChecklistViewSet to include locations in retrieval logic.
- Changed GlobalSearchView to search for locations instead of adventures.
- Adjusted IcsCalendarGeneratorViewSet to handle locations instead of adventures.
- Refactored LocationImageViewSet to remove unused import.
- Updated LocationViewSet to clarify public access for locations.
- Changed LodgingViewSet to reference locations instead of adventures.
- Modified NoteViewSet to prevent listing all locations.
- Updated RecommendationsViewSet to handle locations in parsing and response.
- Adjusted ReverseGeocodeViewSet to search through user locations.
- Updated StatsViewSet to count locations instead of adventures.
- Changed TagsView to reflect activity types for locations.
- Updated TransportationViewSet to reference locations instead of adventures.
- Added new translations for search results related to locations in multiple languages.
- Updated dashboard and profile pages to reflect location counts instead of adventure counts.
- Adjusted search routes to handle locations instead of adventures.
* Update banner image
* style: Update stats component background and border for improved visibility
* refactor: Rename AdventureCard and AdventureModal to LocationCard and LocationModal for consistency
2025-06-25 11:49:34 -04:00
|
|
|
return obj.is_public or obj.user == request.user
|
|
|
|
return obj.user == request.user
|
2025-06-12 15:54:01 -04:00
|
|
|
|
|
|
|
|
2024-09-02 10:29:51 -04:00
|
|
|
class CollectionShared(permissions.BasePermission):
|
|
|
|
"""
|
2025-06-12 15:54:01 -04:00
|
|
|
Allow full access if user is in shared_with of collection(s) or owner,
|
|
|
|
read-only if public or shared_with,
|
|
|
|
write only if owner or shared_with.
|
2024-09-02 10:29:51 -04:00
|
|
|
"""
|
|
|
|
def has_object_permission(self, request, view, obj):
|
2025-06-12 15:54:01 -04:00
|
|
|
user = request.user
|
|
|
|
if not user or not user.is_authenticated:
|
|
|
|
# Anonymous: only read public
|
|
|
|
return request.method in permissions.SAFE_METHODS and obj.is_public
|
2024-09-02 10:29:51 -04:00
|
|
|
|
2025-06-12 15:54:01 -04:00
|
|
|
# Check if user is in shared_with of any collections related to the obj
|
|
|
|
# If obj is a Collection itself:
|
|
|
|
if hasattr(obj, 'shared_with'):
|
|
|
|
if obj.shared_with.filter(id=user.id).exists():
|
|
|
|
return True
|
|
|
|
|
Rename Adventures to Locations (#696)
* Refactor user_id to user in adventures and related models, views, and components
- Updated all instances of user_id to user in the adventures app, including models, serializers, views, and frontend components.
- Adjusted queries and filters to reflect the new user field naming convention.
- Ensured consistency across the codebase for user identification in adventures, collections, notes, and transportation entities.
- Modified frontend components to align with the updated data structure, ensuring proper access control and rendering based on user ownership.
* Refactor adventure-related views and components to use "Location" terminology
- Updated GlobalSearchView to replace AdventureSerializer with LocationSerializer.
- Modified IcsCalendarGeneratorViewSet to use LocationSerializer instead of AdventureSerializer.
- Created new LocationImageViewSet for managing location images, including primary image toggling and image deletion.
- Introduced LocationViewSet for managing locations with enhanced filtering, sorting, and sharing capabilities.
- Updated ReverseGeocodeViewSet to utilize LocationSerializer.
- Added ActivityTypesView to retrieve distinct activity types from locations.
- Refactored user views to replace AdventureSerializer with LocationSerializer.
- Updated frontend components to reflect changes from "adventure" to "location", including AdventureCard, AdventureLink, AdventureModal, and others.
- Adjusted API endpoints in frontend routes to align with new location-based structure.
- Ensured all references to adventures are replaced with locations across the codebase.
* refactor: rename adventures to locations across the application
- Updated localization files to replace adventure-related terms with location-related terms.
- Refactored TypeScript types and variables from Adventure to Location in various routes and components.
- Adjusted UI elements and labels to reflect the change from adventures to locations.
- Ensured all references to adventures in the codebase are consistent with the new location terminology.
* Refactor code structure for improved readability and maintainability
* feat: Implement location details page with server-side loading and deletion functionality
- Added +page.server.ts to handle server-side loading of additional location info.
- Created +page.svelte for displaying location details, including images, visits, and maps.
- Integrated GPX file handling and rendering on the map.
- Updated map route to link to locations instead of adventures.
- Refactored profile and search routes to use LocationCard instead of AdventureCard.
* docs: Update terminology from "Adventure" to "Location" and enhance project overview
* docs: Clarify collection examples in usage documentation
* feat: Enable credentials for GPX file fetch and add CORS_ALLOW_CREDENTIALS setting
* Refactor adventure references to locations across the backend and frontend
- Updated CategoryViewSet to reflect location context instead of adventures.
- Modified ChecklistViewSet to include locations in retrieval logic.
- Changed GlobalSearchView to search for locations instead of adventures.
- Adjusted IcsCalendarGeneratorViewSet to handle locations instead of adventures.
- Refactored LocationImageViewSet to remove unused import.
- Updated LocationViewSet to clarify public access for locations.
- Changed LodgingViewSet to reference locations instead of adventures.
- Modified NoteViewSet to prevent listing all locations.
- Updated RecommendationsViewSet to handle locations in parsing and response.
- Adjusted ReverseGeocodeViewSet to search through user locations.
- Updated StatsViewSet to count locations instead of adventures.
- Changed TagsView to reflect activity types for locations.
- Updated TransportationViewSet to reference locations instead of adventures.
- Added new translations for search results related to locations in multiple languages.
- Updated dashboard and profile pages to reflect location counts instead of adventure counts.
- Adjusted search routes to handle locations instead of adventures.
* Update banner image
* style: Update stats component background and border for improved visibility
* refactor: Rename AdventureCard and AdventureModal to LocationCard and LocationModal for consistency
2025-06-25 11:49:34 -04:00
|
|
|
# If obj is a Location (has collections M2M)
|
2025-06-12 15:54:01 -04:00
|
|
|
if hasattr(obj, 'collections'):
|
|
|
|
# Check if user is in shared_with of any related collection
|
|
|
|
shared_collections = obj.collections.filter(shared_with=user)
|
|
|
|
if shared_collections.exists():
|
|
|
|
return True
|
2024-09-02 10:29:51 -04:00
|
|
|
|
2025-06-12 15:54:01 -04:00
|
|
|
# Read permission if public or owner
|
2024-09-02 10:29:51 -04:00
|
|
|
if request.method in permissions.SAFE_METHODS:
|
Rename Adventures to Locations (#696)
* Refactor user_id to user in adventures and related models, views, and components
- Updated all instances of user_id to user in the adventures app, including models, serializers, views, and frontend components.
- Adjusted queries and filters to reflect the new user field naming convention.
- Ensured consistency across the codebase for user identification in adventures, collections, notes, and transportation entities.
- Modified frontend components to align with the updated data structure, ensuring proper access control and rendering based on user ownership.
* Refactor adventure-related views and components to use "Location" terminology
- Updated GlobalSearchView to replace AdventureSerializer with LocationSerializer.
- Modified IcsCalendarGeneratorViewSet to use LocationSerializer instead of AdventureSerializer.
- Created new LocationImageViewSet for managing location images, including primary image toggling and image deletion.
- Introduced LocationViewSet for managing locations with enhanced filtering, sorting, and sharing capabilities.
- Updated ReverseGeocodeViewSet to utilize LocationSerializer.
- Added ActivityTypesView to retrieve distinct activity types from locations.
- Refactored user views to replace AdventureSerializer with LocationSerializer.
- Updated frontend components to reflect changes from "adventure" to "location", including AdventureCard, AdventureLink, AdventureModal, and others.
- Adjusted API endpoints in frontend routes to align with new location-based structure.
- Ensured all references to adventures are replaced with locations across the codebase.
* refactor: rename adventures to locations across the application
- Updated localization files to replace adventure-related terms with location-related terms.
- Refactored TypeScript types and variables from Adventure to Location in various routes and components.
- Adjusted UI elements and labels to reflect the change from adventures to locations.
- Ensured all references to adventures in the codebase are consistent with the new location terminology.
* Refactor code structure for improved readability and maintainability
* feat: Implement location details page with server-side loading and deletion functionality
- Added +page.server.ts to handle server-side loading of additional location info.
- Created +page.svelte for displaying location details, including images, visits, and maps.
- Integrated GPX file handling and rendering on the map.
- Updated map route to link to locations instead of adventures.
- Refactored profile and search routes to use LocationCard instead of AdventureCard.
* docs: Update terminology from "Adventure" to "Location" and enhance project overview
* docs: Clarify collection examples in usage documentation
* feat: Enable credentials for GPX file fetch and add CORS_ALLOW_CREDENTIALS setting
* Refactor adventure references to locations across the backend and frontend
- Updated CategoryViewSet to reflect location context instead of adventures.
- Modified ChecklistViewSet to include locations in retrieval logic.
- Changed GlobalSearchView to search for locations instead of adventures.
- Adjusted IcsCalendarGeneratorViewSet to handle locations instead of adventures.
- Refactored LocationImageViewSet to remove unused import.
- Updated LocationViewSet to clarify public access for locations.
- Changed LodgingViewSet to reference locations instead of adventures.
- Modified NoteViewSet to prevent listing all locations.
- Updated RecommendationsViewSet to handle locations in parsing and response.
- Adjusted ReverseGeocodeViewSet to search through user locations.
- Updated StatsViewSet to count locations instead of adventures.
- Changed TagsView to reflect activity types for locations.
- Updated TransportationViewSet to reference locations instead of adventures.
- Added new translations for search results related to locations in multiple languages.
- Updated dashboard and profile pages to reflect location counts instead of adventure counts.
- Adjusted search routes to handle locations instead of adventures.
* Update banner image
* style: Update stats component background and border for improved visibility
* refactor: Rename AdventureCard and AdventureModal to LocationCard and LocationModal for consistency
2025-06-25 11:49:34 -04:00
|
|
|
return obj.is_public or obj.user == user
|
2025-06-12 15:54:01 -04:00
|
|
|
|
|
|
|
# Write permission only if owner or shared user via collections
|
Rename Adventures to Locations (#696)
* Refactor user_id to user in adventures and related models, views, and components
- Updated all instances of user_id to user in the adventures app, including models, serializers, views, and frontend components.
- Adjusted queries and filters to reflect the new user field naming convention.
- Ensured consistency across the codebase for user identification in adventures, collections, notes, and transportation entities.
- Modified frontend components to align with the updated data structure, ensuring proper access control and rendering based on user ownership.
* Refactor adventure-related views and components to use "Location" terminology
- Updated GlobalSearchView to replace AdventureSerializer with LocationSerializer.
- Modified IcsCalendarGeneratorViewSet to use LocationSerializer instead of AdventureSerializer.
- Created new LocationImageViewSet for managing location images, including primary image toggling and image deletion.
- Introduced LocationViewSet for managing locations with enhanced filtering, sorting, and sharing capabilities.
- Updated ReverseGeocodeViewSet to utilize LocationSerializer.
- Added ActivityTypesView to retrieve distinct activity types from locations.
- Refactored user views to replace AdventureSerializer with LocationSerializer.
- Updated frontend components to reflect changes from "adventure" to "location", including AdventureCard, AdventureLink, AdventureModal, and others.
- Adjusted API endpoints in frontend routes to align with new location-based structure.
- Ensured all references to adventures are replaced with locations across the codebase.
* refactor: rename adventures to locations across the application
- Updated localization files to replace adventure-related terms with location-related terms.
- Refactored TypeScript types and variables from Adventure to Location in various routes and components.
- Adjusted UI elements and labels to reflect the change from adventures to locations.
- Ensured all references to adventures in the codebase are consistent with the new location terminology.
* Refactor code structure for improved readability and maintainability
* feat: Implement location details page with server-side loading and deletion functionality
- Added +page.server.ts to handle server-side loading of additional location info.
- Created +page.svelte for displaying location details, including images, visits, and maps.
- Integrated GPX file handling and rendering on the map.
- Updated map route to link to locations instead of adventures.
- Refactored profile and search routes to use LocationCard instead of AdventureCard.
* docs: Update terminology from "Adventure" to "Location" and enhance project overview
* docs: Clarify collection examples in usage documentation
* feat: Enable credentials for GPX file fetch and add CORS_ALLOW_CREDENTIALS setting
* Refactor adventure references to locations across the backend and frontend
- Updated CategoryViewSet to reflect location context instead of adventures.
- Modified ChecklistViewSet to include locations in retrieval logic.
- Changed GlobalSearchView to search for locations instead of adventures.
- Adjusted IcsCalendarGeneratorViewSet to handle locations instead of adventures.
- Refactored LocationImageViewSet to remove unused import.
- Updated LocationViewSet to clarify public access for locations.
- Changed LodgingViewSet to reference locations instead of adventures.
- Modified NoteViewSet to prevent listing all locations.
- Updated RecommendationsViewSet to handle locations in parsing and response.
- Adjusted ReverseGeocodeViewSet to search through user locations.
- Updated StatsViewSet to count locations instead of adventures.
- Changed TagsView to reflect activity types for locations.
- Updated TransportationViewSet to reference locations instead of adventures.
- Added new translations for search results related to locations in multiple languages.
- Updated dashboard and profile pages to reflect location counts instead of adventure counts.
- Adjusted search routes to handle locations instead of adventures.
* Update banner image
* style: Update stats component background and border for improved visibility
* refactor: Rename AdventureCard and AdventureModal to LocationCard and LocationModal for consistency
2025-06-25 11:49:34 -04:00
|
|
|
if obj.user == user:
|
2025-06-12 15:54:01 -04:00
|
|
|
return True
|
|
|
|
|
|
|
|
if hasattr(obj, 'collections'):
|
|
|
|
if obj.collections.filter(shared_with=user).exists():
|
|
|
|
return True
|
|
|
|
|
|
|
|
# Default deny
|
|
|
|
return False
|
2024-09-02 10:29:51 -04:00
|
|
|
|
|
|
|
|
|
|
|
class IsOwnerOrSharedWithFullAccess(permissions.BasePermission):
|
|
|
|
"""
|
2025-07-14 18:57:39 -04:00
|
|
|
Permission class that provides access control based on ownership and sharing.
|
|
|
|
|
|
|
|
Access Rules:
|
|
|
|
- Object owners have full access (read/write)
|
|
|
|
- Users shared via collections have full access (read/write)
|
|
|
|
- Collection owners have full access to objects in their collections
|
|
|
|
- Users with direct sharing have full access
|
|
|
|
- Anonymous users get read-only access to public objects
|
|
|
|
- Authenticated users get read-only access to public objects
|
|
|
|
|
|
|
|
Supports multiple sharing patterns:
|
|
|
|
- obj.collections (many-to-many collections)
|
|
|
|
- obj.collection (single collection foreign key)
|
|
|
|
- obj.shared_with (direct sharing many-to-many)
|
|
|
|
- obj.is_public (public access flag)
|
2024-09-02 10:29:51 -04:00
|
|
|
"""
|
2025-07-14 18:57:39 -04:00
|
|
|
|
2024-09-02 10:29:51 -04:00
|
|
|
def has_object_permission(self, request, view, obj):
|
2025-07-14 18:57:39 -04:00
|
|
|
"""
|
|
|
|
Check if the user has permission to access the object.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
request: The HTTP request
|
|
|
|
view: The view being accessed
|
|
|
|
obj: The object being accessed
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
bool: True if access is granted, False otherwise
|
|
|
|
"""
|
2025-06-12 15:54:01 -04:00
|
|
|
user = request.user
|
2025-07-14 18:57:39 -04:00
|
|
|
is_safe_method = request.method in permissions.SAFE_METHODS
|
|
|
|
|
|
|
|
# Anonymous users only get read access to public objects
|
2025-06-12 15:54:01 -04:00
|
|
|
if not user or not user.is_authenticated:
|
2025-07-14 18:57:39 -04:00
|
|
|
return is_safe_method and getattr(obj, 'is_public', False)
|
|
|
|
|
|
|
|
# Owner always has full access
|
|
|
|
if self._is_owner(obj, user):
|
2025-06-12 15:54:01 -04:00
|
|
|
return True
|
2025-07-14 18:57:39 -04:00
|
|
|
|
|
|
|
# Check collection-based access (both ownership and sharing)
|
|
|
|
if self._has_collection_access(obj, user):
|
2025-07-12 09:20:23 -04:00
|
|
|
return True
|
2025-07-14 18:57:39 -04:00
|
|
|
|
|
|
|
# Check direct sharing
|
|
|
|
if self._has_direct_sharing_access(obj, user):
|
2025-06-12 15:54:01 -04:00
|
|
|
return True
|
2025-07-14 18:57:39 -04:00
|
|
|
|
|
|
|
# For safe methods, check if object is public
|
|
|
|
if is_safe_method and getattr(obj, 'is_public', False):
|
2025-07-12 09:20:23 -04:00
|
|
|
return True
|
2025-07-14 18:57:39 -04:00
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
def _is_owner(self, obj, user):
|
|
|
|
"""
|
|
|
|
Check if the user is the owner of the object.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
obj: The object to check
|
|
|
|
user: The user to check ownership for
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
bool: True if user owns the object
|
|
|
|
"""
|
|
|
|
return hasattr(obj, 'user') and obj.user == user
|
|
|
|
|
|
|
|
def _has_collection_access(self, obj, user):
|
|
|
|
"""
|
|
|
|
Check if user has access via collections (either as owner or shared user).
|
|
|
|
|
|
|
|
Handles both many-to-many collections and single collection foreign keys.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
obj: The object to check
|
|
|
|
user: The user to check access for
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
bool: True if user has collection-based access
|
|
|
|
"""
|
|
|
|
# Check many-to-many collections (obj.collections)
|
|
|
|
if hasattr(obj, 'collections'):
|
|
|
|
collections = obj.collections.all()
|
|
|
|
if collections.exists():
|
|
|
|
# User is shared with any collection containing this object
|
|
|
|
if collections.filter(shared_with=user).exists():
|
|
|
|
return True
|
|
|
|
# User owns any collection containing this object
|
|
|
|
if collections.filter(user=user).exists():
|
|
|
|
return True
|
|
|
|
|
|
|
|
# Check single collection foreign key (obj.collection)
|
|
|
|
if hasattr(obj, 'collection') and obj.collection:
|
|
|
|
collection = obj.collection
|
|
|
|
# User is shared with the collection
|
|
|
|
if hasattr(collection, 'shared_with') and collection.shared_with.filter(id=user.id).exists():
|
|
|
|
return True
|
|
|
|
# User owns the collection
|
|
|
|
if hasattr(collection, 'user') and collection.user == user:
|
|
|
|
return True
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
def _has_direct_sharing_access(self, obj, user):
|
|
|
|
"""
|
|
|
|
Check if user has direct sharing access to the object.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
obj: The object to check
|
|
|
|
user: The user to check access for
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
bool: True if user has direct sharing access
|
|
|
|
"""
|
|
|
|
return (hasattr(obj, 'shared_with') and
|
|
|
|
obj.shared_with.filter(id=user.id).exists())
|
|
|
|
|
|
|
|
def has_permission(self, request, view):
|
|
|
|
"""
|
|
|
|
Check if the user has permission to access the view.
|
|
|
|
|
|
|
|
This is called before has_object_permission and provides a way to
|
|
|
|
deny access at the view level (e.g., for unauthenticated users).
|
|
|
|
|
|
|
|
Args:
|
|
|
|
request: The HTTP request
|
|
|
|
view: The view being accessed
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
bool: True if access is granted at the view level
|
|
|
|
"""
|
|
|
|
# Allow authenticated users and anonymous users for safe methods
|
|
|
|
# Individual object permissions are handled in has_object_permission
|
|
|
|
return (request.user and request.user.is_authenticated) or \
|
|
|
|
request.method in permissions.SAFE_METHODS
|