Coverage for apps / core / models.py: 84%
25 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-14 19:13 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-14 19:13 +0000
1from django.db import models
3from .encryption import decrypt_value, encrypt_value, is_encrypted
6class AppSettings(models.Model):
7 """Singleton model for application-wide settings."""
9 # Stored encrypted with 'enc:' prefix
10 _openrouter_api_key = models.CharField(max_length=500, blank=True, db_column="openrouter_api_key")
11 default_ai_model = models.CharField(max_length=100, default="anthropic/claude-3.5-haiku")
13 class Meta:
14 verbose_name = "App Settings"
15 verbose_name_plural = "App Settings"
17 def save(self, *args, **kwargs):
18 self.pk = 1 # Enforce singleton
20 # Encrypt key if not already encrypted
21 if self._openrouter_api_key and not is_encrypted(self._openrouter_api_key):
22 self._openrouter_api_key = encrypt_value(self._openrouter_api_key)
24 super().save(*args, **kwargs)
26 @classmethod
27 def get(cls):
28 """Get or create the singleton instance."""
29 obj, _ = cls.objects.get_or_create(pk=1)
30 return obj
32 @property
33 def openrouter_api_key(self) -> str:
34 """Get the decrypted API key."""
35 return decrypt_value(self._openrouter_api_key)
37 @openrouter_api_key.setter
38 def openrouter_api_key(self, value: str):
39 """Set and encrypt the API key."""
40 if value and not is_encrypted(value):
41 self._openrouter_api_key = encrypt_value(value)
42 else:
43 self._openrouter_api_key = value