django - limit users to edit only their own information - django

I'm playing around with django and built a small app where a user can access their info via the url http:///localhost:8000/username/info/ . I want to add the ability to edit that info through http:///localhost:8000/username/info/edit/, but also want to make sure the currently logged in user (using django.contrib.auth) can access only his information. I accomplished this by doing the following in the view (username in the view args is captured from the url):
#login_required
def edit_info(request, username=''):
if request.user.username == username:
# allow accessing and editing the info..
else:
# redirect to some error page
So, obviously, I don't want user 'johnny' to edit the info belonging to user 'jimmy' by simply pointing his browser to /jimmy/info/edit/. The above works, but my concern is that I'm missing something here as far as security goes. Is this the right way to go about this?
Thanks.

This should work for what you are trying to do without any glaring security risks.
But, why show their username if no one else can see at least a profile or something at this location though? Wouldn't this be more like a 'account' page? Then you wouldn't check against the username in the url, the only url you could go to would be account, and it would just load the logged in user's info.

With the #login_required and parsing the request.user they will never end up on anothers profile. My profile view
#login_required
def user_profile(request):
""" User profile page """
u = User.objects.get(pk=request.user.pk)
return render_to_response('myapp/user_profile.html', {
'user': request.user,
})
Then in the template simply use stuff like:
Welcome <b>{{ user.first_name }} {{ user.last_name }}</b>

Related

django login_required for variable urls

