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""" 

13 

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 

18 

19 

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 ) 

36 

37 def __init__(self, team_slug, email): 

38 super(JoinTeam, self).__init__() 

39 self.user_email = email 

40 self.team_slug = team_slug 

41 

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 

53 

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 

58 

59 return team, user_email 

60 

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 

65 

66 packed = self.get_team_and_user() 

67 if packed is None: 

68 return False 

69 

70 self.reply('A confirmation mail has been sent to %s', self.user_email) 

71 return True 

72 

73 def get_command_text(self): 

74 return super(JoinTeam, self).get_command_text( 

75 self.team_slug, self.user_email) 

76 

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) 

84 

85 

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 ) 

101 

102 def __init__(self, team_slug, email): 

103 super(LeaveTeam, self).__init__() 

104 self.user_email = email 

105 self.team_slug = team_slug 

106 

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 

117 

118 return team, user_email 

119 

120 def pre_confirm(self): 

121 packed = self.get_team_and_user() 

122 if packed is None: 

123 return False 

124 

125 self.reply('A confirmation mail has been sent to %s', self.user_email) 

126 return True 

127 

128 def get_command_text(self): 

129 return super(LeaveTeam, self).get_command_text( 

130 self.team_slug, self.user_email) 

131 

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) 

140 

141 

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 ) 

157 

158 def __init__(self, team_slug): 

159 super(ListTeamPackages, self).__init__() 

160 self.team_slug = team_slug 

161 

162 @property 

163 def user_email(self): 

164 return self.context['email'] 

165 

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 

173 

174 def get_command_text(self): 

175 return super(ListTeamPackages, self).get_command_text( 

176 self.team_slug) 

177 

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 

189 

190 self.reply("Packages found in team %s:", team) 

191 self.list_reply(package for package in 

192 team.packages.all().order_by('name')) 

193 

194 

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 ) 

208 

209 def __init__(self, email): 

210 super(WhichTeams, self).__init__() 

211 self.user_email = email 

212 

213 def handle(self): 

214 user_email = get_or_none(UserEmail, email=self.user_email) 

215 

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'))