Files
ACORE/core/models/connector_config.py
T

87 lines
3.8 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)'),
('nextcloud', 'Nextcloud'),
('onlyoffice', 'OnlyOffice'),
('asterisk', 'Asterisk AMI'),
]
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. Nextcloud: verify_ssl, timeout. '
'OnlyOffice: public_url, callback_base, verify_ssl. '
'Asterisk AMI: originate_context (from-internal), '
'sip_channel (PJSIP/{exten}), analog_channel (DAHDI/{exten}), timeout.'
),
)
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.connector_type == 'asterisk' and self.is_enabled:
errors = {}
if not self.username:
errors['username'] = _('Для AMI нужен логин менеджера')
if not self.password:
errors['password'] = _('Для AMI нужен секрет (password)')
if errors:
raise ValidationError(errors)
elif 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