121 lines
4.0 KiB
Python
121 lines
4.0 KiB
Python
from django.test import TestCase
|
|
from django.urls import reverse
|
|
from django.core.cache import caches
|
|
from unittest.mock import patch, MagicMock
|
|
from rest_framework.test import APIClient
|
|
from rest_framework import status
|
|
|
|
from user.models import FUser
|
|
from utils.slider_captcha import generate_slider_captcha, verify_slider_captcha
|
|
from utils.captcha import check_captcha_required, record_failure
|
|
|
|
default_cache = caches['default']
|
|
|
|
|
|
class TestLoginWithSliderCaptcha(TestCase):
|
|
def setUp(self):
|
|
self.client = APIClient()
|
|
self.login_url = reverse('login_with_slider')
|
|
self.user = FUser.objects.create_user(
|
|
username='testuser',
|
|
email='test@example.com',
|
|
password='testpass123'
|
|
)
|
|
|
|
def _post(self, data):
|
|
return self.client.post(
|
|
self.login_url,
|
|
data,
|
|
format='json'
|
|
)
|
|
|
|
def test_login_without_captcha_required(self):
|
|
response = self._post({
|
|
'account': 'testuser',
|
|
'password': 'testpass123'
|
|
})
|
|
self.assertNotEqual(response.status_code, 20022)
|
|
|
|
@patch('user.views.user.check_captcha_required')
|
|
def test_login_with_captcha_required_no_captcha_provided(self, mock_check):
|
|
mock_check.return_value = True
|
|
|
|
response = self._post({
|
|
'account': 'testuser',
|
|
'password': 'testpass123'
|
|
})
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
self.assertEqual(response.data['code'], 20022)
|
|
|
|
@patch('user.views.user.check_captcha_required')
|
|
@patch('user.views.user.verify_slider_captcha')
|
|
def test_login_with_valid_captcha(self, mock_verify, mock_check):
|
|
mock_check.return_value = True
|
|
mock_verify.return_value = True
|
|
|
|
response = self._post({
|
|
'account': 'testuser',
|
|
'password': 'testpass123',
|
|
'slider_captcha_key': 'test-key',
|
|
'slider_captcha_x': 100
|
|
})
|
|
|
|
mock_verify.assert_called_once_with('test-key', 100)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertIn('access', response.data['data'])
|
|
self.assertIn('refresh', response.data['data'])
|
|
|
|
@patch('user.views.user.check_captcha_required')
|
|
@patch('user.views.user.verify_slider_captcha')
|
|
def test_login_with_invalid_captcha(self, mock_verify, mock_check):
|
|
mock_check.return_value = True
|
|
mock_verify.return_value = False
|
|
|
|
response = self._post({
|
|
'account': 'testuser',
|
|
'password': 'testpass123',
|
|
'slider_captcha_key': 'test-key',
|
|
'slider_captcha_x': 50
|
|
})
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
self.assertEqual(response.data['code'], 20020)
|
|
|
|
@patch('user.views.user.check_captcha_required')
|
|
@patch('user.views.user.verify_slider_captcha')
|
|
def test_login_with_expired_captcha(self, mock_verify, mock_check):
|
|
mock_check.return_value = True
|
|
from utils.slider_captcha import SliderCaptchaError
|
|
mock_verify.side_effect = SliderCaptchaError('验证码已过期')
|
|
|
|
response = self._post({
|
|
'account': 'testuser',
|
|
'password': 'testpass123',
|
|
'slider_captcha_key': 'expired-key',
|
|
'slider_captcha_x': 100
|
|
})
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
self.assertEqual(response.data['code'], 20021)
|
|
|
|
def test_get_identifier_with_ip(self):
|
|
from user.views.user import LoginView
|
|
view = LoginView()
|
|
|
|
request = MagicMock()
|
|
request.META = {'HTTP_X_FORWARDED_FOR': '192.168.1.1'}
|
|
|
|
identifier = view._get_identifier(request)
|
|
self.assertEqual(identifier, '192.168.1.1')
|
|
|
|
def test_get_identifier_without_forwarded_for(self):
|
|
from user.views.user import LoginView
|
|
view = LoginView()
|
|
|
|
request = MagicMock()
|
|
request.META = {'REMOTE_ADDR': '127.0.0.1'}
|
|
|
|
identifier = view._get_identifier(request)
|
|
self.assertEqual(identifier, '127.0.0.1')
|