feat: update login api

This commit is contained in:
2026-06-05 15:36:31 +08:00
parent fd0b3e1982
commit ba9fb33062
15 changed files with 714 additions and 163 deletions
+170
View File
@@ -0,0 +1,170 @@
"""移动端 U4 / CMS 端 U3 新登录语义 + 机构列表接口测试。"""
from rest_framework.test import APIClient
from apps.user.models import User, Institution
from apps.user.auth import TRIAL_INSTITUTION_NAME, TRIAL_INSTITUTION_CODE
from .conftest import (
CacheTestCase,
USER_LOGIN_URL, USER_LOGIN_CODE_URL, USER_INSTITUTION_LIST_URL,
inject_sms_code, create_test_user, ensure_institution,
)
def _trial_institution():
inst, _ = Institution.objects.get_or_create(
code=TRIAL_INSTITUTION_CODE,
defaults={'name': TRIAL_INSTITUTION_NAME, 'type': 'hospital'},
)
return inst
class InstitutionListTest(CacheTestCase):
"""机构列表接口(不分页、登录前可调用)。"""
def setUp(self):
super().setUp()
self.client = APIClient()
def test_list_unpaginated_with_trial_flag(self):
ensure_institution(name='测试医院', code='TEST-HOSP-001')
_trial_institution()
resp = self.client.get(USER_INSTITUTION_LIST_URL)
self.assertEqual(resp.status_code, 200, resp.content)
data = resp.json()
# 不分页:直接返回数组
self.assertIsInstance(data, list)
by_code = {item['code']: item for item in data}
self.assertIn('TEST-HOSP-001', by_code)
self.assertIn(TRIAL_INSTITUTION_CODE, by_code)
self.assertFalse(by_code['TEST-HOSP-001']['is_trial'])
self.assertTrue(by_code[TRIAL_INSTITUTION_CODE]['is_trial'])
class MobileLoginCodeTest(CacheTestCase):
"""U4 验证码登录(移动端)。"""
def setUp(self):
super().setUp()
self.client = APIClient()
def test_trial_first_register_then_login(self):
_trial_institution()
phone = '13900200001'
# 首次:自动注册
inject_sms_code(phone, 'login', code='123456')
resp = self.client.post(USER_LOGIN_CODE_URL, {
'phone': phone, 'code': '123456', 'institution_code': TRIAL_INSTITUTION_CODE,
})
self.assertEqual(resp.status_code, 201, resp.content)
self.assertTrue(resp.json()['is_new_user'])
user = User.objects.get(phone=phone)
self.assertEqual(user.role_type, 'student')
# 再次:登录
inject_sms_code(phone, 'login', code='123456')
resp = self.client.post(USER_LOGIN_CODE_URL, {
'phone': phone, 'code': '123456', 'institution_code': TRIAL_INSTITUTION_CODE,
})
self.assertEqual(resp.status_code, 200, resp.content)
self.assertFalse(resp.json()['is_new_user'])
def test_non_trial_unregistered_403(self):
ensure_institution(name='测试医院', code='TEST-HOSP-001')
phone = '13900200002'
inject_sms_code(phone, 'login', code='123456')
resp = self.client.post(USER_LOGIN_CODE_URL, {
'phone': phone, 'code': '123456', 'institution_code': 'TEST-HOSP-001',
})
self.assertEqual(resp.status_code, 403, resp.content)
self.assertEqual(resp.json()['code'], 'AUTH_NOT_REGISTERED')
def test_non_trial_institution_mismatch_403(self):
inst_a = ensure_institution(name='医院A', code='HOSP-A')
ensure_institution(name='医院B', code='HOSP-B')
phone = '13900200003'
create_test_user(phone=phone, password='x', role_type='student', institution=inst_a)
inject_sms_code(phone, 'login', code='123456')
resp = self.client.post(USER_LOGIN_CODE_URL, {
'phone': phone, 'code': '123456', 'institution_code': 'HOSP-B',
})
self.assertEqual(resp.status_code, 403, resp.content)
self.assertEqual(resp.json()['code'], 'AUTH_INSTITUTION_MISMATCH')
def test_non_trial_registered_match_ok(self):
inst_a = ensure_institution(name='医院A', code='HOSP-A')
phone = '13900200004'
create_test_user(phone=phone, password='x', role_type='student', institution=inst_a)
inject_sms_code(phone, 'login', code='123456')
resp = self.client.post(USER_LOGIN_CODE_URL, {
'phone': phone, 'code': '123456', 'institution_code': 'HOSP-A',
})
self.assertEqual(resp.status_code, 200, resp.content)
self.assertFalse(resp.json()['is_new_user'])
def test_unknown_institution_code(self):
phone = '13900200005'
inject_sms_code(phone, 'login', code='123456')
resp = self.client.post(USER_LOGIN_CODE_URL, {
'phone': phone, 'code': '123456', 'institution_code': 'NOPE',
})
self.assertEqual(resp.json()['code'], 'USER_INSTITUTION_NOT_FOUND')
class CmsPasswordLoginTest(CacheTestCase):
"""U3 密码登录(CMS 端:账号 + 密码 + 角色)。"""
def setUp(self):
super().setUp()
self.client = APIClient()
def test_login_by_phone_ok(self):
phone = '13900300001'
create_test_user(phone=phone, password='Doc12345', role_type='doctor')
resp = self.client.post(USER_LOGIN_URL, {
'account': phone, 'password': 'Doc12345', 'role': 'doctor',
})
self.assertEqual(resp.status_code, 200, resp.content)
def test_login_by_username_ok(self):
user = User.objects.create_user(
username='cms_admin', password='Admin123',
role_type='super_admin', status=1,
)
resp = self.client.post(USER_LOGIN_URL, {
'account': 'cms_admin', 'password': 'Admin123', 'role': 'super_admin',
})
self.assertEqual(resp.status_code, 200, resp.content)
self.assertEqual(resp.json()['user']['id'], user.id)
def test_missing_role_400(self):
phone = '13900300002'
create_test_user(phone=phone, password='Doc12345', role_type='doctor')
resp = self.client.post(USER_LOGIN_URL, {
'account': phone, 'password': 'Doc12345',
})
self.assertIn(resp.status_code, (400, 401))
self.assertEqual(resp.json()['code'], 'AUTH_BAD_CREDENTIALS')
def test_invalid_role(self):
phone = '13900300003'
create_test_user(phone=phone, password='Stu12345', role_type='student')
resp = self.client.post(USER_LOGIN_URL, {
'account': phone, 'password': 'Stu12345', 'role': 'student',
})
self.assertEqual(resp.json()['code'], 'AUTH_INVALID_ROLE')
def test_role_mismatch(self):
phone = '13900300004'
create_test_user(phone=phone, password='Doc12345', role_type='doctor')
resp = self.client.post(USER_LOGIN_URL, {
'account': phone, 'password': 'Doc12345', 'role': 'content_admin',
})
self.assertIn(resp.status_code, (400, 401))
self.assertEqual(resp.json()['code'], 'AUTH_BAD_CREDENTIALS')