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()
Related
When trying to access url get_room_messages if user is not logged in #login_required redirects him to: /accounts/login/?next=/get_room_messages
(as specified in docs)
I want it to do nothing (or redirect to the original url, in this example /get_room_messages). I don't want to hardcode it like #login_required(login_url='/get_room_messages'), ideal solution would be to get somehow original url and pass it into #login_required() decorator.
#login_required()
def get_room_messages(request):
user_id = request.user.user_ID
user = get_object_or_404(CustomUser, pk=user_id)
Thank you for help!
So I have a a HTML page with a table in it which contains details of a certain model. Each row contains details of a different object. I have a cell for a button as well.
Now, what I want is for the user to be able to click on the button and it should take them to the appropriate page for that particular user that they've clicked on. The way I can do this now is by creating a URL that takes a user_id argument along with a view to redirect it to a template. This url can then be added to the button. However, I don't want the user_id to be shown in the URL (being shown in Inspect Element is okay (as in the row ID)).
This rushed, so sorry. How can I do this?
Is there a way to do it without putting any information whatsoever in the URL?
Thank you!
One way to do this is to send user ids from a POST instead of a GET for getting the user info, when the user clicks the button, you submit a hidden form which contains user_id (which you will update accordingly) and pass it to Django. On this POST call you will wire a render of the page for the user according to the POST parameter you are expecting containing the user id.
You can read the post parameters on a request via:
request.POST.get('user_id')
The downside of this approach is that you won't be able to share the link for a certain user, because the link will only contain the get parameters.
Maybe you can refactor your application to use some kind of SPA framework on the front-end. In this way you can load any content on your current page and the URL never changes if you don't want. Take a look for example at AngularJS or Durandal. Both works well with Django.
You can also solve the problem by using POST instead of GET but in my opinion that's not a very elegant solution because POST requests should be used just when you send data to the server.
If your worried about security I don't think keeping the user_id secret will be effective but if for some other reason you have to do this put it in session and redirect to user page without any parameters.
Put your table inside a form and store the id in an attribute of the button on each row:
<button class="mybutton" data-id="{{ my_object.id }}">view</button>
Put a hidden field at the bottom of your form:
<input type="hidden" id="user_id" name="user_id" />
Javascript:
$("table .mybutton").click(function(e) {
e.preventDefault();
$("#user_id").val($(this).attr("data-id"));
$("#my_form").submit();
});
In your table view:
if request.method == "POST":
request.session["user_id"] = request.POST.get('user_id')
return redirect("user_page")
In your details view:
user_id = request.session["user_id"]
creating urls
If the url is relevant to the user; then use the user_id; e.g. http://example.com/mysite/users/<user_id>/userstuff.
obfuscation is not security.
obfuscation is not a permission scheme.
Other possibilities:
http://example.com/mysite/users/<uniqueusername>/userstuff.
http://example.com/mysite/users/<slug>/userstuff.
http://example.com/mysite/users/<encoded>/userstuff, where encoded is either 2-way encoding, or a field on the user model that is unique.
getting logged in user (request.user)
If the url has nothing to do with the user, but you need to get the authenticated user then read the docs: https://docs.djangoproject.com/en/1.7/topics/auth/default/#authentication-in-web-requests.
def my_view(request):
if request.user.is_authenticated():
# use request.user
else:
# something else
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...
Till now i have been using userid's (pk) as an argument in the profile urls for my application. Recently i decided to use the username instead of the user id's So i changed the following :
Urls.py
# This was what i was using previously
url(r'^profile/(?P<uid>\d+)/$', 'app.views.user_profile', name="profile"),
# Changed the above to this.
url(r'^profile/(?P<username>[-\w\d]+)/$', 'app.views.user_profile', name="profile"),
Views.py
# Previous view
#login_required
def user_profile(request, uid):
user = get_object_or_404(models.User, pk=uid)
profile = helpers.get_profile(user)
render_to_response('profile.html', {'profile' : profile})
# Changed the above to
#login_required
def user_profile(request, username):
user = get_object_or_404(models.User, username=username)
profile = helpers.get_profile(user)
render_to_response('profile.html', {'profile' : profile})
Until Now it's all good. When i try to visit 127.0.0.1:8000/profile/some_username/ instead of the previous 127.0.0.1:8000/profile/some_number/ it works fine.
I have a toolbar in the profile.html, which contains links such as:
/profile/edit/
/profile/settings/
in the urls.py these urls map to very simple views. Such as the following.
#login_required
def profile_settings(request):
"""
This view helpers.renders the profile's settings panel
"""
print 'hello'
rec, can = helpers.get_user_or_noprofile(request.user)
if not can is None:
gform = forms.CandidateGeneralSettingsForm(instance=can)
jsform = forms.CandidateJobSearchSettingsForm(instance=can)
data = {'candidate' : can, 'gform' : gform, 'jsform' : jsform }
else:
form = forms.RecruiterSettingsForm(instance=rec)
data = { 'recruiter' : rec, 'form' : form }
return helpers.render(request, 'profile_settings.html', data)
The weird part is after i changed to use username in the profile url. As soon as i click on any of the links in the toolbar, i see the 404 : Error : No User matches the given query. page.
To debug i tried printing a few debug statements within these views and found out something more weird. Nothing gets printed even if i Comment the whole code inside the view and just write a print statement.
This makes me doubt that the problem might be with the login_required decorator. but if that's the case howcome it is working while visitng 127.0.0.1:8000/profile/some_username/.
I really can't think of anything that might be causing this. Any help will be greatly appreciated. Thanks.
PS: Also, JFYI, i am using a custom Email Authentication backend that lets user login through their email address instead of the username.
It doesn't work because edit is not a valid username.
This url /profile/edit/ matches ^profile/(?P<username>[-\w\d]+)/$, and username becomes edit.
Since you don't have a user called "edit", this user = get_object_or_404(models.User, username=username) fails, and raises a 404.
The same for /profile/settings/.
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>