Repository: flask-admin/flask-admin

Issue:
Dangerous Examples with plaintext passwords
I'm amazed how easy the examples make it to build a system with plaintext passwords.

This seems very dangerous. I know people should do this kind of thing themselves, but this is the kind of omission which ends up causing big problems when people just copy and paste. 

Even for those of us who know we should encrypt passwords, the absence of this absolutely required feature in the examples wastes lots of time working out how to implement it.

Given that Flask-Security (which is required for some of the examples eg. Auth) has this kind of thing working "out of the box" surely you should encrypt the password in at least one (if not all) of the examples.

It would presumably (I'm just beginning to learn flask) take 5 or so extra lines and would set people off in a much less dangerous direction.



Discussion:
using 

```
from werkzeug.security import generate_password_hash, check_password_hash
```

This can be implemented with 2 extra lines. I really can't see a reason no to encrypt the passwords?

Would you accept a pull request?

Just in case, there's disclaimer in there plus Flask-Admin examples were only supposed to showcase how different parts of the Flask-Admin work.

I don't mind adding encryption to the example(s), but it is up to developer how they want to manage their users or hash their passwords. Unfortunately, I can not add 3rd party package dependency just to have encryption in one of the examples.

What 3rd party packages would have to be added?

Werkzeug is the foundation of flask and therefore a required component.

Flask-Security, Flask-Login, etc.

Usually Flask-Admin is built around the project and not vice-a-versa. So it is expected that project will have some sort of authentication built in and Flask-Admin will integrate with it.

So, I don't see any problems to add werkzeug password hashing to example(s). 

Pull requests are welcome.


Resolving patch:
diff --git a/examples/auth/auth.py b/examples/auth/auth.py
--- a/examples/auth/auth.py
+++ b/examples/auth/auth.py
@@ -5,6 +5,7 @@
 from flask.ext import admin, login
 from flask.ext.admin.contrib import sqla
 from flask.ext.admin import helpers, expose
+from werkzeug.security import generate_password_hash, check_password_hash
 
 
 # Create Flask application
@@ -59,7 +60,10 @@ def validate_login(self, field):
         if user is None:
             raise validators.ValidationError('Invalid user')
 
-        if user.password != self.password.data:
+        # we're comparing the plaintext pw with the the hash from the db
+        if not check_password_hash(user.password, self.password.data):
+        # to compare plain text passwords use
+        # if user.password != self.password.data:
             raise validators.ValidationError('Invalid password')
 
     def get_user(self):
@@ -125,6 +129,9 @@ def register_view(self):
             user = User()
 
             form.populate_obj(user)
+            # we hash the users password to avoid saving it as plaintext in the db,
+            # remove to use plain text:
+            user.password = generate_password_hash(form.password.data)
 
             db.session.add(user)
             db.session.commit()
@@ -188,7 +195,9 @@ def build_sample_db():
         user.last_name = last_names[i]
         user.login = user.first_name.lower()
         user.email = user.login + "@example.com"
-        user.password = ''.join(random.choice(string.ascii_lowercase + string.digits) for i in range(10))
+        user.password = generate_password_hash(''.join(random.choice(string.ascii_lowercase + string.digits) for i in range(10)))
+        # passwords are hashed, to use plaintext passwords use:
+        # user.password = ''.join(random.choice(string.ascii_lowercase + string.digits) for i in range(10))
         db.session.add(user)
 
     db.session.commit()


Test patch: