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/>.
21 from werkzeug
.wrappers
import Response
as wz_Response
22 from mediagoblin
.tools
.template
import render_template
23 from mediagoblin
.tools
.translate
import (lazy_pass_to_ugettext
as _
,
25 from mediagoblin
.db
.models
import UserBan
, User
26 from datetime
import date
28 class Response(wz_Response
):
29 """Set default response mimetype to HTML, otherwise we get text/plain"""
30 default_mimetype
= u
'text/html'
33 def render_to_response(request
, template
, context
, status
=200, mimetype
=None):
34 """Much like Django's shortcut.render()"""
36 render_template(request
, template
, context
),
40 def render_error(request
, status
=500, title
=_('Oops!'),
41 err_msg
=_('An error occured')):
42 """Render any error page with a given error code, title and text body
44 Title and description are passed through as-is to allow html. Make
45 sure no user input is contained therein for security reasons. The
46 description will be wrapped in <p></p> tags.
48 return Response(render_template(request
, 'mediagoblin/error.html',
49 {'err_code': status
, 'title': title
, 'err_msg': err_msg
}),
52 def render_400(request
, err_msg
=None):
53 """ Render a standard 400 page"""
55 title
= _("Bad Request")
57 err_msg
= _("The request sent to the server is invalid, \
58 please double check it")
60 return render_error(request
, 400, title
, err_msg
)
62 def render_403(request
):
63 """Render a standard 403 page"""
65 title
= _('Operation not allowed')
66 err_msg
= _("Sorry Dave, I can't let you do that!</p><p>You have tried "
67 " to perform a function that you are not allowed to. Have you "
68 "been trying to delete all user accounts again?")
69 return render_error(request
, 403, title
, err_msg
)
71 def render_404(request
):
72 """Render a standard 404 page."""
74 err_msg
= _("There doesn't seem to be a page at this address. Sorry!</p>"
75 "<p>If you're sure the address is correct, maybe the page "
76 "you're looking for has been moved or deleted.")
77 return render_error(request
, 404, err_msg
=err_msg
)
79 def render_user_banned(request
):
80 """Renders the page which tells a user they have been banned, for how long
81 and the reason why they have been banned"
83 user_ban
= UserBan
.query
.get(request
.user
.id)
84 if (user_ban
.expiration_date
is not None and
85 date
.today()>user_ban
.expiration_date
):
88 return redirect(request
,
90 return render_to_response(request
,
91 'mediagoblin/banned.html',
92 {'reason':user_ban
.reason
,
93 'expiration_date':user_ban
.expiration_date
})
95 def render_http_exception(request
, exc
, description
):
96 """Return Response() given a werkzeug.HTTPException
98 :param exc: werkzeug.HTTPException or subclass thereof
99 :description: message describing the error."""
100 # If we were passed the HTTPException stock description on
101 # exceptions where we have localized ones, use those:
102 stock_desc
= (description
== exc
.__class
__.description
)
104 if stock_desc
and exc
.code
== 403:
105 return render_403(request
)
106 elif stock_desc
and exc
.code
== 404:
107 return render_404(request
)
109 return render_error(request
, title
='{0} {1}'.format(exc
.code
, exc
.name
),
114 def redirect(request
, *args
, **kwargs
):
115 """Redirects to an URL, using urlgen params or location string
117 :param querystring: querystring to be appended to the URL
118 :param location: If the location keyword is given, redirect to the URL
120 querystring
= kwargs
.pop('querystring', None)
122 # Redirect to URL if given by "location=..."
123 if 'location' in kwargs
:
124 location
= kwargs
.pop('location')
126 location
= request
.urlgen(*args
, **kwargs
)
129 location
+= querystring
130 return werkzeug
.utils
.redirect(location
)
133 def redirect_obj(request
, obj
):
134 """Redirect to the page for the given object.
136 Requires obj to have a .url_for_self method."""
137 return redirect(request
, location
=obj
.url_for_self(request
.urlgen
))
139 def json_response(serializable
, _disable_cors
=False, *args
, **kw
):
141 Serializes a json objects and returns a werkzeug Response object with the
142 serialized value as the response body and Content-Type: application/json.
144 :param serializable: A json-serializable object
146 Any extra arguments and keyword arguments are passed to the
147 Response.__init__ method.
150 response
= wz_Response(json
.dumps(serializable
), *args
, content_type
='application/json', **kw
)
152 if not _disable_cors
:
154 'Access-Control-Allow-Origin': '*',
155 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
156 'Access-Control-Allow-Headers': 'Content-Type, X-Requested-With'}
157 for key
, value
in six
.iteritems(cors_headers
):
158 response
.headers
.set(key
, value
)
162 def json_error(error_str
, status
=400, *args
, **kwargs
):
164 This is like json_response but takes an error message in and formats
165 it in {"error": error_str}. This also sets the default HTTP status
168 return json_response({"error": error_str
}, status
=status
, *args
, **kwargs
)
170 def form_response(data
, *args
, **kwargs
):
172 Responds using application/x-www-form-urlencoded and returns a werkzeug
173 Response object with the data argument as the body
174 and 'application/x-www-form-urlencoded' as the Content-Type.
176 Any extra arguments and keyword arguments are passed to the
177 Response.__init__ method.
180 response
= wz_Response(
182 content_type
="application/x-www-form-urlencoded",