Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Reset password email and 'Forgot password' solution #1566

Draft
wants to merge 86 commits into
base: master
Choose a base branch
from

Conversation

runoutnow
Copy link
Contributor

@runoutnow runoutnow commented Feb 10, 2021

Description

The new function (at the moment only for Mysql!) can be turned on and off in config.py: EMAIL_PROT = True|False. Default is False so people who don't got an Email protocol available can keep changing their passwords.

Reset password-button
When EMAIL_PROT is turned on the "reset password-button" won't forward to the "change-password-form", instead it will create an unique hash and send an Email to the known Email-address with an unique url. After confirmation of this email the user has got 15 minutes to change the password. In those 15 minutes it is not possible to send another email with a link. After changing the password or when the 15 minutes have been passed the user is unable to visit the "change password-form".
The process can be restarted by clicking the "reset password-button" again. :-)

This way the user must have access to the known Emailaddress in order to change a password. So if a password has been stolen it can not be changed by the attacker... unless the emailaddress has also been hacked.

N.B.
If you have build the possibility to let a user change his/her Emailaddress, then the only way to make the new code effective is to send an Email with an “ack-change”-link to the new Emailaddress AND the old Emailaddress. So the attacker is not able to change the Emailaddress (and indirectly is still able to change the password then).

Forgot password
When EMAIL_PROT = True there will also appear a "Forgot my password" url in the login_db.html.
The user can then fill in the emailaddress which will receive a link to reset the password.
The "change password-form" can only be visited for 15 minutes and requires the unique hash in the url.

ADDITIONAL INFORMATION

  • Has associated issue:
  • Is CRUD MVC related.
  • Is Auth, RBAC security related.
  • Changes the security db schema.
  • [x ] Introduces new feature
  • Removes existing feature

The f-string was wrong
…st where multiple processes/workers are available

Problem:
'2013. Lost connection to MySQL server during query' error when there are two processes (workers) available.
The problem is automatically solved by SQLAlchemy, but when you visit a view which got the @has_access decorator
flask_appbuilder.security.manager.load_user is used which uses flask_appbuilder.security.sqla.manager. def get_user_by_id
and that transaction can not be rolled back. This raises the OperationalError 2013, 'Lost connection to MySQL server during query':

Can be reproduced by:
resetting the webserver... the 2nd or 3th time you refresh the browser the error will raise
Problem:
'2013. Lost connection to MySQL server during query' error when there are multiple processes (workers) available.
The problem is automatically solved by SQLAlchemy, but when you visit a view which got the @has_access decorator
flask_appbuilder.security.manager.load_user is used which uses flask_appbuilder.security.sqla.manager. def get_user_by_id
and that transaction can not be rolled back. This raises the OperationalError 2013, 'Lost connection to MySQL server during query':

Can be reproduced by:
resetting the webserver... the 2nd or 3th time you refresh the browser the error will raise
fix: [multiple workers] causing a fatal error
Extended with UserResetPassword for sending a unique hash to the Email of the user
Extended with ForgotMyPasswordForm for sending an unique hash to the Email of the user
Template for sending the Email with the reset_hash to the user
@dpgaspar
Copy link
Owner

dpgaspar commented Mar 1, 2021

@runoutnow

Left a couple of tips here: https://github.com/dpgaspar/Flask-AppBuilder/pull/1579/files

see if it works for you.

Also black is complaining

would reformat /home/runner/work/Flask-AppBuilder/Flask-AppBuilder/flask_appbuilder/const.py
would reformat /home/runner/work/Flask-AppBuilder/Flask-AppBuilder/flask_appbuilder/security/views.py
would reformat /home/runner/work/Flask-AppBuilder/Flask-AppBuilder/flask_appbuilder/tests/test_mvc.py
All done! 💥 💔 💥
3 files would be reformatted, 80 files would be left unchanged.

@runoutnow
Copy link
Contributor Author

@runoutnow

Left a couple of tips here: https://github.com/dpgaspar/Flask-AppBuilder/pull/1579/files

see if it works for you.

Also black is complaining

would reformat /home/runner/work/Flask-AppBuilder/Flask-AppBuilder/flask_appbuilder/const.py
would reformat /home/runner/work/Flask-AppBuilder/Flask-AppBuilder/flask_appbuilder/security/views.py
would reformat /home/runner/work/Flask-AppBuilder/Flask-AppBuilder/flask_appbuilder/tests/test_mvc.py
All done! 💥 💔 💥
3 files would be reformatted, 80 files would be left unchanged.

Thanks I will try that later.
I was trying to fix the flake8 errors, but it seems like your configuration is custom... I have installed flake8

  • Locally I don't got "wrong order" errors, which I do have when I run the test on github.
  • Also Locally I have got the "E501 line too long (83 > 79 characters)" errors, and those errors won't appear on github

