Files
ACORE/core/tests_access_summary.py
lokses a62f023a90 employees: сводка итоговых разрешений на карточке сотрудника
На карточке Employee — вкладка «Доступ (сводка)»: по каждому
ограниченному разделу портала показывает итог (есть/нет) и источник
(какая группа дала право, individual grant/revoke override, личное право).

Считается теми же правилами, что Employee.has_perm (override имеет
приоритет над группами), поэтому сводка 1-в-1 совпадает с реальной
проверкой доступа. Править по-прежнему: поле «Группы» + инлайн
«Доп. права на разделы портала» (grant/revoke).

- core/access_summary.py: employee_access_summary()
- EmployeeAdmin: readonly effective_access_summary + вкладка
- core/tests_access_summary.py: 6 тестов (в т.ч. совпадение с has_perm)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-21 17:21:58 +03:00

102 lines
4.0 KiB
Python

from datetime import date
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase
from apps.employees.models import Employee, EmployeePermissionOverride
from core.access_summary import employee_access_summary
from core.models import PortalAccess
def portal_perm(codename: str) -> Permission:
ct = ContentType.objects.get_for_model(PortalAccess, for_concrete_model=False)
return Permission.objects.get(content_type=ct, codename=codename)
def make_employee(**overrides):
n = Employee.objects.count() + 1
defaults = {
'username': f'sum.user{n}',
'email': f'sum.user{n}@company.local',
'first_name': 'Тест',
'last_name': 'Сводка',
'hire_date': date(2026, 1, 1),
'user_location_type': 'office',
'mattermost_sync_enabled': False,
'ad_sync_enabled': False,
'is_staff': False,
}
defaults.update(overrides)
return Employee.objects.create(**defaults)
def row_for(rows, key):
return next(r for r in rows if r.key == key)
class AccessSummaryTests(TestCase):
def test_rows_cover_all_restricted_sections(self):
from core.portal_sections import RESTRICTED_KEYS
rows = employee_access_summary(make_employee())
self.assertEqual({r.key for r in rows}, set(RESTRICTED_KEYS))
def test_no_access_by_default(self):
rows = employee_access_summary(make_employee())
self.assertFalse(row_for(rows, 'reports').allowed)
self.assertEqual(row_for(rows, 'reports').source_text(), '—')
def test_group_grant_shows_source(self):
emp = make_employee()
group = Group.objects.create(name='Тест-отчёты')
group.permissions.add(portal_perm('access_reports'))
emp.groups.add(group)
rows = employee_access_summary(emp)
reports = row_for(rows, 'reports')
self.assertTrue(reports.allowed)
self.assertIn('Тест-отчёты', reports.source_text())
def test_override_revoke_wins_over_group(self):
emp = make_employee()
group = Group.objects.create(name='Тест-отчёты2')
group.permissions.add(portal_perm('access_reports'))
emp.groups.add(group)
EmployeePermissionOverride.objects.create(
employee=emp, permission=portal_perm('access_reports'),
override_type='revoke', is_active=True,
)
reports = row_for(employee_access_summary(emp), 'reports')
self.assertFalse(reports.allowed)
self.assertIn('отозвано', reports.source_text())
def test_override_grant_without_group(self):
emp = make_employee()
EmployeePermissionOverride.objects.create(
employee=emp, permission=portal_perm('access_rro'),
override_type='grant', is_active=True,
)
rro = row_for(employee_access_summary(emp), 'rro')
self.assertTrue(rro.allowed)
self.assertIn('выдано', rro.source_text())
def test_summary_matches_has_perm(self):
"""Сводка обязана совпадать с фактической проверкой Employee.has_perm."""
emp = make_employee()
group = Group.objects.create(name='Тест-микс')
group.permissions.add(portal_perm('access_reports'))
emp.groups.add(group)
EmployeePermissionOverride.objects.create(
employee=emp, permission=portal_perm('access_rro'),
override_type='grant', is_active=True,
)
EmployeePermissionOverride.objects.create(
employee=emp, permission=portal_perm('access_reports'),
override_type='revoke', is_active=True,
)
emp = Employee.objects.get(pk=emp.pk) # сброс кэша прав
for r in employee_access_summary(emp):
self.assertEqual(
r.allowed, emp.has_perm(f'core.access_{r.key}'),
msg=f'Расхождение по разделу {r.key}',
)