Coverage for src/ptf_tools/signals.py: 83%
71 statements
« prev ^ index » next coverage.py v7.7.0, created at 2025-04-09 14:54 +0000
« prev ^ index » next coverage.py v7.7.0, created at 2025-04-09 14:54 +0000
1from itertools import chain
3from allauth.account.signals import user_signed_up
4from django.contrib.auth.models import Group, User
5from django.dispatch import receiver
6from django.http import HttpRequest
7from django.urls import reverse_lazy
8from ptf.models import Collection
9from ptf.utils import send_email_from_template
11from comments_moderation.models import CommentModerator
12from comments_moderation.rights import ModeratorUserRights
13from comments_moderation.utils import update_moderation_right
15from .models import Invitation, InvitationExtraData
18@receiver(user_signed_up)
19def update_user_from_invite(
20 sender, request: HttpRequest | None = None, user: User | None = None, **kwargs
21):
22 """
23 Update extra information on the user signing up from the attached invitation.
24 The extra information is either basic data (first name, last name)
25 or app specific extra information (eg. for comment moderation).
26 """
28 if not isinstance(user, User): 28 ↛ 29line 28 didn't jump to line 29 because the condition on line 28 was never true
29 return
31 try:
32 invite: Invitation | None = Invitation.objects.get(email__iexact=user.email)
33 # TODO: Log if no invitation attached to the user
34 # This should not happened since signup is closed outside of invitation system
35 except Invitation.DoesNotExist:
36 invite = None
38 if invite is None: 38 ↛ 39line 38 didn't jump to line 39 because the condition on line 38 was never true
39 return
41 if invite.first_name: 41 ↛ 43line 41 didn't jump to line 43 because the condition on line 41 was always true
42 user.first_name = invite.first_name
43 if invite.last_name: 43 ↛ 46line 43 didn't jump to line 46 because the condition on line 43 was always true
44 user.last_name = invite.last_name
46 extra_data = InvitationExtraData(**invite.extra_data)
48 # Handle comment moderation related data
49 if extra_data.moderator: 49 ↛ 116line 49 didn't jump to line 116 because the condition on line 49 was always true
50 # The list of users that "invited" the signing up user as a comment moderator.
51 # We will send an e-mail to notify them of the account creation.
52 users_to_mail = []
53 # Mark the user as a comment moderator
54 try:
55 comment_moderator = CommentModerator.objects.get(user=user)
56 except CommentModerator.DoesNotExist:
57 comment_moderator = CommentModerator(user=user)
59 comment_moderator.is_moderator = True
60 comment_moderator.save()
62 # Staff moderators - Fill the selected collections
63 if extra_data.moderator.collections:
64 pids = chain.from_iterable(c.pid for c in extra_data.moderator.collections)
65 collections_id = Collection.objects.filter(pid__in=set(pids)).values_list(
66 "pk", flat=True
67 )
68 comment_moderator.collections.add(*collections_id)
70 users_to_mail.extend(c.user_id for c in extra_data.moderator.collections)
72 # Base moderatos - Create a moderaton right entry associated to
73 # the selected comments
74 if extra_data.moderator.comments:
75 processed_comments = []
76 for comment in extra_data.moderator.comments:
77 try:
78 users_to_mail.append(comment.user_id)
79 if comment.id in processed_comments: 79 ↛ 80line 79 didn't jump to line 80 because the condition on line 79 was never true
80 continue
81 right_creator = User.objects.get(pk=comment.user_id)
82 rights = ModeratorUserRights(right_creator)
83 error, _ = update_moderation_right(comment.id, user.pk, rights)
84 # TODO: Log if the the POST request is unsuccessful ?
85 processed_comments.append(comment.id)
86 # Catch any exception and continue the workflow.
87 # We don't want this additional processing to result in the sign up
88 # failing.
89 except Exception:
90 continue
91 # Send notification e-mail
92 if users_to_mail:
93 recipient_list = User.objects.filter(pk__in=set(users_to_mail)).values(
94 "first_name", "last_name", "email"
95 )
96 if recipient_list: 96 ↛ 116line 96 didn't jump to line 116 because the condition on line 96 was always true
97 for r in recipient_list:
98 context_data = {
99 "full_name": f"{r['first_name']} {r['last_name']}",
100 "sign_up_name": f"{user.first_name} {user.last_name}",
101 "sign_up_email": user.email,
102 "comment_moderator_url": request.build_absolute_uri(
103 reverse_lazy("comment_moderators")
104 ),
105 "invitation_date": invite.created,
106 "email_signature": "The editorial team",
107 }
108 send_email_from_template(
109 "mail/comment_moderator_account_created.html",
110 context_data,
111 "[TRAMMEL] Comment moderator sign up",
112 to=[r["email"]],
113 )
115 # Add the newly created user to the given user groups.
116 if extra_data.user_groups:
117 group_pks = []
118 for group_pk in extra_data.user_groups:
119 try:
120 group_pks.append(int(group_pk))
121 except ValueError:
122 pass
123 if group_pks: 123 ↛ 128line 123 didn't jump to line 128 because the condition on line 123 was always true
124 user_groups = Group.objects.filter(pk__in=group_pks)
125 if user_groups: 125 ↛ 128line 125 didn't jump to line 128 because the condition on line 125 was always true
126 user.groups.add(*user_groups)
128 user.save()