Can you share the settings of flake8? Thanks

@dpgaspar
Copy link
Owner

dpgaspar commented Mar 2, 2021

@runoutnow
Left a couple of tips here: https://github.com/dpgaspar/Flask-AppBuilder/pull/1579/files
see if it works for you.
Also black is complaining

would reformat /home/runner/work/Flask-AppBuilder/Flask-AppBuilder/flask_appbuilder/const.py
would reformat /home/runner/work/Flask-AppBuilder/Flask-AppBuilder/flask_appbuilder/security/views.py
would reformat /home/runner/work/Flask-AppBuilder/Flask-AppBuilder/flask_appbuilder/tests/test_mvc.py
All done! 💥 💔 💥
3 files would be reformatted, 80 files would be left unchanged.

Thanks I will try that later.
I was trying to fix the flake8 errors, but it seems like your configuration is custom... I have installed flake8

  • Locally I don't got "wrong order" errors, which I do have when I run the test on github.
  • Also Locally I have got the "E501 line too long (83 > 79 characters)" errors, and those errors won't appear on github

Can you share the settings of flake8? Thanks

Take a look at:
https://github.com/dpgaspar/Flask-AppBuilder/blob/master/.github/workflows/ci.yml#L33
and:
https://github.com/dpgaspar/Flask-AppBuilder/blob/master/.flake8

So it should just work running flake8 flask_appbuilder, are your requirements from requirements.txt and requirements-dev.txt? Maybe it's time to get all this on pre-commit

@runoutnow
Copy link
Contributor Author

Take a look at:
https://github.com/dpgaspar/Flask-AppBuilder/blob/master/.github/workflows/ci.yml#L33
and:
https://github.com/dpgaspar/Flask-AppBuilder/blob/master/.flake8

So it should just work running flake8 flask_appbuilder, are your requirements from requirements.txt and requirements-dev.txt? Maybe it's time to get all this on pre-commit

I had installed black and flake8 manually... Then I saw the requirements*.txt and installed those... but that didn't make a difference. I am sure it will work when I have flake8 configured with https://github.com/dpgaspar/Flask-AppBuilder/blob/master/.flake8 is what I needed...

haha I would love to have a pre-commit option... I am going to search for it... If I need to change 3 files, it's going to start the tests 3 times and ofcourse 3 lovely emails 😄

@RosterIn
Copy link

RosterIn commented Apr 5, 2021

hi, any updates on the progress ?

@runoutnow
Copy link
Contributor Author

hi, any updates on the progress ?

Hello,
Unfortunately not, it is on my todo list, but I don't got time for it at the moment.
It's not something I can do in between as I am complete new into Github and writing tests.

I need to setup and find the right commando's to collect py files and commit them to a certain pull request.
I have been able to add files to the git map, but haven't been able to do a commit (as a test) from bash to github.
About writing the tests... I haven't looked into that yet as I was setting up Github first.

I guess it will easily take a few months before I am able to start looking into this, sorry.
But the code works.... just copy it into your flaskappbuilder python files and you can start using it if you want.

@MaximSlagter
Copy link

MaximSlagter commented Jan 18, 2022

@runoutnow, are there any updates for this issue? :)

@runoutnow
Copy link
Contributor Author

@runoutnow, are there any updates for this issue? :)

Unfortunately not as I haven’t looked into it anymore. The code is working, I am using it for a year already.
But there are no working tests written.

Today I’ve looked into it again, but the standard tests which I didn’t write are failing already.
Somehow it tries to add the same users multiple times which causes an integrity error, also when I remove app.db

For me it’s also annoying that I am stuck with this feature as I now am no longer able to update flask_appbuilder normally anymore. In order to keep the “forgot password” feature I have to manually replace the files in the flask_appbuilder directory.

Perhaps someone can assist me with writing the tests?
Another option (for me) is to get the code for this feature out of fab so I can easily update fab again while I still can use the features of this pull request. However it has always been my intention to give something back to the people who has contributed to fab.

test fail.pdf

@runoutnow
Copy link
Contributor Author

runoutnow commented Jan 20, 2022

Removed the db and started with
nosetests -v flask_appbuilder.tests.test_0_fixture

Resulted into way less errors for
nosetests -v flask_appbuilder.tests.test_mvc
Ran 50 tests in 40.548s
FAILED (errors=1, failures=4)

What is the right order to make the tests succesful? =]

@stale
Copy link

stale bot commented Apr 27, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs. Feel free to reopen it if it's still relevant to you. Thank you

@stale stale bot added the stale label Apr 27, 2022
@stale stale bot removed the stale label Apr 15, 2023
@runoutnow runoutnow marked this pull request as ready for review April 15, 2023 15:00
@runoutnow runoutnow marked this pull request as draft April 15, 2023 15:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants