Bump copyright year
[mailman-postorious.git] / src / postorius / auth / utils.py
blob3b403da7e742a5f452b2a7f71a9e923a450132b6
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 1998-2022 by the Free Software Foundation, Inc.
4 # This file is part of Postorius.
6 # Postorius is free software: you can redistribute it and/or modify it under
7 # the terms of the GNU General Public License as published by the Free
8 # Software Foundation, either version 3 of the License, or (at your option)
9 # any later version.
11 # Postorius is distributed in the hope that it will be useful, but WITHOUT
12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 # more details.
16 # You should have received a copy of the GNU General Public License along with
17 # Postorius. If not, see <http://www.gnu.org/licenses/>.
19 """
20 Authentication and authorization-related utilities.
21 """
23 from allauth.account.models import EmailAddress
25 from postorius.models import Domain, List
28 ALL_ROSTER = ['owner', 'moderator', 'member', 'nomember']
31 def user_is_in_list_roster(user, mailing_list, roster):
32 """Checks if a user is in a MailingList roster.
34 :param user: User to check access permissions for.
35 :type user: django.contrib.auth.model.User
36 :param mailing_list: MailingList to check permissions for.
37 :type mailing_list: postorius.models.List
38 :param roster: Access permissions required.
39 :type roster: str
40 """
41 if not user.is_authenticated:
42 return False
43 addresses = set(email.lower() for email in
44 EmailAddress.objects.filter(
45 user=user, verified=True).values_list(
46 "email", flat=True))
47 if roster not in ALL_ROSTER:
48 raise ValueError(f'{roster} is a valid List Roster.')
50 roster_addresses = set(
51 [member.email.lower()
52 for member in mailing_list.get_roster(roster, fields=['email'])])
53 if addresses & roster_addresses:
54 return True # At least one address is in the roster
55 return False
58 def set_list_access_props(user, mlist, owner=True, moderator=True):
59 """Update user's access permissions of a MailingList.
61 :param user: The user to check permissions for.
62 :type user: django.contrib.auth.model.User
63 :param mlist: MailingList to check permissions for.
64 :type mlist: postorius.models.List
65 :param owner: Set is_list_owner.
66 :type owner: bool
67 :param moderator: Set is_list_moderator.
68 :type moderator: bool
69 """
70 # If given a mailinglist id, get the List object instead.
71 if isinstance(mlist, str):
72 mlist = List.objects.get_or_404(mlist)
73 # If not already set, check if the user is in list ownership roster.
74 if (not hasattr(user, 'is_list_owner')) and owner:
75 user.is_list_owner = user_is_in_list_roster(user, mlist, 'owner')
76 # If not already set, check if the user is in list moderator roster.
77 if not hasattr(user, 'is_list_moderator') and moderator:
78 user.is_list_moderator = user_is_in_list_roster(
79 user, mlist, 'moderator')
82 def set_domain_access_props(user, domain):
83 """Update user's access permissions for a domain.
85 :param user: The user to check permissions for.
86 :type user: django.contrib.auth.model.User
87 :param domain: Domain to check permissions for.
88 :type domain: postorius.models.Domain
89 """
90 # TODO: This is very slow as it involves first iterating over every domain
91 # owner and then each of their addresses. Create an API in Core to
92 # facilitate this.
93 if isinstance(domain, str):
94 domain = Domain.objects.get_or_404(domain)
95 owner_addresses = []
96 for owner in domain.owners:
97 owner_addresses.extend(owner.addresses)
98 owner_addresses = set([each.email for each in owner_addresses])
99 user_addresses = set(EmailAddress.objects.filter(
100 user=user, verified=True).values_list("email", flat=True))
101 user.is_domain_owner = owner_addresses & user_addresses