Django Tastypie User Objects Only Authorization - python

I want to use Tastypie authorization to give users access to only their objects. However, I am having problems understanding if I am doing it correctly. I followed the example here:
http://django-tastypie.readthedocs.org/en/latest/authorization.html#implementing-your-own-authorization
When I try to create a new object, I get a 404 error because there are problems evaluating
def create_detail(self, object_list, bundle):
return bundle.obj.user == bundle.request.user
Everything works if I comment that out. I thought commenting those two lines out would allow the user to create objects for other users, but when I tried it, I correctly get a 401 (UNAUTHORIZED) response.
Does that mean those two lines are unnecessary? How is Tastypie able to correctly determine if I am authorized to create objects?
When I was running this, I sent a POST request with 'user' equal to the appropriate URI (something like '/api/v1/user/1/'). I'm not sure if Tastypie is having problems determining
bundle.obj.user
when I do it that way.
Is it safe to just leave those two lines commented out? Is Tastypie authorizing the user with one of the other methods?

try:
def create_detail(self, object_list, bundle):
return bundle.obj == bundle.request.user

It looks like bundle.obj isn't populated during the create_detail authorization.
Also, create_detail for a user really doesn't make much sense, because there's no object for the user to own until its created anyways. You could just check if bundle.request.user is a valid user with permissions on the model.
In my case, I needed to check if the created object referenced an object owned by the user, so here's what I came up with:
def create_detail(self, object_list, bundle):
resource=BookResource()
book=resource.get_via_uri(bundle.data["book"], bundle.request)
return book.user == bundle.request.user
Anyways, bottom line: tastypie's docs are a little off.
And, I hope this helps.

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.

Unittest sensitive_post_parameters decorator in django view

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
)

ValueError: View didn't return an HttpResponse object. It returned None instead

def frontblog(request):
if request.method=='POST':
for post in Posts.objects(tags=request.POST('search')):
posttitle=post.post_title
postcont=post.post_content
postdate=post.post_date
posttag=post.post_tags
return render_to_response("frontblog.html",
RequestContext(request,
{'post':post}))
I have tried to send the data from mongo db database as by search using tag post get retrieved and should be send to display on html page.
NB : answer based on badly indented code, so it's a bit of a guessing game... but if you want a correct answer learn to post correctly indented code.
You start your code with a test on request.method=='POST' and everything else is under that branch, which means that if it's a GET request (or PUT or whatever) your view function implicitely returns None.
There are quite a few other WTFs in your code but fix this one first. BTW a "search" should be done as GET request, not POST. Also, in a POST request, request.GET will most probably be empty. Finally, you DO want to use a Form to sanitize user inputs... Well, unless you don't mind your site or app being hacked by the first script-kiddie, that is.

Tastypie Authorization not exactly authorizating?

Lets say that we want to be able to update only those objects of which the stage integer field is lower than 3. (or a similar example, that we want to limit the permission to object update only to the Owner users=fields.foreignkey). So the first example authorization will look like this:
class RecordAuthorization(Authorization):
def update_detail(self, object_list, bundle):
if bundle.obj.stage < 3:
return True
raise Unauthorized("You can't update this")
or the second example:
class RecordAuthorization(Authorization):
def update_detail(self, object_list, bundle):
if bundle.obj.user == bundle.request.user:
return True
raise Unauthorized("You can't update this")
Actually neither of them will work (I tested the first one and it does not work).
When you look closely into the tastypie documentation they say:
object_list is the collection of objects being processed as part of
the request.
So this means that in object_list, there are the json objects only rewrote to python list of dicts? So there are NOT the real object from database, therefore this filtering:
def update_list(self, object_list, bundle):
return object_list.filter(stage__lt=3)
won't work as expected (allowing updates only to objects having stage lower than 3). And will do something like-> if the json (sent through API, not the object in database) stage is lower than 3 allow updated. So actually you can update an object with stage=5 (in database) to stage=1!
I get the same strange results for the update_detail function, too. So I suspect that the bundle.obj is also the object but already with "json-updated" properties.
So to make things work I need to do this:?!
class RecordAuthorization(Authorization):
def update_detail(self, object_list, bundle):
if User.objects.get(pk=bundle.obj.user.pk) == bundle.request.user:
return True
raise Unauthorized("You can't update this")
For update_list, the object_list argument will be a queryset (or other iterable for non-Django ORM data sources) that should be filtered.
For update_detail, you want to check the properties of bundle.obj, which is an instance of your Resource.Meta.object_class, such as a Django model. If you set Resource.Meta.queryset, Resource.Meta.object_class is set for you.
There are indentation errors in your code, you should be raising Unauthorized at the method level, not the class level. If fixing that doesn't solve the issue, please post your resources.

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.

Categories