how to use PasswordChangeView django 2.2 - python

I've to try make a change password page with Django.contrib.auth.views.PasswordChangeView like:
[views.py]
class ChangePasswordView(LoginRequiredMixin, PasswordChangeView):
template_name = 'accounts/password_change.html'
success_url = reverse_lazy('account:password_change_done')
class ChangePasswordDoneView(LoginRequiredMixin, PasswordChangeDoneView):
template_name = 'accounts/password_change_done.html'
With URL like:
[urls.py]
path('profile/update/password/', views.ChangePasswordView.as_view(),
name='password_change'),
path('profile/update/password/success/', views.ChangePasswordDoneView.as_view(),
name='password_change_done'),
I use custom user, but I look the source code, Django get the user by request.user so its not be a problem if I use the custom user.
But why my change password not work, if I change the password with right old password and new password the form return the success page but not changing my password and I try to use wrong password in old password but always return the success page. What's the problem?

iam so sory, my problem is in my form action not to password_change url but in my success url. my fail not check this. thanks

Related

I have a problem with python Django 'Login' has no attribute 'filter'

I made a website with python Django. My models are two which called 'Login' and 'Ch'.
And my website has 'signup' and 'home' page. The 'signup' page is literally signup page. User can register his/her ID and password. Then these information save in 'id' and 'pw' in the 'Login' model.
Now, Typing his/her ID and password, user can login through 'home' page. This is my plan. However, the login process consistently happen problem with the sentence 'Login' has no attribute 'filter'.
My partial code is
log = Login.objects.all()
try:
ch = log.filter(id = request.POST["login_id"], pw = ghv(request.POST["login_pw"])) #ghv is user definition function for get hash value of password
if (ch):
id = request.POST["login_id"]
return render(request,'pdg/home2.html')
else:
return render(request, "pdg/home_e.html")
except ObjectDoesNotExist:
return render(request, "pdg/home_e.html")
Signup process has no problem. I think that after signup process complete, Being added the user data in 'Login' model is cause the problem. Because restarting the runserver is effective for solving this error. However I want to find a solution for this error without restarting the runserver.
Please help me.. And THANK YOU.
ch = Login.objects.filter(login_id=login_Id, login_pw=login_pw)

Django Allauth Signup Prevent Login

Is there anyway to prevent the Allauth Signup form from automatically logging in the User?
I found a similar post here with no answers:
prevent user login after registration using django-allauth
You get logged in because this behavior is baked into the signup view of the allauth. When the form is valid, the view calls the function called complete_signup that does two things:
Emits the user_signed_up signal
Logs a user in
To solve this, we need to leave the step 1 and replace the step 2 with a simple redirect.
Here's how this can be done:
Extend the SignupView from allauth/account/views.py and override its form_valid method like this:
class CustomSignupView(SignupView):
def form_valid(self, form):
# By assigning the User to a property on the view, we allow subclasses
# of SignupView to access the newly created User instance
self.user = form.save(self.request)
try:
signals.user_signed_up.send(
sender=self.user.__class__,
request=self.request,
user=self.user,
**{}
)
return HttpResponseRedirect(self.get_success_url())
except ImmediateHttpResponse as e:
return e.response
Haven't tested the code, but it should be working.
Wire your new view up in urls.py, so it replaces the old Signup view url.
I am using django-allauth 0.42.0
There is no need to extend the SignUp view, it can be achieved by the setting:
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
in your project settings.py file.

Django Registration Redux Custom View

