twisted render_GET redirect to function - python

I can't seem to find any documentation on how to use twisted.web.util.Redirect to redirect to another function.
For more information see below.
I have the following code:
class Login(Resource):
isLeaf = True
def getChild(self, name, request):
if name == '':
return self
return Resource.getChild(self, name, request)
def render_GET(self, request):
saml = SamlRequest(request)
print('redirecting to sso')
return Redirect(saml.sso())
class SamlRequest(object):
self.auth = OneLogin_Saml2_Auth(self.request, custom_base_path=settings_path)
def sso(self):
return self.auth.login()
I need to redirect to page login to the login function inside OneLogin_Saml2_Auth.
When I try to redirect as-is I receive the error
raise TypeError("Unicode object not allowed as URL")
Is there a way to accomplish this?

twisted.web.util.Redirect is a kind of Resource, not something you return from a render method. It's most suitable if you have a "static" redirect that exists in your URL structure and redirects to a fixed location.
If you want to write a custom resource that redirects to a dynamic URL, use twisted.web.util.redirectTo(url, request), which you can call from your render_GET method just like you tried to do with Redirect.

Related

django-csrf protection on ajax post

I am working on django 1.7 and python 2.7. To prevent csrf attack on ajax post request i have added csrf token in ajax header before send.
In views i have added csrf_protect decorator to check the token. Everything is working fine in this scenario. But In my project this function in views.py is being called internally in other views where i haven't implemented csrf token, this causing 403 error.So what i want to do is only when there is ajax post call have to check csrf_protect decorator. Every other calls can neglect.
def check_token(func):
def wrapper(request, *args, **kwargs):
if request.is_ajax():
return csrf_protect(func(request,*args, **kwargs))
return func(request,*args, **kwargs )
return wrapper
#check_token
def myViews(request,mob,id):
"""function starts here"""
Your decorator is equivalent to
myViews = check_token(myViews)
You could apply it manually to a new name:
def unprotected_view(request,mob,id):
"""function starts here"""
...
protected_view = check_token(unprotected_view)
Now you have a decorated and a non-decorated name for it.
Calling views from within other views is not really what Django views are supposed to do. If you have some generic functionality to craft a response, make that a separate function. Then let your protected view call that function and your other views call it as well:
#csrf_protect
def my_view(request, mob, id):
return craft_generic_response(request, mob, id)
def craft_generic_response(request, mob, id)
# do stuff to create response
return response
def another_view(request, mob, id):
# do stuff
response = craft_generic_response(**kwargs)
# do more stuff

Get the Flask view function that matches a url

I have some url paths and want to check if they point to a url rule in my Flask app. How can I check this using Flask?
from flask import Flask, json, request, Response
app = Flask('simple_app')
#app.route('/foo/<bar_id>', methods=['GET'])
def foo_bar_id(bar_id):
if request.method == 'GET':
return Response(json.dumps({'foo': bar_id}), status=200)
#app.route('/bar', methods=['GET'])
def bar():
if request.method == 'GET':
return Response(json.dumps(['bar']), status=200)
test_route_a = '/foo/1' # return foo_bar_id function
test_route_b = '/bar' # return bar function
app.url_map stores the object that maps and matches rules with endpoints. app.view_functions maps endpoints to view functions.
Call match to match a url to an endpoint and values. It will raise 404 if the route is not found, and 405 if the wrong method is specified. You'll need the method as well as the url to match.
Redirects are treated as exceptions, you'll need to catch and test these recursively to find the view function.
It's possible to add rules that don't map to views, you'll need to catch KeyError when looking up the view.
from werkzeug.routing import RequestRedirect, MethodNotAllowed, NotFound
def get_view_function(url, method='GET'):
"""Match a url and return the view and arguments
it will be called with, or None if there is no view.
"""
adapter = app.url_map.bind('localhost')
try:
match = adapter.match(url, method=method)
except RequestRedirect as e:
# recursively match redirects
return get_view_function(e.new_url, method)
except (MethodNotAllowed, NotFound):
# no match
return None
try:
# return the view function and arguments
return app.view_functions[match[0]], match[1]
except KeyError:
# no view is associated with the endpoint
return None
There are many more options that can be passed to bind to effect how matches are made, see the docs for details.
The view function can also raise 404 (or other) errors, so this only guarantees that a url will match a view, not that the view returns a 200 response.
In addition to the #davidism answer (The core developer of flask).
Note that if you want to discover the view function of the current url processed by flask app. You can use the Request object of flask which :
The request object used by default in Flask. Remembers the
matched endpoint and view arguments.
and the Flask.view_functtions which:
#: A dictionary mapping endpoint names to view functions.
#: To register a view function, use the :meth:route decorator.
def get_view_function():
if request.url_rule:
return current_app.view_functions.get(request.url_rule.endpoint, None)

Different login views in Pyramid

