Files
ACORE/core/models/connector_config.py
T
lokses 19bc2874aa Nextcloud connector: скелет провижининга Group Folders (Фаза 2)
- ConnectorConfig: тип 'nextcloud' (host/username/token, шифруется)
- NextcloudService: OCS-клиент Group Folders (create/ACL/quota, идемпотентный ensure_folder)
- NextcloudSyncService: отделы → 03_Отделы/* ↔ nc-dept-<код>; аптеки → 02_Аптеки/* ↔ nc-svc
- Сигналы Directory/Pharmacy с гейтом на включённый коннектор (по умолч. no-op)
- Celery-задачи + команда nextcloud_sync (dry-run по умолчанию, --apply)
- NextcloudSyncLog + admin; тесты (пути, гейт, идемпотентность ensure_folder)

Членство юзеров идёт через AD/LDAP, коннектор ведёт только папки+ACL.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 11:09:49 +03:00

72 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)'),
('nextcloud', 'Nextcloud'),
]
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