| """ |
| Secret model for encrypted credential storage. |
| """ |
|
|
| import uuid |
|
|
| from django.conf import settings |
| from django.db import models |
|
|
|
|
| class Secret(models.Model): |
| """ |
| Stores encrypted secrets (API keys, credentials) that are injected |
| as environment variables when scripts run. |
| """ |
|
|
| id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) |
|
|
| |
| key = models.CharField( |
| max_length=100, |
| unique=True, |
| help_text="Environment variable name (uppercase, underscores allowed)", |
| ) |
|
|
| |
| encrypted_value = models.TextField( |
| help_text="Fernet-encrypted secret value", |
| ) |
|
|
| |
| description = models.TextField( |
| blank=True, |
| help_text="Optional description of what this secret is used for", |
| ) |
|
|
| |
| created_at = models.DateTimeField(auto_now_add=True) |
| updated_at = models.DateTimeField(auto_now=True) |
|
|
| |
| created_by = models.ForeignKey( |
| settings.AUTH_USER_MODEL, |
| on_delete=models.SET_NULL, |
| null=True, |
| blank=True, |
| related_name="created_secrets", |
| ) |
|
|
| class Meta: |
| db_table = "secrets" |
| verbose_name = "secret" |
| verbose_name_plural = "secrets" |
| ordering = ["key"] |
|
|
| def __str__(self): |
| return self.key |
|
|
| def get_masked_value(self) -> str: |
| """ |
| Return a masked preview of the decrypted value. |
| Shows first 3 and last 3 characters with ... in between. |
| Example: "sk-abc123xyz789" -> "sk-...789" |
| """ |
| from core.services import EncryptionService |
|
|
| try: |
| value = EncryptionService.decrypt(self.encrypted_value) |
| if len(value) <= 8: |
| return "*" * len(value) |
| return f"{value[:3]}...{value[-3:]}" |
| except Exception: |
| return "[decryption error]" |
|
|
| def get_decrypted_value(self) -> str: |
| """Return the decrypted secret value.""" |
| from core.services import EncryptionService |
|
|
| return EncryptionService.decrypt(self.encrypted_value) |
|
|
| def set_value(self, plaintext: str) -> None: |
| """Encrypt and store a new value.""" |
| from core.services import EncryptionService |
|
|
| self.encrypted_value = EncryptionService.encrypt(plaintext) |
|
|