I am trying to write a basic website in django. I need the user (i'm still using the default one) to be able to login, logout, register, etc. I have the basic functionality set up, but I want the user to be able to visit a profile page where it will display basic information about the user. Naturally, the profile page must use the login_required decorator but the way I have it set up now is that once anybody signs in they can see any profile page.
Part of the URL file:
url(r'^profile/(?P<username>[\w.#+-]+)/$',
login_required(ProfilePageView.as_view())),
As you can see, the url should consist of "profile/" follow by the username of the user. How can I set it up so that only the user with the username following the "profile/" part of the url can see that page. With this code some user could login with any username and then just change the url and resend the get request.
You can do something like this. if you have created a Profile model for each user you can also access the Profile information using profile_info=request.user.profile
def login_user(request):
username=request.POST.get('username','')
password=request.POST.get('password','')
user=auth.authenticate(username=username,password=password)
if user is not None:
auth.login(request,user)
return HttpResponseRedirect('/loggin/')
else:
return HttpResponseRedirect('/invalid/')
def loggin(request):
username=None
if request.user.is_authenticated:
#profile_info=request.user.profile
info=request.user
return render(request,'base.html',locals())
<head>
<body>
<h5>{{info.first_name}}{{info.first_name}}</h5>
</body>
</head>

How to get request.user in a code, which does not have any relation to views?

I want to get user.pk from request (for logged in user) in order to avoid additional DB queries.
In views there is incoming request variable. How to get this request somewhere else (not in views)? Directly importing HttpRequest does not help, because HttpRequest gets user object because of middleware modification. How can I get this 'modified' HttpRequest with user object? What do I need to import?
EDIT:
I want to implement customized user address, so user may have 2 types of addresses, like mysite.com/username or mysite.com/id123, so one link from navigation menu (My page) is dynamic. For the creation of navigation menu I use django-sitetree, where I want to do something like:
from sitetree.sitetreeapp import register_items_hook
def my_items_processor(tree_items, tree_sender):
# get somehow `request`
if tree_sender == 'menu.children':
for item in tree_items:
if request.user.username:
item.url = request.user.username
else:
item.url = request.user.pk
return tree_items
I just answered this same question (albeit relating to forms) in another question. Please see my answer there.
Assuming you have setup threadlocals.py as detailed in that post, and stored it as sitetree/threadlocals.py:
from sitetree.sitetreeapp import register_items_hook
from sitetree.threadlocals import get_current_user
def my_items_processor(tree_items, tree_sender):
user = get_current_user()
if tree_sender == 'menu.children':
for item in tree_items:
if user.username:
item.url = user.username
else:
item.url = user.pk
return tree_items

django User registration and authentication by email

I want to make users active by sending them an activation email to click. I guess it is currently not incorporated in Django 1.6.The user-registration app coded in Django seems to serve this purpose. But I have some doubts with regard to the DefaultForm it provides in forms.py. I want to have more fields included in it. How can I achieve that in class RegistrationForm(forms.Form) implemented there. If I install this app, is it a good idea to change include more fields directly there, is there a better way to achieve the same.
In the views.py, I see some methods such as the following are not implemented. I dont have a clear picture of what these methods need to do. should I redirect the url here to the pages?
def register(self, request, **cleaned_data):
raise NotImplementedError
def activate(self, request, *args, **kwargs):
raise NotImplementedError
def get_success_url(self, request, user):
raise NotImplementedError
You need to first let them sign up and mark them as is_active=False for the time being. Something like this:
from django.contrib.auth.models import User
from django.core.mail import send_mail
from django.http import HttpResponseRedirect
def signup(request):
# form to sign up is valid
user = User.objects.create_user('username', 'email', 'password')
user.is_active=False
user.save()
# now send them an email with a link in order to activate their user account
# you can also use an html django email template to send the email instead
# if you want
send_mail('subject', 'msg [include activation link to View here to activate account]', 'from_email', ['to_email'], fail_silently=False)
return HttpResponseRedirect('register_success_view')
Then once they click the link in the email it takes them to the next view (note: you need to put a link in the email so that you know which user it is. This may be 16-digit salt or something. The below view uses the user.pk:
def activate_view(request, pk):
user = User.objects.get(pk=pk)
user.is_active=True
user.save()
return HttpResponseRedirect('activation_success_view')
Hope that helps. Good Luck!
Basically you can use django's user model(https://docs.djangoproject.com/en/1.9/ref/contrib/auth/). However, in user model email is not a required field. You need to modify the model to make email an required field.
In your views, you might need the following method:
1) Sign up: after sign up, set user.is_active=False and call function send_email to include an activation link in the email. In the link, you might want to include the user's information (for example, user.id) so when the user click the link, you know which user to activate.
2) send_email: send a link to user's email address for verification. The link includes user's id. For example:
http://127.0.0.1:8000/activation/?id=4
3) Activate: get the id information from the URL using id=request.GET.get('id'). Query user=user whose id is id. set user.is_active=True.
Actually I implemented an reusable application like your request, check this(https://github.com/JunyiJ/django-register-activate) if you are interested.
Hope that helps. Good luck!
check this out... i Hope it helps out with not only the solution u need but also the explanation.. Because i think django-registration app is meant for default Django User. So if u want to have extra fields in your registration form, Start thinking of customizing ur Django User and Its authentication yourself. You dont need the django-registration app here..
Here are some tutorials thats will help
http://www.caktusgroup.com/blog/2013/08/07/migrating-custom-user-model-django/
and many more...

django : already logged in but, request.user.is_authenticated is guest

My website use to login function of django.contrib.auth.views.login.
But, some pages has problems about getting user information.
I tried to request.user & request.user.is_authenticated(). then request.user = "admin"(ok) but, request.user.is_authenticated() = guest..
And, Staying logged in After close browser.
what is problem?
Thank you.
If some pages will not show {{ user }} but others will, you're most likely not using RequestContext in the views where the user isn't available.
You can use a function like django's render shortcut to automatically use RequestContext.
As for the user staying logged in after closing the browser - that's normal. Your user is identified by a cookie that sits on your browser and is persistent.

Need help on django urls

How to validate the url if some change the name in url and update the form,
Suppose :
If i want to update a profile ,after click on the update button.ulr link will be like below
url : http://localhost:8000/profile_edit/sushanth/
i found there is an security loop here,a person can change the name on the url and he can edit other person profile,how to close this loop hole while updating the form in django.
Thanks in advance...:)
You just need to check in your view that the user is the correct one.
#login_required
def profile_edit(request, username):
if username != request.user.username:
return HttpResponseNotAllowed()