PluginConfig — Modelo base
PluginConfig — Base Model
PluginConfig es el modelo Django central que registra cada conector. Todos los plugins (Telegram, Gitea, Inbox) comparten este mismo modelo y se distinguen por el campo servicio.
Campos del modelo
| Campo | Tipo | Descripción |
|---|---|---|
usuario |
ForeignKey → User | Propietario del plugin. Puede ser null en configuraciones de sistema. |
servicio |
CharField (choices) | Tipo de conector: telegram, gitea, inbox. |
identificador |
CharField (120) | Nombre único del bot o endpoint. Ej: @joe_bot, pogit.pedroospino.net. |
token_cifrado |
BinaryField | Token o credenciales cifradas con Fernet. Nunca se almacena en texto plano. |
metadatos |
JSONField | Configuración específica del plugin (ej. webhook_secret). Varía por servicio. |
activo |
BooleanField | Borrado lógico (Regla GUARDIAN). Siempre usar activo=True al filtrar en producción. |
creado_en |
DateTimeField | Fecha de creación (auto). |
modificado_en |
DateTimeField | Última modificación (auto). |
(servicio, identificador) es único en la base de datos. No se pueden tener dos configs del mismo tipo con el mismo identificador.
Métodos
set_token(plaintext: str)
Cifra el token en texto plano usando Fernet y lo guarda en token_cifrado. Llamar siempre antes de save() cuando se configure un nuevo token.
get_token() → str
Descifra y devuelve el token en texto plano. Usado internamente por los clientes de cada plugin.
Crear un PluginConfig desde Django Admin o shell
from apps.common.models import PluginConfig
from django.contrib.auth import get_user_model
User = get_user_model()
user = User.objects.get(username="pedro")
config = PluginConfig(
usuario=user,
servicio="telegram",
identificador="@joe_bot",
metadatos={"webhook_secret": "mi_secret_seguro"},
)
config.set_token("1234567890:ABCDefghIJKlmnOPQrsTUVwxyz") # Bot token de Telegram
config.save()
Servicios soportados
| Valor | Etiqueta | Mecanismo | Token esperado |
|---|---|---|---|
telegram |
Telegram | Webhook HTTP | Bot token de BotFather |
gitea |
Gitea | Webhook HTTP | No aplica (usa webhook_secret en metadatos) |
inbox |
Buzón IMAP | Polling (Celery Beat) | JSON cifrado: {"user": "...", "pass": "...", "host": "..."} |
Seguridad
- El campo
token_cifradousa cifrado simétrico Fernet (AES-128-CBC + HMAC-SHA256). - La clave Fernet se almacena en la variable de entorno
FERNET_KEY, nunca en el código. - Los webhooks validan la autenticidad via header secreto antes de acceder al
PluginConfig. - El método
delete()está sobreescrito para realizar borrado lógico (Regla GUARDIAN): estableceactivo=Falseen lugar de eliminar el registro.
PluginConfig is the central Django model that registers each connector. All plugins (Telegram, Gitea, Inbox) share this same model and are distinguished by the service field.
Model fields
| Field | Type | Description |
|---|---|---|
usuario |
ForeignKey → User | Plugin owner. Can be null for system-level configurations. |
servicio |
CharField (choices) | Connector type: telegram, gitea, inbox. |
identificador |
CharField (120) | Unique bot or endpoint name. E.g.: @joe_bot, pogit.pedroospino.net. |
token_cifrado |
BinaryField | Token or credentials encrypted with Fernet. Never stored as plaintext. |
metadatos |
JSONField | Plugin-specific configuration (e.g. webhook_secret). Varies by service. |
activo |
BooleanField | Logical deletion (GUARDIAN Rule). Always filter with activo=True in production. |
creado_en |
DateTimeField | Creation date (auto). |
modificado_en |
DateTimeField | Last modification (auto). |
(servicio, identificador) is unique in the database. You cannot have two configs of the same type with the same identifier.
Methods
set_token(plaintext: str)
Encrypts the plaintext token using Fernet and saves it to token_cifrado. Always call before save() when configuring a new token.
get_token() → str
Decrypts and returns the token as plaintext. Used internally by each plugin's client.
Create a PluginConfig from Django Admin or shell
from apps.common.models import PluginConfig
from django.contrib.auth import get_user_model
User = get_user_model()
user = User.objects.get(username="pedro")
config = PluginConfig(
usuario=user,
servicio="telegram",
identificador="@joe_bot",
metadatos={"webhook_secret": "my_secure_secret"},
)
config.set_token("1234567890:ABCDefghIJKlmnOPQrsTUVwxyz") # Telegram Bot token
config.save()
Supported services
| Value | Label | Mechanism | Expected token |
|---|---|---|---|
telegram |
Telegram | HTTP Webhook | BotFather bot token |
gitea |
Gitea | HTTP Webhook | N/A (uses webhook_secret in metadatos) |
inbox |
IMAP Inbox | Polling (Celery Beat) | Encrypted JSON: {"user": "...", "pass": "...", "host": "..."} |
Security
- The
token_cifradofield uses Fernet symmetric encryption (AES-128-CBC + HMAC-SHA256). - The Fernet key is stored in the
FERNET_KEYenvironment variable, never in code. - Webhooks validate authenticity via secret header before accessing
PluginConfig. - The
delete()method is overridden to perform logical deletion (GUARDIAN Rule): setsactivo=Falseinstead of deleting the record.