remove unused AUTH_PROFILE_MODULE setting
[mygpo.git] / mygpo / web / views / device.py
blobfd5052699024b49bc392e1dd363cd1c96a70c0a4
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 functools import wraps
19 from xml.parsers.expat import ExpatError
21 from django.shortcuts import render
22 from django.core.urlresolvers import reverse
23 from django.http import HttpResponseRedirect, HttpResponseBadRequest, \
24 HttpResponseNotFound
25 from django.contrib import messages
26 from mygpo.web.forms import DeviceForm, SyncForm
27 from mygpo.web.utils import symbian_opml_changes
28 from django.utils.translation import ugettext as _
29 from django.contrib.auth.decorators import login_required
30 from django.views.decorators.vary import vary_on_cookie
31 from django.views.decorators.cache import never_cache, cache_control
33 from restkit.errors import Unauthorized
35 from mygpo.api import simple
36 from mygpo.decorators import allowed_methods, repeat_on_conflict
37 from mygpo.users.models import Device, DeviceUIDException, \
38 DeviceDoesNotExist
39 from mygpo.users.tasks import sync_user, set_device_task_state
40 from mygpo.db.couchdb.podcast_state import podcast_states_for_device
41 from mygpo.db.couchdb.user import set_device_deleted, unsync_device
44 @vary_on_cookie
45 @cache_control(private=True)
46 @login_required
47 def overview(request):
49 device_groups = request.user.get_grouped_devices()
50 deleted_devices = request.user.inactive_devices
52 return render(request, 'devicelist.html', {
53 'device_groups': device_groups,
54 'deleted_devices': deleted_devices,
59 def device_decorator(f):
60 @login_required
61 @vary_on_cookie
62 @cache_control(private=True)
63 @wraps(f)
64 def _decorator(request, uid, *args, **kwargs):
66 try:
67 device = request.user.get_device_by_uid(uid, only_active=False)
69 except DeviceDoesNotExist as e:
70 return HttpResponseNotFound(str(e))
72 return f(request, device, *args, **kwargs)
74 return _decorator
78 @login_required
79 @device_decorator
80 def show(request, device):
82 request.user.sync_group(device)
84 subscriptions = list(device.get_subscribed_podcasts())
85 synced_with = request.user.get_synced(device)
87 sync_targets = list(request.user.get_sync_targets(device))
88 sync_form = SyncForm()
89 sync_form.set_targets(sync_targets,
90 _('Synchronize with the following devices'))
92 return render(request, 'device.html', {
93 'device': device,
94 'sync_form': sync_form,
95 'subscriptions': subscriptions,
96 'synced_with': synced_with,
97 'has_sync_targets': len(sync_targets) > 0,
101 @login_required
102 @never_cache
103 @allowed_methods(['POST'])
104 def create(request):
105 device_form = DeviceForm(request.POST)
107 if not device_form.is_valid():
109 messages.error(request, _('Please fill out all fields.'))
111 return HttpResponseRedirect(reverse('device-edit-new'))
114 device = Device()
115 device.name = device_form.cleaned_data['name']
116 device.type = device_form.cleaned_data['type']
117 device.uid = device_form.cleaned_data['uid'].replace(' ', '-')
118 try:
119 request.user.set_device(device)
120 request.user.save()
121 messages.success(request, _('Device saved'))
123 except DeviceUIDException as e:
124 messages.error(request, _(unicode(e)))
126 return render(request, 'device-create.html', {
127 'device': device,
128 'device_form': device_form,
131 except Unauthorized:
132 messages.error(request, _("You can't use the same Device "
133 "ID for two devices."))
135 return render(request, 'device-create.html', {
136 'device': device,
137 'device_form': device_form,
141 return HttpResponseRedirect(reverse('device-edit', args=[device.uid]))
145 @device_decorator
146 @login_required
147 @allowed_methods(['POST'])
148 def update(request, device):
149 device_form = DeviceForm(request.POST)
151 uid = device.uid
153 if device_form.is_valid():
155 device.name = device_form.cleaned_data['name']
156 device.type = device_form.cleaned_data['type']
157 device.uid = device_form.cleaned_data['uid'].replace(' ', '-')
158 try:
159 request.user.update_device(device)
160 messages.success(request, _('Device updated'))
161 uid = device.uid # accept the new UID after rest has succeeded
163 except DeviceUIDException as e:
164 messages.error(request, _(str(e)))
166 except Unauthorized as u:
167 messages.error(request, _("You can't use the same Device "
168 "ID for two devices."))
170 return HttpResponseRedirect(reverse('device-edit', args=[uid]))
173 @login_required
174 @vary_on_cookie
175 @cache_control(private=True)
176 @allowed_methods(['GET'])
177 def edit_new(request):
179 device = Device()
181 device_form = DeviceForm({
182 'name': device.name,
183 'type': device.type,
184 'uid': device.uid
187 return render(request, 'device-create.html', {
188 'device': device,
189 'device_form': device_form,
195 @device_decorator
196 @login_required
197 @allowed_methods(['GET'])
198 def edit(request, device):
200 device_form = DeviceForm({
201 'name': device.name,
202 'type': device.type,
203 'uid': device.uid
206 synced_with = request.user.get_synced(device)
208 sync_targets = list(request.user.get_sync_targets(device))
209 sync_form = SyncForm()
210 sync_form.set_targets(sync_targets,
211 _('Synchronize with the following devices'))
213 return render(request, 'device-edit.html', {
214 'device': device,
215 'device_form': device_form,
216 'sync_form': sync_form,
217 'synced_with': synced_with,
218 'has_sync_targets': len(sync_targets) > 0,
222 @device_decorator
223 @login_required
224 def upload_opml(request, device):
226 if not 'opml' in request.FILES:
227 return HttpResponseRedirect(reverse('device-edit', args=[device.uid]))
229 opml = request.FILES['opml'].read()
231 try:
232 subscriptions = simple.parse_subscription(opml, 'opml')
233 simple.set_subscriptions(subscriptions, request.user, device.uid, None)
235 except ExpatError as ee:
236 msg = _('Could not upload subscriptions: {err}').format(err=str(ee))
237 messages.error(request, msg)
238 return HttpResponseRedirect(reverse('device-edit', args=[device.uid]))
240 return HttpResponseRedirect(reverse('device', args=[device.uid]))
243 @device_decorator
244 @login_required
245 def opml(request, device):
246 response = simple.format_podcast_list(simple.get_subscriptions(request.user, device.uid), 'opml', request.user.username)
247 response['Content-Disposition'] = 'attachment; filename=%s.opml' % device.uid
248 return response
251 @device_decorator
252 @login_required
253 def symbian_opml(request, device):
254 subscriptions = simple.get_subscriptions(request.user, device.uid)
255 subscriptions = map(symbian_opml_changes, subscriptions)
257 response = simple.format_podcast_list(subscriptions, 'opml', request.user.username)
258 response['Content-Disposition'] = 'attachment; filename=%s.opml' % device.uid
259 return response
262 @device_decorator
263 @login_required
264 @allowed_methods(['POST'])
265 def delete(request, device):
266 user = request.user
267 unsync_device(user, device)
268 set_device_deleted(user, device, True)
269 set_device_task_state.delay(user)
270 return HttpResponseRedirect(reverse('devices'))
273 @login_required
274 @device_decorator
275 def delete_permanently(request, device):
277 @repeat_on_conflict(['state'])
278 def remove_device(state, dev):
279 state.remove_device(dev)
280 state.save()
282 states = podcast_states_for_device(device.id)
283 for state in states:
284 remove_device(state=state, dev=device)
286 @repeat_on_conflict(['user'])
287 def _remove(user, device):
288 user.remove_device(device)
289 user.save()
291 _remove(user=request.user, device=device)
293 return HttpResponseRedirect(reverse('devices'))
295 @device_decorator
296 @login_required
297 def undelete(request, device):
298 user = request.user
299 set_device_deleted(user, device, False)
300 set_device_task_state.delay(user)
301 return HttpResponseRedirect(reverse('device', args=[device.uid]))
304 @device_decorator
305 @login_required
306 @allowed_methods(['POST'])
307 def sync(request, device):
309 form = SyncForm(request.POST)
310 if not form.is_valid():
311 return HttpResponseBadRequest('invalid')
314 @repeat_on_conflict(['user'])
315 def do_sync(user, device, sync_target):
316 user.sync_devices(device, sync_target)
317 user.save()
320 try:
321 target_uid = form.get_target()
322 sync_target = request.user.get_device_by_uid(target_uid)
323 do_sync(user=request.user, device=device, sync_target=sync_target)
325 except DeviceDoesNotExist as e:
326 messages.error(request, str(e))
328 sync_user.delay(request.user)
330 return HttpResponseRedirect(reverse('device', args=[device.uid]))
333 @device_decorator
334 @login_required
335 @allowed_methods(['GET'])
336 def unsync(request, device):
338 @repeat_on_conflict(['user'])
339 def do_unsync(user, device):
340 user.unsync_device(device)
341 user.save()
343 try:
344 do_unsync(user=request.user, device=device)
346 except ValueError, e:
347 messages.error(request, 'Could not unsync the device: {err}'.format(
348 err=str(e)))
350 return HttpResponseRedirect(reverse('device', args=[device.uid]))
353 from mygpo.web import views
354 history = views.history