mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 04:31:13 -05:00
- Created a base email template (base.html) for consistent styling across all emails. - Added moderation approval email template (moderation_approved.html) to notify users of approved submissions. - Added moderation rejection email template (moderation_rejected.html) to inform users of required changes for their submissions. - Created password reset email template (password_reset.html) for users requesting to reset their passwords. - Developed a welcome email template (welcome.html) to greet new users and provide account details and tips for using ThrillWiki.
370 lines
12 KiB
Python
370 lines
12 KiB
Python
"""
|
|
Versioning API endpoints for ThrillWiki.
|
|
|
|
Provides REST API for:
|
|
- Version history for entities
|
|
- Specific version details
|
|
- Comparing versions
|
|
- Diff with current state
|
|
- Version restoration (optional)
|
|
"""
|
|
|
|
from typing import List
|
|
from uuid import UUID
|
|
from django.shortcuts import get_object_or_404
|
|
from django.http import Http404
|
|
from ninja import Router
|
|
|
|
from apps.entities.models import Park, Ride, Company, RideModel
|
|
from apps.versioning.models import EntityVersion
|
|
from apps.versioning.services import VersionService
|
|
from api.v1.schemas import (
|
|
EntityVersionSchema,
|
|
VersionHistoryResponseSchema,
|
|
VersionDiffSchema,
|
|
VersionComparisonSchema,
|
|
ErrorSchema,
|
|
MessageSchema
|
|
)
|
|
|
|
router = Router(tags=['Versioning'])
|
|
|
|
|
|
# Park Versions
|
|
|
|
@router.get(
|
|
'/parks/{park_id}/versions',
|
|
response={200: VersionHistoryResponseSchema, 404: ErrorSchema},
|
|
summary="Get park version history"
|
|
)
|
|
def get_park_versions(request, park_id: UUID, limit: int = 50):
|
|
"""
|
|
Get version history for a park.
|
|
|
|
Returns up to `limit` versions in reverse chronological order (newest first).
|
|
"""
|
|
park = get_object_or_404(Park, id=park_id)
|
|
versions = VersionService.get_version_history(park, limit=limit)
|
|
|
|
return {
|
|
'entity_id': str(park.id),
|
|
'entity_type': 'park',
|
|
'entity_name': park.name,
|
|
'total_versions': VersionService.get_version_count(park),
|
|
'versions': [
|
|
EntityVersionSchema.from_orm(v) for v in versions
|
|
]
|
|
}
|
|
|
|
|
|
@router.get(
|
|
'/parks/{park_id}/versions/{version_number}',
|
|
response={200: EntityVersionSchema, 404: ErrorSchema},
|
|
summary="Get specific park version"
|
|
)
|
|
def get_park_version(request, park_id: UUID, version_number: int):
|
|
"""Get a specific version of a park by version number."""
|
|
park = get_object_or_404(Park, id=park_id)
|
|
version = VersionService.get_version_by_number(park, version_number)
|
|
|
|
if not version:
|
|
raise Http404("Version not found")
|
|
|
|
return EntityVersionSchema.from_orm(version)
|
|
|
|
|
|
@router.get(
|
|
'/parks/{park_id}/versions/{version_number}/diff',
|
|
response={200: VersionDiffSchema, 404: ErrorSchema},
|
|
summary="Compare park version with current"
|
|
)
|
|
def get_park_version_diff(request, park_id: UUID, version_number: int):
|
|
"""
|
|
Compare a specific version with the current park state.
|
|
|
|
Returns the differences between the version and current values.
|
|
"""
|
|
park = get_object_or_404(Park, id=park_id)
|
|
version = VersionService.get_version_by_number(park, version_number)
|
|
|
|
if not version:
|
|
raise Http404("Version not found")
|
|
|
|
diff = VersionService.get_diff_with_current(version)
|
|
|
|
return {
|
|
'entity_id': str(park.id),
|
|
'entity_type': 'park',
|
|
'entity_name': park.name,
|
|
'version_number': version.version_number,
|
|
'version_date': version.created,
|
|
'differences': diff['differences'],
|
|
'changed_field_count': diff['changed_field_count']
|
|
}
|
|
|
|
|
|
# Ride Versions
|
|
|
|
@router.get(
|
|
'/rides/{ride_id}/versions',
|
|
response={200: VersionHistoryResponseSchema, 404: ErrorSchema},
|
|
summary="Get ride version history"
|
|
)
|
|
def get_ride_versions(request, ride_id: UUID, limit: int = 50):
|
|
"""Get version history for a ride."""
|
|
ride = get_object_or_404(Ride, id=ride_id)
|
|
versions = VersionService.get_version_history(ride, limit=limit)
|
|
|
|
return {
|
|
'entity_id': str(ride.id),
|
|
'entity_type': 'ride',
|
|
'entity_name': ride.name,
|
|
'total_versions': VersionService.get_version_count(ride),
|
|
'versions': [
|
|
EntityVersionSchema.from_orm(v) for v in versions
|
|
]
|
|
}
|
|
|
|
|
|
@router.get(
|
|
'/rides/{ride_id}/versions/{version_number}',
|
|
response={200: EntityVersionSchema, 404: ErrorSchema},
|
|
summary="Get specific ride version"
|
|
)
|
|
def get_ride_version(request, ride_id: UUID, version_number: int):
|
|
"""Get a specific version of a ride by version number."""
|
|
ride = get_object_or_404(Ride, id=ride_id)
|
|
version = VersionService.get_version_by_number(ride, version_number)
|
|
|
|
if not version:
|
|
raise Http404("Version not found")
|
|
|
|
return EntityVersionSchema.from_orm(version)
|
|
|
|
|
|
@router.get(
|
|
'/rides/{ride_id}/versions/{version_number}/diff',
|
|
response={200: VersionDiffSchema, 404: ErrorSchema},
|
|
summary="Compare ride version with current"
|
|
)
|
|
def get_ride_version_diff(request, ride_id: UUID, version_number: int):
|
|
"""Compare a specific version with the current ride state."""
|
|
ride = get_object_or_404(Ride, id=ride_id)
|
|
version = VersionService.get_version_by_number(ride, version_number)
|
|
|
|
if not version:
|
|
raise Http404("Version not found")
|
|
|
|
diff = VersionService.get_diff_with_current(version)
|
|
|
|
return {
|
|
'entity_id': str(ride.id),
|
|
'entity_type': 'ride',
|
|
'entity_name': ride.name,
|
|
'version_number': version.version_number,
|
|
'version_date': version.created,
|
|
'differences': diff['differences'],
|
|
'changed_field_count': diff['changed_field_count']
|
|
}
|
|
|
|
|
|
# Company Versions
|
|
|
|
@router.get(
|
|
'/companies/{company_id}/versions',
|
|
response={200: VersionHistoryResponseSchema, 404: ErrorSchema},
|
|
summary="Get company version history"
|
|
)
|
|
def get_company_versions(request, company_id: UUID, limit: int = 50):
|
|
"""Get version history for a company."""
|
|
company = get_object_or_404(Company, id=company_id)
|
|
versions = VersionService.get_version_history(company, limit=limit)
|
|
|
|
return {
|
|
'entity_id': str(company.id),
|
|
'entity_type': 'company',
|
|
'entity_name': company.name,
|
|
'total_versions': VersionService.get_version_count(company),
|
|
'versions': [
|
|
EntityVersionSchema.from_orm(v) for v in versions
|
|
]
|
|
}
|
|
|
|
|
|
@router.get(
|
|
'/companies/{company_id}/versions/{version_number}',
|
|
response={200: EntityVersionSchema, 404: ErrorSchema},
|
|
summary="Get specific company version"
|
|
)
|
|
def get_company_version(request, company_id: UUID, version_number: int):
|
|
"""Get a specific version of a company by version number."""
|
|
company = get_object_or_404(Company, id=company_id)
|
|
version = VersionService.get_version_by_number(company, version_number)
|
|
|
|
if not version:
|
|
raise Http404("Version not found")
|
|
|
|
return EntityVersionSchema.from_orm(version)
|
|
|
|
|
|
@router.get(
|
|
'/companies/{company_id}/versions/{version_number}/diff',
|
|
response={200: VersionDiffSchema, 404: ErrorSchema},
|
|
summary="Compare company version with current"
|
|
)
|
|
def get_company_version_diff(request, company_id: UUID, version_number: int):
|
|
"""Compare a specific version with the current company state."""
|
|
company = get_object_or_404(Company, id=company_id)
|
|
version = VersionService.get_version_by_number(company, version_number)
|
|
|
|
if not version:
|
|
raise Http404("Version not found")
|
|
|
|
diff = VersionService.get_diff_with_current(version)
|
|
|
|
return {
|
|
'entity_id': str(company.id),
|
|
'entity_type': 'company',
|
|
'entity_name': company.name,
|
|
'version_number': version.version_number,
|
|
'version_date': version.created,
|
|
'differences': diff['differences'],
|
|
'changed_field_count': diff['changed_field_count']
|
|
}
|
|
|
|
|
|
# Ride Model Versions
|
|
|
|
@router.get(
|
|
'/ride-models/{model_id}/versions',
|
|
response={200: VersionHistoryResponseSchema, 404: ErrorSchema},
|
|
summary="Get ride model version history"
|
|
)
|
|
def get_ride_model_versions(request, model_id: UUID, limit: int = 50):
|
|
"""Get version history for a ride model."""
|
|
model = get_object_or_404(RideModel, id=model_id)
|
|
versions = VersionService.get_version_history(model, limit=limit)
|
|
|
|
return {
|
|
'entity_id': str(model.id),
|
|
'entity_type': 'ride_model',
|
|
'entity_name': str(model),
|
|
'total_versions': VersionService.get_version_count(model),
|
|
'versions': [
|
|
EntityVersionSchema.from_orm(v) for v in versions
|
|
]
|
|
}
|
|
|
|
|
|
@router.get(
|
|
'/ride-models/{model_id}/versions/{version_number}',
|
|
response={200: EntityVersionSchema, 404: ErrorSchema},
|
|
summary="Get specific ride model version"
|
|
)
|
|
def get_ride_model_version(request, model_id: UUID, version_number: int):
|
|
"""Get a specific version of a ride model by version number."""
|
|
model = get_object_or_404(RideModel, id=model_id)
|
|
version = VersionService.get_version_by_number(model, version_number)
|
|
|
|
if not version:
|
|
raise Http404("Version not found")
|
|
|
|
return EntityVersionSchema.from_orm(version)
|
|
|
|
|
|
@router.get(
|
|
'/ride-models/{model_id}/versions/{version_number}/diff',
|
|
response={200: VersionDiffSchema, 404: ErrorSchema},
|
|
summary="Compare ride model version with current"
|
|
)
|
|
def get_ride_model_version_diff(request, model_id: UUID, version_number: int):
|
|
"""Compare a specific version with the current ride model state."""
|
|
model = get_object_or_404(RideModel, id=model_id)
|
|
version = VersionService.get_version_by_number(model, version_number)
|
|
|
|
if not version:
|
|
raise Http404("Version not found")
|
|
|
|
diff = VersionService.get_diff_with_current(version)
|
|
|
|
return {
|
|
'entity_id': str(model.id),
|
|
'entity_type': 'ride_model',
|
|
'entity_name': str(model),
|
|
'version_number': version.version_number,
|
|
'version_date': version.created,
|
|
'differences': diff['differences'],
|
|
'changed_field_count': diff['changed_field_count']
|
|
}
|
|
|
|
|
|
# Generic Version Endpoints
|
|
|
|
@router.get(
|
|
'/versions/{version_id}',
|
|
response={200: EntityVersionSchema, 404: ErrorSchema},
|
|
summary="Get version by ID"
|
|
)
|
|
def get_version(request, version_id: UUID):
|
|
"""Get a specific version by its ID."""
|
|
version = get_object_or_404(EntityVersion, id=version_id)
|
|
return EntityVersionSchema.from_orm(version)
|
|
|
|
|
|
@router.get(
|
|
'/versions/{version_id}/compare/{other_version_id}',
|
|
response={200: VersionComparisonSchema, 404: ErrorSchema},
|
|
summary="Compare two versions"
|
|
)
|
|
def compare_versions(request, version_id: UUID, other_version_id: UUID):
|
|
"""
|
|
Compare two versions of the same entity.
|
|
|
|
Both versions must be for the same entity.
|
|
"""
|
|
version1 = get_object_or_404(EntityVersion, id=version_id)
|
|
version2 = get_object_or_404(EntityVersion, id=other_version_id)
|
|
|
|
comparison = VersionService.compare_versions(version1, version2)
|
|
|
|
return {
|
|
'version1': EntityVersionSchema.from_orm(version1),
|
|
'version2': EntityVersionSchema.from_orm(version2),
|
|
'differences': comparison['differences'],
|
|
'changed_field_count': comparison['changed_field_count']
|
|
}
|
|
|
|
|
|
# Optional: Version Restoration
|
|
# Uncomment if you want to enable version restoration via API
|
|
|
|
# @router.post(
|
|
# '/versions/{version_id}/restore',
|
|
# response={200: MessageSchema, 404: ErrorSchema},
|
|
# summary="Restore a version"
|
|
# )
|
|
# def restore_version(request, version_id: UUID):
|
|
# """
|
|
# Restore an entity to a previous version.
|
|
#
|
|
# This creates a new version with change_type='restored'.
|
|
# Requires authentication and appropriate permissions.
|
|
# """
|
|
# version = get_object_or_404(EntityVersion, id=version_id)
|
|
#
|
|
# # Check authentication
|
|
# if not request.user.is_authenticated:
|
|
# return 401, {'error': 'Authentication required'}
|
|
#
|
|
# # Restore version
|
|
# restored_version = VersionService.restore_version(
|
|
# version,
|
|
# user=request.user,
|
|
# comment='Restored via API'
|
|
# )
|
|
#
|
|
# return {
|
|
# 'message': f'Successfully restored to version {version.version_number}',
|
|
# 'new_version_number': restored_version.version_number
|
|
# }
|