Coverage for distro_tracker/mail/control/commands/teams.py: 94%
117 statements
« prev ^ index » next coverage.py v6.5.0, created at 2025-01-12 09:15 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2025-01-12 09:15 +0000
1# Copyright 2013 The Distro Tracker Developers
2# See the COPYRIGHT file at the top-level directory of this distribution and
3# at https://deb.li/DTAuthors
4#
5# This file is part of Distro Tracker. It is subject to the license terms
6# in the LICENSE file found in the top-level directory of this
7# distribution and at https://deb.li/DTLicense. No part of Distro Tracker,
8# including this file, may be copied, modified, propagated, or distributed
9# except according to the terms contained in the LICENSE file.
10"""
11Implements all commands which deal with teams.
12"""
14from distro_tracker.core.models import Team, UserEmail
15from distro_tracker.core.utils import get_or_none
16from distro_tracker.mail.control.commands.base import Command
17from distro_tracker.mail.control.commands.confirmation import needs_confirmation
20@needs_confirmation
21class JoinTeam(Command):
22 """
23 Command which lets users join an existing public team.
24 """
25 META = {
26 'description': """join-team <team-slug> [<email>]
27 Adds <email> to team with the slug given by <team-slug>. If
28 <email> is not given, it adds the From address email to the team.
29 If the team is not public or it does not exist, a warning is
30 returned.""",
31 'name': 'join-team',
32 }
33 REGEX_LIST = (
34 r'\s+(?P<team_slug>\S+)(?:\s+(?P<email>\S+))?$',
35 )
37 def __init__(self, team_slug, email):
38 super(JoinTeam, self).__init__()
39 self.user_email = email
40 self.team_slug = team_slug
42 def get_team_and_user(self):
43 team = get_or_none(Team, slug=self.team_slug)
44 if not team:
45 self.error('Team with the slug "%s" does not exist.',
46 self.team_slug)
47 return
48 if not team.public:
49 self.error("The given team is not public. "
50 "Please contact %s if you wish to join",
51 team.owner.main_email)
52 return
54 user_email, _ = UserEmail.objects.get_or_create(email=self.user_email)
55 if user_email in team.members.all():
56 self.warning("You are already a member of the team.")
57 return
59 return team, user_email
61 def pre_confirm(self):
62 if not self.validate_email(self.user_email):
63 self.warning('%s is not a valid email.', self.user_email)
64 return False
66 packed = self.get_team_and_user()
67 if packed is None:
68 return False
70 self.reply('A confirmation mail has been sent to %s', self.user_email)
71 return True
73 def get_command_text(self):
74 return super(JoinTeam, self).get_command_text(
75 self.team_slug, self.user_email)
77 def handle(self):
78 packed = self.get_team_and_user()
79 if packed is None: 79 ↛ 80line 79 didn't jump to line 80, because the condition on line 79 was never true
80 return
81 team, user_email = packed
82 team.add_members([user_email])
83 self.reply('You have successfully joined the team "%s"', team)
86@needs_confirmation
87class LeaveTeam(Command):
88 """
89 Command which lets users leave a team they are already a member of.
90 """
91 META = {
92 'description': """leave-team <team-slug> [<email>]
93 Removes <email> from the team with the slug given by <team-slug>. If
94 <email> is not given, it uses the From address email.
95 If the user is not a member of the team, a warning is returned.""",
96 'name': 'leave-team',
97 }
98 REGEX_LIST = (
99 r'\s+(?P<team_slug>\S+)(?:\s+(?P<email>\S+))?$',
100 )
102 def __init__(self, team_slug, email):
103 super(LeaveTeam, self).__init__()
104 self.user_email = email
105 self.team_slug = team_slug
107 def get_team_and_user(self):
108 team = get_or_none(Team, slug=self.team_slug)
109 if not team:
110 self.error('Team with the slug "%s" does not exist.',
111 self.team_slug)
112 return
113 user_email = get_or_none(UserEmail, email=self.user_email)
114 if not user_email or user_email not in team.members.all():
115 self.warning("You are not a member of the team.")
116 return
118 return team, user_email
120 def pre_confirm(self):
121 packed = self.get_team_and_user()
122 if packed is None:
123 return False
125 self.reply('A confirmation mail has been sent to %s', self.user_email)
126 return True
128 def get_command_text(self):
129 return super(LeaveTeam, self).get_command_text(
130 self.team_slug, self.user_email)
132 def handle(self):
133 packed = self.get_team_and_user()
134 if packed is None: 134 ↛ 135line 134 didn't jump to line 135, because the condition on line 134 was never true
135 return
136 team, user_email = packed
137 team.remove_members([user_email])
138 self.reply('You have successfully left the team "%s" (slug: %s)',
139 team, team.slug)
142class ListTeamPackages(Command):
143 """
144 Lists all the packages of a particular team, provided that the team is
145 public or the email doing the query is a member of the team.
146 """
147 META = {
148 'description': """list-team-packages <team-slug>
149 Lists all packages of the team with the slug given by <team-slug>.
150 If the team is private, the packages are returned only if the From email
151 is a member of the team.""",
152 'name': 'list-team-packages',
153 }
154 REGEX_LIST = (
155 r'\s+(?P<team_slug>\S+)$',
156 )
158 def __init__(self, team_slug):
159 super(ListTeamPackages, self).__init__()
160 self.team_slug = team_slug
162 @property
163 def user_email(self):
164 return self.context['email']
166 def get_team(self):
167 team = get_or_none(Team, slug=self.team_slug)
168 if not team: 168 ↛ 169line 168 didn't jump to line 169, because the condition on line 168 was never true
169 self.error('Team with the slug "%s" does not exist.',
170 self.team_slug)
171 return
172 return team
174 def get_command_text(self):
175 return super(ListTeamPackages, self).get_command_text(
176 self.team_slug)
178 def handle(self):
179 team = self.get_team()
180 if not team: 180 ↛ 181line 180 didn't jump to line 181, because the condition on line 180 was never true
181 return
182 if not team.public:
183 user_email = get_or_none(UserEmail, email=self.user_email)
184 if not user_email or user_email not in team.members.all():
185 self.error(
186 "The team is private. "
187 "Only team members can see its packages.")
188 return
190 self.reply("Packages found in team %s:", team)
191 self.list_reply(package for package in
192 team.packages.all().order_by('name'))
195class WhichTeams(Command):
196 """
197 Returns a list of teams that the given email is a member of.
198 """
199 META = {
200 'description': """which-teams [<email>]
201 Lists all teams that <email> is a member of. If <email> is not given, the
202 sender's email is used.""",
203 'name': 'which-teams',
204 }
205 REGEX_LIST = (
206 r'(?:\s+(?P<email>\S+))?$',
207 )
209 def __init__(self, email):
210 super(WhichTeams, self).__init__()
211 self.user_email = email
213 def handle(self):
214 user_email = get_or_none(UserEmail, email=self.user_email)
216 if not user_email or user_email.teams.count() == 0:
217 self.warning("%s is not a member of any team.", self.user_email)
218 else:
219 self.reply("Teams that %s is a member of:", self.user_email)
220 self.list_reply(
221 team.slug
222 for team in user_email.teams.all().order_by('name'))