"""Тесты hardening безопасности ACORE.""" from datetime import date from unittest import mock from django.contrib.auth.models import Group from django.test import Client, TestCase from apps.employees.models import Employee from core.security import user_requires_mandatory_2fa def make_employee(**overrides): n = Employee.objects.count() + 1 defaults = { 'username': f'sec.user{n}', 'email': f'sec.user{n}@company.local', 'first_name': 'Тест', 'last_name': 'Безопасность', 'hire_date': date(2026, 1, 1), 'user_location_type': 'pharmacy', 'mattermost_sync_enabled': False, 'ad_sync_enabled': False, 'is_staff': False, } defaults.update(overrides) return Employee.objects.create(**defaults) from core.test_utils import login_2fa class Mandatory2FATests(TestCase): def test_staff_requires_2fa(self): user = make_employee(is_staff=True) self.assertTrue(user_requires_mandatory_2fa(user)) def test_hr_group_does_not_require_mandatory_2fa(self): user = make_employee() user.groups.add(Group.objects.get(name='HR')) if hasattr(user, '_group_perm_cache'): del user._group_perm_cache self.assertFalse(user_requires_mandatory_2fa(user)) def test_it_group_requires_2fa_without_staff(self): user = make_employee() user.groups.add(Group.objects.get(name='IT')) if hasattr(user, '_group_perm_cache'): del user._group_perm_cache self.assertTrue(user_requires_mandatory_2fa(user)) def test_regular_user_without_totp_not_required(self): user = make_employee() self.assertFalse(user_requires_mandatory_2fa(user)) def test_hr_portal_accessible_without_2fa(self): user = make_employee() user.groups.add(Group.objects.get(name='HR')) client = Client() client.force_login(user) response = client.get('/hr-portal/', HTTP_HX_REQUEST='true') self.assertEqual(response.status_code, 200) class HRPortalITSeparationTests(TestCase): def test_hr_sees_ticket_number_without_it_manager_link(self): from apps.hiring.services import create_hiring_request from apps.locations.models import Pharmacy from core.models import Directory hr_user = make_employee(user_location_type='office') hr_user.groups.add(Group.objects.get(name='HR')) dept = Directory.objects.filter(directory_type__code='department').first() if dept: hr_user.department = dept hr_user.save(update_fields=['department']) pharmacy = Pharmacy.objects.filter(is_active=True).first() if not pharmacy: self.skipTest('no pharmacy fixture') create_hiring_request( requester=hr_user, last_name='Тест', first_name='Кандидат', middle_name='', user_location_type='pharmacy', user_pharmacy_id=pharmacy.pk, hire_date=date(2026, 6, 1), trial_days=3, ) client = Client() client.force_login(hr_user) response = client.get('/hr-portal/', HTTP_HX_REQUEST='true') self.assertEqual(response.status_code, 200) self.assertNotIn('href="/it-manager/"', response.content.decode()) class ModalAddEmployeeSecurityTests(TestCase): def test_regular_user_forbidden(self): user = make_employee() login_2fa(self.client, user) response = self.client.get('/modal-add-employee/') self.assertEqual(response.status_code, 403) def test_hr_user_allowed(self): user = make_employee() user.groups.add(Group.objects.get(name='HR')) self.client.force_login(user) response = self.client.get('/modal-add-employee/') self.assertEqual(response.status_code, 200) class ADSyncLogPasswordTests(TestCase): def test_create_log_does_not_contain_password(self): from apps.ad_connector.services.sync_service import sync_employee_to_ad from apps.ad_connector.models import ADSyncLog employee = make_employee( user_location_type='office', email='office@test.local', department_id=None, ) from core.models import Directory dept = Directory.objects.filter(directory_type__code='department').first() mock_service = mock.MagicMock() mock_service.use_ssl = True mock_service.users_ou = 'OU=Users,DC=test,DC=local' mock_service.domain = 'test.local' mock_service.get_user_by_dn.return_value = None mock_service.get_user_by_sam_account_name.return_value = None mock_service.get_user_by_email.return_value = None with mock.patch('apps.ad_connector.services.sync_service.ADService', return_value=mock_service): with mock.patch( 'apps.ad_connector.services.sync_service.generate_random_password', return_value='SecretPass123', ): sync_employee_to_ad(employee) log = ADSyncLog.objects.filter(employee=employee, action='create').latest('created_at') self.assertNotIn('SecretPass123', log.message) employee.refresh_from_db() self.assertNotIn('SecretPass123', employee.ad_sync_error or '')