Django - Accessing model from django.contrib's User class via ManyToManyKey - django

I am making a Hacker News Clone in Django as taught in a Tuts+ Course [Git Repo]
In views.py file, for vote view, I tried using this code to increase security by checking if user has liked the story already.
#login_required
def vote(request):
story = get_object_or_404(Story, pk=request.POST.get('story'))
user = request.user
if user.is_authenticated() and story not in user.liked_stories:
story.points += 1
story.save()
user.liked_stories.add(story)
user.save()
return HttpResponse()
But it gives me this Error:
NameError: global name 'liked_stories' is not defined
[18/Aug/2013 19:26:43] "POST /vote/ HTTP/1.1" 500 11148
I am able to use user.liked_stories in index view so why not in vote view?
Error:
Internal Server Error: /vote/
Traceback (most recent call last):
File "/home/sourabh/.virtualenvs/django/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 115, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/home/sourabh/.virtualenvs/django/local/lib/python2.7/site-packages/django/contrib/auth/decorators.py", line 25, in _wrapped_view
return view_func(request, *args, **kwargs)
File "/home/sourabh/Code/django_apps/HackerNews/stories/views.py", line 53, in vote
if user.is_authenticated() and story not in liked_stories:
NameError: global name 'liked_stories' is not defined
[18/Aug/2013 20:08:35] "POST /vote/ HTTP/1.1" 500 11161

There you go:
if user.is_authenticated() and story not in liked_stories:
In this line the error is thrown. The code you have posted does not resemble the code you are executing.

Related

Django Rest Framework request header based permission

I'm building a Django app with Django Rest Framework to host it on my organisation's domain. The domain implements a custom authentication protocol. When someone accesses the domain, say to app1.domainname.com, they are redirected to the organisation's login page (login.domainname.com) and they have to log in with their staff account. After the user is authenticated, the user is redirected back to their initial destination (app1.domain.com). The information of the user is then stored in some custom header fields of the HTTP request sent to the app. E.g.
GET / HTTP/2
Content-Type:
User-Agent: ...
...
X-Username: johndoe1
X-Firstname: John
X-Lastname: Doe
X-Email: johndoe#domainname.com
etc.
I'm trying to implement custom permission for my REST API that looks for these fields in the headers, and then authorise the user based on their user information. This is what I'm currently having:
from rest_framework.permissions import BasePermission
allowed = ['johndoe1', 'dicksmith2', 'username3']
class CutomPerm(BasePermission):
message = "You don't have permission to access this object"
def has_object_permission(self, request, view, obj):
print(request.headers)
username = request.headers['X-Username']
return username in allowed
But when I run the server, it seems like the custom headers are passed through to the backend. For some requests they are, but ultimately the user is not authorised because the has_object_permission method raises a KeyError:
[10/Mar/2020 10:03:29] "GET /api/obj/ HTTP/1.1" 200 81
[10/Mar/2020 10:03:29] "GET /favicon.ico/ HTTP/1.1" 200 11
{'Content-Length': '', 'Content-Type': 'text/plain', 'Host': 'localhost:8000', 'Connection': 'keep-alive', etc., 'X-Username': 'johndoe1', 'X-Firstname': 'John', etc.}
Forbidden: /api/obj/1/
[10/Mar/2020 10:04:35] "GET /api/obj/1/ HTTP/1.1" 403 6581
{'Content-Length': '', 'Content-Type': 'text/plain', 'Host': 'localhost:8000', 'Connection': 'keep-alive', etc.} # no custom headers here
[10/Mar/2020 10:04:35] "GET /favicon.ico/ HTTP/1.1" 200 11
Internal Server Error: /api/obj/1/
Traceback (most recent call last):
File "/path/to/project/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/path/to/project/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/path/to/project/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/path/to/project/venv/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/path/to/project/venv/lib/python3.8/site-packages/rest_framework/viewsets.py", line 114, in view
return self.dispatch(request, *args, **kwargs)
File "/path/to/project/venv/lib/python3.8/site-packages/rest_framework/views.py", line 505, in dispatch
response = self.handle_exception(exc)
File "/path/to/project/venv/lib/python3.8/site-packages/rest_framework/views.py", line 465, in handle_exception
self.raise_uncaught_exception(exc)
File "/path/to/project/venv/lib/python3.8/site-packages/rest_framework/views.py", line 476, in raise_uncaught_exception
raise exc
File "/path/to/project/venv/lib/python3.8/site-packages/rest_framework/views.py", line 502, in dispatch
response = handler(request, *args, **kwargs)
File "/path/to/project/venv/lib/python3.8/site-packages/rest_framework/mixins.py", line 54, in retrieve
instance = self.get_object()
File "/path/to/project/venv/lib/python3.8/site-packages/rest_framework/generics.py", line 99, in get_object
self.check_object_permissions(self.request, obj)
File "/path/to/project/venv/lib/python3.8/site-packages/rest_framework/views.py", line 343, in check_object_permissions
if not permission.has_object_permission(request, self, obj):
File "/path/to/project/project/app/permissions.py", line 11, in has_object_permission
username = request.headers['X-Username']
File "/path/to/project/venv/lib/python3.8/site-packages/django/http/request.py", line 388, in __getitem__
return super().__getitem__(key.replace('_', '-'))
File "/path/to/project/venv/lib/python3.8/site-packages/django/utils/datastructures.py", line 320, in __getitem__
return self._store[key.lower()][1]
KeyError: 'X-Username'
Note that in the 2 header dictionaries printed out, the first one has all the custom headers but the second one doesn't.
I think this is because there are some redirecting happening behind the scene and the final request that gets to the rest framework permission check has lost all of its custom headers. Is there anyway to check for permissions based on the custom headers?
Thanks
Django modifies the http header keys.
You have to access the header as:
username = request.META.get('HTTP_X_USERNAME', None)
if username:
# your logic
pass
checkout Django header docs:
https://docs.djangoproject.com/en/3.0/ref/request-response/#django.http.HttpRequest.META

