Files
ACORE/apps/portal_connector/tests.py
T
lokses 7a149dd84d portal: отдельные виджеты PNMS/PVMS-прав в ролях и seed-миграции.
Вынесены can_* для кассы и посещаемости, синхронизация в builders/signals, seed групп в core.0023–0024.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-06 17:22:41 +03:00

212 lines
7.7 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.
from datetime import date
from django.contrib.auth.models import Group
from django.test import SimpleTestCase, TestCase, override_settings
from apps.employees.models import Employee
from apps.portal_connector.client import PnmsClient, PnmsClientError
from apps.portal_connector.msorter_client import MsorterClient, MsorterClientError
from apps.portal_connector.msorter_services import build_msorter_payload
class PnmsClientTlsTests(SimpleTestCase):
"""В проде identity-payload может содержать password_hash — только https://."""
@override_settings(
DEBUG=False,
PNMS_SYNC_ENABLED=True,
PNMS_BASE_URL='http://pnms.example',
PNMS_ACORE_TOKEN='secret',
)
def test_http_rejected_when_debug_false(self):
with self.assertRaises(PnmsClientError) as cm:
PnmsClient().post('/api/sync/from-acore/employees/', {'employees': []})
self.assertIn('https://', str(cm.exception))
@override_settings(
DEBUG=False,
PNMS_SYNC_ENABLED=True,
PNMS_BASE_URL='https://pnms.example',
PNMS_ACORE_TOKEN='secret',
)
def test_https_allowed_when_debug_false(self):
PnmsClient()._ensure_tls()
@override_settings(
DEBUG=True,
PNMS_SYNC_ENABLED=True,
PNMS_BASE_URL='http://localhost:8001',
PNMS_ACORE_TOKEN='secret',
)
def test_http_allowed_in_debug(self):
PnmsClient()._ensure_tls()
class MsorterClientTlsTests(SimpleTestCase):
@override_settings(
DEBUG=False,
MSORTER_SYNC_ENABLED=True,
MSORTER_BASE_URL='http://msorter.example',
MSORTER_ACORE_TOKEN='secret',
)
def test_http_rejected_when_debug_false(self):
with self.assertRaises(MsorterClientError) as cm:
MsorterClient().post('/api/sync/from-acore/employees/', {'employees': []})
self.assertIn('https://', str(cm.exception))
class MsorterPayloadTests(TestCase):
def test_access_false_without_group(self):
emp = Employee.objects.create_user(
username='no-mail',
password='x',
first_name='N',
last_name='M',
hire_date=date(2020, 1, 1),
)
payload = build_msorter_payload(emp)
self.assertFalse(payload['access'])
self.assertFalse(payload['is_active'])
def test_access_true_with_pochta_group(self):
emp = Employee.objects.create_user(
username='has-mail',
password='x',
first_name='H',
last_name='M',
hire_date=date(2020, 1, 1),
)
group, _ = Group.objects.get_or_create(name='Почта')
emp.groups.add(group)
payload = build_msorter_payload(emp, include_password=True)
self.assertTrue(payload['access'])
self.assertTrue(payload['is_active'])
self.assertIn('password_hash', payload)
self.assertTrue(payload['reset_password'])
class PvmsClientTlsTests(SimpleTestCase):
@override_settings(
DEBUG=False,
PVMS_SYNC_ENABLED=True,
PVMS_BASE_URL='http://pvms.example',
PVMS_ACORE_TOKEN='secret',
)
def test_http_rejected_when_debug_false(self):
from apps.portal_connector.pvms_client import PvmsClient, PvmsClientError
with self.assertRaises(PvmsClientError) as cm:
PvmsClient().post('/api/sync/from-acore/employees/', {'employees': []})
self.assertIn('https://', str(cm.exception))
class PvmsPayloadTests(TestCase):
def test_employee_payload(self):
from apps.portal_connector.pvms_builders import build_pvms_employee_payload
emp = Employee.objects.create_user(
username='pvms-user',
password='x',
first_name='P',
last_name='V',
hire_date=date(2020, 1, 1),
)
payload = build_pvms_employee_payload(emp, include_password=True)
self.assertEqual(payload['acore_id'], emp.pk)
self.assertEqual(payload['username'], 'pvms-user')
self.assertIn('password_hash', payload)
self.assertTrue(payload['reset_password'])
self.assertEqual(payload['role'], 'employee')
class PasswordPushSignalTests(TestCase):
@override_settings(
PNMS_SYNC_ENABLED=True,
PVMS_SYNC_ENABLED=True,
MSORTER_SYNC_ENABLED=True,
)
def test_password_change_enqueues_include_password(self):
from unittest.mock import patch
emp = Employee.objects.create_user(
username='pwd-sync',
password='old',
first_name='P',
last_name='W',
hire_date=date(2020, 1, 1),
)
with (
patch('apps.portal_connector.tasks.push_employee_to_pnms.delay') as pnms,
patch('apps.portal_connector.tasks.push_employee_to_pvms.delay') as pvms,
patch('apps.portal_connector.tasks.push_employee_to_msorter.delay') as msorter,
):
emp.set_password('new-secret')
emp.save()
pnms.assert_called_once_with(emp.pk, include_password=True)
pvms.assert_called_once_with(emp.pk, include_password=True)
msorter.assert_called_once_with(emp.pk, include_password=True)
class PushAllDefaultsTests(SimpleTestCase):
def test_push_all_identity_defaults_no_passwords(self):
import inspect
from apps.portal_connector.tasks import push_all_identity_to_pnms
params = inspect.signature(push_all_identity_to_pnms).parameters
self.assertEqual(params['include_password'].default, False)
class PosPermissionsSeedTests(TestCase):
def test_pnms_can_permissions_exist_and_revisor_seeded(self):
from django.contrib.auth.models import Permission
from apps.portal_connector.pos_permissions import (
PNMS_ACCESS_APP_LABEL,
PNMS_ACCESS_MODEL,
POS_PERMISSION_CODENAMES,
)
qs = Permission.objects.filter(
content_type__app_label=PNMS_ACCESS_APP_LABEL,
content_type__model=PNMS_ACCESS_MODEL,
)
self.assertEqual(qs.count(), len(POS_PERMISSION_CODENAMES))
revisor = Group.objects.get(name='Ревизор')
codes = set(revisor.permissions.filter(
content_type__model=PNMS_ACCESS_MODEL,
).values_list('codename', flat=True))
self.assertIn('can_deactivate_receipt', codes)
self.assertIn('can_create_return', codes)
self.assertIn('can_do_inventory', codes)
def test_build_employee_payload_includes_group_pos_perms(self):
from apps.portal_connector.builders import build_employee_payload
emp = Employee.objects.create_user(
username='pos-revisor',
password='x',
first_name='R',
last_name='V',
hire_date=date(2020, 1, 1),
)
emp.groups.add(Group.objects.get(name='Ревизор'))
payload = build_employee_payload(emp)
self.assertIn('can_deactivate_receipt', payload['pos_permissions'])
self.assertIn('can_do_inventory', payload['pos_permissions'])
class GroupChangePushTests(TestCase):
@override_settings(PNMS_SYNC_ENABLED=True, PVMS_SYNC_ENABLED=False, MSORTER_SYNC_ENABLED=False)
def test_group_m2m_enqueues_pnms_push(self):
from unittest.mock import patch
emp = Employee.objects.create_user(
username='grp-sync',
password='x',
first_name='G',
last_name='S',
hire_date=date(2020, 1, 1),
)
group = Group.objects.get(name='Фармацевт')
with patch('apps.portal_connector.tasks.push_employee_to_pnms.delay') as pnms:
emp.groups.add(group)
pnms.assert_called_once_with(emp.pk, include_password=False)