1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
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.
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.
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/>.
20 from werkzeug
.wrappers
import Response
as wz_Response
21 from mediagoblin
.tools
.template
import render_template
22 from mediagoblin
.tools
.translate
import (lazy_pass_to_ugettext
as _
,
24 from mediagoblin
.db
.models
import UserBan
, User
25 from datetime
import date
27 class Response(wz_Response
):
28 """Set default response mimetype to HTML, otherwise we get text/plain"""
29 default_mimetype
= u
'text/html'
32 def render_to_response(request
, template
, context
, status
=200, mimetype
=None):
33 """Much like Django's shortcut.render()"""
35 render_template(request
, template
, context
),
39 def render_error(request
, status
=500, title
=_('Oops!'),
40 err_msg
=_('An error occured')):
41 """Render any error page with a given error code, title and text body
43 Title and description are passed through as-is to allow html. Make
44 sure no user input is contained therein for security reasons. The
45 description will be wrapped in <p></p> tags.
47 return Response(render_template(request
, 'mediagoblin/error.html',
48 {'err_code': status
, 'title': title
, 'err_msg': err_msg
}),
51 def render_400(request
, err_msg
=None):
52 """ Render a standard 400 page"""
54 title
= _("Bad Request")
56 err_msg
= _("The request sent to the server is invalid, \
57 please double check it")
59 return render_error(request
, 400, title
, err_msg
)
61 def render_403(request
):
62 """Render a standard 403 page"""
64 title
= _('Operation not allowed')
65 err_msg
= _("Sorry Dave, I can't let you do that!</p><p>You have tried "
66 " to perform a function that you are not allowed to. Have you "
67 "been trying to delete all user accounts again?")
68 return render_error(request
, 403, title
, err_msg
)
70 def render_404(request
):
71 """Render a standard 404 page."""
73 err_msg
= _("There doesn't seem to be a page at this address. Sorry!</p>"
74 "<p>If you're sure the address is correct, maybe the page "
75 "you're looking for has been moved or deleted.")
76 return render_error(request
, 404, err_msg
=err_msg
)
78 def render_user_banned(request
):
79 """Renders the page which tells a user they have been banned, for how long
80 and the reason why they have been banned"
82 user_ban
= UserBan
.query
.get(request
.user
.id)
83 if (user_ban
.expiration_date
is not None and
84 date
.today()>user_ban
.expiration_date
):
87 return redirect(request
,
89 return render_to_response(request
,
90 'mediagoblin/banned.html',
91 {'reason':user_ban
.reason
,
92 'expiration_date':user_ban
.expiration_date
})
94 def render_http_exception(request
, exc
, description
):
95 """Return Response() given a werkzeug.HTTPException
97 :param exc: werkzeug.HTTPException or subclass thereof
98 :description: message describing the error."""
99 # If we were passed the HTTPException stock description on
100 # exceptions where we have localized ones, use those:
101 stock_desc
= (description
== exc
.__class
__.description
)
103 if stock_desc
and exc
.code
== 403:
104 return render_403(request
)
105 elif stock_desc
and exc
.code
== 404:
106 return render_404(request
)
108 return render_error(request
, title
='{0} {1}'.format(exc
.code
, exc
.name
),
113 def redirect(request
, *args
, **kwargs
):
114 """Redirects to an URL, using urlgen params or location string
116 :param querystring: querystring to be appended to the URL
117 :param location: If the location keyword is given, redirect to the URL
119 querystring
= kwargs
.pop('querystring', None)
121 # Redirect to URL if given by "location=..."
122 if 'location' in kwargs
:
123 location
= kwargs
.pop('location')
125 location
= request
.urlgen(*args
, **kwargs
)
128 location
+= querystring
129 return werkzeug
.utils
.redirect(location
)
132 def redirect_obj(request
, obj
):
133 """Redirect to the page for the given object.
135 Requires obj to have a .url_for_self method."""
136 return redirect(request
, location
=obj
.url_for_self(request
.urlgen
))
138 def json_response(serializable
, _disable_cors
=False, *args
, **kw
):
140 Serializes a json objects and returns a werkzeug Response object with the
141 serialized value as the response body and Content-Type: application/json.
143 :param serializable: A json-serializable object
145 Any extra arguments and keyword arguments are passed to the
146 Response.__init__ method.
149 response
= wz_Response(json
.dumps(serializable
), *args
, content_type
='application/json', **kw
)
151 if not _disable_cors
:
153 'Access-Control-Allow-Origin': '*',
154 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
155 'Access-Control-Allow-Headers': 'Content-Type, X-Requested-With'}
156 for key
, value
in cors_headers
.iteritems():
157 response
.headers
.set(key
, value
)
161 def json_error(error_str
, status
=400, *args
, **kwargs
):
163 This is like json_response but takes an error message in and formats
164 it in {"error": error_str}. This also sets the default HTTP status
167 return json_response({"error": error_str
}, status
=status
, *args
, **kwargs
)
169 def form_response(data
, *args
, **kwargs
):
171 Responds using application/x-www-form-urlencoded and returns a werkzeug
172 Response object with the data argument as the body
173 and 'application/x-www-form-urlencoded' as the Content-Type.
175 Any extra arguments and keyword arguments are passed to the
176 Response.__init__ method.
179 response
= wz_Response(
181 content_type
="application/x-www-form-urlencoded",