112 lines
3.8 KiB
Python
112 lines
3.8 KiB
Python
from django.contrib.auth import authenticate, login, logout
|
|
from rest_framework import permissions, status
|
|
from rest_framework.response import Response
|
|
from rest_framework.views import APIView
|
|
|
|
from .migration_service import apply_visitor_migration
|
|
from .models import UserSession, VisitorMigration
|
|
from .serializers import RegisterSerializer, UserSerializer
|
|
|
|
|
|
def client_ip(request):
|
|
forwarded = request.META.get("HTTP_X_FORWARDED_FOR")
|
|
return forwarded.split(",")[0].strip() if forwarded else request.META.get("REMOTE_ADDR")
|
|
|
|
|
|
class RegisterView(APIView):
|
|
permission_classes = [permissions.AllowAny]
|
|
|
|
def post(self, request):
|
|
serializer = RegisterSerializer(
|
|
data=request.data,
|
|
context={"ip_address": client_ip(request)},
|
|
)
|
|
serializer.is_valid(raise_exception=True)
|
|
user = serializer.save()
|
|
login(request, user)
|
|
self._record_session(request, user)
|
|
payload = UserSerializer(user).data
|
|
payload["visitor_migration_pending"] = hasattr(user, "visitor_migration")
|
|
return Response(payload, status=status.HTTP_201_CREATED)
|
|
|
|
@staticmethod
|
|
def _record_session(request, user):
|
|
if not request.session.session_key:
|
|
request.session.save()
|
|
UserSession.objects.update_or_create(
|
|
session_key=request.session.session_key,
|
|
defaults={
|
|
"user": user,
|
|
"user_agent": request.headers.get("User-Agent", "")[:300],
|
|
"ip_address": client_ip(request),
|
|
},
|
|
)
|
|
|
|
|
|
class LoginView(APIView):
|
|
permission_classes = [permissions.AllowAny]
|
|
|
|
def post(self, request):
|
|
user = authenticate(
|
|
request,
|
|
username=request.data.get("username", ""),
|
|
password=request.data.get("password", ""),
|
|
)
|
|
if user is None or not user.is_active:
|
|
return Response(
|
|
{"error": {"code": "invalid_credentials", "message": "用户名或密码错误"}},
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
login(request, user)
|
|
RegisterView._record_session(request, user)
|
|
return Response(UserSerializer(user).data)
|
|
|
|
|
|
class LogoutView(APIView):
|
|
def post(self, request):
|
|
if request.session.session_key:
|
|
UserSession.objects.filter(session_key=request.session.session_key).delete()
|
|
logout(request)
|
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
|
|
|
|
|
class MeView(APIView):
|
|
def get(self, request):
|
|
return Response(UserSerializer(request.user).data)
|
|
|
|
def patch(self, request):
|
|
serializer = UserSerializer(request.user, data=request.data, partial=True)
|
|
serializer.is_valid(raise_exception=True)
|
|
serializer.save()
|
|
return Response(serializer.data)
|
|
|
|
|
|
class VisitorMigrationView(APIView):
|
|
def get(self, request):
|
|
migration = VisitorMigration.objects.filter(user=request.user).first()
|
|
if migration is None:
|
|
return Response({"pending": False, "summary": {}})
|
|
return Response(
|
|
{
|
|
"pending": migration.status == VisitorMigration.Status.PENDING,
|
|
"status": migration.status,
|
|
"summary": migration.summary,
|
|
}
|
|
)
|
|
|
|
def post(self, request):
|
|
migration = VisitorMigration.objects.filter(user=request.user).first()
|
|
if migration is None:
|
|
return Response(
|
|
{"error": {"code": "no_visitor_data", "message": "没有待迁移的游客数据"}},
|
|
status=status.HTTP_404_NOT_FOUND,
|
|
)
|
|
migration = apply_visitor_migration(request.user)
|
|
return Response(
|
|
{
|
|
"pending": False,
|
|
"status": migration.status,
|
|
"summary": migration.summary,
|
|
}
|
|
)
|