Remove ObjectId from the tree
[mediagoblin.git] / mediagoblin / decorators.py
1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
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
17 from functools import wraps
18
19 from urlparse import urljoin
20 from werkzeug.exceptions import Forbidden
21 from werkzeug.urls import url_quote
22
23 from mediagoblin.db.sql.models import MediaEntry, User
24 from mediagoblin.tools.response import redirect, render_404
25
26
27 def require_active_login(controller):
28 """
29 Require an active login from the user.
30 """
31 @wraps(controller)
32 def new_controller_func(request, *args, **kwargs):
33 if request.user and \
34 request.user.get('status') == u'needs_email_verification':
35 return redirect(
36 request, 'mediagoblin.user_pages.user_home',
37 user=request.user.username)
38 elif not request.user or request.user.get('status') != u'active':
39 next_url = urljoin(
40 request.urlgen('mediagoblin.auth.login',
41 qualified=True),
42 request.url)
43
44 return redirect(request, 'mediagoblin.auth.login',
45 next=url_quote(next_url))
46
47 return controller(request, *args, **kwargs)
48
49 return new_controller_func
50
51 def active_user_from_url(controller):
52 """Retrieve User() from <user> URL pattern and pass in as url_user=...
53
54 Returns a 404 if no such active user has been found"""
55 @wraps(controller)
56 def wrapper(request, *args, **kwargs):
57 user = User.query.filter_by(username=request.matchdict['user']).first()
58 if user is None:
59 return render_404(request)
60
61 return controller(request, *args, url_user=user, **kwargs)
62
63 return wrapper
64
65
66 def user_may_delete_media(controller):
67 """
68 Require user ownership of the MediaEntry to delete.
69 """
70 @wraps(controller)
71 def wrapper(request, *args, **kwargs):
72 uploader_id = MediaEntry.query.get(request.matchdict['media']).uploader
73 if not (request.user.is_admin or
74 request.user.id == uploader_id):
75 raise Forbidden()
76
77 return controller(request, *args, **kwargs)
78
79 return wrapper
80
81
82 def user_may_alter_collection(controller):
83 """
84 Require user ownership of the Collection to modify.
85 """
86 @wraps(controller)
87 def wrapper(request, *args, **kwargs):
88 creator_id = request.db.User.find_one(
89 {'username': request.matchdict['user']}).id
90 if not (request.user.is_admin or
91 request.user.id == creator_id):
92 raise Forbidden()
93
94 return controller(request, *args, **kwargs)
95
96 return wrapper
97
98
99 def uses_pagination(controller):
100 """
101 Check request GET 'page' key for wrong values
102 """
103 @wraps(controller)
104 def wrapper(request, *args, **kwargs):
105 try:
106 page = int(request.GET.get('page', 1))
107 if page < 0:
108 return render_404(request)
109 except ValueError:
110 return render_404(request)
111
112 return controller(request, page=page, *args, **kwargs)
113
114 return wrapper
115
116
117 def get_user_media_entry(controller):
118 """
119 Pass in a MediaEntry based off of a url component
120 """
121 @wraps(controller)
122 def wrapper(request, *args, **kwargs):
123 user = request.db.User.find_one(
124 {'username': request.matchdict['user']})
125
126 if not user:
127 return render_404(request)
128 media = request.db.MediaEntry.find_one(
129 {'slug': request.matchdict['media'],
130 'state': u'processed',
131 'uploader': user.id})
132
133 # no media via slug? Grab it via object id
134 if not media:
135 media = MediaEntry.query.filter_by(
136 id=request.matchdict['media'],
137 state=u'processed',
138 uploader=user.id).first()
139 # Still no media? Okay, 404.
140 if not media:
141 return render_404(request)
142
143 return controller(request, media=media, *args, **kwargs)
144
145 return wrapper
146
147
148 def get_user_collection(controller):
149 """
150 Pass in a Collection based off of a url component
151 """
152 @wraps(controller)
153 def wrapper(request, *args, **kwargs):
154 user = request.db.User.find_one(
155 {'username': request.matchdict['user']})
156
157 if not user:
158 return render_404(request)
159
160 collection = request.db.Collection.find_one(
161 {'slug': request.matchdict['collection'],
162 'creator': user.id})
163
164 # Still no collection? Okay, 404.
165 if not collection:
166 return render_404(request)
167
168 return controller(request, collection=collection, *args, **kwargs)
169
170 return wrapper
171
172
173 def get_user_collection_item(controller):
174 """
175 Pass in a CollectionItem based off of a url component
176 """
177 @wraps(controller)
178 def wrapper(request, *args, **kwargs):
179 user = request.db.User.find_one(
180 {'username': request.matchdict['user']})
181
182 if not user:
183 return render_404(request)
184
185 collection = request.db.Collection.find_one(
186 {'slug': request.matchdict['collection'],
187 'creator': user.id})
188
189 collection_item = request.db.CollectionItem.find_one(
190 {'id': request.matchdict['collection_item'] })
191
192 # Still no collection item? Okay, 404.
193 if not collection_item:
194 return render_404(request)
195
196 return controller(request, collection_item=collection_item, *args, **kwargs)
197
198 return wrapper
199
200
201 def get_media_entry_by_id(controller):
202 """
203 Pass in a MediaEntry based off of a url component
204 """
205 @wraps(controller)
206 def wrapper(request, *args, **kwargs):
207 media = MediaEntry.query.filter_by(
208 id=request.matchdict['media'],
209 state=u'processed').first()
210 # Still no media? Okay, 404.
211 if not media:
212 return render_404(request)
213
214 return controller(request, media=media, *args, **kwargs)
215
216 return wrapper