(Django 1.8, Django-Registration-Redux 1.4)
After following the answer in this SO post: django-registration-redux add extra field
I've implemented a custom view with my own template to register a user, and my custom form is correctly rendered.
user_views.py
class SignupView(RegistrationView):
form_class = MyRegistrationForm
def register(self, request, form):
print form
print request
new_user = super(SignupView, self).register(request, form)
my_user_model = MyUserModel()
my_user_model.user = new_user
my_user_model.save()
return new_user
However, register doesn't seem to get called. But, when I define post() - the request comes through with all of the form data.
urls.py
url(
r'^accounts/register/',
user_views.SignupView.as_view(),
name='signup'
), # Customized-Register
url(
r'^accounts/',
include('registration.backends.default.urls')
), # Registration-Redux
Would appreciate guidance on the correct usage, thanks!
Ok - I've determined the solution. It had to do with my custom form not collecting the (required) username field.
Incase it helps, I figured it out by implementing form_invalid(self, form) as RegistrationView is a derived class of Django's FormView, which hinted me towards it.
This SO answer helped override the username requirement: Django Registration Redux: how to change the unique identifier from username to email and use email as login
Hope it helps
Try this line:
new_user = super(MyRegistrationView, self).register(form_class)
and change the url to:
url(r'^accounts/register/$', MyRegistrationView.as_view(),
name='registration_register'),
Hope it works!

Admin(only) registration of users, Flask-Security

I'm currently building a login for a webapp using Flask-Security (which includes Flask-WTForms, Flask-SQLalchemy and Flask-Login). I've been able to fairly painlessly set up the majority of my login flow, including forgotten password; however I want to make it so that the only way users can be registered is through a page only accessible to the admins. I've managed to configure Roles (Admin, User) and set up the following view:
#app.route('/adminregister')
#roles_accepted('admin')
def adminregister():
return render_template('*')
This creates the portal that is successfully limited to accounts with an Admin role. I'm unsure how to proceed for here however, as Flask-security has no built in means to enable what I'm trying to do.
I've overridden RegisterForm already to enforce password rules through a regexp:
# fixed register form
class ExtendedRegisterForm(RegisterForm):
password = TextField('Password', [validators.Required(), validators.Regexp(r'(?=.*?[0-9])(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[$-/:-?{-~!"^_`\[\]])')])
Basically I want a form, located at /adminregister, that when visited by an admin allows for the entry of an email address, at which point first the user is created in the database with a random and secure password, and then a similar process to a forgotten password happens and a 1 time password code is created to reset the password.
Useful things I've looked at:
Within flask-security/views.py there is the forgotten passsword code:
def forgot_password():
"""View function that handles a forgotten password request."""
form_class = _security.forgot_password_form
if request.json:
form = form_class(MultiDict(request.json))
else:
form = form_class()
if form.validate_on_submit():
send_reset_password_instructions(form.user)
if request.json is None:
do_flash(*get_message('PASSWORD_RESET_REQUEST', email=form.user.email))
if request.json:
return _render_json(form, include_user=False)
return _security.render_template(config_value('FORGOT_PASSWORD_TEMPLATE'),
forgot_password_form=form,
**_ctx('forgot_password'))
Within flask_security/registerable.py there is the code for register_user
def register_user(**kwargs):
confirmation_link, token = None, None
kwargs['password'] = encrypt_password(kwargs['password'])
user = _datastore.create_user(**kwargs)
_datastore.commit()
if _security.confirmable:
confirmation_link, token = generate_confirmation_link(user)
do_flash(*get_message('CONFIRM_REGISTRATION', email=user.email))
user_registered.send(app._get_current_object(),
user=user, confirm_token=token)
if config_value('SEND_REGISTER_EMAIL'):
send_mail(config_value('EMAIL_SUBJECT_REGISTER'), user.email, 'welcome',
user=user, confirmation_link=confirmation_link)
return user
I want to somehow combine these two, so that upon submission of a form with the sole field "Email" at '/adminregister' the email is added with a secure, random password in the database and the email address is sent an email with a link to change there password (and ideally a message explaining). I'm not even sure where I would add such code, as there is nothing to specifically override, especially as I can't find a way to override RegisterForm to have FEWER fields and the same functionality.
The structure of my code is in line with the flask-security documentation's quickstart.
Thank you in advance for any guidance you can offer.
I ended up using a work around as follows:
I enabled registration but limited registration view to users with an admin role.
I used del form.password in views -> register to no longer send the form with a password field.
I did the following in .registerable, generating a random password to fill the table.
kwargs['password'] = encrypt_password(os.urandom(24))
Upon admin entry of an email in the registration form, I had confimable enabled. This means the user would immediatly get an email to confirm their account and explaining they'd been registered. Upon confirmation they are redirected to the forgotten password page and asked to change their password (which is limited based on security).
If anyone comes up with a more direct way I'd appreciate it. I'm leaving this here in case anyone has the same problem.
The register process creates a signal with blinker that you can access like this:
from flask.ext.security.signals import user_registered
#user_registered.connect_via(app)
def user_registered_sighandler(app, user, confirm_token):
user_datastore.deactivate_user(user)
db.session.commit()
Which will deactivate any newly registered users.
I know this is an ancient question, but I think I have an elegant answer.
first import register_user
from flask_security.registerable import register_user
Then since you do not want just anyone to register ensure registerable is disabled (though disabled is the default so you can omit this) and since you want to send confirmation email, enable confirmable, and changeable for users to change their paswords
app.config['SECURITY_CONFIRMABLE'] = True
app.config['SECURITY_REGISTERABLE'] = False
app.config['SECURITY_RECOVERABLE'] = True
Then, you can do your create your user registration view and decorate it with role required. I have used my own custom registration form so I have had to go an extra mile to check if user already exists and return an error accourdingly
#app.route('/admin/create/user', methods=['GET', 'POST'])
#roles_required('admin')
def admin_create_user():
form = RegistrationForm(request.form)
if request.method == 'POST' and form.validate_on_submit():
email = form.email.data
password = form.password.data
user_exists = session.query(User).filter_by(email=email).first()
if user_exists:
form.email.errors.append(email + ' is already associated with another user')
form.email.data = email
email = ''
return render_template('create-user.html', form = form)
else:
register_user(
email=email,
password = password)
flash('User added successfully')
return render_template('create-user.html', form = form)
Also see flask-security - admin create user, force user to choose password
Here's another solution I found after poking through flask-security-too. I made an admin create user form, and simply add the following code after creating the user in the database:
from flask_security.recoverable import send_reset_password_instructions
# my code is maintains self.created_id after creating the user record
# this is due to some complex class involved which handles my crudapi stuff
# your code may vary
user = User.query.filter_by(id=self.created_id).one()
send_reset_password_instructions(user)

