/
views.py
324 lines (258 loc) · 11.8 KB
/
views.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import re
import json
from django.conf import settings
from django.core.context_processors import csrf
from django.db.utils import DatabaseError
from django.http import HttpResponseRedirect
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.views.decorators.http import last_modified, require_safe
from django.views.generic.base import TemplateView
from django.shortcuts import redirect, render as django_render
import basket
import requests
from lib import l10n_utils
from commonware.decorators import xframe_allow
from funfactory.urlresolvers import reverse
from lib.l10n_utils.dotlang import _, lang_file_is_active
from bedrock.firefox import version_re
from bedrock.firefox.utils import is_current_or_newer
from bedrock.mozorg import email_contribute
from bedrock.mozorg.credits import CreditsFile
from bedrock.mozorg.decorators import cache_control_expires
from bedrock.mozorg.forms import (ContributeForm,
ContributeStudentAmbassadorForm,
WebToLeadForm)
from bedrock.mozorg.forums import ForumsFile
from bedrock.mozorg.models import TwitterCache
from bedrock.mozorg.util import hide_contrib_form
from bedrock.mozorg.util import HttpResponseJSON
from bedrock.newsletter.forms import NewsletterFooterForm
credits_file = CreditsFile('credits')
forums_file = ForumsFile('forums')
def csrf_failure(request, reason=''):
template_vars = {'reason': reason}
return l10n_utils.render(request, 'mozorg/csrf-failure.html', template_vars,
status=403)
@xframe_allow
def hacks_newsletter(request):
return l10n_utils.render(request,
'mozorg/newsletter/hacks.mozilla.org.html')
@csrf_exempt
def contribute(request, template, return_to_form):
newsletter_id = 'about-mozilla'
has_contribute_form = (request.method == 'POST' and
'contribute-form' in request.POST)
has_newsletter_form = (request.method == 'POST' and
'newsletter-form' in request.POST)
locale = getattr(request, 'locale', 'en-US')
contribute_success = False
newsletter_success = False
# This is ugly, but we need to handle two forms. I would love if
# these forms could post to separate pages and get redirected
# back, but we're forced to keep the error/success workflow on the
# same page. Please change this.
if has_contribute_form:
form = ContributeForm(request.POST)
if (form.is_valid()):
data = form.cleaned_data.copy()
honeypot = data.pop('office_fax')
if not honeypot:
contribute_success = email_contribute.handle_form(request, form)
if contribute_success:
# If form was submitted successfully, return a new, empty
# one.
form = ContributeForm()
else:
# send back a clean form if honeypot was filled in
form = ContributeForm()
else:
form = ContributeForm()
if has_newsletter_form:
newsletter_form = NewsletterFooterForm(newsletter_id, locale,
request.POST,
prefix='newsletter')
if newsletter_form.is_valid():
data = newsletter_form.cleaned_data
try:
basket.subscribe(data['email'],
newsletter_id,
format=data['fmt'],
country=data['country'])
newsletter_success = True
except basket.BasketException:
msg = newsletter_form.error_class(
[_('We apologize, but an error occurred in our system. '
'Please try again later.')]
)
newsletter_form.errors['__all__'] = msg
else:
newsletter_form = NewsletterFooterForm(newsletter_id, locale, prefix='newsletter')
return l10n_utils.render(request,
template,
{'form': form,
'contribute_success': contribute_success,
'newsletter_form': newsletter_form,
'newsletter_success': newsletter_success,
'return_to_form': return_to_form,
'hide_form': hide_contrib_form(request.locale)})
@xframe_allow
@csrf_exempt
def contribute_embed(request, template, return_to_form):
"""The same as contribute but allows frame embedding."""
return contribute(request, template, return_to_form)
def process_partnership_form(request, template, success_url_name, template_vars=None, form_kwargs=None):
template_vars = template_vars or {}
form_kwargs = form_kwargs or {}
if request.method == 'POST':
form = WebToLeadForm(data=request.POST, **form_kwargs)
msg = 'Form invalid'
stat = 400
success = False
if form.is_valid():
data = form.cleaned_data.copy()
honeypot = data.pop('office_fax')
if honeypot:
msg = 'Visitor invalid'
stat = 400
else:
interest = data.pop('interest')
data['00NU0000002pDJr'] = interest
data['oid'] = '00DU0000000IrgO'
data['lead_source'] = form_kwargs.get('lead_source', 'www.mozilla.org/about/partnerships/')
# As we're doing the Salesforce POST in the background here,
# `retURL` is never visited/seen by the user. I believe it
# is required by Salesforce though, so it should hang around
# as a placeholder (with a valid URL, just in case).
data['retURL'] = ('http://www.mozilla.org/en-US/about/'
'partnerships?success=1')
r = requests.post('https://www.salesforce.com/servlet/'
'servlet.WebToLead?encoding=UTF-8', data)
msg = requests.status_codes._codes.get(r.status_code, ['error'])[0]
stat = r.status_code
success = True
if request.is_ajax():
return HttpResponseJSON({'msg': msg, 'errors': form.errors}, status=stat)
# non-AJAX POST
else:
# if form is not valid, render template to retain form data/error messages
if not success:
template_vars.update(csrf(request))
template_vars['form'] = form
template_vars['form_success'] = success
return l10n_utils.render(request, template, template_vars)
# if form is valid, redirect to avoid refresh double post possibility
else:
return HttpResponseRedirect("%s?success" % (reverse(success_url_name)))
# no form POST - build form, add CSRF, & render template
else:
# without auto_id set, all id's get prefixed with 'id_'
form = WebToLeadForm(auto_id='%s', **form_kwargs)
template_vars.update(csrf(request))
template_vars['form'] = form
template_vars['form_success'] = True if ('success' in request.GET) else False
return l10n_utils.render(request, template, template_vars)
@csrf_protect
def partnerships(request):
return process_partnership_form(request, 'mozorg/partnerships.html', 'mozorg.partnerships')
def plugincheck(request, template='mozorg/plugincheck.html'):
"""
Determine whether the current UA is the latest Firefox,
passes the result to the template and renders the
specified template.
"""
user_agent = request.META.get('HTTP_USER_AGENT', '')
user_version = "0"
ua_regexp = r"Firefox/(%s)" % version_re
match = re.search(ua_regexp, user_agent)
if match:
user_version = match.group(1)
data = {
'is_latest': is_current_or_newer(user_version)
}
return l10n_utils.render(request, template, data)
@xframe_allow
def contribute_studentambassadors_landing(request):
try:
tweets = TwitterCache.objects.get(account='mozstudents').tweets
except (TwitterCache.DoesNotExist, DatabaseError):
tweets = []
return l10n_utils.render(request,
'mozorg/contribute/studentambassadors/landing.html',
{'tweets': tweets})
@csrf_protect
def contribute_studentambassadors_join(request):
form = ContributeStudentAmbassadorForm(request.POST or None)
if form.is_valid():
try:
form.save()
except basket.BasketException:
msg = form.error_class(
[_('We apologize, but an error occurred in our system. '
'Please try again later.')])
form.errors['__all__'] = msg
else:
return redirect('mozorg.contribute.studentambassadors.thanks')
return l10n_utils.render(
request,
'mozorg/contribute/studentambassadors/join.html', {'form': form}
)
def holiday_calendars(request, template='mozorg/projects/holiday-calendars.html'):
"""Generate the table of holiday calendars from JSON."""
calendars = []
json_file = settings.MEDIA_ROOT + '/caldata/calendars.json'
with open(json_file) as calendar_data:
calendars = json.load(calendar_data)
letters = set()
for calendar in calendars:
letters.add(calendar['country'][:1])
data = {
'calendars': sorted(calendars, key=lambda k: k['country']),
'letters': sorted(letters),
'CALDATA_URL': settings.MEDIA_URL + 'caldata/'
}
return l10n_utils.render(request, template, data)
@cache_control_expires(2)
@last_modified(credits_file.last_modified_callback)
@require_safe
def credits_view(request):
"""Display the names of our contributors."""
ctx = {'credits': credits_file}
# not translated
return django_render(request, 'mozorg/credits.html', ctx)
@cache_control_expires(2)
@last_modified(forums_file.last_modified_callback)
@require_safe
def forums_view(request):
"""Display our mailing lists and newsgroups."""
ctx = {'forums': forums_file}
return l10n_utils.render(request, 'mozorg/about/forums/forums.html', ctx)
class Robots(TemplateView):
template_name = 'mozorg/robots.txt'
def render_to_response(self, context, **response_kwargs):
response_kwargs['content_type'] = 'text/plain'
return super(Robots, self).render_to_response(
context, **response_kwargs)
def get_context_data(self, **kwargs):
SITE_URL = getattr(settings, 'SITE_URL', '')
return {'disallow_all': not SITE_URL.endswith('://www.mozilla.org')}
class HomeTestView(TemplateView):
"""Home page view that will use a different template for a QS."""
template_name = 'mozorg/home.html'
def post(self, request, *args, **kwargs):
# required for newsletter form post that is handled in newsletter/helpers.py
return self.get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
ctx = super(HomeTestView, self).get_context_data(**kwargs)
ctx['has_contribute'] = lang_file_is_active('mozorg/contribute')
locale = l10n_utils.get_locale(self.request)
locale = locale if locale in settings.MOBILIZER_LOCALE_LINK else 'en-US'
ctx['mobilizer_link'] = settings.MOBILIZER_LOCALE_LINK[locale]
return ctx
def render_to_response(self, context, **response_kwargs):
return l10n_utils.render(self.request,
self.get_template_names(),
context,
**response_kwargs)