Getting "AuthStateMissing ... Session value state missing." when going to callback URI when using AtlassianOAuth2 with Django

I was trying to setup oauth2 authentication in a Django app. Here's my settings:
*other parts ommited*
# AUTH STUFF
AUTHENTICATION_BACKENDS = (
'social_core.backends.atlassian.AtlassianOAuth2',
'django.contrib.auth.backends.ModelBackend',
)
SOCIAL_AUTH_ATLASSIAN_KEY = ' *my atlassian key here* '
SOCIAL_AUTH_ATLASSIAN_KEY_SECRET = ' *my atlassian secret key here* '
LOGIN_URL = '/auth/login/atlassian-oauth2'
LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/'
SOCIAL_AUTH_URL_NAMESPACE = 'social'
SESSION_COOKIE_SECURE = False
# i had to do that^, based on what i have read from
# https://stackoverflow.com/questions/37617308/session-value-missing-after-redirect-with-django-python-social-auth
# but it still doesn't work, sadly...
And then here's my view for the login page:
def index(request):
session_id = request.session.session_key
session_id = hashlib.sha256(str(session_id).encode('utf-8')).hexdigest()
auth_url = 'https://auth.atlassian.com/authorize?audience=api.atlassian.com&client_id=*my_client_id_here*&scope=read%3Ajira-user%20read%3Ajira-work%20manage%3Ajira-project&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fcomplete%2Fatlassian%2F&state=$'+ session_id +'&response_type=code&prompt=consent'
print(auth_url)
context = {
'message': 'You are now authenticated'
if request.user.is_authenticated else 'You are not authenticated',
'auth_url': auth_url
}
return render(request, 'core/home.html', context)
to explain the stuff below --
the url that I used for Authorization grant before was just:
<a href="{% url "social:begin" "* name of backend here *" %}"> which is from the docs https://python-social-auth-docs.readthedocs.io/en/latest/configuration/django.html. It worked for facebook and google for me - but not with atlassian. So I checked the guide for the atlassian oauth2 (https://developer.atlassian.com/cloud/jira/platform/oauth-2-authorization-code-grants-3lo-for-apps/) and it said that I had to use the Jira Platform Rest API Authorization URL. So it worked for me. I was able to access the page where it asked for authorization from an Atlassian user.
When I click accept, Django Gives me an error that says "AuthStateMissing at /complete/atlassian/". The traceback shows that it raise AuthStateMissing(self, 'state'). I read from the Atlassian Guide that I had to have a state that is "a value that is associated with the user you are directing to the authorization URL, e.g., a hash of the user’s session ID", so I took the hash of the cookie of a user, then placed it to the auth_url -- but it still doesn't work.Here's the request information:
Here's the message from the terminal:
[15/May/2019 02:36:13] "GET /home/ HTTP/1.1" 200 1008
Internal Server Error: /complete/atlassian/
Traceback (most recent call last):
File "/home/vasiliy/.virtualenvs/dj_atlassian/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/vasiliy/.virtualenvs/dj_atlassian/lib/python3.7/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/vasiliy/.virtualenvs/dj_atlassian/lib/python3.7/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/vasiliy/.virtualenvs/dj_atlassian/lib/python3.7/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File "/home/vasiliy/.virtualenvs/dj_atlassian/lib/python3.7/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/home/vasiliy/.virtualenvs/dj_atlassian/lib/python3.7/site-packages/social_django/utils.py", line 49, in wrapper
return func(request, backend, *args, **kwargs)
File "/home/vasiliy/.virtualenvs/dj_atlassian/lib/python3.7/site-packages/social_django/views.py", line 33, in complete
*args, **kwargs)
File "/home/vasiliy/.virtualenvs/dj_atlassian/lib/python3.7/site-packages/social_core/actions.py", line 43, in do_complete
user = backend.complete(user=user, *args, **kwargs)
File "/home/vasiliy/.virtualenvs/dj_atlassian/lib/python3.7/site-packages/social_core/backends/base.py", line 40, in complete
return self.auth_complete(*args, **kwargs)
File "/home/vasiliy/.virtualenvs/dj_atlassian/lib/python3.7/site-packages/social_core/utils.py", line 259, in wrapper
return func(*args, **kwargs)
File "/home/vasiliy/.virtualenvs/dj_atlassian/lib/python3.7/site-packages/social_core/backends/oauth.py", line 388, in auth_complete
state = self.validate_state()
File "/home/vasiliy/.virtualenvs/dj_atlassian/lib/python3.7/site-packages/social_core/backends/oauth.py", line 90, in validate_state
raise AuthStateMissing(self, 'state')
social_core.exceptions.AuthStateMissing: Session value state missing.
really hope you guys could help. thanks
in my settings.py file.
SOCIAL_AUTH_REDIRECT_IS_HTTPS = True
My production server uses nginx to redirect HTTP to HTTPS, and this was the cause for the session state to go missing. Good luck-- hope this helps!

