Files
ACORE/apps/employees/models/permissions.py
T
lokses 3359a8db13 employees: HR-заявки, приглашения на пароль, профиль и 2FA
Модель/сервисы HR-заявок с заменами, приглашения на установку пароля
(инвайты), обновлённая страница профиля сотрудника и правки 2FA.

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

113 lines
4.3 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 django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from core.models import BaseModel
class PermissionGroup(BaseModel):
"""
Расширение стандартной auth.Group — добавляет описание и флаг активности.
Права назначаются через стандартный механизм auth.Group.permissions.
"""
group = models.OneToOneField(
'auth.Group', on_delete=models.CASCADE,
related_name='profile', verbose_name=_('Группа')
)
description = models.TextField(_('Описание'), blank=True)
is_active = models.BooleanField(_('Активна'), default=True)
class Meta:
verbose_name = _('Группа разрешений')
verbose_name_plural = _('Группы разрешений')
ordering = ['group__name']
def __str__(self):
return self.group.name
def permission_codes(self) -> list[str]:
return list(
self.group.permissions.values_list('codename', flat=True)
)
class GroupSectionAccess(BaseModel):
"""
Действия Create/Update/Delete по разделу портала для auth.Group.
Просмотр раздела — Django permission core.access_<section_key> на группе.
"""
group = models.ForeignKey(
'auth.Group',
on_delete=models.CASCADE,
related_name='section_access',
verbose_name=_('Группа'),
)
section_key = models.CharField(_('Раздел'), max_length=64, db_index=True)
can_create = models.BooleanField(_('Создать'), default=True)
can_update = models.BooleanField(_('Обновить'), default=True)
can_delete = models.BooleanField(_('Удалить'), default=True)
class Meta:
verbose_name = _('Доступ группы к разделу')
verbose_name_plural = _('Доступы групп к разделам')
ordering = ['group__name', 'section_key']
constraints = [
models.UniqueConstraint(
fields=['group', 'section_key'],
name='uniq_group_section_access',
),
]
def __str__(self):
return f'{self.group.name}: {self.section_key}'
class EmployeePermissionOverride(BaseModel):
"""
Индивидуальные override-ы прав для сотрудника.
grant — выдать право сверх группы.
revoke — отозвать право даже если оно есть в группе.
Поддерживает временны́е ограничения через valid_from / valid_until.
"""
OVERRIDE_TYPES = [
('grant', _('Выдать')),
('revoke', _('Отозвать')),
]
employee = models.ForeignKey(
'employees.Employee', on_delete=models.CASCADE,
related_name='permission_overrides', verbose_name=_('Сотрудник')
)
permission = models.ForeignKey(
'auth.Permission', on_delete=models.CASCADE,
verbose_name=_('Разрешение')
)
override_type = models.CharField(
_('Тип'), max_length=10, choices=OVERRIDE_TYPES
)
valid_from = models.DateField(_('Действует с'), null=True, blank=True)
valid_until = models.DateField(_('Действует до'), null=True, blank=True)
is_active = models.BooleanField(_('Активен'), default=True)
comment = models.TextField(_('Причина / комментарий'), blank=True)
class Meta:
verbose_name = _('Override разрешения')
verbose_name_plural = _('Override разрешений')
ordering = ['employee', 'permission__codename']
indexes = [
models.Index(fields=['employee', 'is_active']),
]
def __str__(self):
return f"{self.employee} — {self.get_override_type_display()}: {self.permission.codename}"
def is_currently_active(self) -> bool:
if not self.is_active:
return False
today = timezone.now().date()
if self.valid_from and today < self.valid_from:
return False
if self.valid_until and today > self.valid_until:
return False
return True