Restrict access to Django template - django

I need to restrict access to a template in Django. This is the scenario:
A guest user uses a form
If the form is validated and fine send the user to the example.com/success/ url.
If the guest user tries to send that link example.com/success to a friend. The friend will see that page as a 404.
I have no clue how to achieve this. Any ideas?

Instead of going to a different URL (/success/), you could just show something different when the form was properly filled. For example, in your view:
def my_view(request, ...):
form = ...
show_success = False
if ... post method ...:
if form.is_valid():
... save etc. ...
show_success = True
return render(request, ..., {'show_success': show_success})
In your template:
{% if show_success %}
Success message here
{% else %}
Form here
{% endif %}

Related

Why is my ModelForm not showing the right settings?

I have two Model Forms, one for notification types and one for privacy settings. Both show the defaults and not what is saved in the database. How can I make the form show the choice that's stored in the database instead of the defaults? Example: Say the user chose a Direct Message privacy of "Friends and Followers". When they visit the privacy options page again after having saved the changes, it shows "Open" instead of reflecting what is in the database. I tried assigning the values saved in the database directly to the form when rendering the page when the request is GET but that didn't do anything, even though the debug print shows that the value of form.dm_privacy is indeed what's in the database, it still shows "Open".
Both forms work fine, the changes get saved and everything. I don't understand why it's not reflecting the changes though, is this just something that Model Forms do and not something I can change?
privacy_options.html
{% extends "accbase.html" %}
{% block content %}
<h1>Privacy Options</h1>
<form method="post">
{% csrf_token %}
{{form.as_p}}
<button type="submit">Save</button>
</form>
{% endblock %}
views.py
#login_required
def privacy_options(request):
"""
Holds all privacy options such as.. open/closed DMs, who can see profile/posts on profile
"""
if request.method == "POST":
form = PrivacyOptionForm(request.POST)
if form.is_valid():
print("Before saving:",request.user.dm_privacy, request.user.profile_privacy, request.user.included_in_find_friends)
user = request.user.username
request.user.dm_privacy = form.cleaned_data['dm_privacy']
request.user.profile_privacy = form.cleaned_data['profile_privacy']
request.user.included_in_find_friends = form.cleaned_data['included_in_find_friends']
request.user.save()
print("After save:",request.user.dm_privacy, request.user.profile_privacy, request.user.included_in_find_friends)
return render(request, 'acc_manage/acc_nav.html', {'username':user})
else:
form = PrivacyOptionForm()
form.included_in_find_friends = request.user.included_in_find_friends
form.profile_privacy = request.user.profile_privacy
form.dm_privacy = request.user.dm_privacy
print("\n\n",form.dm_privacy, "\n\n")
return render(request, 'acc_manage/privacy_options.html', {'form': form})
Fixed it by changing form = PrivacyOptionForm() to form = PrivacyOptionForm(instance=request.user)

Django user permission inside template

I created a custom auth permission in django via admin site, and i added that permission to a user (not a group), now i want to ask if the request user in a template has it but nothing works.It's not a duplicate, i already checked similar questions and none of this work:
{% if perms.auth.add_something %}
{% if 'auth.add_something' in request.user.get_all_permissions %}
{% if request.user.has_perm('add_something') %}
I add my view:
class NotificationSelectView(View):
template = 'myapp/notification_read.html'
def get(self, request, *args, **kwargs):
t = tree(request)
req_var_list = []
analist = notifications_list(request.user)
level = LevelProcess.objects.get(
level_hierarchical = 3
)
subprocess= Process.objects.filter(level = level)
user = request.user
t.update({
'subprocess': subprocess,
'analist':analist,
})
return render(request, self.template, t)
The idea it's to make it inside template, not to use more code in views.
Any ideas ?, thanks in advance.
django in template it uses the variable perms for the permissions of the logged in user so you can use inside template
{% if perms.auth.add_something %}
{{do_smth}}
{% endif %}
from the django documentation there is a section Authentication data in templates which describes also permissions in templates

how can I ensure a user will not delete another user object in my website [Django]

