Files
ACORE/core/models/connector_config.py
T
lokses b788bc2a7c Шифрование секретов ConnectorConfig (password/token) в БД
- EncryptedCharField (core/models/fields.py): прозрачное Fernet-шифрование
  на границе с БД, читатели и админка не меняются
- ConnectorConfig.password/token переведены на EncryptedCharField,
  колонки расширены под шифртекст
- Миграция 0004: расширение колонок -> шифрование существующих значений -> смена типа
- FIELD_ENCRYPTION_KEY в settings (default = SECRET_KEY); на проде задавать отдельно ДО migrate

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 15:31:37 +03:00

71 lines
3.2 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.translation import gettext_lazy as _
from django.core.exceptions import ValidationError
from .base import BaseModel
from .fields import EncryptedCharField
class ConnectorConfig(BaseModel):
CONNECTOR_TYPES = [
('mattermost', 'Mattermost'),
('ad', 'Active Directory'),
('carbonio', 'Carbonio CE'),
('mail', 'Почта (IMAP/SMTP)'),
]
connector_type = models.CharField(
_('Тип коннектора'), max_length=20,
choices=CONNECTOR_TYPES, unique=True
)
is_enabled = models.BooleanField(_('Включён'), default=False)
# Подключение
host = models.CharField(_('Хост'), max_length=255, blank=True)
port = models.PositiveIntegerField(_('Порт'), null=True, blank=True)
use_ssl = models.BooleanField(_('Использовать SSL'), default=True)
# Аутентификация
username = models.CharField(_('Логин'), max_length=255, blank=True)
# password/token хранятся в БД зашифрованными (Fernet). max_length задан с
# запасом под шифртекст, который длиннее открытого текста.
password = EncryptedCharField(_('Пароль'), max_length=512, blank=True)
token = EncryptedCharField(
_('Токен / API Key'), max_length=1024, blank=True,
help_text=_('Bearer-токен или API-ключ, если используется вместо логина/пароля')
)
# Дополнительные параметры коннектора
extra_config = models.JSONField(
_('Дополнительные параметры'), default=dict, blank=True,
help_text=_('Специфичные для коннектора настройки в формате JSON')
)
notes = models.TextField(_('Примечания'), blank=True)
class Meta:
verbose_name = _('Настройки коннектора')
verbose_name_plural = _('Настройки коннекторов')
ordering = ['connector_type']
def __str__(self):
status = '✓' if self.is_enabled else '✗'
return f'{status} {self.get_connector_type_display()}'
def clean(self):
super().clean()
if self.is_enabled and not self.host:
raise ValidationError({'host': _('Хост обязателен для включённого коннектора')})
if self.is_enabled and not self.token and not self.username:
raise ValidationError(
_('Для включённого коннектора необходимо указать токен или логин')
)
@classmethod
def get_for(cls, connector_type: str) -> 'ConnectorConfig | None':
"""Получить конфиг коннектора. Возвращает None если не найден или отключён."""
try:
cfg = cls.objects.get(connector_type=connector_type)
return cfg if cfg.is_enabled else None
except cls.DoesNotExist:
return None