From 2b506771148411473aa69dbc22ee58768c62def5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=AD=C3=B0ir=20Valberg=20Gu=C3=B0mundsson?= Date: Sat, 13 Jan 2024 20:42:31 +0100 Subject: [PATCH] Initial stuff for services. --- src/membership/admin.py | 7 ++ ...ccess_serviceaccess_unique_user_service.py | 64 +++++++++++++++++++ src/membership/models.py | 21 ++++++ src/project/settings.py | 2 + src/services/__init__.py | 0 src/services/admin.py | 1 + src/services/apps.py | 6 ++ src/services/migrations/__init__.py | 0 src/services/models.py | 1 + src/services/registry.py | 21 ++++++ src/services/services.py | 27 ++++++++ src/services/tests.py | 1 + src/services/views.py | 1 + 13 files changed, 152 insertions(+) create mode 100644 src/membership/migrations/0006_serviceaccess_serviceaccess_unique_user_service.py create mode 100644 src/services/__init__.py create mode 100644 src/services/admin.py create mode 100644 src/services/apps.py create mode 100644 src/services/migrations/__init__.py create mode 100644 src/services/models.py create mode 100644 src/services/registry.py create mode 100644 src/services/services.py create mode 100644 src/services/tests.py create mode 100644 src/services/views.py diff --git a/src/membership/admin.py b/src/membership/admin.py index 69e2c22..f1ad815 100644 --- a/src/membership/admin.py +++ b/src/membership/admin.py @@ -20,6 +20,7 @@ from .emails import InviteEmail from .models import Member from .models import Membership from .models import MembershipType +from .models import ServiceAccess from .models import SubscriptionPeriod from .models import WaitingListEntry @@ -46,6 +47,12 @@ class SubscriptionPeriodAdmin(admin.ModelAdmin): """Admin for SubscriptionPeriod model.""" +@admin.register(ServiceAccess) +class ServiceAccessAdmin(admin.ModelAdmin): + """Admin for ServiceAccess model.""" + pass + + class MembershipInlineAdmin(admin.TabularInline): """Inline admin.""" diff --git a/src/membership/migrations/0006_serviceaccess_serviceaccess_unique_user_service.py b/src/membership/migrations/0006_serviceaccess_serviceaccess_unique_user_service.py new file mode 100644 index 0000000..9354287 --- /dev/null +++ b/src/membership/migrations/0006_serviceaccess_serviceaccess_unique_user_service.py @@ -0,0 +1,64 @@ +# Generated by Django 5.0.1 on 2024-01-13 19:20 + +import django.db.models.deletion +import django_registries.registry +import services.registry +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("membership", "0005_member"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name="ServiceAccess", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "modified", + models.DateTimeField(auto_now=True, verbose_name="modified"), + ), + ( + "created", + models.DateTimeField(auto_now_add=True, verbose_name="created"), + ), + ( + "service", + django_registries.registry.ChoicesField( + choices=[], + registry=services.registry.ServiceRegistry, + verbose_name="service", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to=settings.AUTH_USER_MODEL, + ), + ), + ], + options={ + "verbose_name": "service access", + "verbose_name_plural": "service accesses", + }, + ), + migrations.AddConstraint( + model_name="serviceaccess", + constraint=models.UniqueConstraint( + fields=("user", "service"), name="unique_user_service" + ), + ), + ] diff --git a/src/membership/models.py b/src/membership/models.py index f9e5ddd..fc6c352 100644 --- a/src/membership/models.py +++ b/src/membership/models.py @@ -12,6 +12,8 @@ from django.contrib.postgres.fields import RangeOperators from django.db import models from django.utils import timezone from django.utils.translation import gettext as _ + +from services.registry import ServiceRegistry from djmoney.money import Money from utils.mixins import CreatedModifiedAbstract @@ -245,3 +247,22 @@ class WaitingListEntry(CreatedModifiedAbstract): class Meta: verbose_name = _("waiting list entry") verbose_name_plural = _("waiting list entries") + + +class ServiceAccess(CreatedModifiedAbstract): + class Meta: + verbose_name = _("service access") + verbose_name_plural = _("service accesses") + constraints = [ + models.UniqueConstraint( + fields=["user", "service"], + name="unique_user_service", + ), + ] + + user = models.ForeignKey("auth.User", on_delete=models.PROTECT) + + service = ServiceRegistry.choices_field(verbose_name=_("service")) + + def __str__(self): + return f"{self.user} - {self.service}" diff --git a/src/project/settings.py b/src/project/settings.py index d6a800c..06521c0 100644 --- a/src/project/settings.py +++ b/src/project/settings.py @@ -46,12 +46,14 @@ THIRD_PARTY_APPS = [ "allauth", "allauth.account", "django_view_decorator", + "django_registries", ] LOCAL_APPS = [ "utils", "accounting", "membership", + "services", ] INSTALLED_APPS = [ diff --git a/src/services/__init__.py b/src/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/services/admin.py b/src/services/admin.py new file mode 100644 index 0000000..846f6b4 --- /dev/null +++ b/src/services/admin.py @@ -0,0 +1 @@ +# Register your models here. diff --git a/src/services/apps.py b/src/services/apps.py new file mode 100644 index 0000000..11e745d --- /dev/null +++ b/src/services/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ServicesConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "services" diff --git a/src/services/migrations/__init__.py b/src/services/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/services/models.py b/src/services/models.py new file mode 100644 index 0000000..6b20219 --- /dev/null +++ b/src/services/models.py @@ -0,0 +1 @@ +# Create your models here. diff --git a/src/services/registry.py b/src/services/registry.py new file mode 100644 index 0000000..8fc430e --- /dev/null +++ b/src/services/registry.py @@ -0,0 +1,21 @@ +from django_registries.registry import Interface +from django_registries.registry import Registry + + +class ServiceRegistry(Registry): + """Registry for services""" + + implementations_module = "services" + + +class ServiceInterface(Interface): + """Interface for services""" + + registry = ServiceRegistry + + public: bool = False + + # TODO: add a way to add a something which defines the required fields for a service + # - maybe a list of tuples with the field name and the type of the field + # this could be used to generate a form for the service, and also to validate + # the data saved in a JSONField on the ServiceAccess model diff --git a/src/services/services.py b/src/services/services.py new file mode 100644 index 0000000..e5580ac --- /dev/null +++ b/src/services/services.py @@ -0,0 +1,27 @@ +from .registry import ServiceInterface + + +class MailService(ServiceInterface): + slug = "mail" + + +class MatrixService(ServiceInterface): + slug = "matrix" + + +class MastodonService(ServiceInterface): + slug = "mastodon" + + +class NextcloudService(ServiceInterface): + slug = "nextcloud" + + +class HedgeDocService(ServiceInterface): + slug = "hedgedoc" + public = True + + +class RalllyService(ServiceInterface): + slug = "rallly" + public = True diff --git a/src/services/tests.py b/src/services/tests.py new file mode 100644 index 0000000..a39b155 --- /dev/null +++ b/src/services/tests.py @@ -0,0 +1 @@ +# Create your tests here. diff --git a/src/services/views.py b/src/services/views.py new file mode 100644 index 0000000..60f00ef --- /dev/null +++ b/src/services/views.py @@ -0,0 +1 @@ +# Create your views here.