Advertisement
Uno-Dan

Geoff's Project

Aug 26th, 2019
558
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.18 KB | None | 0 0
  1. from flask import Flask, redirect, url_for, request
  2. from flask_sqlalchemy import SQLAlchemy
  3. from flask_login import LoginManager, current_user, login_user, logout_user  # UserMixin
  4. from flask_admin import Admin, expose, AdminIndexView
  5. from flask_admin.helpers import validate_form_on_submit
  6. from flask_admin.contrib import sqla
  7. from flask_security import Security, SQLAlchemyUserDatastore, RoleMixin, UserMixin
  8. from flask_security.utils import hash_password
  9. from wtforms import Form, StringField, PasswordField, ValidationError
  10. from wtforms.validators import DataRequired
  11. from werkzeug.security import generate_password_hash, check_password_hash
  12. import os
  13.  
  14. from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey
  15.  
  16. # Create Flask application
  17. app = Flask(__name__)
  18. FILE = 'sample_db.sqlite'
  19. config = {
  20.     'DATABASE_FILE': FILE,
  21.     'SQLALCHEMY_DATABASE_URI': f'sqlite:///{FILE}',
  22.     'SECRET_KEY': '123456790',
  23.     'SQLALCHEMY_ECHO': True,
  24.     'SECURITY_PASSWORD_SALT': 'ATGUOHAELKiubahiughaerGOJAEGj',
  25. }
  26. app.config.update(config)
  27.  
  28. # Instantiate extensions
  29. db = SQLAlchemy(app)
  30.  
  31. # Define models
  32. if hasattr(db, 'Table'):
  33.     roles_users = db.Table(
  34.         'roles_users',
  35.         Column('user_id', Integer(), ForeignKey('user.id')),
  36.         Column('role_id', Integer(), ForeignKey('role.id'))
  37.     )
  38.  
  39.  
  40. class Role(db.Model, RoleMixin):
  41.     id = Column(Integer(), primary_key=True)
  42.     name = Column(String(80), unique=True)
  43.     description = Column(String(255))
  44.  
  45.     def __str__(self):
  46.         return self.name
  47.  
  48.  
  49. class User(db.Model, UserMixin):
  50.     id = Column(Integer, primary_key=True)
  51.     username = Column(String(20), unique=True, nullable=False)
  52.     email = Column(String(120), unique=True, nullable=False)
  53.     password = Column(String(60), nullable=False)
  54.     image_file = Column(String(20), nullable=False, default='default.jpg')
  55.     # posts = db.relationship('Post', backref='author', lazy=True)
  56.     active = Column(Boolean())
  57.     confirmed_at = Column(DateTime())
  58.  
  59.     if hasattr(db, 'relationship') and hasattr(db, 'backref'):
  60.         roles = db.relationship('Role', secondary=roles_users, backref=db.backref('users', lazy='dynamic'))
  61.  
  62.     def __repr__(self):
  63.         return f"User('{self.username}', '{self.email}'')"
  64.  
  65.  
  66. # Setup Flask-Security
  67. user_datastore = SQLAlchemyUserDatastore(db, User, Role)
  68. security = Security(app, user_datastore)
  69.  
  70.  
  71. # Define login and registration forms (for flask-login)
  72. class LoginForm(Form):
  73.     username = StringField(validators=[DataRequired()])
  74.     password = PasswordField(validators=[DataRequired()])
  75.  
  76.     def validate_login(self):
  77.         user = self.get_user()
  78.  
  79.         if user is None:
  80.             raise ValidationError('Invalid user')
  81.  
  82.         if not check_password_hash(user.password, self.password.data):
  83.             raise ValidationError('Invalid password')
  84.  
  85.     def get_user(self):
  86.         return db.session.query(User).filter_by(username=self.username.data).first()
  87.  
  88.  
  89. class RegistrationForm(Form):
  90.     username = StringField(validators=[DataRequired()])
  91.     email = StringField()
  92.     password = PasswordField(validators=[DataRequired()])
  93.  
  94.     def validate_login(self):
  95.         if db.session.query(User).filter_by(username=self.username.data).count() > 0:
  96.             raise ValidationError('Duplicate username')
  97.  
  98.  
  99. # Create customized model view class
  100. class MyModelView(sqla.ModelView):
  101.  
  102.     def is_accessible(self):
  103.         return current_user.is_authenticated
  104.  
  105.  
  106. # Create customized index view class that handles login & registration
  107. class MyAdminIndexView(AdminIndexView):
  108.  
  109.     @expose('/')
  110.     def index(self):
  111.         if not current_user.is_authenticated:
  112.             return redirect(url_for('.login_view'))
  113.         return super(MyAdminIndexView, self).index()
  114.  
  115.     @expose('/login/', methods=('GET', 'POST'))
  116.     def login_view(self):
  117.         if current_user.is_authenticated:
  118.             return redirect(url_for('.index'))
  119.         form = LoginForm(request.form)
  120.         if validate_form_on_submit(form):
  121.             user = form.get_user()
  122.             if user is None:
  123.                 print('User not found!')
  124.                 return redirect(url_for('.index'))
  125.             elif not check_password_hash(user.password, form.password.data):
  126.                 print('Invalid password!')
  127.                 return redirect(url_for('.index'))
  128.             else:
  129.                 login_user(user)
  130.                 print('logged user in...')
  131.  
  132.         if current_user.is_authenticated:
  133.             return redirect(url_for('.index'))
  134.         link = '<p>Don\'t have an account? <a href="' + url_for('.register_view') + '">Click here to register.</a></p>'
  135.         self._template_args['form'] = form
  136.         self._template_args['link'] = link
  137.         return super(MyAdminIndexView, self).index()
  138.  
  139.     @expose('/register/', methods=('GET', 'POST'))
  140.     def register_view(self):
  141.         form = RegistrationForm(request.form)
  142.         if validate_form_on_submit(form):
  143.             user = User()
  144.  
  145.             form.populate_obj(user)
  146.             user.password = generate_password_hash(form.password.data)
  147.  
  148.             db.session.add(user)
  149.             db.session.commit()
  150.  
  151.             login_user(user)
  152.             return redirect(url_for('.index'))
  153.         link = '<p>Already have an account? <a href="' + url_for('.login_view') + '">Click here to log in.</a></p>'
  154.         self._template_args['form'] = form
  155.         self._template_args['link'] = link
  156.         return super(MyAdminIndexView, self).index()
  157.  
  158.     @expose('/logout/')
  159.     def logout_view(self):
  160.         logout_user()
  161.         return redirect(url_for('.index'))
  162.  
  163.  
  164. # Initialize flask-login
  165. def init_login():
  166.     login_manager = LoginManager()
  167.     login_manager.init_app(app)
  168.  
  169.     # Create user loader function
  170.     @login_manager.user_loader
  171.     def load_user(user_id):
  172.         return db.session.query(User).get(user_id)
  173.  
  174.  
  175. # Flask views
  176. @app.route('/')
  177. def index():
  178.     return '<a href="/admin/">Click me to get to Admin!</a>'
  179.  
  180.  
  181. # Initialize flask-login
  182. init_login()
  183.  
  184. # Create admin
  185. admin = Admin(app, 'Example: Auth', index_view=MyAdminIndexView(), base_template='my_master.html')
  186.  
  187. # Add view
  188. admin.add_view(MyModelView(User, db.session))
  189. admin.add_view(MyModelView(Role, db.session))
  190.  
  191.  
  192. def build_sample_db():
  193.  
  194.     db.drop_all()
  195.     db.create_all()
  196.     # test_user = User(username="test", email="[email protected]", password=generate_password_hash("test"))
  197.     # db.session.add(test_user)
  198.  
  199.     with app.app_context():
  200.         user_role = Role()
  201.         super_user_role = Role()
  202.         db.session.add(user_role)
  203.         db.session.add(super_user_role)
  204.         db.session.commit()
  205.  
  206.         user_datastore.create_user(
  207.             username='admin',
  208.             email='admin',
  209.             password=hash_password('admin')  # ,
  210.             # roles=[user_role, super_user_role]
  211.         )
  212.         db.session.commit()
  213.     return
  214.  
  215.  
  216. if __name__ == '__main__':
  217.     # Build a sample db on the fly, if one does not exist yet.
  218.     app_dir = os.path.realpath(os.path.dirname(__file__))
  219.     database_path = os.path.join(app_dir, app.config['DATABASE_FILE'])
  220.     if not os.path.exists(database_path):
  221.         build_sample_db()
  222.     app.run(debug=True)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement