243 lines
8.7 KiB
Python
243 lines
8.7 KiB
Python
"""
|
|
App Version Check API Views
|
|
アプリバージョンチェック機能
|
|
"""
|
|
|
|
from rest_framework import status
|
|
from rest_framework.decorators import api_view, permission_classes
|
|
from rest_framework.permissions import AllowAny
|
|
from rest_framework.response import Response
|
|
from django.utils.decorators import method_decorator
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
from django.views import View
|
|
from django.http import JsonResponse
|
|
import json
|
|
import logging
|
|
|
|
from .models import AppVersion
|
|
from .serializers import AppVersionCheckSerializer, AppVersionResponseSerializer
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@api_view(['POST'])
|
|
@permission_classes([AllowAny])
|
|
def app_version_check(request):
|
|
"""
|
|
アプリバージョンチェックAPI
|
|
|
|
POST /api/app/version-check
|
|
|
|
Request:
|
|
{
|
|
"current_version": "1.2.3",
|
|
"platform": "android",
|
|
"build_number": "123"
|
|
}
|
|
|
|
Response:
|
|
{
|
|
"latest_version": "1.3.0",
|
|
"update_required": false,
|
|
"update_available": true,
|
|
"update_message": "新機能が追加されました。更新をお勧めします。",
|
|
"download_url": "https://play.google.com/store/apps/details?id=com.example.app",
|
|
"release_date": "2025-08-25T00:00:00Z"
|
|
}
|
|
"""
|
|
try:
|
|
# リクエストデータの検証
|
|
serializer = AppVersionCheckSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response({
|
|
'error': 'Invalid request data',
|
|
'details': serializer.errors
|
|
}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
current_version = serializer.validated_data['current_version']
|
|
platform = serializer.validated_data['platform']
|
|
build_number = serializer.validated_data.get('build_number')
|
|
|
|
# 最新バージョン情報を取得
|
|
latest_version_obj = AppVersion.get_latest_version(platform)
|
|
|
|
if not latest_version_obj:
|
|
return Response({
|
|
'error': 'No version information available for this platform'
|
|
}, status=status.HTTP_404_NOT_FOUND)
|
|
|
|
# バージョン比較
|
|
comparison = AppVersion.compare_versions(current_version, latest_version_obj.version)
|
|
|
|
# レスポンスデータ作成
|
|
response_data = {
|
|
'latest_version': latest_version_obj.version,
|
|
'update_required': False,
|
|
'update_available': False,
|
|
'update_message': latest_version_obj.update_message or 'アプリは最新版です',
|
|
'download_url': latest_version_obj.download_url or '',
|
|
'release_date': latest_version_obj.release_date
|
|
}
|
|
|
|
if comparison < 0: # current_version < latest_version
|
|
response_data['update_available'] = True
|
|
|
|
# 強制更新が必要かチェック
|
|
if latest_version_obj.is_required:
|
|
response_data['update_required'] = True
|
|
response_data['update_message'] = (
|
|
latest_version_obj.update_message or
|
|
'このバージョンは古すぎるため、更新が必要です。'
|
|
)
|
|
else:
|
|
response_data['update_message'] = (
|
|
latest_version_obj.update_message or
|
|
'新しいバージョンが利用可能です。更新をお勧めします。'
|
|
)
|
|
|
|
# レスポンス検証
|
|
response_serializer = AppVersionResponseSerializer(data=response_data)
|
|
if response_serializer.is_valid():
|
|
return Response(response_serializer.validated_data, status=status.HTTP_200_OK)
|
|
else:
|
|
logger.error(f"Response serialization error: {response_serializer.errors}")
|
|
return Response({
|
|
'error': 'Internal server error'
|
|
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
|
|
except Exception as e:
|
|
logger.error(f"App version check error: {e}")
|
|
return Response({
|
|
'error': 'Internal server error',
|
|
'message': str(e)
|
|
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
|
|
|
|
@method_decorator(csrf_exempt, name='dispatch')
|
|
class AppVersionManagementView(View):
|
|
"""アプリバージョン管理ビュー(管理者用)"""
|
|
|
|
def get(self, request):
|
|
"""全バージョン情報取得"""
|
|
try:
|
|
platform = request.GET.get('platform')
|
|
|
|
queryset = AppVersion.objects.all().order_by('-created_at')
|
|
if platform:
|
|
queryset = queryset.filter(platform=platform)
|
|
|
|
versions = []
|
|
for version in queryset:
|
|
versions.append({
|
|
'id': version.id,
|
|
'version': version.version,
|
|
'platform': version.platform,
|
|
'build_number': version.build_number,
|
|
'is_latest': version.is_latest,
|
|
'is_required': version.is_required,
|
|
'update_message': version.update_message,
|
|
'download_url': version.download_url,
|
|
'release_date': version.release_date.isoformat(),
|
|
'created_at': version.created_at.isoformat()
|
|
})
|
|
|
|
return JsonResponse({
|
|
'versions': versions,
|
|
'total': len(versions)
|
|
})
|
|
|
|
except Exception as e:
|
|
logger.error(f"Version list error: {e}")
|
|
return JsonResponse({
|
|
'error': 'Failed to fetch versions'
|
|
}, status=500)
|
|
|
|
def post(self, request):
|
|
"""新バージョン登録"""
|
|
try:
|
|
data = json.loads(request.body)
|
|
|
|
# 必須フィールドチェック
|
|
required_fields = ['version', 'platform']
|
|
for field in required_fields:
|
|
if field not in data:
|
|
return JsonResponse({
|
|
'error': f'Missing required field: {field}'
|
|
}, status=400)
|
|
|
|
# バージョンオブジェクト作成
|
|
version_obj = AppVersion(
|
|
version=data['version'],
|
|
platform=data['platform'],
|
|
build_number=data.get('build_number'),
|
|
is_latest=data.get('is_latest', False),
|
|
is_required=data.get('is_required', False),
|
|
update_message=data.get('update_message'),
|
|
download_url=data.get('download_url')
|
|
)
|
|
|
|
version_obj.save()
|
|
|
|
return JsonResponse({
|
|
'message': 'Version created successfully',
|
|
'id': version_obj.id,
|
|
'version': version_obj.version,
|
|
'platform': version_obj.platform
|
|
}, status=201)
|
|
|
|
except json.JSONDecodeError:
|
|
return JsonResponse({
|
|
'error': 'Invalid JSON data'
|
|
}, status=400)
|
|
except Exception as e:
|
|
logger.error(f"Version creation error: {e}")
|
|
return JsonResponse({
|
|
'error': 'Failed to create version'
|
|
}, status=500)
|
|
|
|
def put(self, request):
|
|
"""バージョン情報更新"""
|
|
try:
|
|
data = json.loads(request.body)
|
|
version_id = data.get('id')
|
|
|
|
if not version_id:
|
|
return JsonResponse({
|
|
'error': 'Version ID is required'
|
|
}, status=400)
|
|
|
|
try:
|
|
version_obj = AppVersion.objects.get(id=version_id)
|
|
except AppVersion.DoesNotExist:
|
|
return JsonResponse({
|
|
'error': 'Version not found'
|
|
}, status=404)
|
|
|
|
# フィールド更新
|
|
updateable_fields = [
|
|
'build_number', 'is_latest', 'is_required',
|
|
'update_message', 'download_url'
|
|
]
|
|
|
|
for field in updateable_fields:
|
|
if field in data:
|
|
setattr(version_obj, field, data[field])
|
|
|
|
version_obj.save()
|
|
|
|
return JsonResponse({
|
|
'message': 'Version updated successfully',
|
|
'id': version_obj.id,
|
|
'version': version_obj.version
|
|
})
|
|
|
|
except json.JSONDecodeError:
|
|
return JsonResponse({
|
|
'error': 'Invalid JSON data'
|
|
}, status=400)
|
|
except Exception as e:
|
|
logger.error(f"Version update error: {e}")
|
|
return JsonResponse({
|
|
'error': 'Failed to update version'
|
|
}, status=500)
|