Unittest sensitive_post_parameters decorator in django view - python

I have a view to create new users in my django project.
I am applying the #sensitive_post_parameters decorator to that view to make sure the password isn't logged if there is an unhandled exception or something like that (as indicated in the comments in the source code https://docs.djangoproject.com/en/2.0/_modules/django/views/decorators/debug/).
When I proceed to test the view, I would like to make sure that this protection of the sensitive information is still in place (that I didn't delete the decorator to the function by mistake or something).
I am aware, since the decorator is applied to my function, I can't test it directly from the view tests.
But, for example, with the #login_required decorator, I can test its effects with assertRedirects (as explained here How to test if a view is decorated with "login_required" (Django)).
I have been searching for a way to do that, but I can't find one that works.
I thought of something like this:
def test_senstive_post_parameters(self):
request = RequestFactory().post('create_user', data={})
my_sensitive_parameters = ['password']
self.assertEqual(
request.sensitive_post_parameters,
my_senstive_parameters
)
but that gives me an
AttributeError: 'WSGIRequest' object has no attribute 'sensitive_post_parameters'
Any help would be appreciated.
Even it is telling me I shouldn't be attempting to test this, though I would really like to, as it is seems like an important behaviour that I should make sure remains in my code as it is later modified.

You have created a request using RequestFactory, but you have not actually used it. To test the effect of your view you need to import the view and call it.
from myapp.views import create_user
def test_senstive_post_parameters(self):
request = RequestFactory().post('create_user', data={})
response = create_user(request)
my_sensitive_parameters = ['password']
self.assertEqual(
request.sensitive_post_parameters,
my_senstive_parameters
)

Related

how to login to graphql page(localhost:8000/graphql) with django

I want to use #login_required function like below code.
and I want to check the query correctly works.
import graphene
from graphql_jwt.decorators import login_required
class Query(graphene.ObjectType):
user = graphene.Field(UserType)
#login_required
def resolve_me(self, info):
user=info.context.user
return types.UserProfileResponse(user=user)
i put the code into graphql(localhost:8000/graphql)
query{me{user{id}}}}
the message is you do not have permission to perform this action
I think maybe I have to give token to graphql. but i don't know how to give token.
could you teach me?
#login_required is a decorator for a view function (which takes a request as its first parameter), you cannot use it on your method.
You either have to do the check manually (if user.is_authenticated ...) or move this to the view. Latter is the better option, because a view can decide how to respond in this case, whereas your method can't.

Flask: How do I get the returned value from a function that uses #app.route decorator?

So I'm pretty new to Flask and I'm trying to make my mind around one thing. So, if I understand well when you write a function within a Flask app and you use the #app.route decorator in that function, it only runs when you hit that path/url.
I have a small oauth app written in Flask that goes through all the authorization flow and then it return the token.
My question is how do I get that token from the #decorated function? For example, lets say I have something like this:
#app.route(/token/)
def getToken(code): #code from the callback url.
#/Stuff to get the Token/
#/**********************/
return token
If I hit the (/token/) url-path the function returns the token. But now I need to get that token and use it in another function to write and read from the API I just got the token from. My initial thought was doing this:
token = getToken(code)
But if I do that, I get this error:
RuntimeError: working outside of request context
So again, my question is, how do I get the token so I can pass it as a parameter to other functions.
Extract the token generation code into a separate function, so that you can call it from anywhere, including the view function. It's a good practice to keep the application logic away from the view, and it also helps with unit testing.
I assume your route includes a placeholder for code, which you skipped:
def generateToken(code):
#/Stuff to get the Token/
#/**********************/
return token
#app.route('/token/<string:code>')
def getToken(code):
return generateToken(code)
Just keep in mind that generateToken shouldn't depend on the request object. If you need any request data (e.g. HTTP header), you should pass it explicitly in arguments. Otherwise you will get the "working outside of request context" exception you mentioned.
It is possible to call request-dependent views directly, but you need to mock the request object, which is a bit tricky. Read the request context documentation to learn more.
not sure what the context is. You could just call the method.
from yourmodule import get_token
def yourmethod():
token = get_token()
Otherwise, you could use the requests library in order to retrieve the data from the route
>>> import requests
>>> response = requests.get('www.yoursite.com/yourroute/')
>>> print response.text
If you're looking for unittests, Flask comes with a mock client
def test_get_token():
resp = self.app.get('/yourroute')
# do something with resp.data

