From a11f23e0f522557741ec3d4faa30929e31f8a2e1 Mon Sep 17 00:00:00 2001 From: Matthias Kestenholz Date: Mon, 8 Jul 2024 16:34:07 +0200 Subject: [PATCH] Add a mechanism to automatically add users to projects depending on their email address --- accounts/models.py | 13 ++++++++++++ .../migrations/0003_project__email_domains.py | 21 +++++++++++++++++++ projects/models.py | 19 +++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 projects/migrations/0003_project__email_domains.py diff --git a/accounts/models.py b/accounts/models.py index a39b815..41bf782 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -1,9 +1,12 @@ from authlib.base_user import BaseUser from authlib.roles import RoleField +from django.contrib.auth import signals from django.db import models from django.utils.crypto import get_random_string from django.utils.translation import gettext_lazy as _ +from projects.models import Project + class User(BaseUser): full_name = models.CharField(_("full name"), max_length=200) @@ -31,3 +34,13 @@ def cycle_token(self): self.save() cycle_token.alters_data = True + + +def add_user_to_projects(sender, user, **kwargs): + domain = user.email.rsplit("@")[-1] + for project in Project.objects.filter(_email_domains__icontains=domain): + if domain in project.email_domains: + project.users.add(user) + + +signals.user_logged_in.connect(add_user_to_projects) diff --git a/projects/migrations/0003_project__email_domains.py b/projects/migrations/0003_project__email_domains.py new file mode 100644 index 0000000..150e3a7 --- /dev/null +++ b/projects/migrations/0003_project__email_domains.py @@ -0,0 +1,21 @@ +# Generated by Django 5.1b1 on 2024-07-08 14:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("projects", "0002_catalog_created_at_catalog_updated_at_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="project", + name="_email_domains", + field=models.TextField( + blank=True, + help_text="User accounts on these domains will automatically get access to this project. One domain per line.", + verbose_name="email domains", + ), + ), + ] diff --git a/projects/models.py b/projects/models.py index e518f3a..5db38b3 100644 --- a/projects/models.py +++ b/projects/models.py @@ -2,6 +2,7 @@ import polib from django.conf import global_settings, settings +from django.core import validators from django.db import models from django.urls import reverse from django.utils.translation import gettext_lazy as _ @@ -41,6 +42,13 @@ class Project(models.Model): blank=True, # Only internal is fine. limit_choices_to={"is_staff": False}, ) + _email_domains = models.TextField( + _("email domains"), + blank=True, + help_text=_( + "User accounts on these domains will automatically get access to this project. One domain per line." + ), + ) objects = ProjectQuerySet.as_manager() @@ -55,6 +63,17 @@ def __str__(self): def get_absolute_url(self): return reverse("projects:project", kwargs={"slug": self.slug}) + @property + def email_domains(self): + return [v.strip() for v in self._email_domains.strip().splitlines()] + + def clean(self): + validator = validators.DomainNameValidator( + message=_("Some of the lines are not valid domain names.") + ) + for domain in self.email_domains: + validator(domain) + def get_api_url(self): return f"/api/pofile/{self.slug}/"