This is a very small commit. All that I have done here is to clean up my code
[mediagoblin.git] / mediagoblin / decorators.py
CommitLineData
bb3eaf20 1# GNU MediaGoblin -- federated, autonomous media hosting
cf29e8a8 2# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
bb3eaf20
CAW
3#
4# This program is free software: you can redistribute it and/or modify
5# it 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
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Affero General Public License for more details.
13#
14# You should have received a copy of the GNU Affero General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
1e03504e 17from functools import wraps
bb3eaf20 18
3a199328 19from urlparse import urljoin
7f4e42b0 20from werkzeug.exceptions import Forbidden, NotFound
059eaee4 21from werkzeug.urls import url_quote
bb3eaf20 22
f91dcc9d 23from mediagoblin import mg_globals as mgg
6bba33d7 24from mediagoblin.db.models import MediaEntry, User, MediaComment, Privilege, \
25 UserBan
26from mediagoblin.tools.response import redirect, render_404, render_user_banned
bb3eaf20
CAW
27
28
29def require_active_login(controller):
30 """
31 Require an active login from the user.
32 """
1e03504e 33 @wraps(controller)
bb3eaf20 34 def new_controller_func(request, *args, **kwargs):
a72c504b 35 if request.user and \
066d49b2 36 request.user.status == u'needs_email_verification':
d43b472a
CAW
37 return redirect(
38 request, 'mediagoblin.user_pages.user_home',
5a4e3ff1 39 user=request.user.username)
066d49b2 40 elif not request.user or request.user.status != u'active':
3a199328
JW
41 next_url = urljoin(
42 request.urlgen('mediagoblin.auth.login',
43 qualified=True),
44 request.url)
45
059eaee4 46 return redirect(request, 'mediagoblin.auth.login',
56c113c7 47 next=next_url)
bb3eaf20
CAW
48
49 return controller(request, *args, **kwargs)
50
1e03504e 51 return new_controller_func
3eb6fc4f 52
ad742028
SS
53def active_user_from_url(controller):
54 """Retrieve User() from <user> URL pattern and pass in as url_user=...
55
56 Returns a 404 if no such active user has been found"""
57 @wraps(controller)
58 def wrapper(request, *args, **kwargs):
59 user = User.query.filter_by(username=request.matchdict['user']).first()
60 if user is None:
61 return render_404(request)
62
63 return controller(request, *args, url_user=user, **kwargs)
64
65 return wrapper
66
3fb96fc9 67def user_has_privilege(privilege_name):
6bba33d7 68
3fb96fc9 69 def user_has_privilege_decorator(controller):
9b8ef022 70 @wraps(controller)
9b8ef022 71 def wrapper(request, *args, **kwargs):
72 user_id = request.user.id
3fb96fc9 73 privileges_of_user = Privilege.query.filter(
74 Privilege.all_users.any(
75 User.id==user_id))
6bba33d7 76 if UserBan.query.filter(UserBan.user_id==user_id).count():
77 return render_user_banned(request)
78 elif not privileges_of_user.filter(
3fb96fc9 79 Privilege.privilege_name==privilege_name).count():
9b8ef022 80 raise Forbidden()
81
82 return controller(request, *args, **kwargs)
83
84 return wrapper
3fb96fc9 85 return user_has_privilege_decorator
9b8ef022 86
53c5e0b0 87
502073f2
JW
88def user_may_delete_media(controller):
89 """
53c5e0b0 90 Require user ownership of the MediaEntry to delete.
502073f2 91 """
1e03504e 92 @wraps(controller)
502073f2 93 def wrapper(request, *args, **kwargs):
461dd971 94 uploader_id = kwargs['media'].uploader
bec591d8 95 if not (request.user.is_admin or
5c2b8486 96 request.user.id == uploader_id):
cfa92229 97 raise Forbidden()
502073f2
JW
98
99 return controller(request, *args, **kwargs)
100
1e03504e 101 return wrapper
502073f2 102
3eb6fc4f 103
be5be115
AW
104def user_may_alter_collection(controller):
105 """
106 Require user ownership of the Collection to modify.
107 """
108 @wraps(controller)
109 def wrapper(request, *args, **kwargs):
110 creator_id = request.db.User.find_one(
111 {'username': request.matchdict['user']}).id
112 if not (request.user.is_admin or
5c2b8486 113 request.user.id == creator_id):
cfa92229 114 raise Forbidden()
be5be115
AW
115
116 return controller(request, *args, **kwargs)
117
118 return wrapper
119
120
3eb6fc4f
BK
121def uses_pagination(controller):
122 """
123 Check request GET 'page' key for wrong values
124 """
1e03504e 125 @wraps(controller)
3eb6fc4f
BK
126 def wrapper(request, *args, **kwargs):
127 try:
1301a8ad 128 page = int(request.GET.get('page', 1))
3eb6fc4f 129 if page < 0:
de12b4e7 130 return render_404(request)
3eb6fc4f 131 except ValueError:
de12b4e7 132 return render_404(request)
3eb6fc4f 133
439e37f7 134 return controller(request, page=page, *args, **kwargs)
3eb6fc4f 135
1e03504e 136 return wrapper
724933b1
CAW
137
138
01674e10 139def get_user_media_entry(controller):
724933b1
CAW
140 """
141 Pass in a MediaEntry based off of a url component
142 """
1e03504e 143 @wraps(controller)
724933b1 144 def wrapper(request, *args, **kwargs):
7f4e42b0 145 user = User.query.filter_by(username=request.matchdict['user']).first()
01674e10 146 if not user:
7f4e42b0
SS
147 raise NotFound()
148
7de20e52
CAW
149 media = None
150
151 # might not be a slug, might be an id, but whatever
152 media_slug = request.matchdict['media']
153
e4e50a27
CAW
154 # if it starts with id: it actually isn't a slug, it's an id.
155 if media_slug.startswith(u'id:'):
156 try:
157 media = MediaEntry.query.filter_by(
158 id=int(media_slug[3:]),
159 state=u'processed',
160 uploader=user.id).first()
161 except ValueError:
162 raise NotFound()
7de20e52
CAW
163 else:
164 # no magical id: stuff? It's a slug!
165 media = MediaEntry.query.filter_by(
697c74c2 166 slug=media_slug,
7de20e52
CAW
167 state=u'processed',
168 uploader=user.id).first()
724933b1 169
724933b1 170 if not media:
7de20e52 171 # Didn't find anything? Okay, 404.
7f4e42b0 172 raise NotFound()
724933b1
CAW
173
174 return controller(request, media=media, *args, **kwargs)
175
1e03504e 176 return wrapper
aba81c9f 177
243c3843 178
be5be115
AW
179def get_user_collection(controller):
180 """
181 Pass in a Collection based off of a url component
182 """
183 @wraps(controller)
184 def wrapper(request, *args, **kwargs):
185 user = request.db.User.find_one(
186 {'username': request.matchdict['user']})
187
188 if not user:
189 return render_404(request)
190
191 collection = request.db.Collection.find_one(
192 {'slug': request.matchdict['collection'],
5c2b8486 193 'creator': user.id})
be5be115
AW
194
195 # Still no collection? Okay, 404.
196 if not collection:
197 return render_404(request)
198
199 return controller(request, collection=collection, *args, **kwargs)
200
201 return wrapper
202
203
204def get_user_collection_item(controller):
205 """
206 Pass in a CollectionItem based off of a url component
207 """
208 @wraps(controller)
209 def wrapper(request, *args, **kwargs):
210 user = request.db.User.find_one(
211 {'username': request.matchdict['user']})
212
213 if not user:
214 return render_404(request)
215
be5be115 216 collection_item = request.db.CollectionItem.find_one(
5c2b8486 217 {'id': request.matchdict['collection_item'] })
be5be115
AW
218
219 # Still no collection item? Okay, 404.
220 if not collection_item:
221 return render_404(request)
222
223 return controller(request, collection_item=collection_item, *args, **kwargs)
224
225 return wrapper
226
227
aba81c9f
E
228def get_media_entry_by_id(controller):
229 """
230 Pass in a MediaEntry based off of a url component
231 """
1e03504e 232 @wraps(controller)
aba81c9f 233 def wrapper(request, *args, **kwargs):
71717fd5 234 media = MediaEntry.query.filter_by(
461dd971 235 id=request.matchdict['media_id'],
71717fd5 236 state=u'processed').first()
aba81c9f
E
237 # Still no media? Okay, 404.
238 if not media:
de12b4e7 239 return render_404(request)
aba81c9f 240
461dd971
E
241 given_username = request.matchdict.get('user')
242 if given_username and (given_username != media.get_uploader.username):
243 return render_404(request)
244
aba81c9f
E
245 return controller(request, media=media, *args, **kwargs)
246
1e03504e 247 return wrapper
f91dcc9d
SS
248
249
30a9fe7c 250def get_media_comment_by_id(controller):
251 """
252 Pass in a MediaComment based off of a url component
253 """
254 @wraps(controller)
255 def wrapper(request, *args, **kwargs):
256 comment = MediaComment.query.filter_by(
257 id=request.matchdict['comment']).first()
258 # Still no media? Okay, 404.
259 if not comment:
260 return render_404(request)
261
262 return controller(request, comment=comment, *args, **kwargs)
263
264 return wrapper
265
266
267
f91dcc9d
SS
268def get_workbench(func):
269 """Decorator, passing in a workbench as kwarg which is cleaned up afterwards"""
270
271 @wraps(func)
272 def new_func(*args, **kwargs):
bd6fe977 273 with mgg.workbench_manager.create() as workbench:
f91dcc9d
SS
274 return func(*args, workbench=workbench, **kwargs)
275
276 return new_func
9b8ef022 277
6bba33d7 278def require_admin_or_moderator_login(controller):
9b8ef022 279 """
6bba33d7 280 Require an login from an administrator or a moderator.
9b8ef022 281 """
282 @wraps(controller)
283 def new_controller_func(request, *args, **kwargs):
6bba33d7 284 admin_privilege = Privilege.one({'privilege_name':u'admin'})
285 moderator_privilege = Privilege.one({'privilege_name':u'moderator'})
9b8ef022 286 if request.user and \
6bba33d7 287 not admin_privilege in request.user.all_privileges and \
288 not moderator_privilege in request.user.all_privileges:
289
9b8ef022 290 raise Forbidden()
291 elif not request.user:
292 next_url = urljoin(
293 request.urlgen('mediagoblin.auth.login',
294 qualified=True),
295 request.url)
296
297 return redirect(request, 'mediagoblin.auth.login',
298 next=next_url)
299
300 return controller(request, *args, **kwargs)
301
302 return new_controller_func
303
6bba33d7 304def user_not_banned(controller):
305 """
306 Requires that the user has not been banned. Otherwise redirects to the page
307 explaining why they have been banned
308 """
309 @wraps(controller)
310 def wrapper(request, *args, **kwargs):
311 if request.user:
312 user_banned = UserBan.query.get(request.user.id)
313 if user_banned:
314 return render_user_banned(request)
315 return controller(request, *args, **kwargs)
316
317 return wrapper
318