app.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import os
  2. from flask import Flask, url_for, redirect, render_template, request, abort
  3. from flask_sqlalchemy import SQLAlchemy
  4. from flask_security import Security, SQLAlchemyUserDatastore, \
  5. UserMixin, RoleMixin, login_required, current_user
  6. from flask_security.utils import encrypt_password
  7. import flask_admin
  8. from flask_admin.contrib import sqla
  9. from flask_admin import helpers as admin_helpers
  10. # Create Flask application
  11. app = Flask(__name__)
  12. app.config.from_pyfile('config.py')
  13. db = SQLAlchemy(app)
  14. # Define models
  15. roles_users = db.Table(
  16. 'roles_users',
  17. db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
  18. db.Column('role_id', db.Integer(), db.ForeignKey('role.id'))
  19. )
  20. class Role(db.Model, RoleMixin):
  21. id = db.Column(db.Integer(), primary_key=True)
  22. name = db.Column(db.String(80), unique=True)
  23. description = db.Column(db.String(255))
  24. def __str__(self):
  25. return self.name
  26. class User(db.Model, UserMixin):
  27. id = db.Column(db.Integer, primary_key=True)
  28. first_name = db.Column(db.String(255))
  29. last_name = db.Column(db.String(255))
  30. email = db.Column(db.String(255), unique=True)
  31. password = db.Column(db.String(255))
  32. active = db.Column(db.Boolean())
  33. confirmed_at = db.Column(db.DateTime())
  34. roles = db.relationship('Role', secondary=roles_users,
  35. backref=db.backref('users', lazy='dynamic'))
  36. def __str__(self):
  37. return self.email
  38. # Setup Flask-Security
  39. user_datastore = SQLAlchemyUserDatastore(db, User, Role)
  40. security = Security(app, user_datastore)
  41. # Create customized model view class
  42. class MyModelView(sqla.ModelView):
  43. def is_accessible(self):
  44. if not current_user.is_active or not current_user.is_authenticated:
  45. return False
  46. if current_user.has_role('superuser'):
  47. return True
  48. return False
  49. def _handle_view(self, name, **kwargs):
  50. """
  51. Override builtin _handle_view in order to redirect users when a view is not accessible.
  52. """
  53. if not self.is_accessible():
  54. if current_user.is_authenticated:
  55. # permission denied
  56. abort(403)
  57. else:
  58. # login
  59. return redirect(url_for('security.login', next=request.url))
  60. # Flask views
  61. @app.route('/')
  62. def index():
  63. return render_template('index.html')
  64. # Create admin
  65. admin = flask_admin.Admin(
  66. app,
  67. 'Example: Auth',
  68. base_template='my_master.html',
  69. template_mode='bootstrap3',
  70. )
  71. # Add model views
  72. admin.add_view(MyModelView(Role, db.session))
  73. admin.add_view(MyModelView(User, db.session))
  74. # define a context processor for merging flask-admin's template context into the
  75. # flask-security views.
  76. @security.context_processor
  77. def security_context_processor():
  78. return dict(
  79. admin_base_template=admin.base_template,
  80. admin_view=admin.index_view,
  81. h=admin_helpers,
  82. get_url=url_for
  83. )
  84. def build_sample_db():
  85. """
  86. Populate a small db with some example entries.
  87. """
  88. import string
  89. import random
  90. db.drop_all()
  91. db.create_all()
  92. with app.app_context():
  93. user_role = Role(name='user')
  94. super_user_role = Role(name='superuser')
  95. db.session.add(user_role)
  96. db.session.add(super_user_role)
  97. db.session.commit()
  98. test_user = user_datastore.create_user(
  99. first_name='Admin',
  100. email='admin',
  101. password=encrypt_password('admin'),
  102. roles=[user_role, super_user_role]
  103. )
  104. first_names = [
  105. 'Harry', 'Amelia', 'Oliver', 'Jack', 'Isabella', 'Charlie', 'Sophie', 'Mia',
  106. 'Jacob', 'Thomas', 'Emily', 'Lily', 'Ava', 'Isla', 'Alfie', 'Olivia', 'Jessica',
  107. 'Riley', 'William', 'James', 'Geoffrey', 'Lisa', 'Benjamin', 'Stacey', 'Lucy'
  108. ]
  109. last_names = [
  110. 'Brown', 'Smith', 'Patel', 'Jones', 'Williams', 'Johnson', 'Taylor', 'Thomas',
  111. 'Roberts', 'Khan', 'Lewis', 'Jackson', 'Clarke', 'James', 'Phillips', 'Wilson',
  112. 'Ali', 'Mason', 'Mitchell', 'Rose', 'Davis', 'Davies', 'Rodriguez', 'Cox', 'Alexander'
  113. ]
  114. for i in range(len(first_names)):
  115. tmp_email = first_names[i].lower() + "." + last_names[i].lower() + "@example.com"
  116. tmp_pass = ''.join(random.choice(string.ascii_lowercase + string.digits) for i in range(10))
  117. user_datastore.create_user(
  118. first_name=first_names[i],
  119. last_name=last_names[i],
  120. email=tmp_email,
  121. password=encrypt_password(tmp_pass),
  122. roles=[user_role, ]
  123. )
  124. db.session.commit()
  125. return
  126. if __name__ == '__main__':
  127. # Build a sample db on the fly, if one does not exist yet.
  128. app_dir = os.path.realpath(os.path.dirname(__file__))
  129. database_path = os.path.join(app_dir, app.config['DATABASE_FILE'])
  130. if not os.path.exists(database_path):
  131. build_sample_db()
  132. # Start app
  133. app.run(debug=True)