[UserSettings] refactor, add tests
[mygpo.git] / mygpo / web / views / settings.py
blob920d99ec88b5a00a76b82a4c10ed56e38e3a14d7
2 # This file is part of my.gpodder.org.
4 # my.gpodder.org is free software: you can redistribute it and/or modify it
5 # under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or (at your
7 # option) any later version.
9 # my.gpodder.org is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
12 # License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with my.gpodder.org. If not, see <http://www.gnu.org/licenses/>.
18 from django.shortcuts import render
19 from django.core.urlresolvers import reverse
20 from django.http import HttpResponseRedirect
21 from django.contrib.auth import logout
22 from django.contrib import messages
23 from django.forms import ValidationError
24 from django.utils.translation import ugettext as _
25 from django.contrib.auth.decorators import login_required
26 from django.contrib.sites.models import RequestSite
27 from django.views.decorators.vary import vary_on_cookie
28 from django.views.decorators.cache import never_cache, cache_control
29 from django.utils.decorators import method_decorator
30 from django.views.generic.base import View
31 from django.utils.html import strip_tags
33 from mygpo.podcasts.models import Podcast
34 from mygpo.usersettings.models import UserSettings
35 from mygpo.decorators import allowed_methods
36 from mygpo.web.forms import UserAccountForm, ProfileForm, FlattrForm
37 from mygpo.web.utils import normalize_twitter
38 from mygpo.flattr import Flattr
39 from mygpo.users.settings import PUBLIC_SUB_USER, PUBLIC_SUB_PODCAST, \
40 FLATTR_TOKEN, FLATTR_AUTO, FLATTR_MYGPO, FLATTR_USERNAME
43 @login_required
44 @vary_on_cookie
45 @cache_control(private=True)
46 @allowed_methods(['GET', 'POST'])
47 def account(request):
49 if request.method == 'GET':
51 site = RequestSite(request)
52 flattr = Flattr(request.user, site.domain, request.is_secure())
53 userpage_token = request.user.profile.get_token('userpage_token')
55 profile_form = ProfileForm({
56 'twitter': request.user.profile.twitter,
57 'about': request.user.profile.about,
60 form = UserAccountForm({
61 'email': request.user.email,
62 'public': request.user.profile.settings.get_wksetting(PUBLIC_SUB_USER)
65 flattr_form = FlattrForm({
66 'enable': request.user.profile.settings.get_wksetting(FLATTR_AUTO),
67 'token': request.user.profile.settings.get_wksetting(FLATTR_TOKEN),
68 'flattr_mygpo': request.user.profile.settings.get_wksetting(FLATTR_MYGPO),
69 'username': request.user.profile.settings.get_wksetting(FLATTR_USERNAME),
72 return render(request, 'account.html', {
73 'site': site,
74 'form': form,
75 'profile_form': profile_form,
76 'flattr_form': flattr_form,
77 'flattr': flattr,
78 'userpage_token': userpage_token,
81 try:
82 form = UserAccountForm(request.POST)
84 if not form.is_valid():
85 raise ValueError(_('Oops! Something went wrong. Please double-check the data you entered.'))
87 if form.cleaned_data['password_current']:
88 if not request.user.check_password(form.cleaned_data['password_current']):
89 raise ValueError('Current password is incorrect')
91 request.user.set_password(form.cleaned_data['password1'])
93 request.user.email = form.cleaned_data['email']
95 try:
96 request.user.save()
97 except Exception as ex:
98 # TODO: which exception?
99 messages.error(request, str(ex))
101 messages.success(request, 'Account updated')
103 except (ValueError, ValidationError) as e:
104 messages.error(request, str(e))
106 return render(request, 'account.html', {
107 'form': form,
111 class ProfileView(View):
112 """ Updates the public profile and redirects back to the account view """
114 def post(self, request):
115 user = request.user
117 form = ProfileForm(request.POST)
119 if not form.is_valid():
120 raise ValueError(_('Oops! Something went wrong. Please double-check the data you entered.'))
122 request.user.twitter = normalize_twitter(form.cleaned_data['twitter'])
123 request.user.about = strip_tags(form.cleaned_data['about'])
125 request.user.save()
126 messages.success(request, _('Data updated'))
128 return HttpResponseRedirect(reverse('account') + '#profile')
131 class FlattrSettingsView(View):
132 """ Updates Flattr settings and redirects back to the Account page """
134 def post(self, request):
135 user = request.user
137 form = FlattrForm(request.POST)
139 if not form.is_valid():
140 raise ValueError('asdf')
142 auto_flattr = form.cleaned_data.get('enable', False)
143 flattr_mygpo = form.cleaned_data.get('flattr_mygpo', False)
144 username = form.cleaned_data.get('username', '')
146 settings = user.profile.settings
147 settings.set_wksetting(FLATTR_AUTO, auto_flattr)
148 settings.set_wksetting(FLATTR_MYGPO, flattr_mygpo)
149 settings.set_wksetting(FLATTR_USERNAME, username)
150 settings.save()
152 return HttpResponseRedirect(reverse('account') + '#flattr')
155 class FlattrLogout(View):
156 """ Removes Flattr authentication token """
158 def get(self, request):
159 user = request.user
160 settings = user.profile.settings
161 settings.set_wksetting(FLATTR_AUTO, False)
162 settings.set_wksetting(FLATTR_TOKEN, False)
163 settings.set_wksetting(FLATTR_MYGPO, False)
164 settings.save()
165 return HttpResponseRedirect(reverse('account') + '#flattr')
168 class FlattrTokenView(View):
169 """ Callback for the Flattr authentication
171 Updates the user's Flattr token and redirects back to the account page """
173 def get(self, request):
175 user = request.user
176 site = RequestSite(request)
177 flattr = Flattr(user, site.domain, request.is_secure())
179 url = request.build_absolute_uri()
180 token = flattr.process_retrieved_code(url)
181 if token:
182 messages.success(request, _('Authentication successful'))
183 settings = user.profile.settings
184 settings.set_wksetting(FLATTR_TOKEN, token)
185 settings.save()
187 else:
188 messages.error(request, _('Authentication failed. Try again later'))
190 return HttpResponseRedirect(reverse('account') + '#flattr')
193 class AccountRemoveGoogle(View):
194 """ Removes the connected Google account """
196 @method_decorator(login_required)
197 def post(self, request):
198 request.user.google_email = None
199 request.user.save()
200 messages.success(request, _('Your account has been disconnected'))
201 return HttpResponseRedirect(reverse('account'))
204 @login_required
205 @never_cache
206 @allowed_methods(['GET', 'POST'])
207 def delete_account(request):
209 if request.method == 'GET':
210 return render(request, 'delete_account.html')
212 user.is_active = False
213 user.deleted = True
214 user.save()
215 logout(request)
216 return render(request, 'deleted_account.html')
220 class DefaultPrivacySettings(View):
222 public = True
224 @method_decorator(login_required)
225 @method_decorator(never_cache)
226 def post(self, request):
227 profile = request.user.profile
228 profile.set_setting(PUBLIC_SUB_USER.name, self.public)
229 profile.save()
230 return HttpResponseRedirect(reverse('privacy'))
233 class PodcastPrivacySettings(View):
235 public = True
237 @method_decorator(login_required)
238 @method_decorator(never_cache)
239 def post(self, request, podcast_id):
240 podcast = Podcast.objects.get(id=podcast_id)
242 settings, created = UserSettings.objects.get_or_create(
243 user=request.user,
244 content_type=ContentType.objects.get_for_model(podcast),
245 object_id=podcast.pk,
248 settings.set_wksetting(PUBLIC_SUB_PODCAST, self.public)
249 settings.save()
250 return HttpResponseRedirect(reverse('privacy'))
253 @login_required
254 @never_cache
255 def privacy(request):
256 site = RequestSite(request)
257 user = request.user
259 podcasts = Podcast.objects.filter(subscription__user=user)\
260 .distinct('pk')
261 private = UserSettings.objects.get_private_podcasts(user)
263 subscriptions = []
264 for podcast in podcasts:
266 subscriptions.append( (podcast, podcast in private) )
268 return render(request, 'privacy.html', {
269 'private_subscriptions': not request.user.profile.settings.get_wksetting(PUBLIC_SUB_USER),
270 'subscriptions': subscriptions,
271 'domain': site.domain,
275 @vary_on_cookie
276 @cache_control(private=True)
277 @login_required
278 def share(request):
279 site = RequestSite(request)
281 user = request.user
283 if 'public_subscriptions' in request.GET:
284 user.profile.subscriptions_token = ''
285 user.profile.save()
287 elif 'private_subscriptions' in request.GET:
288 user.profile.create_new_token('subscriptions_token')
289 user.profile.save()
291 token = user.profile.get_token('subscriptions_token')
293 return render(request, 'share.html', {
294 'site': site,
295 'token': token,