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 django_couchdb_utils
.auth
.models
import UsernameException
, \
36 from mygpo
.decorators
import allowed_methods
, repeat_on_conflict
37 from mygpo
.web
.forms
import UserAccountForm
, ProfileForm
, FlattrForm
38 from mygpo
.web
.utils
import normalize_twitter
39 from mygpo
.flattr
import Flattr
40 from mygpo
.users
.settings
import PUBLIC_SUB_PODCAST
, PUBLIC_SUB_USER
, \
41 FLATTR_TOKEN
, FLATTR_AUTO
42 from mygpo
.db
.couchdb
.podcast
import podcast_by_id
, podcasts_to_dict
43 from mygpo
.db
.couchdb
.podcast_state
import podcast_state_for_user_podcast
, \
45 from mygpo
.db
.couchdb
.user
import update_flattr_settings
50 @cache_control(private
=True)
51 @allowed_methods(['GET', 'POST'])
54 if request
.method
== 'GET':
56 site
= RequestSite(request
)
57 flattr
= Flattr(request
.user
, site
.domain
)
58 userpage_token
= request
.user
.get_token('userpage_token')
60 profile_form
= ProfileForm({
61 'twitter': request
.user
.twitter
,
62 'about': request
.user
.about
,
65 form
= UserAccountForm({
66 'email': request
.user
.email
,
67 'public': request
.user
.get_wksetting(PUBLIC_SUB_USER
)
70 flattr_form
= FlattrForm({
71 'enable': request
.user
.get_wksetting(FLATTR_AUTO
),
72 'token': request
.user
.get_wksetting(FLATTR_TOKEN
),
75 return render(request
, 'account.html', {
77 'profile_form': profile_form
,
78 'flattr_form': flattr_form
,
80 'userpage_token': userpage_token
,
84 form
= UserAccountForm(request
.POST
)
86 if not form
.is_valid():
87 raise ValueError(_('Oops! Something went wrong. Please double-check the data you entered.'))
89 if form
.cleaned_data
['password_current']:
90 if not request
.user
.check_password(form
.cleaned_data
['password_current']):
91 raise ValueError('Current password is incorrect')
93 request
.user
.set_password(form
.cleaned_data
['password1'])
95 request
.user
.email
= form
.cleaned_data
['email']
99 except (UsernameException
, PasswordException
) as ex
:
100 messages
.error(request
, str(ex
))
102 messages
.success(request
, 'Account updated')
104 except (ValueError, ValidationError
) as e
:
105 messages
.error(request
, str(e
))
107 return render(request
, 'account.html', {
112 class ProfileView(View
):
113 """ Updates the public profile and redirects back to the account view """
115 def post(self
, request
):
118 form
= ProfileForm(request
.POST
)
120 if not form
.is_valid():
121 raise ValueError(_('Oops! Something went wrong. Please double-check the data you entered.'))
123 request
.user
.twitter
= normalize_twitter(form
.cleaned_data
['twitter'])
124 request
.user
.about
= strip_tags(form
.cleaned_data
['about'])
127 messages
.success(request
, _('Data updated'))
129 return HttpResponseRedirect(reverse('account'))
132 class FlattrSettingsView(View
):
133 """ Updates Flattr settings and redirects back to the Account page """
135 def post(self
, request
):
138 form
= FlattrForm(request
.POST
)
140 if not form
.is_valid():
141 raise ValueError('asdf')
143 auto_flattr
= form
.cleaned_data
.get('enable', False)
144 update_flattr_settings(user
, None, auto_flattr
)
146 return HttpResponseRedirect(reverse('account'))
149 class FlattrTokenView(View
):
150 """ Callback for the Flattr authentication
152 Updates the user's Flattr token and redirects back to the account page """
154 def get(self
, request
):
157 site
= RequestSite(request
)
158 flattr
= Flattr(user
, site
.domain
)
160 url
= request
.build_absolute_uri()
161 token
= flattr
.process_retrieved_code(url
)
163 messages
.success(request
, _('Authentication successful'))
164 update_flattr_settings(user
, token
)
167 messages
.error(request
, _('Authentication failed. Try again later'))
169 return HttpResponseRedirect(reverse('account'))
175 @allowed_methods(['GET', 'POST'])
176 def delete_account(request
):
178 if request
.method
== 'GET':
179 return render(request
, 'delete_account.html')
181 @repeat_on_conflict(['user'])
183 user
.is_active
= False
187 do_delete(user
=request
.user
)
190 return render(request
, 'deleted_account.html')
194 class DefaultPrivacySettings(View
):
198 @method_decorator(login_required
)
199 @method_decorator(never_cache
)
200 def post(self
, request
):
201 self
.set_privacy_settings(user
=request
.user
)
202 messages
.success(request
, 'Success')
203 return HttpResponseRedirect(reverse('privacy'))
205 @repeat_on_conflict(['user'])
206 def set_privacy_settings(self
, user
):
207 user
.settings
[PUBLIC_SUB_USER
.name
] = self
.public
211 class PodcastPrivacySettings(View
):
215 @method_decorator(login_required
)
216 @method_decorator(never_cache
)
217 def post(self
, request
, podcast_id
):
218 podcast
= podcast_by_id(podcast_id
)
219 state
= podcast_state_for_user_podcast(request
.user
, podcast
)
220 self
.set_privacy_settings(state
=state
)
221 messages
.success(request
, 'Success')
222 return HttpResponseRedirect(reverse('privacy'))
224 @repeat_on_conflict(['state'])
225 def set_privacy_settings(self
, state
):
226 state
.settings
[PUBLIC_SUB_PODCAST
.name
] = self
.public
233 def privacy(request
):
234 site
= RequestSite(request
)
236 subscriptions
= subscriptions_by_user(request
.user
)
237 podcasts
= podcasts_to_dict([x
[1] for x
in subscriptions
])
239 included_subscriptions
= set(filter(None, [podcasts
.get(x
[1], None) for x
in subscriptions
if x
[0] == True]))
240 excluded_subscriptions
= set(filter(None, [podcasts
.get(x
[1], None) for x
in subscriptions
if x
[0] == False]))
242 return render(request
, 'privacy.html', {
243 'public_subscriptions': request
.user
.get_wksetting(PUBLIC_SUB_USER
),
244 'included_subscriptions': included_subscriptions
,
245 'excluded_subscriptions': excluded_subscriptions
,
246 'domain': site
.domain
,
251 @cache_control(private
=True)
254 site
= RequestSite(request
)
256 if 'public_subscriptions' in request
.GET
:
257 @repeat_on_conflict(['user'])
259 user
.subscriptions_token
= ''
262 elif 'private_subscriptions' in request
.GET
:
263 @repeat_on_conflict(['user'])
265 user
.create_new_token('subscriptions_token')
272 _update(user
=request
.user
)
274 token
= request
.user
.get_token('subscriptions_token')
276 return render(request
, 'share.html', {