django.test.testcase and request objects

I'm sure I'm missing something hideously obvious here, but this test is currently failing:
def test_index_view_returns_correct_html_document(self):
request = HttpRequest()
response = LogIn(request)
expected_html = render_to_string('login.html')
self.assertEqual(response.content, expected_html)
It fails with the error ''HttpRequest' object has no attribute 'user''
The view that's being tested has this piece of code that checks whether a user is currently logged in, and throws a redirect if so:
if request.user.is_authenticated():
return HttpResponseRedirect(reverse('index'))
What am I missing? I've looked in the docs but can't seem to find an explanation. I'm sure it's something obvious. Or I'm doing something wrong.
You've just constructed a bare request and passed it to the function, so it hasn't gone through any of the middleware - including the authentication one that adds the user object.
You should probably use the test client for this test, as it simulates the whole request/response cycle.

Multiple decorators for a view in Django: Execution order

I am trying to decorate a Django view by two decorators, one for checking login, and one for checking is_active.
The first one is the built-in #login_required, and the second one is the following:
def active_required(function):
dec = user_passes_test(lambda u: u.is_active, '/notallowed', '')
return dec(function)
Now, the decorators in Python work inside out, however the following does not work:
#active_required
#login_required
def foo(request):
...
I want to first check if the user is logged in, and redirect to login page if not, and if he or she is logged in, I want to check whether he or she is active, and if not, perform redirect to '/notallowed'.
What happens is that if the login_required fails, the user is not redirected to the login page, but #active_required is executed, and since the user is null in that case, #active_required decorator fails and the user is redirected to /notallowed.
Changing the order seems to work,
#login_required
#active_required
def foo(request):
...
but I suspect there is something wrong with this approach too.
What is the proper way to combine two decorators, and why does the execution order differ from simple Python decorators?
Now, the decorators in Python work from the inside out
Well I guess that depends on your definition of inside out. In your case, you want #login_required to execute first, and so it should be the "outermost" (top) decorator.
As you noted, your last example works, and is indeed the correct way to do this.
edit
The confusion might be how these particular decorators work.
#login_required(#original_view) returns a new view, which first checks if you are logged in, and then calls original_view
so
#login_required(
#active_required(
#my_view
)
)
first checks if you are logged in, then
first(second) checks if you are active, then
runs my_view
Decorators are applied in the order they appear in the source. Thus, your second example:
#login_required
#active_required
def foo(request):
...
is equivalent to the following:
def foo(request):
...
foo = login_required(active_required(foo))
Thus, if the code of one decorator depends on something set by (or ensured by) another, you have to put the dependent decorator "inside" the depdended-on decorator.
However, as Chris Pratt notes, you should avoid having decorator dependencies; when necessary, create a single new decorator that calls both in the right order.
It only really makes sense to stack decorators if they have truly unique functionality. Based on your description, there's never going to be a scenario where you will want to use active_required but not login_required. Therefore, it makes more sense to have a login_and_active_required decorator that checks both and branches accordingly. Less to type, less to document, and negates the problem.
To explain it a bit more (I was also confused at first): active_required is applied first in a sense that it takes my_view and wraps it in some code. Then login_required is applied and wraps the result in some more code.
But when this wrapped version of my_view is actually invoked, first the code added by login_required is executed (checking that you're logged in), then the code added by active_required is executed (checking that you're active) and then finally my_view is executed.

Manually calling a class based generic view in Django

I'm currently trying to call a class based Generic view from within another class based generic view and cant seem to do it correctly.
Ways I've tried:
result = CategoryTypes.as_view() # The same way you put it in the urlconf
print result
Prints: <function CategoryTypes at 0x92bd924>
CategoryTypes.as_view()(self.request)
# &
CategoryTypes().dispatch(self.request)
Tracebacks:
ContentNotRenderedError at /crm/categories/company/ The response content must be rendered before it can be accessed.
result = CategoryTypes().__init__()
print result
Prints: None
How do I call this from another view? I've seriously tried every method in the class and way of calling it I can think of.
The first way -- CategoryTypes.as_view()(self.request) -- is right. The problem is that if your view returns a TemplateResponse, its render method isn't called automatically.
So if you need to access the content of the response, call render() on it first.
Or you can directly access just content via result.rendered_content. Before making this be sure you will set session into your request before passing into a view:
self.request.session = {}
CategoryTypes.as_view()(self.request)

Categories