121 lines
3.6 KiB
Python
121 lines
3.6 KiB
Python
"""
|
||
用户模块视图 - 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))
|