Get Username from a Cookie

I use the backend solution from django. I just want to get a username from the cookie or the session_key to get to know the user. How I can do it?
from django.contrib.auth.models import User
from django.contrib.sessions.models import Session
def start(request, template_name="registration/my_account.html"):
user_id = request.session.get('session_key')
if user_id:
name = request.user.username
return render_to_response(template_name, locals())
else:
return render_to_response('account/noauth.html')
Only else is coming up. What am I doing wrong?
Am I right then that authenticated means he is logged in?
--> Okay this I got!
Firstly, if you have some clarification to a question, update the question, don't post an answer or (even worse) another question, as you have done. Secondly, if the user is logged out, by definition he doesn't have a username.
I mean the advantage of Cookies is to identify a user again. I just want to place his name on the webpage. Even if he is logged out. Or isnt't it possible?
You can check if a user is authenticated by calling the, apptly named, is_authenticated method. Your code would then look somewhat like this:
def start(request, template_name="registration/my_account.html"):
if request.user.is_authenticated():
name = request.user.username
return render_to_response(template_name, locals())
else:
return render_to_response('account/noauth.html')
No need to access the session yourself, Django handles all of that automatically (provided you use both django.contrib.sessions and django.contrib.auth).
/edit: in order to have a user's username, he needs to be authenticated. There's no good way around that.
piquadrat has absolutely the right answer, but if for some reason you do need to get the user from the session, you call get_decoded() on the session object:
session_data = request.session.get_decoded()
user_id = session_data['_auth_user_id']
You need to enable the AuthenticationMiddleware and SessionMiddleware in your MIDDLEWARE_CLASSES setting in your settings.py to access request.user in your views.
http://docs.djangoproject.com/en/1.2/topics/auth/#authentication-in-web-requests
You can then access the username using request.user.username

Categories

Resources