- P0/P1 审计修复: 滑块验证码不再下发 x_position/成败即销毁 key、 user-login 补失败计数+滑块门控、限流标识改 X-Real-IP、 百度翻译 appkey 环境化、ChangeEmail/ChangePhone 补调 avalidate、 logs/tasks.py Count(filter=Q) 修复、chat 收藏 SSRF 内网黑名单 - P1 #6/7: token_blacklist + ROTATE_REFRESH_TOKENS 开启, /user/token/refresh/ 挂载 - #2 JWT HttpOnly Cookie 双模认证: user/cookie_auth.py 种/清 Cookie, user/authentication.py CookieOrHeaderJWTAuthentication(Bearer 优先/_COOKIE 兜底), user/views/token.py CookieTokenRefreshView + UserLogoutAPIView(/user/logout/), create_standardized_response 自动对含 token 的响应种 Cookie, 异步视图内 RefreshToken.for_user 全部 sync_to_async 包裹(修 SynchronousOnlyOperation 500), WS ChatConsumer 优先读 Cookie token - P2 #11 限流: utils/rate_limit.py 固定窗口频控, shorturl 生成 匿名10次/分+登录60次/分, 邮箱验证码 同邮箱60s1次+同IP10次/10min, 登录/注册验证码 错5次作废+成功即销毁防重放, 换绑邮箱/手机 同步落地, urls.py 补挂 shorturl 路由(此前 404)
109 lines
7.2 KiB
Python
109 lines
7.2 KiB
Python
from django.urls import path
|
||
from .views.user import SendUserEmailAPIView, UserLoginOrRegisterAPIView, UserLoginAPIView, LoginView, ChangePasswordAPIView, UserUpdateAPIView, ForgotPasswordSendCodeAPIView, ForgotPasswordResetAPIView, UploadAvatarAPIView, PublicProfileAPIView
|
||
from .views.qr_login import QRTokenView, QRStatusView, QRScanView, QRConfirmView, QRCancelView
|
||
from .views.wallet import (
|
||
WalletBalanceAPIView,
|
||
WalletTransactionsAPIView,
|
||
EarnPointsAPIView,
|
||
EarnCoinsAPIView,
|
||
SpendPointsAPIView,
|
||
SpendCoinsAPIView,
|
||
CheckinStatusAPIView,
|
||
CheckinAPIView,
|
||
)
|
||
from .views.tasks import (
|
||
TaskListAPIView, TaskTrackAPIView, TaskClaimAPIView, UserLevelAPIView,
|
||
)
|
||
from .views.email import SendChangeEmailCodeAPIView, ChangeEmailAPIView
|
||
from .views.phone import SendPhoneCodeAPIView, ChangePhoneAPIView
|
||
from .views.favorites import MyFavoritesView, FavoriteToggleView
|
||
from .views.token import CookieTokenRefreshView, UserLogoutAPIView
|
||
from .views.captcha import CaptchaAPIView
|
||
from .views.slider_captcha import SliderCaptchaGenerateView, SliderCaptchaVerifyView
|
||
from .views.blacklist import BlacklistListAPIView, BlacklistAddAPIView, BlacklistRemoveAPIView, BlacklistCheckAPIView
|
||
from .views.login_record import LoginRecordListAPIView, LoginRecordDeleteAPIView, LoginRecordClearAPIView
|
||
from .views.invitation import InviteCodeAPIView, InviteStatsAPIView, InviteRecordsAPIView
|
||
from .views.user import FollowToggleView
|
||
from .views.favorites import MyFavoritesView
|
||
from .views.region import RegionListView
|
||
from .views.activities import UserActivityView
|
||
from .views.settings import (
|
||
UploadCoverAPIView,
|
||
PrivacySettingsAPIView,
|
||
NotificationSettingsAPIView,
|
||
UserDeviceListView,
|
||
UserDeviceRemoveView,
|
||
UserDeviceClearOthersView,
|
||
)
|
||
|
||
from .views.index import user_index
|
||
|
||
urlpatterns = [
|
||
path('', user_index, name='user_index'),
|
||
path('send-user-email/', SendUserEmailAPIView.as_view(), name='send_user_email'),
|
||
path('send_user_email/', SendUserEmailAPIView.as_view(), name='send_user_email_old'),
|
||
path('login-register/', UserLoginOrRegisterAPIView.as_view(), name='user_login_register'),
|
||
path('user_login_or_register/', UserLoginOrRegisterAPIView.as_view(), name='user_login_register_old'),
|
||
path('user-login/', UserLoginAPIView.as_view(), name='user_login'),
|
||
path('user_login/', UserLoginAPIView.as_view(), name='user_login_old'),
|
||
path('login/', LoginView.as_view(), name='login_with_slider'),
|
||
path('change-password/', ChangePasswordAPIView.as_view(), name='change_password'),
|
||
path('change_password/', ChangePasswordAPIView.as_view(), name='change_password_old'),
|
||
path('profile/', UserUpdateAPIView.as_view(), name='user_profile'),
|
||
path('update-profile/', UserUpdateAPIView.as_view(), name='user_update_profile'),
|
||
path('wallet/balance/', WalletBalanceAPIView.as_view(), name='wallet_balance'),
|
||
path('wallet/transactions/', WalletTransactionsAPIView.as_view(), name='wallet_transactions'),
|
||
path('wallet/earn/points/', EarnPointsAPIView.as_view(), name='wallet_earn_points'),
|
||
path('wallet/earn/coins/', EarnCoinsAPIView.as_view(), name='wallet_earn_coins'),
|
||
path('wallet/spend/points/', SpendPointsAPIView.as_view(), name='wallet_spend_points'),
|
||
path('wallet/spend/coins/', SpendCoinsAPIView.as_view(), name='wallet_spend_coins'),
|
||
path('wallet/checkin/status/', CheckinStatusAPIView.as_view(), name='wallet_checkin_status'),
|
||
path('wallet/checkin/', CheckinAPIView.as_view(), name='wallet_checkin'),
|
||
path('send-email-code/', SendChangeEmailCodeAPIView.as_view(), name='send_email_code'),
|
||
path('change-email/', ChangeEmailAPIView.as_view(), name='change_email'),
|
||
path('forgot-password/send-code/', ForgotPasswordSendCodeAPIView.as_view(), name='forgot_password_send_code'),
|
||
path('forgot-password/reset/', ForgotPasswordResetAPIView.as_view(), name='forgot_password_reset'),
|
||
path('send-phone-code/', SendPhoneCodeAPIView.as_view(), name='send_phone_code'),
|
||
path('change-phone/', ChangePhoneAPIView.as_view(), name='change_phone'),
|
||
path('captcha/', CaptchaAPIView.as_view(), name='captcha'),
|
||
path('slider-captcha/generate/', SliderCaptchaGenerateView.as_view(), name='slider-captcha-generate'),
|
||
path('slider-captcha/verify/', SliderCaptchaVerifyView.as_view(), name='slider-captcha-verify'),
|
||
path('upload-avatar/', UploadAvatarAPIView.as_view(), name='upload_avatar'),
|
||
path('blacklist/', BlacklistListAPIView.as_view(), name='blacklist'),
|
||
path('blacklist/add/', BlacklistAddAPIView.as_view(), name='blacklist_add'),
|
||
path('blacklist/<int:pk>/remove/', BlacklistRemoveAPIView.as_view(), name='blacklist_remove'),
|
||
path('blacklist/check/<int:user_id>/', BlacklistCheckAPIView.as_view(), name='blacklist_check'),
|
||
path('login-records/', LoginRecordListAPIView.as_view(), name='login_records'),
|
||
path('login-records/<int:pk>/delete/', LoginRecordDeleteAPIView.as_view(), name='login_record_delete'),
|
||
path('login-records/clear/', LoginRecordClearAPIView.as_view(), name='login_records_clear'),
|
||
path('public-profile/<int:user_id>/', PublicProfileAPIView.as_view(), name='public_profile'),
|
||
path('invite/code/', InviteCodeAPIView.as_view(), name='invite_code'),
|
||
path('invite/stats/', InviteStatsAPIView.as_view(), name='invite_stats'),
|
||
path('invite/records/', InviteRecordsAPIView.as_view(), name='invite_records'),
|
||
path('tasks/', TaskListAPIView.as_view(), name='task_list'),
|
||
path('tasks/track/', TaskTrackAPIView.as_view(), name='task_track'),
|
||
path('tasks/claim/<int:task_id>/', TaskClaimAPIView.as_view(), name='task_claim'),
|
||
path('level/', UserLevelAPIView.as_view(), name='user_level'),
|
||
path('favorites/', MyFavoritesView.as_view(), name='my_favorites'),
|
||
# 修复:新增统一收藏切换端点(Android FavoritesApi.toggleFavorite 依赖此路由)
|
||
path('favorites/toggle/', FavoriteToggleView.as_view(), name='my_favorites_toggle'),
|
||
# 修复:挂载 JWT 刷新端点(支持 HttpOnly Cookie 与 Bearer 刷新)
|
||
path('token/refresh/', CookieTokenRefreshView.as_view(), name='token_refresh'),
|
||
# 修复:挂载用户登出端点(清除 HttpOnly Cookie)
|
||
path('logout/', UserLogoutAPIView.as_view(), name='user_logout'),
|
||
path('regions/', RegionListView.as_view(), name='region_list'),
|
||
path('qr-token/', QRTokenView.as_view(), name='qr_token'),
|
||
path('qr-status/<str:token>/', QRStatusView.as_view(), name='qr_status'),
|
||
path('qr-scan/', QRScanView.as_view(), name='qr_scan'),
|
||
path('qr-confirm/', QRConfirmView.as_view(), name='qr_confirm'),
|
||
path('qr-cancel/', QRCancelView.as_view(), name='qr_cancel'),
|
||
path('follow/<int:user_id>/', FollowToggleView.as_view(), name='follow_toggle'),
|
||
path('activities/', UserActivityView.as_view(), name='user_activities'),
|
||
path('profile/cover/', UploadCoverAPIView.as_view(), name='upload_cover'),
|
||
path('privacy/', PrivacySettingsAPIView.as_view(), name='privacy_settings'),
|
||
path('notification-settings/', NotificationSettingsAPIView.as_view(), name='notification_settings'),
|
||
path('devices/', UserDeviceListView.as_view(), name='user_devices'),
|
||
path('devices/<int:pk>/remove/', UserDeviceRemoveView.as_view(), name='user_device_remove'),
|
||
path('devices/clear-others/', UserDeviceClearOthersView.as_view(), name='user_device_clear_others'),
|
||
]
|