Test permission denied not catched

I try to check with unittests if it is possible to access a certain url without the proper permissions.
When I wrote the test everything worked correctly. I don't know if the error started to occurs after a Django update because I didn't check the test after the update and just started to write new tests which failed. So I checked my old test which is now failing too.
class MemberTestMethods(TestCase):
def setUp(self):
# Create user
user = User.objects.create_user('temp', 'temp#temp.tld', 'temppass')
user.first_name = 'temp_first'
user.last_name = 'temp_last'
user.save()
# login with user
self.client.login(username='temp', password='temppass')
# Create member
member = Member.objects.create(salutation=Member.MR, first_name='Temp', last_name='Temp')
member.save()
def test_member_list_permission(self):
"User should only access member list if view permission is set"
user = User.objects.get(username='temp')
response = self.client.get(reverse('members:list'))
self.assertEqual(response.status_code, 403)
user.user_permissions.add(Permission.objects.get(codename='view_member'))
response = self.client.get(reverse('members:list'))
self.assertEqual(response.status_code, 200)
After running python manage.py test I get the following error
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
WARNING:django.request:Forbidden (Permission denied): /de/reporting/
Traceback (most recent call last):
File "/home/***/.virtualenvs/pyVerein/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/***/.virtualenvs/pyVerein/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/***/.virtualenvs/pyVerein/lib/python3.6/site-packages/django/core/handlers/base.py", line 124, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/***/.virtualenvs/pyVerein/lib/python3.6/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/home/***/.virtualenvs/pyVerein/lib/python3.6/site-packages/django/contrib/auth/mixins.py", line 52, in dispatch
return super().dispatch(request, *args, **kwargs)
File "/home/***/.virtualenvs/pyVerein/lib/python3.6/site-packages/django/contrib/auth/mixins.py", line 84, in dispatch
return self.handle_no_permission()
File "/home/***/.virtualenvs/pyVerein/lib/python3.6/site-packages/django/contrib/auth/mixins.py", line 43, in handle_no_permission
raise PermissionDenied(self.get_permission_denied_message())
django.core.exceptions.PermissionDenied
Previously the test ran successfully while checking for HTTP-Code 403 like it is describe in the documentation (https://docs.djangoproject.com/en/2.1/topics/testing/tools/#exceptions)
The full Sourceode is available at Github (https://github.com/HamburgerJungeJr/pyVerein/tree/pyReportJasper/pyVerein/members)
Am I missing a change in the Django-Test system?
I just found the solution. The PyReportJasper-package set the global logging level to INFO. After changing this the error is gone.

django-social auth example app giving ValueError(Missing backend entry)

While using the example app of the django social-auth the user can login to the social accounts but when they are redirected back to our portal it gives a value error Missing backend entry.
Actual error:
[01/Nov/2013 15:49:21] "GET /login/twitter/ HTTP/1.1" 302 0
[01/Nov/2013 15:49:25] "GET /complete/twitter/?oauth_token=ZETJZMsQQhdWzawgrt8xI
9DMEfyCb2N8jpXkVpYfC8&oauth_verifier=zmIXXCAfa2foLolK1v8PIBMQLlrQD6uEYiJ8fwjT14HTTP/1.1" 302 0
Internal Server Error: /login/error/
Traceback (most recent call last):
File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 115, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "C:\Python27\lib\site-packages\python_social_auth-0.1.14py2.7.egg\social\apps\django_app\utils.py", line 31, in wrapper
redirect_uri=uri, *args, **kwargs)
File "..\social_auth\views.py", line 19, in load_strategy
return get_strategy(BACKENDS, STRATEGY, STORAGE, *args, **kwargs)
File "C:\Python27\lib\site-packages\python_social_auth-0.1.14-py2.7.egg\social\strategies\utils.py", line 10, in get_strategy
raise ValueError('Missing backend entry')ValueError: Missing backend entry

BaseDeleteView throws AttributeError (render_to_response missing)

I try to implement a view based on BaseDeleteView for a website that acts as a frontend to an REST backend. Both sides communicate over HTTP requests. What I want to achieve is that I send a GET request to an activation URI (send per email after registration). Inside this view I first send a HTTP request to a backend, and then delete the activation object from the database of the frontend. I don't want to have a confirmation page, so DeleteView is not possible.
class ActivationView(BaseDeleteView):
success_url = "/activation/success/"
def get_object(self, queryset=None):
uuid = self.kwargs['uuid']
try:
obj = AccountRegistration.objects.get(uuid=uuid)
except ObjectDoesNotExist:
raise Http404('Registration not found.')
return obj
def delete(self, request, *args, **kwargs):
obj = self.get_obj()
if obj.expire_date < datetime.now():
obj.delete()
raise Http404('Registration expired.')
# send a http request to the backend
t = Transaction('/activate/%s/' % obj.account_name)
t.emit()
# delete the object
obj.delete()
# and redirect the request
return HttpResponseRedirect(self.get_success_url())
My urls.py looks like that:
url(r'^activate/(?P<uuid>\w+)/$',
ActivationView.as_view(), name="account-activate"),
But I get the following error:
Traceback (most recent call last):
File "/home/crito/.pythonbrew/venvs/Python-2.7.2/thirty-web/lib/python2.7/site-packages/django/contrib/staticfiles/handlers.py", line 68, in __call__
return self.application(environ, start_response)
File "/home/crito/.pythonbrew/venvs/Python-2.7.2/thirty-web/lib/python2.7/site-packages/django/core/handlers/wsgi.py", line 272, in __call__
response = self.get_response(request)
File "/home/crito/.pythonbrew/venvs/Python-2.7.2/thirty-web/lib/python2.7/site-packages/django/core/handlers/base.py", line 169, in get_response
response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
File "/home/crito/.pythonbrew/venvs/Python-2.7.2/thirty-web/lib/python2.7/site-packages/django/core/handlers/base.py", line 203, in handle_uncaught_exception
return debug.technical_500_response(request, *exc_info)
File "/home/crito/.pythonbrew/venvs/Python-2.7.2/thirty-web/lib/python2.7/site-packages/django/core/handlers/base.py", line 111, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/home/crito/.pythonbrew/venvs/Python-2.7.2/thirty-web/lib/python2.7/site-packages/django/views/generic/base.py", line 47, in view
return self.dispatch(request, *args, **kwargs)
File "/home/crito/.pythonbrew/venvs/Python-2.7.2/thirty-web/lib/python2.7/site-packages/django/views/generic/base.py", line 68, in dispatch
return handler(request, *args, **kwargs)
File "/home/crito/.pythonbrew/venvs/Python-2.7.2/thirty-web/lib/python2.7/site-packages/django/views/generic/detail.py", line 100, in get
return self.render_to_response(context)
AttributeError: 'ActivationView' object has no attribute 'render_to_response'
In my eyes it shouldn't even call render_to_response. Any ideas?
If you want to leave out the confirmation page, just call your DeleteView directly with POST. This is most desirable as the deletion of an object should be protected by csrf.
You've inherited from BaseDeleteView, which as the documentation states, doesn't include the TemplateResponseMixin - ie all the bits that are to do with rendering a response.
Inherit from DeleteView instead.