2026-01-29 10:02:15 +08:00

121 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
用户模块视图 - App端用户
"""
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework_simplejwt.tokens import RefreshToken
from utils.response import success, error
from apps.admins.authentication import AppJWTAuthentication
from .models import User
from .serializers import (
UserSerializer,
UserDetailSerializer,
PhoneLoginSerializer,
UpdateUserSerializer
)
def get_app_tokens(user):
"""
为App用户生成JWT Token
在token中添加 user_type='app' 以区分管理员
"""
refresh = RefreshToken.for_user(user)
# 添加自定义声明
refresh['user_type'] = 'app'
refresh['phone'] = user.phone
return {
'access': str(refresh.access_token),
'refresh': str(refresh),
}
class AuthViewSet(viewsets.ViewSet):
"""认证视图集 - App端"""
permission_classes = [AllowAny]
@action(detail=False, methods=['post'], url_path='phone-login')
def phone_login(self, request):
"""
手机号一键登录
POST /api/v1/auth/phone-login
"""
serializer = PhoneLoginSerializer(data=request.data)
if not serializer.is_valid():
return error(message=str(serializer.errors))
phone = serializer.validated_data['phone']
# 获取或创建用户
user, created = User.objects.get_or_create(
phone=phone,
defaults={'nickname': f'用户{phone[-4:]}'}
)
if not user.is_active:
return error(code=101, message='账号已被禁用')
# 生成JWT Token带user_type='app'标识)
tokens = get_app_tokens(user)
return success(data={
'user': UserSerializer(user).data,
'token': tokens,
'is_new_user': created
}, message='登录成功')
@action(detail=False, methods=['post'], url_path='refresh')
def refresh_token(self, request):
"""
刷新Token
POST /api/v1/auth/refresh
"""
refresh_token = request.data.get('refresh')
if not refresh_token:
return error(message='refresh token不能为空')
try:
refresh = RefreshToken(refresh_token)
# 验证是否为app token
user_type = refresh.get('user_type', 'app')
if user_type not in ['app', None]:
return error(code=103, message='无效的用户Token')
return success(data={
'access': str(refresh.access_token),
'refresh': str(refresh),
})
except Exception as e:
return error(code=103, message='Token已过期或无效')
class UserViewSet(viewsets.ViewSet):
"""用户视图集 - App端"""
authentication_classes = [AppJWTAuthentication]
permission_classes = [IsAuthenticated]
@action(detail=False, methods=['get'])
def me(self, request):
"""
获取当前用户信息
GET /api/v1/users/me
"""
return success(data=UserSerializer(request.user).data)
@action(detail=False, methods=['put'])
def update_me(self, request):
"""
更新当前用户信息
PUT /api/v1/users/update_me
"""
serializer = UpdateUserSerializer(request.user, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return success(data=UserSerializer(request.user).data, message='更新成功')
return error(message=str(serializer.errors))