Advertisement
Guest User

Untitled

a guest
Sep 11th, 2017
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.42 KB | None | 0 0
  1. # THIS PROJECT IS AN EXAMPLE APP. SOME CODE MAY NOT BE ACTUALLY USEFUL
  2. # FOR DEMONSTRATION PURPOSES ONLY
  3. # YOUR MILEAGE MAY VARY
  4. # Requirements are Flask, Flask-WTF, Flask-SQLAlchemy, bcrypt
  5.  
  6. import os
  7.  
  8. from flask import (Flask,
  9. Blueprint,
  10. redirect,
  11. render_template_string,
  12. request,
  13. url_for)
  14. from flask_login import UserMixin
  15. from flask_principal import Permission, RoleNeed
  16.  
  17. from flask_security import (
  18. login_required,
  19. RoleMixin,
  20. Security,
  21. SQLAlchemyUserDatastore,
  22. utils,
  23. )
  24. from flask_sqlalchemy import SQLAlchemy
  25. from flask_wtf import FlaskForm
  26. from wtforms import (
  27. HiddenField,
  28. StringField,
  29. SubmitField,
  30. TextAreaField)
  31. from wtforms.validators import DataRequired
  32.  
  33. BASE_PATH = os.path.abspath(os.path.dirname(__file__))
  34.  
  35. # Instantiate the extensions but do not initialize them yet.
  36. db = SQLAlchemy()
  37. security = Security()
  38.  
  39. # The following are template strings which are utilized by jinja2. Jinja2
  40. # is a template language which provides specific tags that allow the ability to
  41. # execute python code during the parsing process.
  42.  
  43. # The index template string for the main page
  44. index_template = '''
  45. <div class="nav">
  46. {% if current_user.is_authenticated %}
  47. Welcome, {{ current_user.email }}
  48. <a href="{{ url_for('security.logout') }}">Logout</a>
  49. <a href="{{ url_for('blog.blog_index') }}">View All</a>
  50. {% else %}
  51. <a href="{{ url_for('security.login') }}">Login</a>
  52. {% endif %}
  53. </div>
  54.  
  55. {% if posts %}
  56. {% for post in posts %}
  57. <div>
  58. <h1>{{ post.title }}</h1>
  59. <p> {{ post.text }} </p>
  60. {% endfor %}
  61. </div>
  62. {% else %}
  63. <p>No posts yet. Try again later</p>
  64. {% endif %}
  65. '''
  66.  
  67. blog_index_template = '''
  68. {% if posts %}
  69. <table class="posts-table">
  70. <thead>
  71. <tr>
  72. <th>post id</th>
  73. <th>title</th>
  74. <th>text</th>
  75. </tr>
  76. </thead>
  77. <tbody>
  78. {% for post in posts %}
  79. <tr>
  80. <td>{{ post.id }}</td>
  81. <td><a href="{{ url_for('blog.edit_post', post_id=post.id) }}">{{ post.title }}</a></td>
  82. <td>{{ post.text }}</td>
  83. </tr>
  84. {% endfor %}
  85. </tbody>
  86. </table>
  87. {% else %}
  88. <p> You don't have any posts </p>
  89. {% endif %}
  90. <a href = "{{ url_for('blog.create_post') }}">Create Post</a>
  91. '''
  92.  
  93. # The template string for creating/editing a blog post
  94. create_post_template = '''
  95. <div class="post-form">
  96. <form action="{% if form.id %} {{url_for('blog.edit_post', post_id=form.id.data) }} {% else %} {{ url_for('blog.create_post') }} {% endif %}" method="POST" name="post_form">
  97. {% if form.id %}
  98. {{ form.id }}
  99. {% endif %}
  100. {{ form.csrf_token }}
  101. {{ form.title.label }}
  102. {{ form.title }}
  103. {{ form.text.label }}
  104. {{ form.text }}
  105. {{ form.submit() }}
  106. </form>
  107. </div>
  108. '''
  109.  
  110. # Customize your own error pages
  111. error_template = '''
  112. <div id="error">
  113. <h1> Sorry, there was an error</h1>
  114. <p>Error:# {{ status_code }}</p>
  115. </div>
  116. '''
  117.  
  118.  
  119. # Blog post creation form
  120. class CreatePostForm(FlaskForm):
  121. """
  122. The form used to create a blog post
  123. """
  124. title = StringField('Title', validators=[DataRequired()])
  125. text = TextAreaField('Text', validators=[DataRequired()])
  126. submit = SubmitField('Submit')
  127.  
  128.  
  129. class EditPostForm(CreatePostForm):
  130. id = HiddenField()
  131.  
  132.  
  133. # Create the Models
  134. class Post(db.Model):
  135. __tablename__ = 'posts'
  136.  
  137. id = db.Column(db.Integer(), primary_key=True)
  138. title = db.Column(db.String(100))
  139. text = db.Column(db.Text())
  140.  
  141. @classmethod
  142. def all(cls):
  143. """
  144. Returns all researcher items from the database
  145. """
  146. return db.session.query(cls).all()
  147.  
  148.  
  149. roles_users = db.Table(
  150. 'roles_users',
  151. db.Column('user_id', db.Integer(), db.ForeignKey('users.id')),
  152. db.Column('role_id', db.Integer(), db.ForeignKey('roles.id')))
  153.  
  154.  
  155. class Role(RoleMixin, db.Model):
  156. __tablename__ = 'roles'
  157.  
  158. id = db.Column(db.Integer(), primary_key=True)
  159. name = db.Column(db.String(80), unique=True)
  160. description = db.Column(db.String(255))
  161.  
  162. def __eq__(self, other):
  163. return (self.name == other or
  164. self.name == getattr(other, 'name', None))
  165.  
  166. def __ne__(self, other):
  167. return (self.name != other and
  168. self.name != getattr(other, 'name', None))
  169.  
  170.  
  171. class User(UserMixin, db.Model):
  172. __tablename__ = 'users'
  173.  
  174. id = db.Column(db.Integer, primary_key=True)
  175. email = db.Column(db.String(255), unique=True)
  176. password = db.Column(db.String(120))
  177. active = db.Column(db.Boolean())
  178. confirmed_at = db.Column(db.DateTime())
  179. last_login_at = db.Column(db.DateTime())
  180. current_login_at = db.Column(db.DateTime())
  181. last_login_ip = db.Column(db.String(100))
  182. current_login_ip = db.Column(db.String(100))
  183. login_count = db.Column(db.Integer)
  184. registered_at = db.Column(db.DateTime())
  185.  
  186. roles = db.relationship('Role', secondary=roles_users,
  187. backref=db.backref('users', lazy='dynamic'))
  188.  
  189.  
  190. # Create settings object
  191. settings = {
  192. 'SECRET_KEY': 'super not secure development key',
  193. 'DEBUG': True,
  194. 'SQLALCHEMY_TRACK_MODIFICATIONS': False,
  195. 'SQLALCHEMY_DATABASE_URI': 'sqlite:///' + os.path.join(BASE_PATH,
  196. 'posts.db'),
  197. 'SQLALCHEMY_ECHO': True,
  198. 'SECURITY_PASSWORD_HASH': 'bcrypt',
  199. 'SECURITY_PASSWORD_SALT': os.environ.get('SECURITY_SALT', 'dev secret'),
  200. 'SECUIRTY_CONFIRMABLE': False,
  201. 'SECURITY_REGISTERABLE': False,
  202. 'SECURITY_TRACKABLE': True,
  203. 'SECURITY_CHANGEABLE': True
  204. }
  205.  
  206. # Create the main Flask application
  207. app = Flask(__name__)
  208. app.config.update(settings)
  209.  
  210. # Initialize extensions
  211. db.init_app(app)
  212. security.init_app(app,
  213. SQLAlchemyUserDatastore(db, User, Role),
  214. register_blueprint=True)
  215.  
  216.  
  217. # Public Endpoints
  218. @app.route('/', methods=['GET'])
  219. def index():
  220. posts = Post.all()
  221. return render_template_string(index_template, posts=posts)
  222.  
  223.  
  224. # Register errorhandlers
  225. @app.errorhandler(404)
  226. def page_not_found(e):
  227. return render_template_string(error_template, status_code=404), 404
  228.  
  229.  
  230. @app.errorhandler(500)
  231. def server_error(e):
  232. return render_template_string(error_template, status_code=500), 500
  233.  
  234.  
  235. # Create blog blueprint
  236. blog = Blueprint('blog', __name__, url_prefix='/blog')
  237.  
  238. # Create admin role for blog endpoints
  239. admin_permission = Permission(RoleNeed('admin'))
  240.  
  241.  
  242. # Create the blog routes
  243. @blog.route('/', methods=['GET'])
  244. @login_required
  245. @admin_permission.require()
  246. def blog_index():
  247. posts = Post.all()
  248. return render_template_string(blog_index_template, posts=posts)
  249.  
  250.  
  251. @blog.route('/create', methods=['GET', 'POST'])
  252. @login_required
  253. @admin_permission.require()
  254. def create_post():
  255. form = CreatePostForm(request.form)
  256. if form.validate_on_submit():
  257. post = Post(title=form.title.data,
  258. text=form.text.data)
  259. db.session.add(post)
  260. db.session.commit()
  261. return redirect(url_for('blog.blog_index'))
  262. return render_template_string(create_post_template, form=form)
  263.  
  264.  
  265. @blog.route('/edit/<int:post_id>', methods=['GET', 'POST'])
  266. @login_required
  267. @admin_permission.require()
  268. def edit_post(post_id):
  269. post = Post.query.get(post_id)
  270. form = EditPostForm(request.form, obj=post)
  271. if form.validate_on_submit():
  272. form.populate_obj(post)
  273. db.session.merge(post)
  274. db.session.commit()
  275. return redirect(url_for('blog.blog_index'))
  276. return render_template_string(create_post_template, form=form)
  277.  
  278.  
  279. # Register bluprints
  280. app.register_blueprint(blog)
  281.  
  282.  
  283. # Utils
  284. def create_and_seed_db():
  285. # Hack for running db commands w/o context
  286. ctx = app.test_request_context()
  287. ctx.push()
  288. db.create_all()
  289. # Create the administrator role
  290. user_datastore = app.extensions['security'].datastore
  291. user_datastore.find_or_create_role(name='admin',
  292. description='Administrator')
  293. # Create the demo user
  294. encrypted_password = utils.hash_password('demo')
  295. user = User(email='demo', password=encrypted_password)
  296. db.session.add(user)
  297. db.session.commit()
  298. user_datastore.add_role_to_user('demo', 'admin')
  299. db.session.commit()
  300.  
  301. return
  302.  
  303.  
  304. if __name__ == '__main__':
  305. # This will create the database if it doesn't already exist.
  306. if not os.path.exists(
  307. app.config['SQLALCHEMY_DATABASE_URI'].split('///')[1]):
  308. create_and_seed_db()
  309. app.run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement