summaryrefslogtreecommitdiffstats
path: root/core/models
diff options
context:
space:
mode:
Diffstat (limited to 'core/models')
-rw-r--r--core/models/__init__.py1
-rw-r--r--core/models/config.py111
2 files changed, 112 insertions, 0 deletions
diff --git a/core/models/__init__.py b/core/models/__init__.py
new file mode 100644
index 0000000..87bfe4e
--- /dev/null
+++ b/core/models/__init__.py
@@ -0,0 +1 @@
+from .config import Config # noqa
diff --git a/core/models/config.py b/core/models/config.py
new file mode 100644
index 0000000..8a2e40b
--- /dev/null
+++ b/core/models/config.py
@@ -0,0 +1,111 @@
+from typing import ClassVar
+
+import pydantic
+from django.db import models
+from django.utils.functional import classproperty
+
+
+class Config(models.Model):
+ """
+ A configuration setting for either the server or a specific user or identity.
+
+ The possible options and their defaults are defined at the bottom of the file.
+ """
+
+ key = models.CharField(max_length=500)
+
+ user = models.ForeignKey(
+ "users.user",
+ blank=True,
+ null=True,
+ related_name="configs",
+ on_delete=models.CASCADE,
+ )
+
+ identity = models.ForeignKey(
+ "users.identity",
+ blank=True,
+ null=True,
+ related_name="configs",
+ on_delete=models.CASCADE,
+ )
+
+ json = models.JSONField(blank=True, null=True)
+ image = models.ImageField(blank=True, null=True, upload_to="config/%Y/%m/%d/")
+
+ class Meta:
+ unique_together = [
+ ("key", "user", "identity"),
+ ]
+
+ @classproperty
+ def system(cls):
+ cls.system = cls.load_system()
+ return cls.system
+
+ system: ClassVar["Config.ConfigOptions"] # type: ignore
+
+ @classmethod
+ def load_system(cls):
+ """
+ Load all of the system config options and return an object with them
+ """
+ values = {}
+ for config in cls.objects.filter(user__isnull=True, identity__isnull=True):
+ values[config.key] = config.image or config.json
+ return cls.SystemOptions(**values)
+
+ @classmethod
+ def load_user(cls, user):
+ """
+ Load all of the user config options and return an object with them
+ """
+ values = {}
+ for config in cls.objects.filter(user=user, identity__isnull=True):
+ values[config.key] = config.image or config.json
+ return cls.UserOptions(**values)
+
+ @classmethod
+ def load_identity(cls, identity):
+ """
+ Load all of the identity config options and return an object with them
+ """
+ values = {}
+ for config in cls.objects.filter(user__isnull=True, identity=identity):
+ values[config.key] = config.image or config.json
+ return cls.IdentityOptions(**values)
+
+ @classmethod
+ def set_system(cls, key, value):
+ config_field = cls.SystemOptions.__fields__[key]
+ if not isinstance(value, config_field.type_):
+ raise ValueError(f"Invalid type for {key}: {type(value)}")
+ cls.objects.update_or_create(
+ key=key,
+ defaults={"json": value},
+ )
+
+ @classmethod
+ def set_identity(cls, identity, key, value):
+ config_field = cls.IdentityOptions.__fields__[key]
+ if not isinstance(value, config_field.type_):
+ raise ValueError(f"Invalid type for {key}: {type(value)}")
+ cls.objects.update_or_create(
+ identity=identity,
+ key=key,
+ defaults={"json": value},
+ )
+
+ class SystemOptions(pydantic.BaseModel):
+
+ site_name: str = "takahē"
+ highlight_color: str = "#449c8c"
+ identity_max_age: int = 24 * 60 * 60
+
+ class UserOptions(pydantic.BaseModel):
+
+ pass
+
+ class IdentityOptions(pydantic.BaseModel):
+
+ toot_mode: bool = False