Adds more support for oauth - access_token & decorators still to do
[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
bb3eaf20 21
f91dcc9d 22from mediagoblin import mg_globals as mgg
5adb906a 23from mediagoblin import messages
b0c8328e 24from mediagoblin.db.models import MediaEntry, User
1e03504e 25from mediagoblin.tools.response import redirect, render_404
5adb906a 26from mediagoblin.tools.translate import pass_to_ugettext as _
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
53c5e0b0 67
502073f2
JW
68def user_may_delete_media(controller):
69 """
53c5e0b0 70 Require user ownership of the MediaEntry to delete.
502073f2 71 """
1e03504e 72 @wraps(controller)
502073f2 73 def wrapper(request, *args, **kwargs):
461dd971 74 uploader_id = kwargs['media'].uploader
bec591d8 75 if not (request.user.is_admin or
5c2b8486 76 request.user.id == uploader_id):
cfa92229 77 raise Forbidden()
502073f2
JW
78
79 return controller(request, *args, **kwargs)
80
1e03504e 81 return wrapper
502073f2 82
3eb6fc4f 83
be5be115
AW
84def user_may_alter_collection(controller):
85 """
86 Require user ownership of the Collection to modify.
87 """
88 @wraps(controller)
89 def wrapper(request, *args, **kwargs):
90 creator_id = request.db.User.find_one(
91 {'username': request.matchdict['user']}).id
92 if not (request.user.is_admin or
5c2b8486 93 request.user.id == creator_id):
cfa92229 94 raise Forbidden()
be5be115
AW
95
96 return controller(request, *args, **kwargs)
97
98 return wrapper
99
100
3eb6fc4f
BK
101def uses_pagination(controller):
102 """
103 Check request GET 'page' key for wrong values
104 """
1e03504e 105 @wraps(controller)
3eb6fc4f
BK
106 def wrapper(request, *args, **kwargs):
107 try:
1301a8ad 108 page = int(request.GET.get('page', 1))
3eb6fc4f 109 if page < 0:
de12b4e7 110 return render_404(request)
3eb6fc4f 111 except ValueError:
de12b4e7 112 return render_404(request)
3eb6fc4f 113
439e37f7 114 return controller(request, page=page, *args, **kwargs)
3eb6fc4f 115
1e03504e 116 return wrapper
724933b1
CAW
117
118
01674e10 119def get_user_media_entry(controller):
724933b1
CAW
120 """
121 Pass in a MediaEntry based off of a url component
122 """
1e03504e 123 @wraps(controller)
724933b1 124 def wrapper(request, *args, **kwargs):
7f4e42b0 125 user = User.query.filter_by(username=request.matchdict['user']).first()
01674e10 126 if not user:
7f4e42b0
SS
127 raise NotFound()
128
7de20e52
CAW
129 media = None
130
131 # might not be a slug, might be an id, but whatever
132 media_slug = request.matchdict['media']
133
e4e50a27
CAW
134 # if it starts with id: it actually isn't a slug, it's an id.
135 if media_slug.startswith(u'id:'):
136 try:
137 media = MediaEntry.query.filter_by(
138 id=int(media_slug[3:]),
139 state=u'processed',
140 uploader=user.id).first()
141 except ValueError:
142 raise NotFound()
7de20e52
CAW
143 else:
144 # no magical id: stuff? It's a slug!
145 media = MediaEntry.query.filter_by(
697c74c2 146 slug=media_slug,
7de20e52
CAW
147 state=u'processed',
148 uploader=user.id).first()
724933b1 149
724933b1 150 if not media:
7de20e52 151 # Didn't find anything? Okay, 404.
7f4e42b0 152 raise NotFound()
724933b1
CAW
153
154 return controller(request, media=media, *args, **kwargs)
155
1e03504e 156 return wrapper
aba81c9f 157
243c3843 158
be5be115
AW
159def get_user_collection(controller):
160 """
161 Pass in a Collection based off of a url component
162 """
163 @wraps(controller)
164 def wrapper(request, *args, **kwargs):
165 user = request.db.User.find_one(
166 {'username': request.matchdict['user']})
167
168 if not user:
169 return render_404(request)
170
171 collection = request.db.Collection.find_one(
172 {'slug': request.matchdict['collection'],
5c2b8486 173 'creator': user.id})
be5be115
AW
174
175 # Still no collection? Okay, 404.
176 if not collection:
177 return render_404(request)
178
179 return controller(request, collection=collection, *args, **kwargs)
180
181 return wrapper
182
183
184def get_user_collection_item(controller):
185 """
186 Pass in a CollectionItem based off of a url component
187 """
188 @wraps(controller)
189 def wrapper(request, *args, **kwargs):
190 user = request.db.User.find_one(
191 {'username': request.matchdict['user']})
192
193 if not user:
194 return render_404(request)
195
be5be115 196 collection_item = request.db.CollectionItem.find_one(
5c2b8486 197 {'id': request.matchdict['collection_item'] })
be5be115
AW
198
199 # Still no collection item? Okay, 404.
200 if not collection_item:
201 return render_404(request)
202
203 return controller(request, collection_item=collection_item, *args, **kwargs)
204
205 return wrapper
206
207
aba81c9f
E
208def get_media_entry_by_id(controller):
209 """
210 Pass in a MediaEntry based off of a url component
211 """
1e03504e 212 @wraps(controller)
aba81c9f 213 def wrapper(request, *args, **kwargs):
71717fd5 214 media = MediaEntry.query.filter_by(
461dd971 215 id=request.matchdict['media_id'],
71717fd5 216 state=u'processed').first()
aba81c9f
E
217 # Still no media? Okay, 404.
218 if not media:
de12b4e7 219 return render_404(request)
aba81c9f 220
461dd971
E
221 given_username = request.matchdict.get('user')
222 if given_username and (given_username != media.get_uploader.username):
223 return render_404(request)
224
aba81c9f
E
225 return controller(request, media=media, *args, **kwargs)
226
1e03504e 227 return wrapper
f91dcc9d
SS
228
229
230def get_workbench(func):
231 """Decorator, passing in a workbench as kwarg which is cleaned up afterwards"""
232
233 @wraps(func)
234 def new_func(*args, **kwargs):
bd6fe977 235 with mgg.workbench_manager.create() as workbench:
f91dcc9d
SS
236 return func(*args, workbench=workbench, **kwargs)
237
238 return new_func
5adb906a
RE
239
240
241def allow_registration(controller):
242 """ Decorator for if registration is enabled"""
243 @wraps(controller)
244 def wrapper(request, *args, **kwargs):
245 if not mgg.app_config["allow_registration"]:
246 messages.add_message(
247 request,
248 messages.WARNING,
249 _('Sorry, registration is disabled on this instance.'))
250 return redirect(request, "index")
251
252 return controller(request, *args, **kwargs)
253
254 return wrapper
255
256
257def auth_enabled(controller):
258 """Decorator for if an auth plugin is enabled"""
259 @wraps(controller)
260 def wrapper(request, *args, **kwargs):
261 if not mgg.app.auth:
262 messages.add_message(
263 request,
264 messages.WARNING,
265 _('Sorry, authentication is disabled on this instance.'))
266 return redirect(request, 'index')
267
268 return controller(request, *args, **kwargs)
269
270 return wrapper