app.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. # -*- coding: utf-8 -*-
  2. """
  3. flaskbb.app
  4. ~~~~~~~~~~~~~~~~~~~~
  5. manages the app creation and configuration process
  6. :copyright: (c) 2013 by the FlaskBB Team.
  7. :license: BSD, see LICENSE for more details.
  8. """
  9. import os
  10. import logging
  11. from flask import Flask, render_template
  12. from flask.ext.login import current_user
  13. from flask_debugtoolbar import DebugToolbarExtension
  14. # Import the user blueprint
  15. from flaskbb.user.views import user
  16. from flaskbb.user.models import User, Guest
  17. # Import the auth blueprint
  18. from flaskbb.auth.views import auth
  19. # Import the admin blueprint
  20. from flaskbb.admin.views import admin
  21. # Import the PM blueprint
  22. from flaskbb.pms.views import pms
  23. from flaskbb.pms.models import PrivateMessage
  24. # Import the forum blueprint
  25. from flaskbb.forum.views import forum
  26. from flaskbb.forum.models import *
  27. from flaskbb.extensions import db, login_manager, mail, cache
  28. from flaskbb.template_filters import (format_date, time_since, is_online,
  29. edit_post, delete_post, delete_topic,
  30. post_reply, crop_title)
  31. DEFAULT_BLUEPRINTS = (
  32. (forum, ""),
  33. (auth, ""),
  34. (user, "/u"),
  35. (pms, "/pm"),
  36. (admin, "/admin")
  37. )
  38. def create_app(config=None, blueprints=None):
  39. """
  40. Creates the app.
  41. """
  42. if blueprints is None:
  43. blueprints = DEFAULT_BLUEPRINTS
  44. # Initialize the app
  45. app = Flask("flaskbb")
  46. configure_app(app, config)
  47. configure_extensions(app)
  48. configure_blueprints(app, blueprints)
  49. configure_template_filters(app)
  50. configure_before_handlers(app)
  51. configure_errorhandlers(app)
  52. configure_logging(app)
  53. return app
  54. def configure_app(app, config):
  55. """
  56. Configures the app. If no configuration file is choosen,
  57. the app will use the example configuration.
  58. """
  59. # Get the configuration file
  60. if config is None:
  61. from flaskbb.configs.default import DefaultConfig
  62. app.config.from_object(DefaultConfig)
  63. app.logger.info("No configuration specified. Using the Default config")
  64. else:
  65. app.config.from_object(config)
  66. def configure_extensions(app):
  67. """
  68. Configures the extensions
  69. """
  70. # Flask-SQLAlchemy
  71. db.init_app(app)
  72. # Flask-Mail
  73. mail.init_app(app)
  74. # Flask-Cache
  75. cache.init_app(app)
  76. # Flask-Debugtoolbar
  77. toolbar = DebugToolbarExtension(app)
  78. # Flask-Login
  79. login_manager.login_view = app.config["LOGIN_VIEW"]
  80. login_manager.refresh_view = app.config["REAUTH_VIEW"]
  81. login_manager.anonymous_user = Guest
  82. @login_manager.user_loader
  83. def load_user(id):
  84. """
  85. Loads the user. Required by the `login` extension
  86. """
  87. unread_count = db.session.query(db.func.count(PrivateMessage.id)).\
  88. filter(PrivateMessage.unread == True,
  89. PrivateMessage.user_id == id).subquery()
  90. u = db.session.query(User, unread_count).filter(User.id == id).first()
  91. user, user.pm_unread = u
  92. return user
  93. login_manager.init_app(app)
  94. def configure_blueprints(app, blueprints):
  95. """
  96. Configures the blueprints
  97. """
  98. for blueprint, url_prefix in blueprints:
  99. app.register_blueprint(blueprint, url_prefix=url_prefix)
  100. def configure_template_filters(app):
  101. """
  102. Configures the template filters
  103. """
  104. app.jinja_env.filters['format_date'] = format_date
  105. app.jinja_env.filters['time_since'] = time_since
  106. app.jinja_env.filters['is_online'] = is_online
  107. app.jinja_env.filters['edit_post'] = edit_post
  108. app.jinja_env.filters['delete_post'] = delete_post
  109. app.jinja_env.filters['delete_topic'] = delete_topic
  110. app.jinja_env.filters['post_reply'] = post_reply
  111. app.jinja_env.filters['crop_title'] = crop_title
  112. def configure_before_handlers(app):
  113. """
  114. Configures the before request handlers
  115. """
  116. @app.before_request
  117. def update_lastseen():
  118. """
  119. Updates `lastseen` before every reguest if the user is authenticated
  120. """
  121. if current_user.is_authenticated():
  122. current_user.lastseen = datetime.utcnow()
  123. db.session.add(current_user)
  124. db.session.commit()
  125. @app.before_request
  126. def get_user_permissions():
  127. current_user.permissions = current_user.get_permissions()
  128. def configure_errorhandlers(app):
  129. """
  130. Configures the error handlers
  131. """
  132. @app.errorhandler(403)
  133. def forbidden_page(error):
  134. return render_template("errors/forbidden_page.html"), 403
  135. @app.errorhandler(404)
  136. def page_not_found(error):
  137. return render_template("errors/page_not_found.html"), 404
  138. @app.errorhandler(500)
  139. def server_error_page(error):
  140. return render_template("errors/server_error.html"), 500
  141. def configure_logging(app):
  142. """
  143. Configures logging.
  144. """
  145. logs_folder = os.path.join(app.root_path, os.pardir, "logs")
  146. from logging.handlers import SMTPHandler
  147. formatter = logging.Formatter(
  148. '%(asctime)s %(levelname)s: %(message)s '
  149. '[in %(pathname)s:%(lineno)d]')
  150. info_log = os.path.join(logs_folder, app.config['INFO_LOG'])
  151. info_file_handler = logging.handlers.RotatingFileHandler(
  152. info_log,
  153. maxBytes=100000,
  154. backupCount=10
  155. )
  156. info_file_handler.setLevel(logging.INFO)
  157. info_file_handler.setFormatter(formatter)
  158. app.logger.addHandler(info_file_handler)
  159. error_log = os.path.join(logs_folder, app.config['ERROR_LOG'])
  160. error_file_handler = logging.handlers.RotatingFileHandler(
  161. error_log,
  162. maxBytes=100000,
  163. backupCount=10
  164. )
  165. error_file_handler.setLevel(logging.ERROR)
  166. error_file_handler.setFormatter(formatter)
  167. app.logger.addHandler(error_file_handler)
  168. if app.config["SEND_LOGS"]:
  169. mail_handler = \
  170. SMTPHandler(app.config['MAIL_SERVER'],
  171. app.config['DEFAULT_MAIL_SENDER'],
  172. app.config['ADMINS'],
  173. 'application error, no admins specified',
  174. (
  175. app.config['MAIL_USERNAME'],
  176. app.config['MAIL_PASSWORD'],
  177. ))
  178. mail_handler.setLevel(logging.ERROR)
  179. mail_handler.setFormatter(formatter)
  180. app.logger.addHandler(mail_handler)