From 44af0d4c59eed1c3715e9044e75c159cfddf54cc Mon Sep 17 00:00:00 2001 From: Andrew Godwin Date: Wed, 16 Nov 2022 17:23:46 -0700 Subject: Add start of a settings (config) system --- core/models/__init__.py | 1 + core/models/config.py | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 core/models/__init__.py create mode 100644 core/models/config.py (limited to 'core/models') 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 -- cgit v1.2.3