feat: Send confirmation email to trust giver
This commit is contained in:
parent
2ebb0b7ee4
commit
0d3e1e3891
5 changed files with 65 additions and 16 deletions
|
@ -1,8 +1,8 @@
|
|||
from djeveric.emails import ConfirmationEmail
|
||||
|
||||
|
||||
class ConfidantConfirmationEmail(ConfirmationEmail):
|
||||
class TrustBridgeConfirmationEmail(ConfirmationEmail):
|
||||
subject = "TODO"
|
||||
|
||||
def get_message(self, context):
|
||||
return '"token": "{token}", "uid": "{uid}", "rtid": "{rtid}", "rid": "{rid}"'.format(**context)
|
||||
def get_body(self, context: dict[str]) -> str:
|
||||
return "{token}".format(**context)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from django.conf import settings
|
||||
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
|
||||
from django.contrib.auth.models import PermissionsMixin
|
||||
from django.contrib.auth.validators import UnicodeUsernameValidator
|
||||
|
@ -5,8 +6,11 @@ from django.core.mail import send_mail
|
|||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from djeveric.fields import ConfirmationField
|
||||
from djeveric.models import ConfirmableModelMixin
|
||||
|
||||
from userausfall import ldap
|
||||
from userausfall.emails import TrustBridgeConfirmationEmail
|
||||
|
||||
|
||||
class MissingUserAttribute(Exception):
|
||||
|
@ -98,13 +102,24 @@ class User(PermissionsMixin, AbstractBaseUser):
|
|||
return ldap.create_account(self.username, raw_password)
|
||||
|
||||
def get_or_create_trust_bridge(self):
|
||||
"""Returns a trust bridge instance. If it doesn't exist it is created."""
|
||||
try:
|
||||
return self.trust_bridge
|
||||
except TrustBridge.DoesNotExist:
|
||||
return TrustBridge.objects.create(trust_taker=self)
|
||||
|
||||
def get_primary_email(self):
|
||||
"""Returns the primary email address for this user."""
|
||||
return f"{self.username}@{settings.USERAUSFALL['PRIMARY_EMAIL_DOMAIN']}"
|
||||
|
||||
class TrustBridge(models.Model):
|
||||
is_trusted = models.BooleanField(default=False)
|
||||
|
||||
class TrustBridge(ConfirmableModelMixin, models.Model):
|
||||
is_trusted = ConfirmationField(email_class=TrustBridgeConfirmationEmail)
|
||||
trust_giver = models.ForeignKey("User", on_delete=models.SET_NULL, null=True)
|
||||
trust_taker = models.OneToOneField("User", on_delete=models.CASCADE, related_name="trust_bridge")
|
||||
|
||||
def get_confirmation_email_recipient(self) -> str:
|
||||
return self.trust_giver.get_primary_email()
|
||||
|
||||
def _has_confirmation_recipient(self):
|
||||
return self.trust_giver is not None
|
||||
|
|
|
@ -1,10 +1,25 @@
|
|||
from rest_framework import serializers
|
||||
|
||||
from userausfall.models import TrustBridge
|
||||
from userausfall.models import TrustBridge, User
|
||||
|
||||
|
||||
class TrustBridgeSerializer(serializers.ModelSerializer):
|
||||
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ["username"]
|
||||
# the UniqueValidator for username prevents successful validation for existing users
|
||||
extra_kwargs = {"username": {"validators": []}}
|
||||
|
||||
|
||||
class TrustBridgeSerializer(serializers.HyperlinkedModelSerializer):
|
||||
trust_giver = UserSerializer()
|
||||
|
||||
class Meta:
|
||||
model = TrustBridge
|
||||
fields = ["is_trusted", "trust_giver"]
|
||||
read_only_fields = ["is_trusted"]
|
||||
|
||||
def update(self, instance: TrustBridge, validated_data):
|
||||
instance.trust_giver, _ = User.objects.get_or_create(username=validated_data["trust_giver"]["username"])
|
||||
instance.save()
|
||||
return instance
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from django.core import mail
|
||||
from rest_framework import status
|
||||
|
||||
from userausfall.rest_api.tests import UserausfallAPITestCase
|
||||
|
@ -6,9 +7,7 @@ from userausfall.tests import UserMixin
|
|||
|
||||
class TrustBridgeTestCase(UserMixin, UserausfallAPITestCase):
|
||||
def test_retrieve_trust_bridge(self):
|
||||
"""
|
||||
Retrieve the trust bridge information of a user without an ldap account.
|
||||
"""
|
||||
"""Retrieve the trust bridge information of a user without an ldap account."""
|
||||
url = "/trust-bridge/"
|
||||
self.authenticate_user()
|
||||
response = self.client.get(self.get_api_url(url))
|
||||
|
@ -22,13 +21,29 @@ class TrustBridgeTestCase(UserMixin, UserausfallAPITestCase):
|
|||
)
|
||||
|
||||
def test_update_trust_bridge(self):
|
||||
"""
|
||||
Update the trust giver of the user's trust bridge.
|
||||
"""
|
||||
"""Update the trust giver of the user's trust bridge."""
|
||||
url = "/trust-bridge/"
|
||||
other_user = self.create_user()
|
||||
trust_giver = self.create_user()
|
||||
self.create_user()
|
||||
self.authenticate_user()
|
||||
response = self.client.put(self.get_api_url(url), {"trust_giver": other_user.pk})
|
||||
response = self.client.put(
|
||||
self.get_api_url(url),
|
||||
{
|
||||
"trust_giver": {
|
||||
"username": trust_giver.username,
|
||||
},
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(self.user.trust_bridge.trust_giver, other_user)
|
||||
self.assertEqual(self.user.trust_bridge.trust_giver, trust_giver)
|
||||
|
||||
def test_set_trust_giver(self):
|
||||
"""When setting a trust giver a confirmation email is sent."""
|
||||
self.trust_giver = self.create_user()
|
||||
self.create_user()
|
||||
trust_bridge = self.user.get_or_create_trust_bridge()
|
||||
trust_bridge.trust_giver = self.trust_giver
|
||||
trust_bridge.save()
|
||||
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
self.assertIn(self.user.trust_bridge.get_confirmation_token(), mail.outbox[0].body)
|
||||
|
|
|
@ -200,3 +200,7 @@ USERAUSFALL_LDAP = {
|
|||
"ADMIN_USER_DN": "cn=admin,dc=local",
|
||||
"ADMIN_USER_PASSWORD": os.environ.get("USERAUSFALL_LDAP_PASSWORD"),
|
||||
}
|
||||
|
||||
USERAUSFALL = {
|
||||
"PRIMARY_EMAIL_DOMAIN": "systemausfall.org",
|
||||
}
|
||||
|
|
Reference in a new issue