view wikked/web.py @ 131:9d22cf4d2412

Massive change that should have been several smaller ones, but whatever: - URLs are not slugified anymore, just quoted. - `getPage` now raises an error if the page doesn't exist. - Fixed the Mercurial SCM provider to be able to commit new files. - Fixed various issues with meta-pages and new files. - Better exception classes. - Configurable default file extension, main page name, and templates folder. - New CLI command to cache the wiki. - A few other small fixes.
author Ludovic Chabant <ludovic@chabant.com>
date Sun, 01 Dec 2013 21:50:29 -0800
parents 7c8543878b47
children 7e4287d9b3bb
line wrap: on
line source

import os
import os.path
import logging
from flask import Flask, abort, g
from utils import find_wiki_root

# Create the main app.
app = Flask("wikked.web")
app.config.from_object('wikked.settings')
app.config.from_envvar('WIKKED_SETTINGS', silent=True)


# Setup some config defaults.
app.config.setdefault('SQL_DEBUG', False)
app.config.setdefault('SQL_COMMIT_ON_TEARDOWN', False)


# Find the wiki root, and further configure the app if there's a
# config file in there.
wiki_root = find_wiki_root()
config_path = os.path.join(wiki_root, '.wiki', 'app.cfg')
if os.path.isfile(config_path):
    app.config.from_pyfile(config_path)


# Make the app serve static content and wiki assets in DEBUG mode.
if app.config['DEBUG']:
    from werkzeug import SharedDataMiddleware
    import os
    app.wsgi_app = SharedDataMiddleware(app.wsgi_app, {
      '/': os.path.join(
          os.path.dirname(os.path.dirname(__file__)),
          'build'),
      '/files': os.path.join(wiki_root)
    })


# Customize logging.
if app.config['DEBUG']:
    l = logging.getLogger('wikked')
    l.setLevel(logging.DEBUG)

if app.config['SQL_DEBUG']:
    l = logging.getLogger('sqlalchemy')
    l.setLevel(logging.DEBUG)


# Set the wiki as a request global, and open/close the database.
# NOTE: this must happen before the login extension is registered
#       because it will also add a `before_request` callback, and
#       that will call our authentication handler that needs
#       access to the context instance for the wiki.
@app.before_request
def before_request():
    g.wiki = wiki


@app.teardown_request
def teardown_request(exception):
    return exception


# SQLAlchemy.
@app.teardown_appcontext
def shutdown_session(exception=None):
    wiki = getattr(g, 'wiki', None)
    if wiki:
        if app.config['SQL_COMMIT_ON_TEARDOWN'] and exception is None:
            wiki.db.session.commit()
        wiki.db.session.remove()
        return exception


# Login extension.
def user_loader(username):
    return g.wiki.auth.getUser(username)


from flask.ext.login import LoginManager
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.user_loader(user_loader)
login_manager.unauthorized_handler(lambda: abort(401))


# Bcrypt extension.
try:
    from flaskext.bcrypt import Bcrypt
    app.bcrypt = Bcrypt(app)
except ImportError:
    app.logger.warning("Bcrypt not available... falling back to SHA512.")

    import hashlib

    class SHA512Fallback(object):
        def check_password_hash(self, reference, check):
            check_hash = hashlib.sha512(check).hexdigest()
            return check_hash == reference

        def generate_password_hash(self, password):
            return hashlib.sha512(password).hexdigest()

    app.bcrypt = SHA512Fallback()


# Create the wiki.
from wiki import Wiki, WikiParameters

def create_wiki(update_on_start=True):
    params = WikiParameters(root=wiki_root)
    wiki = Wiki(params)
    wiki.start(update_on_start)
    return wiki


wiki = create_wiki(bool(app.config.get('UPDATE_WIKI_ON_START')))


# Import the views.
# (this creates a PyLint warning but it's OK)
import views