| from rest_framework.views import APIView |
| from rest_framework.response import Response |
| from rest_framework import status |
| from rest_framework.permissions import AllowAny |
| from django.views.decorators.csrf import csrf_exempt |
| from django.utils.decorators import method_decorator |
| from api.utils.auth import ThirdPartyAuth, ThirdPartyUserManager |
| from django.contrib.auth.models import User |
| import logging |
|
|
| logger = logging.getLogger(__name__) |
|
|
|
|
| @method_decorator(csrf_exempt, name='dispatch') |
| class TokenValidateView(APIView): |
| """ |
| Token验证接口 |
| 用户可以通过此接口验证Token是否有效,并获取用户信息 |
| """ |
| permission_classes = [AllowAny] |
| |
| def post(self, request): |
| """ |
| 验证Token |
| |
| 支持的参数传递方式: |
| 1. JSON: {"token": "your_token"} |
| 2. Form data: token=your_token |
| 3. URL参数: ?token=your_token |
| 4. Header: Authorization: Token your_token |
| """ |
| |
| token = self.get_token_from_request(request) |
| |
| if not token: |
| return Response({ |
| 'valid': False, |
| 'error': 'Token参数缺失', |
| 'message': '请提供Token参数。支持的方式:1) JSON: {"token": "your_token"} 2) Form data: token=your_token 3) URL参数: ?token=your_token 4) Header: Authorization: Token your_token', |
| 'example': { |
| 'curl_header': 'curl -H "Authorization: Token 0c47b3d5b1aa561a5032f50e95bf069afa9a9e55" http://your-domain/api/token/validate/', |
| 'curl_param': 'curl -X POST http://your-domain/api/token/validate/?token=0c47b3d5b1aa561a5032f50e95bf069afa9a9e55', |
| 'curl_json': 'curl -X POST -H "Content-Type: application/json" -d \'{"token":"0c47b3d5b1aa561a5032f50e95bf069afa9a9e55"}\' http://your-domain/api/token/validate/' |
| } |
| }, status=status.HTTP_400_BAD_REQUEST) |
| |
| |
| validation_result = ThirdPartyAuth.validate_token(token) |
| |
| if not validation_result['valid']: |
| return Response({ |
| 'valid': False, |
| 'error': 'Token验证失败', |
| 'message': validation_result.get('message', 'Token无效或已过期'), |
| 'token_preview': f"{token[:8]}..." if len(token) > 8 else token |
| }, status=status.HTTP_401_UNAUTHORIZED) |
| |
| |
| user_name = validation_result.get('user_name') |
| |
| if not user_name: |
| return Response({ |
| 'valid': False, |
| 'error': '用户信息获取失败', |
| 'message': '第三方API返回的数据中没有用户名信息' |
| }, status=status.HTTP_500_INTERNAL_SERVER_ERROR) |
| |
| |
| local_user = ThirdPartyUserManager.get_user_by_third_party_username(user_name) |
| local_user_exists = local_user is not None |
| |
| return Response({ |
| 'valid': True, |
| 'message': 'Token验证成功', |
| 'user_info': { |
| 'third_party_username': user_name, |
| 'local_user_exists': local_user_exists, |
| 'local_username': local_user.username if local_user else None, |
| 'local_user_id': local_user.id if local_user else None |
| }, |
| 'token_info': { |
| 'token_preview': f"{token[:8]}..." if len(token) > 8 else token, |
| 'token_length': len(token) |
| }, |
| 'next_steps': { |
| 'message': '现在您可以使用此Token访问其他API接口', |
| 'note': '如果local_user_exists为false,系统将在您首次使用其他API时自动创建本地用户账户和数据目录' |
| } |
| }, status=status.HTTP_200_OK) |
| |
| def get(self, request): |
| """ |
| GET方法也支持Token验证(通过URL参数) |
| """ |
| return self.post(request) |
| |
| def get_token_from_request(self, request): |
| """ |
| 从请求中获取Token |
| """ |
| |
| if hasattr(request, 'data') and 'token' in request.data: |
| return request.data.get('token') |
| |
| |
| auth_header = request.META.get('HTTP_AUTHORIZATION', '') |
| if auth_header.startswith('Token '): |
| return auth_header[6:] |
| if auth_header.startswith('Bearer '): |
| return auth_header[7:] |
| |
| |
| token = request.GET.get('token') |
| if token: |
| return token |
| |
| |
| if hasattr(request, 'POST') and 'token' in request.POST: |
| return request.POST.get('token') |
| |
| return None |
|
|
|
|
| @method_decorator(csrf_exempt, name='dispatch') |
| class UserInfoView(APIView): |
| """ |
| 获取当前用户信息的接口 |
| 需要有效的Token |
| """ |
| |
| def get(self, request): |
| """ |
| 获取当前用户信息 |
| """ |
| |
| user = request.user |
| |
| if not user or not user.is_authenticated: |
| return Response({ |
| 'error': '用户未认证', |
| 'message': '请提供有效的Token' |
| }, status=status.HTTP_401_UNAUTHORIZED) |
| |
| |
| try: |
| from api.models import ThirdPartyUserMapping |
| mapping = ThirdPartyUserMapping.objects.get(user=user) |
| third_party_info = { |
| 'third_party_user_id': mapping.third_party_user_id, |
| 'third_party_username': mapping.third_party_username, |
| 'created_at': mapping.created_at, |
| 'updated_at': mapping.updated_at |
| } |
| except ThirdPartyUserMapping.DoesNotExist: |
| third_party_info = None |
| |
| |
| projects_count = user.projects.count() |
| |
| return Response({ |
| 'user_info': { |
| 'local_user_id': user.id, |
| 'local_username': user.username, |
| 'email': user.email, |
| 'first_name': user.first_name, |
| 'last_name': user.last_name, |
| 'date_joined': user.date_joined, |
| 'last_login': user.last_login |
| }, |
| 'third_party_info': third_party_info, |
| 'statistics': { |
| 'projects_count': projects_count |
| }, |
| 'data_directories': { |
| 'user_base_dir': f'/media/users/{user.id}/', |
| 'projects_dir': f'/media/users/{user.id}/projects/' |
| } |
| }, status=status.HTTP_200_OK) |