There are some URLs which are handled by my Pyramid application. When an unauthenticated user tries to open any URL then the user is redirected to login form:
def forbidden(request):
if request.user.keyname == 'guest':
return HTTPFound(location=request.route_url('auth.login',))
request.response.status = 403
return dict(subtitle=u"Access denied")
config.add_view(forbidden, context=HTTPForbidden, renderer='auth/forbidden.mako')
But for some urls (routes) I have to return not the login form, but a 401 Unauthorized status code with WWW-Authenticate header. How I can setup my routes to accomplish this? I am guessing that I have to use route_predicate.
You can wrap those two errors into your custom one, and raise that in place of both. Then you can handle your exception and run the desired scenario for each error. Here is an example:
class YourError(HTTPException):
def __init__(self, error):
super(YourError, self).__init__()
self.error = error
def handle(self, request):
if error is HTTPForbidden or is instance(error, HTTPForbidden):
return self._handle403(request)
elif error is HTTPUnauthorized or is instance(error, HTTPUnauthorized):
return self._handle401(request)
def _handle403(self, request):
# do your stuff for 403
def _handle401(self, request):
# do your stuff for 401
# ...modify your view
def forbidden(context, request):
return context.handle(request)
Then edit your view configuration:
config.add_view(forbidden, context=YourError, renderer='auth/forbidden.mako')
And then in other views where you need to return 403 or 401, go this way:
def another_view(request)
...
raise YourError(HTTPForbidden)
# or
raise YourError(HTTPUnauthorized)
...
Then you will only need to implement your handling logic inside the YourError class.
I came across some discussion on the Pyramid issues list that looks like it might address this problem.
That said, I think what you might be able to do is override the Forbidden view using hooks and create a custom exception handler. Then in there I think you could differentiate between 403 and 401 errors and redirect / display an appropriate response message and customize the response however you need.

Manipulate URL fragment on redirect in Django

I have been using Django's auth module but recently had to switch off of it. The auth module handled session expirations by redirecting to the login page and setting the page you were logged out from as the ?next=/currentPage parameter.
So if my session expired on #dashboard I would be redirected to:
mydomain/account/login?next=/#dashboard
After moving off of Django auth module, I noticed this has changed to:
mydomain/account/login/#dashboard
This seems consistent with how I understand it should function after reading URL Fragment and 302 redirects, however, I'd like to manipulate this fragment but don't see it anywhere in my HttpResponse object.
django.contrib.auth uses the following functions to handle this request, but I don't see where they're moving the fragment. Realistically I'd just like to remove the fragment completely, but if I can't I'd settle for having it back in ?next= parameter.
def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
"""
Decorator for views that checks that the user passes the given test,
redirecting to the log-in page if necessary. The test should be a callable
that takes the user object and returns True if the user passes.
"""
def decorator(view_func):
#wraps(view_func, assigned=available_attrs(view_func))
def _wrapped_view(request, *args, **kwargs):
if test_func(request.user):
return view_func(request, *args, **kwargs)
path = request.build_absolute_uri()
# urlparse chokes on lazy objects in Python 3, force to str
resolved_login_url = force_str(
resolve_url(login_url or settings.LOGIN_URL))
# If the login url is the same scheme and net location then just
# use the path as the "next" url.
login_scheme, login_netloc = urlparse(resolved_login_url)[:2]
current_scheme, current_netloc = urlparse(path)[:2]
if ((not login_scheme or login_scheme == current_scheme) and
(not login_netloc or login_netloc == current_netloc)):
path = request.get_full_path()
from django.contrib.auth.views import redirect_to_login
return redirect_to_login(
path, resolved_login_url, redirect_field_name)
return _wrapped_view
return decorator
def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):
"""
Decorator for views that checks that the user is logged in, redirecting
to the log-in page if necessary.
"""
actual_decorator = user_passes_test(
lambda u: u.is_authenticated(),
login_url=login_url,
redirect_field_name=redirect_field_name
)
if function:
return actual_decorator(function)
return actual_decorator
They're not removing it. Fragments are never sent to the backend: that's just how browsers work.
Note that your original URL is not being interpreted as next="/#dashboard" at all, but next="/", with a subsequent fragment of "dashboard". That is, the fragment is separate to the querystring, not part of it.
What you need to do is to encode the hash, so that it is part of the querystring itself.
mydomain/account/login?next=/%23dashboard

response redirect to a different page when 405 raise

I have a view function which I want to use only request method is POST. I got to know about require_POST decorator here, but what I want is that if method is not POST then redirect user to different view using HttpResponseRedirect. How can I do this ?
from django.views.decorators.http import require_POST
#require_POST
def my_view(request):
# I can assume now that only POST requests make it this far
# ...
I know I can do it by adding two lines of code, without using require_POST redirect in my method itself like
if request.method != 'POST':
return HttpResponseRedirect(view_url)
but I am more interested in using decorator itself and when this decorator raises 405, then redirect to another view.
A custom decorator is the way to go.
I myself use one similar to the one you need and I'll post the code.
Do upvote #aychedee s answer since he was first. :)
def require_post_decorator(function=None, redirect_url='/'):
def _decorator(view_function):
def _view(request, *args, **kwargs):
if request.method == 'POST':
#do some before the view is reached stuffs here.
return view_function(request, *args, **kwargs)
else:
return HttpResponseRedirect(redirect_url)
_view.__name__ = view_function.__name__
_view.__dict__ = view_function.__dict__
_view.__doc__ = view_function.__doc__
return _view
if function:
return _decorator(function)
return _decorator
You would have to use a custom decorator. You can see the code for the Django decorator here. It's already returned a response before your code is reached at all, so absolutely nothing you do in your view function would be run anyway.
There is nothing wrong with manually returning a redirect if the request is not a POST. If you use this pattern in a few different places in your code I would then refactor it into a decorator later. But if this is the first place you are using it then it's overkill.

Categories