How to send password reset mail from custom Django views? - python

I have Django 2.0.2 with custom User model. One of feature is give anonymous users way to create order without "register-first" on site.
Main idea is:
Anonymous user fill order form, enter e-mail address and click Create Order;
Django create User with entered e-mail and random generated password;
Next, Django (or Celery) send to e-mail link for reset password (like from standard reset form);
User check e-mail and click to reset link, re-enter his own password.
This was killed two functions by one: user register and create first order.
And question: how can I send reset password mail from my custom views? I understand, link will generate and send on PasswordResetView view, but how to call to them on custom view?

To send the password reset link from a view you can fill out a PasswordResetForm which is what is used by the PasswordResetView
https://docs.djangoproject.com/en/2.0/topics/auth/default/#django.contrib.auth.forms.PasswordResetForm
As described in another stackoverflow answer here https://stackoverflow.com/a/30068895/9394660 the form can be filled like this:
from django.contrib.auth.forms import PasswordResetForm
form = PasswordResetForm({'email': user.email})
if form.is_valid():
request = HttpRequest()
request.META['SERVER_NAME'] = 'www.mydomain.com'
request.META['SERVER_PORT'] = '443'
form.save(
request= request,
use_https=True,
from_email="username#gmail.com",
email_template_name='registration/password_reset_email.html')
Note: if you are not using https replace the port with 80 and dont include use_https=True
Also depending on the situation you may already have a request and wouldn't need to create one

Related

Reset password after first successful login in Django python

I am building an web application using existing Auth features in Django where admin create user profile with username and password. Admin created user name and password will be given to user to login. So for security reasons I need to ask user to reset password (given by admin) after user's first successful login. To reset password, I will be displaying template where user should be entering only new password and new password again for confirmation. This new password will be updated in sqlite database.
So whenever admin changes the users password. I need to ask users to reset password after first successful login.
I know this if off topic for stacoverflow and for reasons I couldnt post a question in StackExchange. Please refer me or help will be appreciated.
You can have a boolean attribute in the User model which gets set True, whenever Admin user sets the password for that user.
Then in middleware, you can check if that User needs to set the password, then correspondingly you can redirect the user to Reset password view.
You can use these blogs to create a password reset views. Middleware logic you need to write by yourself, for setting that attribute you can override User save in admin.py, set that attribute and call super

When to redirect when to render

​My scenario:
​My app, handles signup at /profile/signup/ using SingupView(FormView).
class SignupView(FormView):
template_name = "profile/signup.html"
template_name_signup_confirmed = "profile/created.html"
template_name_inactive = "profile/inactive.html"
def form_valid(self, form):
# Create and save inactive user
self.created_user = self.create_user(form, commit=False)
self.created_user.is_active = False
self.created_user.save()
# Create and save user's profile
profile = self.create_profile(form)
# Send registration email
self.send_registration_email([self.created_user.email], registration_code=profile.registration_code)
# Response
return render_to_response(self.template_name_signup_confirmed, {'email': self.created_user.email})
def form_invalid(self, form):
if 'email' in form.errors and form.errors['email'].as_text() == \
'* An inactive user is registered with this email address.':
return render_to_response(self.template_name_inactive, {'email': form.data["email"]})
return render_to_response(self.template_name, self.get_context_data(form=form))
In SingupView().form_valid(form) the User and his Profile are created, user is signed up, but inactive.
After that, in my case there is not success url to redirect, but render a new page, at the same address (/profile/signup/) with a new html saying "An email was sent at youremail#email.com, check and activate".
The same case when an inactive, registered user, tries to signup again, he will get a new page, rendered at the same adress /profile/signup/ saying 'Your email youremail#email.com is already in our db but is not active.. .'
My questions:
Can anyone explains if this is a good way to go, or I need to redirect to new urls, controlled by a new views?
Is there any security risk by using render instead of redirect? Especially on user sign in/sign up?
What is the difference when using redirect or render a new template at the same address? What is the best practice in Django?
Is it ok, to display user's email, in the signup confirmation page and also in the alert page that says that user is registered but inactive in db?
The common pattern for this sort of behaviour is to use a redirect.
I would personally prefer that as it avoid the confuson of one view doing two things - one view displays and processes the form, the other displays a success message.
If the user manages to POST the form data a second time, what do you do?
https://en.wikipedia.org/wiki/Post/Redirect/Get
I am not aware of any greater security risk from using render rather than redirect (though someone with more expertise may know more than me about that).

