Coverage for src/couchers/tasks.py: 100%

58 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-07-22 16:44 +0000

1import logging 

2 

3from sqlalchemy.sql import func 

4 

5from couchers import email, urls 

6from couchers.config import config 

7from couchers.constants import SIGNUP_EMAIL_TOKEN_VALIDITY 

8from couchers.crypto import urlsafe_secure_token 

9from couchers.db import session_scope 

10from couchers.models import ( 

11 Cluster, 

12 ClusterRole, 

13 ClusterSubscription, 

14 EventCommunityInviteRequest, 

15 Node, 

16 User, 

17) 

18from couchers.sql import couchers_select as select 

19from couchers.templates.v2 import send_simple_pretty_email 

20from couchers.utils import now 

21 

22logger = logging.getLogger(__name__) 

23 

24 

25def send_signup_email(flow): 

26 logger.info(f"Sending signup email to {flow.email=}:") 

27 

28 # whether we've sent an email at all yet 

29 email_sent_before = flow.email_sent 

30 if flow.email_verified: 

31 # we just send a link to continue, not a verification link 

32 signup_link = urls.signup_link(token=flow.flow_token) 

33 elif flow.email_token and flow.token_is_valid: 

34 # if the verification email was sent and still is not expired, just resend the verification email 

35 signup_link = urls.signup_link(token=flow.email_token) 

36 else: 

37 # otherwise send a fresh email with new token 

38 token = urlsafe_secure_token() 

39 flow.email_verified = False 

40 flow.email_token = token 

41 flow.email_token_expiry = now() + SIGNUP_EMAIL_TOKEN_VALIDITY 

42 signup_link = urls.signup_link(token=flow.email_token) 

43 

44 flow.email_sent = True 

45 

46 send_simple_pretty_email( 

47 flow.email, 

48 "Finish signing up for Couchers.org", 

49 "signup_verify" if not email_sent_before else "signup_continue", 

50 template_args={"flow": flow, "signup_link": signup_link}, 

51 ) 

52 

53 

54def send_email_changed_confirmation_to_new_email(user): 

55 """ 

56 Send an email to user's new email address requesting confirmation of email change 

57 """ 

58 logger.info( 

59 f"Sending email changed (confirmation) email to {user=}'s new email address, (old email: {user.email}, new email: {user.new_email=})" 

60 ) 

61 

62 confirmation_link = urls.change_email_link(confirmation_token=user.new_email_token) 

63 send_simple_pretty_email( 

64 user.new_email, 

65 "Confirm your new email for Couchers.org", 

66 "email_changed_confirmation_new_email", 

67 template_args={"user": user, "confirmation_link": confirmation_link}, 

68 ) 

69 

70 

71def send_content_report_email(content_report): 

72 logger.info("Sending content report email") 

73 email.enqueue_system_email( 

74 config["REPORTS_EMAIL_RECIPIENT"], 

75 "content_report", 

76 template_args={ 

77 "report": content_report, 

78 "author_user_user_link": urls.user_link(username=content_report.author_user.username), 

79 "reporting_user_user_link": urls.user_link(username=content_report.reporting_user.username), 

80 }, 

81 ) 

82 

83 

84def maybe_send_reference_report_email(reference): 

85 if reference.should_report: 

86 logger.info("Sending reference report email") 

87 email.enqueue_system_email( 

88 config["REPORTS_EMAIL_RECIPIENT"], 

89 "reference_report", 

90 template_args={ 

91 "reference": reference, 

92 "from_user_user_link": urls.user_link(username=reference.from_user.username), 

93 "to_user_user_link": urls.user_link(username=reference.to_user.username), 

94 }, 

95 ) 

96 

97 

98def maybe_send_contributor_form_email(form): 

99 if form.should_notify: 

100 email.enqueue_system_email( 

101 config["CONTRIBUTOR_FORM_EMAIL_RECIPIENT"], 

102 "contributor_form", 

103 template_args={"form": form, "user_link": urls.user_link(username=form.user.username)}, 

104 ) 

105 

106 

107def send_event_community_invite_request_email(request: EventCommunityInviteRequest): 

108 email.enqueue_system_email( 

109 config["MODS_EMAIL_RECIPIENT"], 

110 "event_community_invite_request", 

111 template_args={ 

112 "event_link": urls.event_link(occurrence_id=request.occurrence.id, slug=request.occurrence.event.slug), 

113 "user_link": urls.user_link(username=request.user.username), 

114 "view_link": urls.console_link(page="api/org.couchers.admin.Admin"), 

115 }, 

116 ) 

117 

118 

119def send_account_deletion_report_email(reason): 

120 logger.info("Sending account deletion report email") 

121 email.enqueue_system_email( 

122 config["REPORTS_EMAIL_RECIPIENT"], 

123 "account_deletion_report", 

124 template_args={ 

125 "reason": reason, 

126 }, 

127 ) 

128 

129 

130def enforce_community_memberships(): 

131 """ 

132 Go through all communities and make sure every user in the polygon is also a member 

133 """ 

134 with session_scope() as session: 

135 for node in session.execute(select(Node)).scalars().all(): 

136 existing_users = select(ClusterSubscription.user_id).where( 

137 ClusterSubscription.cluster == node.official_cluster 

138 ) 

139 users_needing_adding = ( 

140 session.execute( 

141 select(User) 

142 .where(User.is_visible) 

143 .where(func.ST_Contains(node.geom, User.geom)) 

144 .where(~User.id.in_(existing_users)) 

145 ) 

146 .scalars() 

147 .all() 

148 ) 

149 for user in users_needing_adding: 

150 node.official_cluster.cluster_subscriptions.append( 

151 ClusterSubscription( 

152 user=user, 

153 role=ClusterRole.member, 

154 ) 

155 ) 

156 session.commit() 

157 

158 

159def enforce_community_memberships_for_user(session, user): 

160 """ 

161 Adds a given user to all the communities they belong in based on their location. 

162 """ 

163 cluster_ids = ( 

164 session.execute( 

165 select(Cluster.id) 

166 .join(Node, Node.id == Cluster.parent_node_id) 

167 .where(Cluster.is_official_cluster) 

168 .where(func.ST_Contains(Node.geom, user.geom)) 

169 ) 

170 .scalars() 

171 .all() 

172 ) 

173 

174 for cluster_id in cluster_ids: 

175 session.add( 

176 ClusterSubscription( 

177 user=user, 

178 cluster_id=cluster_id, 

179 role=ClusterRole.member, 

180 ) 

181 ) 

182 session.commit()