Implement Unflag feature on the Package Details page
[aur2.git] / archlinux / aur / views.py
blobea7b57733263adee6e12f2faabb7ef0fd109df8a
1 from re import sub
2 import os
3 import sys
4 import tarfile
5 import hashlib
7 from django.shortcuts import render_to_response, get_object_or_404
8 from django.http import HttpResponse, HttpResponseRedirect
9 from django import forms
10 from django.core.paginator import Paginator, EmptyPage, InvalidPage
11 from django.contrib.auth.decorators import login_required
12 from django.core.urlresolvers import reverse
13 from django.core import serializers
14 from django.utils.translation import ugettext
16 from aur.models import *
17 from aur.forms import PackageSearchForm, PackageSubmitForm
19 # Helper functions for permissions
20 # This should perhaps be elsewhere. In the future Django may support
21 # permissions per object instance.
22 def _user_can_modify_package(user, package):
23 """Returns whether a user has permissions to modify a specific package
24 *user* should be a :class:`User`
25 *package* should be a :class:`Package` object or a package name
26 """
27 if not isinstance(package, Package):
28 package = Package.objects.get(name=package)
29 return _user_is_maintainer(user, package) or user.has_perm('package.can_change_package')
31 def _user_can_delete_package(user, package):
32 """Returns whether a user has permissions to delete a specific package
33 *user* should be a :class:`User`
34 *package* should be a :class:`Package` object or a package name
35 """
36 return user.has_perm('package.can_delete_package')
38 def _user_is_maintainer(user, package):
39 """Returns whether a user is a maintainer of a specific package
40 *user* should be a :class:`User`
41 *package* should be a :class:`Package` object or a package name
42 """
43 if not isinstance(package, Package):
44 package = Package.objects.get(name=package)
45 return package.maintainers.filter(username=user.username).count() > 0
47 def _user_is_moderator(user):
48 """Returns whether a user is a package moderator
49 *user* should be a :class:`User`
50 """
51 return user.has_perms((
52 'package.can_add_package',
53 'package.can_delete_package',
54 'package.can_change_package',
57 def search(request, query = ''):
58 if request.method == 'GET' and request.GET.has_key('query'):
59 form = PackageSearchForm(request.GET)
60 # If there are any errors in the forum, render the template and exit
61 if not form.is_valid():
62 return render_to_response('aur/search.html', {
63 'form': form,
64 'user': request.user,
65 'is_moderator': _user_is_moderator(request.user),
67 else:
68 form = PackageSearchForm()
69 # Execute the search
70 results = form.search()
71 # Get sorting variables from query string or fallback on defaults
72 if request.GET.has_key('sortby'):
73 sortby = request.GET['sortby']
74 if sortby == 'maintainer':
75 sortby = 'name'
76 else:
77 sortby = 'name'
78 if request.GET.has_key('order') and request.GET['order'] == 'desc':
79 sortby = "".join(('-', sortby))
80 # Sort the results
81 results = results.order_by(sortby, 'repository', 'name')
82 # If we only got one hit, just go to the package's detail page
83 if form.is_bound and results.count() == 1:
84 return HttpResponseRedirect(reverse('aur-package_detail',
85 args=[results[0].name,]))
86 # Initialise the pagination
87 paginator = Paginator(results, int(form.get_or_default('limit')))
88 # Use last page if page number is out of range
89 try:
90 page = paginator.page(int(request.GET.get('page', '1')))
91 except (EmptyPage, InvalidPage):
92 page = paginator.page(paginator.num_pages)
94 return render_to_response('aur/search.html', {
95 'form': form,
96 'packages': page.object_list,
97 'page': page,
98 'user': request.user,
99 'request': request,
100 'is_moderator': _user_is_moderator(request.user),
103 @login_required
104 def submit(request):
105 if request.method == 'POST':
106 form = PackageSubmitForm(request.POST, request.FILES)
107 if form.is_valid():
108 form.save(request.user)
109 return HttpResponseRedirect(reverse('aur-package_detail',
110 args=[form.cleaned_data['package']['name'],]))
111 else:
112 form = PackageSubmitForm()
113 return render_to_response('aur/submit.html', {
114 'user': request.user,
115 'form': form,
118 def comment(request, object_id):
119 if request.POST and 'message' in request.POST:
120 package = get_object_or_404(Package, name=object_id)
121 comment = Comment(package=package, user=request.user,
122 message=request.POST['message'],
123 ip=request.META['REMOTE_ADDR'])
124 if 'reply_to' in request.POST:
125 comment.parent=request.POST['reply_to']
126 comment.save()
127 return HttpResponseRedirect(package.get_absolute_url())
128 elif 'reply_to' in request.POST:
129 return render_to_response('aur/comment_form.html', {
130 'user': request.user,
131 'package_id': object_id,
132 'reply_to': request.POST['reply_to'],
134 else:
135 return HttpResponseRedirect(
136 reverse('aur-package_detail', args=[object_id,]))
138 def flag_out_of_date(request, object_id):
139 package = get_object_or_404(Package, name=object_id)
140 package.outdated = True
141 package.save()
142 return HttpResponseRedirect(package.get_absolute_url())
144 def unflag_out_of_date(request, object_id):
145 package = get_object_or_404(Package, name=object_id)
146 package.outdated = False
147 package.save()
148 return HttpResponseRedirect(package.get_absolute_url())
150 @login_required
151 def notify_of_updates(request, object_id):
152 """Subscribe a user to package updates"""
153 package = get_object_or_404(Package, name=object_id)
154 PackageNotification(package=package, user=request.user).save()
155 return HttpResponseRedirect(package.get_absolute_url())
157 @login_required
158 def denotify_of_updates(request, object_id):
159 """Unsubscribe a user from package updates"""
160 PackageNotification.objects.get(package__name=object_id, user=request.user).delete()
161 return HttpResponseRedirect(reverse('aur-package_detail',
162 args=[object_id,]))
164 def api_search(request, query, format):
165 results = Package.objects.filter(name__icontains=query)
166 data = serializers.serialize(format, results,
167 fields=(
168 'name',
169 'version',
170 'respository__name',
171 'description'
174 return HttpResponse(data, mimetype="application/%s" % format)
176 @login_required
177 def manage_packages(request):
178 if request.method != 'POST':
179 return HttpResponseRedirect(reverse('aur-search'))
180 packages = request.POST.getlist('packages')
181 if request.POST['action'] == 'unflag-ood':
182 for package_name in packages:
183 package = Package.objects.get(name=package_name)
184 if _user_can_modify_package(request.user, package):
185 package.outdated = False
186 package.save()
187 else:
188 return render_to_response('aur/error.html', dict(
189 heading = ugettext("Permission denied"),
190 error = "You are not allowed to edit %s" % package_name,
192 elif request.POST['action'] == 'flag-ood':
193 for package_name in packages:
194 package = Package.objects.get(name=package_name)
195 if _user_can_modify_package(request.user, package):
196 package.outdated = True
197 package.save()
198 else:
199 return render_to_response('aur/error.html', dict(
200 heading = ugettext("Permission denied"),
201 error = "You are not allowed to edit %s" % package_name,
203 elif request.POST['action'] == 'disown':
204 for package_name in packages:
205 package = Package.objects.get(name=package_name)
206 if _user_can_modify_package(request.user, package):
207 package.maintainers.clear()
208 else:
209 return render_to_response('aur/error.html', dict(
210 heading = ugettext("Permission denied"),
211 error = "You cannot disown %s" % package_name,
213 elif request.POST['action'] == 'adopt':
214 for package_name in packages:
215 package = Package.objects.get(name=package_name)
216 if package.maintainers.count() == 0:
217 package.maintainers.add(request.user)
218 elif _user_is_moderator(request.user):
219 package.maintainers.add(request.user)
220 else:
221 return render_to_response('aur/error.html', dict(
222 heading = ugettext("Permission denied"),
223 error = "You cannot adopt %s" % package_name,
225 elif request.POST['action'] == 'delete':
226 for package_name in packages:
227 package = Package.objects.get(name=package_name)
228 if _user_can_delete_package(request.user, package):
229 package.delete()
230 else:
231 return render_to_response('aur/error.html', dict(
232 heading = ugettext("Permission denied"),
233 error = "You are not allowed to delete %s" % package_name,
235 return HttpResponseRedirect(request.META['HTTP_REFERER'])
237 def api_package_info(request, object_id, format):
238 package = get_object_or_404(Package, name=object_id)
239 data = serializers.serialize(format, [package,])
240 return HttpResponse(data, mimetype="application/%s" % format)
242 def api_package_comments(request, object_id):
243 comments = Comment.objects.filter(package=object_id)
244 data = serializers.serialize('json', comments)
245 return HttpResponse(data, mimetype="application/%s" % format)