Keep User authenticated using Django Rest and Phonegap?

I have read multiple tutorials on authentication but I am just as confused. I am trying to log a user in using an html form on the client device, which means I'm not using Django templates. Does it work like the following?
I send a post to rest backend with username, password combo
Django rest checks to see if valid user, and sends token back?
I save token in local storage, and send with every request of user?
What do I send from the front end to make this happen?
Yes, send a post request to a RESTful backend with username and password combo
Django authenticates the username and password and logs the user in which sets a sessionid associated with the user which I believe you are referring to as a token. This is done via the login() method. https://docs.djangoproject.com/en/dev/topics/auth/default/#django.contrib.auth.login
Normally Django would set a sessionid as a coookie or session variable on the client's machine, but I'd imagine you could save it in local storage and then retrieve it each time and validate it's a valid sessionid on each request but it's easier to just let Django's middleware take care of everything by just using sessions.

Next query parameter doesn't work with django allauth for facebook login

I have implemented User account management into my application using Django all-auth. I have enabled login using username and password as well as with facebook connect.
The problem goes like this:
1) User visits a page http://example.com/page1/ and clicks login
2) He's taken to http://example.com/accounts/login?next=/page1/
3) When the user logs in using username and password, the user is redirected back to http://example.com/page1. But if the user logs in with facebook, he's taken to homepage.
How can I get desired behavior with Facebook login too?
You need to override the get_login_redirect_url method of django-allauth.
For this inherit the DefaultAccountAdapter class as
from allauth.account.adapter import DefaultAccountAdapter
class MyAccountAdapter(DefaultAccountAdapter):
def get_login_redirect_url(self, request):
# get the next parameter from request object and return the url
And make changes on settings.py
ADAPTER = "APPNAME.FILENAME.MyAccountAdapter"
ACCOUNT_ADAPTER = "APPNAME.FILENAME.MyAccountAdapter"
This should work !
How are you generating the Facebook login link? Most likely you are not indicating the next parameter there. The allauth documentation gives this example:
Google
To get the proper next parameter you can access request.GET.next.

Customize error messages on django-registration

I have a question about django-registration (https://bitbucket.org/ubernostrum/django-registration), but I can't find their issue tracker or a mailing list for it, so I'll try my luck here.
My application enables login via OpenID and login/password.
Some users "forget their password" on FS on try to reset it (here), but then they get the message:
The user account associated with this e-mail address cannot reset the password.
With no further explanations.
(You can try and reset my password - just type my email (tonylampada at gmail dot com) there to see the error message.
I want to customize that message. A better message would be:
The user account associated with this e-mail address cannot reset the password.
This happens because the user account was created with an OpenID or OAuth provider (tipically Google, Facebook, MyOpenID, etc).
To see the login provider(s) associated with this account, take a look at the user profile.
What is the easiest way to tell django-registration that?
Thanks!
PS: This issue on Github: https://github.com/freedomsponsors/www.freedomsponsors.org/issues/191 (just in case you're feeling like making a pull request today :-))
django-registration uses views from django.contrib.auth.
In this case: reset_password() github
Since this is no class based view, you can't override/inherit from it, but you can pass in a PasswordResetForm from django.contrib.auth.forms
from django.contrib.auth.forms import PasswordResetForm
class CustomResetForm(PasswordResetForm):
def validate(self, value):
#pseudocode
if user.cant_reset_pw:
raise ValidationError("The user account associated with this e-mail address cannot reset the password. and so forth..")
super(CustomResetForm, self).validate(value)
You'll have to wire things together by overriding the url r'^password/change/$' to point to a custom function that calls django.contrib.auth.passwort_reset() with your CustomResetForm.

Categories