From ce8d4bd228c85749a6557145f4ac10aa090fe1bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=AD=C3=B0ir=20Valberg=20Gu=C3=B0mundsson?= Date: Mon, 15 Jul 2024 10:05:53 +0200 Subject: [PATCH] WIP. --- ...erviceaccess_subscription_data_and_more.py | 25 +++++++ src/membership/models.py | 20 ++++-- src/services/registry.py | 20 +++--- src/services/services.py | 22 ++++++- .../templates/services/service_subscribe.html | 3 +- src/services/views.py | 66 +++++++++++++------ 6 files changed, 115 insertions(+), 41 deletions(-) create mode 100644 src/membership/migrations/0007_serviceaccess_subscription_data_and_more.py diff --git a/src/membership/migrations/0007_serviceaccess_subscription_data_and_more.py b/src/membership/migrations/0007_serviceaccess_subscription_data_and_more.py new file mode 100644 index 0000000..7556201 --- /dev/null +++ b/src/membership/migrations/0007_serviceaccess_subscription_data_and_more.py @@ -0,0 +1,25 @@ +# Generated by Django 5.0.6 on 2024-07-15 07:30 + +import django_registries.registry +import services.registry +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('membership', '0006_serviceaccess_serviceaccess_unique_user_service'), + ] + + operations = [ + migrations.AddField( + model_name='serviceaccess', + name='subscription_data', + field=models.JSONField(blank=True, null=True, verbose_name='subscription data'), + ), + migrations.AlterField( + model_name='serviceaccess', + name='service', + field=django_registries.registry.ChoicesField(choices=[('hedgedoc', 'hedgedoc'), ('mail', 'mail'), ('mastodon', 'mastodon'), ('matrix', 'matrix'), ('nextcloud', 'nextcloud'), ('rallly', 'rallly')], registry=services.registry.ServiceRegistry, verbose_name='service'), + ), + ] diff --git a/src/membership/models.py b/src/membership/models.py index d499ef9..71cb1cc 100644 --- a/src/membership/models.py +++ b/src/membership/models.py @@ -1,6 +1,5 @@ """Models for the membership app.""" -from typing import ClassVar from typing import Self from django.contrib.auth.models import User @@ -10,7 +9,6 @@ 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 utils.mixins import CreatedModifiedAbstract @@ -58,14 +56,14 @@ class SubscriptionPeriod(CreatedModifiedAbstract): period = DateRangeField(verbose_name=_("period")) class Meta: - constraints: ClassVar = [ + constraints: ( ExclusionConstraint( name="exclude_overlapping_periods", expressions=[ ("period", RangeOperators.OVERLAPS), ], ), - ] + ) def __str__(self) -> str: return f"{self.period.lower} - {self.period.upper or _('next general assembly')}" @@ -144,19 +142,27 @@ class MembershipType(CreatedModifiedAbstract): class ServiceAccess(CreatedModifiedAbstract): + """Access to a service for a user.""" + class Meta: verbose_name = _("service access") verbose_name_plural = _("service accesses") - constraints = [ + 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): + subscription_data = models.JSONField( + verbose_name=_("subscription data"), + null=True, + blank=True, + ) + + def __str__(self) -> str: return f"{self.user} - {self.service}" diff --git a/src/services/registry.py b/src/services/registry.py index 70b5044..6e9e303 100644 --- a/src/services/registry.py +++ b/src/services/registry.py @@ -1,16 +1,18 @@ +"""Registry for services.""" + from django import forms from django_registries.registry import Interface from django_registries.registry import Registry class ServiceRegistry(Registry): - """Registry for services""" + """Registry for services.""" implementations_module = "services" class ServiceInterface(Interface): - """Interface for services""" + """Interface for services.""" registry = ServiceRegistry @@ -25,16 +27,12 @@ class ServiceInterface(Interface): # 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 - subscribe_fields: list[tuple[str, forms.Field]] = [] + subscribe_fields: tuple[tuple[str, forms.Field]] = [] - def get_form(self) -> type: - """Get the form for the service""" - print(self.subscribe_fields) + def get_form_class(self) -> type: + """Get the form class for the service.""" return type( "ServiceForm", (forms.Form,), - { - field_name: field_type - for field_name, field_type in self.subscribe_fields - }, - )() + dict(self.subscribe_fields), + ) diff --git a/src/services/services.py b/src/services/services.py index 9d5135d..49377da 100644 --- a/src/services/services.py +++ b/src/services/services.py @@ -1,34 +1,46 @@ +"""Service classes for data.coop.""" + from django import forms from .registry import ServiceInterface class MailService(ServiceInterface): + """Mail service.""" + slug = "mail" name = "Mail" url = "https://mail.data.coop" description = "Mail service for data.coop" + subscribe_fields = (("username", forms.CharField()),) + class MatrixService(ServiceInterface): + """Matrix service.""" + slug = "matrix" name = "Matrix" url = "https://matrix.data.coop" description = "Matrix service for data.coop" - subscribe_fields = [ - ("username", forms.CharField()), - ] + subscribe_fields = (("username", forms.CharField()),) class MastodonService(ServiceInterface): + """Mastodon service.""" + slug = "mastodon" name = "Mastodon" url = "https://social.data.coop" description = "Mastodon service for data.coop" + subscribe_fields = (("username", forms.CharField()),) + class NextcloudService(ServiceInterface): + """Nextcloud service.""" + slug = "nextcloud" name = "Nextcloud" url = "https://cloud.data.coop" @@ -36,6 +48,8 @@ class NextcloudService(ServiceInterface): class HedgeDocService(ServiceInterface): + """HedgeDoc service.""" + slug = "hedgedoc" name = "HedgeDoc" url = "https://pad.data.coop" @@ -44,6 +58,8 @@ class HedgeDocService(ServiceInterface): class RalllyService(ServiceInterface): + """Rallly service.""" + slug = "rallly" name = "Rallly" url = "https://when.data.coop" diff --git a/src/services/templates/services/service_subscribe.html b/src/services/templates/services/service_subscribe.html index 8df66cb..8fe86bd 100644 --- a/src/services/templates/services/service_subscribe.html +++ b/src/services/templates/services/service_subscribe.html @@ -5,7 +5,8 @@

Subscribe to {{ service.name }}

-
+ + {% csrf_token %} {{ form }}