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
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
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
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`
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', {
65 'is_moderator': _user_is_moderator(request
.user
),
68 form
= PackageSearchForm()
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':
78 if request
.GET
.has_key('order') and request
.GET
['order'] == 'desc':
79 sortby
= "".join(('-', sortby
))
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
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', {
96 'packages': page
.object_list
,
100 'is_moderator': _user_is_moderator(request
.user
),
105 if request
.method
== 'POST':
106 form
= PackageSubmitForm(request
.POST
, request
.FILES
)
108 form
.save(request
.user
)
109 return HttpResponseRedirect(reverse('aur-package_detail',
110 args
=[form
.cleaned_data
['package']['name'],]))
112 form
= PackageSubmitForm()
113 return render_to_response('aur/submit.html', {
114 'user': request
.user
,
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']
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'],
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
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
148 return HttpResponseRedirect(package
.get_absolute_url())
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())
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',
164 def api_search(request
, query
, format
):
165 results
= Package
.objects
.filter(name__icontains
=query
)
166 data
= serializers
.serialize(format
, results
,
174 return HttpResponse(data
, mimetype
="application/%s" % format
)
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
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
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()
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
)
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
):
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
)