I wrote a function that allows the user to delete his article on a blog website. The problem is, if he plays a little with the url, he can access to another article and delete it.
What is the common strategy to avoid such cases with django?
here are the codes I wrote for the fonction:
views.py
def delete_article(request, id):
deleted = False
logged_user = get_logged_user_from_request(request) #that line allow to ensure that the user is connected. I use the session to achieve that instead of extending the User model
offer = get_object_or_404(Offer, id=id)
if request.method == 'POST':
offer.delete()
deleted = True
return render(request, 'offers/delete_article.html', locals())
urls.py
urlpatterns = patterns('article.views',
url(r'^send_article$', 'send_article', name='send_article'),
url(r'^my_articles$', 'show_my_articles', name='my_articles'),
url(r'^article/(?P<id>\d+)$', 'read', name='read'),
url(r'^articles$', 'show_articles', name='articles'),
url(r'^search_article$', 'search', name='search'),
url(r'^delete_article/(?P<id>\d+)$', 'delete_offer', name='delete_offer'),
)
delete_article.html
{% if not deleted %}
Hey, are you sure you want to delete {{ article.title }}?
<form method="POST">
{% csrf_token %}
<button type="submit" class="deleting_offer_button">delete</button>
</form>
{% elif deleted %}
<p>the article was successfully deleted</p>
get back to the homepage<br />
{% endif %}
As you can see, if the user change the numer of the id in the url, he can delete other article when he is directed to the confirmation of deleting page.
What webmasters are doing to ensure users cannot interfere with objects of other users?
HttpResponseForbidden can be used here which uses a 403 status code. A 403 response generally used when authentication was provided, but the authenticated user is not permitted to perform the requested operation.
Assuming you have author as an foreign key in Offer model, you can change your views like this:
In your views.py you have to import :
from django.http import HttpResponseForbidden
And then in your delete_article method use this code
offer = get_object_or_404(Offer, id=id)
if offer.author != request.user:
return HttpResponseForbidden()
When you get the article/offer. Make sure that the owner of that article is the authenticated user.
I'm not sure what your models look like but it would be something like
offer = get_object_or_404(Offer, id=id, author=logged_user)
This way if they don't own the article, it will 404

Different ways for sending request context with HttpResponseRedirect in django

I have a django app and implemented payment gateway functionality.
Now what i was trying is
After successful transation, need to do redirect user to another page that shows the response details so i am using HttpresponseRedirect to redirect the page, but i have the variable response in the view that contains reponse details, so i need to send this variable as the context to the redirecting url that renders template, so that i can use that response variable to display the results.
so for the above functionality, i got three methods
Sending the variable as the query parameter(which is not safe in this method because it is sensitive credit card transaction details)
Using session framework, which is not working in my case, the code is below
Django messaging framework(which is not so useful in this case)
views.py
def payment(request):
amount = 1
if request.method == 'POST':
form = CreditCardForm(request.POST)
if form.is_valid():
data = form.cleaned_data
...........
...........
response = stripe.payment_purchase(amount,data)
request.session['response'] = response
return HttpResponseRedirect(reverse('paygate:payment_success'))
else:
form = CreditCardForm(initial={'number':'4242424242424242'})
return render_to_response('payment/stripe_payment_form.html',{'form': form,
'response':response,},
context_instance=RequestContext(request))
payment_success url view
class PaymentSuccess(TemplateView):
template_name = 'payment/payment_success.html'
I tried to access response variable in the template, but displaying nothing
payment_success.html
{% extends "base.html" %}
{% block main_title %}Payment{% endblock %}
{% block title %}Success{% endblock %}
{% block content %}
<h1>Response Details</h1>
<p>Your status is <span>{{ request.session.response }}</span></p>
{% endblock %}
So can anyone please let me know the various different safe and secure ways to send context variables(in this case credit card payment details) to redirecting url using HttpResponseRedirect method
I think there is a 4. possible item in your list, that I suggest to use.
The safest and most pragmatic way of accomplish what you want is to have a successful view showing the actual results stored in your database.
The idea behind this is:
payment view is an action that a user performs on your database.
payment_success view is a way of telling the user that the action was performed successfully and with the the input the user desired.
Likewise, the best way of showing that the action is correct is to show its result on the database, i.e. what it is now stored on the database regarding that action.

Django Context contains not defined field when using RequestContext

Hi I'm writing a django project, and I write template code like this:
<ul id="nav">
<li>Home</li>
<li>Users</li>
{% if user %}
<li>Settings</li>
<li>Log Out</li>
{% else %}
<li>Log In</li>
<li>Sign Up</li>
{% endif %}
</ul>
Now in login view I write like this:
def login(request):
if user_logged_in(request):
return redirect('/')
if request.method == 'GET':
form = LogInForm()
return render_to_response(LOGIN_PATH, {'form':form}, context_instance=RequestContext(request))
But when I run the server, no user is logged in, and visit login page, it shows Settings and Log Out(there is a user object in context), but it shouldn't!
If I remove RequestContext, say return render_to_response(LOGIN_PATH, {'form':form}), it will be OK. And
return render_to_response(LOGIN_PATH, {'form':form, 'user':None}, context_instance=RequestContext(request))
is OK too. But I don't want to do it.
I know it's dirty design, well... I'm looking for suggestions and solutions. Many thanks~!
{% if user.is_authenticated %}
your tag just checks for a user object, not for an authenticated one.
check here for more informations on what you can do with an auth user :)
The default setting for TEMPLATE_CONTEXT_PROCESSORS includes "django.contrib.auth.context_processors.auth". This context processor adds a user to cotnext, which will be anonymous if the user is not provided in request so.
If you want to be able to know whether or not the user is authenticated in template the #Samuele Mattiuzzo answer is what you should use, but if you don't want, for any reason, to include the user in context, then you need to modify the default TEMPLATE_CONTEXT_PROCESSORS setting without the auth context processor.
For more information read the docs or the code.