Source code for hapcat

# -*- coding: utf-8 -*-

"""The Hapcat Backend package.
"""

from __future__ import (
    absolute_import,
    division,
)

__version__ = '0.0.4.dev6'

__description__ = """\
The backend daemon for the hapcat project.
"""

__api_versions__ = [
    0,
]

import configparser
import datetime
import flask
import flask_api
import flask_cors
import flask_jwt
import flask_ini
import flask_migrate
import flask_sqlalchemy
import os
import os.path
import pkg_resources
import sys

try:
    import secrets
except ImportError:
    # Import the small module hackily copied from the Python 3.6 library, since
    # no one seems to have backported it on PyPI yet.
    import hapcat.compat.secrets as secrets


app = flask_api.FlaskAPI(
    'hapcat',
)

with app.app_context():
    app.iniconfig = flask_ini.FlaskIni(
        delimiters=('=',),
        comment_prefixes=('#',),
        inline_comment_prefixes=None,
        strict=True,
        interpolation=configparser.ExtendedInterpolation()
    )

    app.iniconfig.read(
        pkg_resources.resource_filename('hapcat', 'data/hapcatd-defaults.conf')
    )

    envconf = os.environ.get('HAPCAT_FLASK_CONFIG', None)

    if envconf:
        app.iniconfig.read(envconf)

app.config['SQLALCHEMY_DATABASE_URI'] = app.iniconfig.get('database', 'dburl')

db = flask_sqlalchemy.SQLAlchemy(app)

migrate = flask_migrate.Migrate(
    app,
    db,
    directory=pkg_resources.resource_filename('hapcat', 'migrations'),
)


flask_cors.CORS(
    app,
    expose_headers='Authorization'
)

insphinx = os.path.basename(sys.argv[0]) in ['sphinx-build', 'sphinx-build.exe']

if not insphinx:
    with app.app_context():
        flask_migrate.upgrade()

[docs]def makejwtsecret(bits=512): """Read or generate the JWT secret. """ if insphinx: # Create a random secret instead of querying while in Sphinx. return secrets.token_bytes(bits // 8) key = u'jwtsecret' from hapcat.models import Secret # First try to get the secret. secret = db.session.query(Secret).filter(Secret.id == key).first() if secret: return secret.payload payload = secrets.token_bytes(bits // 8) secret = Secret(id=key, payload=payload) db.session.add(secret) db.session.commit() return secret.payload
app.config['SECRET_KEY'] = makejwtsecret() app.config['JWT_ALGORITHM'] = 'HS512' app.config['JWT_AUTH_URL_RULE'] = None app.config['JWT_EXPIRATION_DELTA'] = datetime.timedelta(days=30)
[docs]def authenticate(username, password): """Authenticate the user. """ User = hapcat.models.User user = db.session.query(User).filter(User.username == username).scalar() if user is not None and user.password == password: return user
[docs]def identity(payload): """Get the identity from the JWT payload. """ User = hapcat.models.User userid = payload['identity'] return db.session.query(User).filter(User.id == userid).scalar()
jwt = flask_jwt.JWT(app, authenticate, identity)
[docs]@jwt.jwt_payload_handler def payload_handler(identity): """Transform the identity object into a payload. """ current_app = flask.current_app iat = datetime.datetime.utcnow() exp = iat + current_app.config.get('JWT_EXPIRATION_DELTA') nbf = iat + current_app.config.get('JWT_NOT_BEFORE_DELTA') identity = str(identity.id) return { 'exp': exp, 'iat': iat, 'nbf': nbf, 'identity': identity }
import hapcat.apiserver import hapcat.models