Source code for server
# __init__.py, part of the server package
#
# part of https://github.com/varkenvarken/dockerplayground
#
# (c) 2020 Michel Anders (varkenvarken)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
"""
The server module implements an authentication server.
It is a WSGI app implemented in falcon and exposes an app variable that can be called from any WSGI server, like gunicorn.
A typical invocation is::
gunicorn -b 0.0.0.0:8005 server:create_app()
On import a sqlite database is initialized and logging is started.
For more information see `the GitHub repo <https://github.com/varkenvarken/dockerplayground/tree/master/authserver>`_
The following attributes will be initialized to the values defined in the corresponding environment variables
Attributes:
DEBUGLEVEL: can be CRITICAL, ERROR, SUCCESS, INFO, DEBUG, TRACE. Defaults to DEBUG
DATABASE_FILE: path to database file, default to `user.db`
DATABASE_BACKOFF: number of seconds to wait between database connection retries, defaults to 1, doubles every retry.
DATABASE_RETRIES: number of times to retry a database connection. Defaults to 3.
"""
from os import environ
from sys import stderr
import falcon
from loguru import logger
from .server import get_sessionmaker, add_superuser, LoginResource, LogoutResource, VerifySessionResource, RegisterResource, ConfirmRegistrationResource, ForgotPasswordResource, ConfirmForgotPasswordResource, ChoosePasswordResource, StatsResource
logger.remove()
logger.add(stderr, level=environ['DEBUGLEVEL'] if 'DEBUGLEVEL' in environ else 'DEBUG')
DATABASE_FILE = environ['DATABASE_FILE'] if 'DATABASE_FILE' in environ else 'user.db'
DATABASE_BACKOFF = int(environ['DATABASE_BACKOFF']) if 'DATABASE_BACKOFF' in environ else 1
DATABASE_RETRIES = int(environ['DATABASE_RETRIES']) if 'DATABASE_RETRIES' in environ else 3
[docs]def create_app():
"""
An WSGI app factory.
Returns:
:class:`falcon.API`
When the app is created, a SQLAlchemy/sqlite database is initialized with :func:`.server.get_sessionmaker`.
The initialization will also create an admin user with :func:`.server.add_superuser`.
"""
# open the sqlite database and initialize a SQLAlchemy sessionmaker
if get_sessionmaker(f"sqlite:///{DATABASE_FILE}", DATABASE_BACKOFF, DATABASE_RETRIES):
# make sure the superuser is present in the database
if add_superuser():
# initialize the falcon WSGI application
app = falcon.API()
# a parameters in form-urlencoded bodies will be added to the request params (just like query params)
app.req_options.auto_parse_form_urlencoded = True
app.add_route('/login', LoginResource())
app.add_route('/logout', LogoutResource())
app.add_route('/verifysession', VerifySessionResource())
app.add_route('/register', RegisterResource())
app.add_route('/confirmregistration', ConfirmRegistrationResource())
app.add_route('/forgotpassword', ForgotPasswordResource())
app.add_route('/confirmforgotpassword', ConfirmForgotPasswordResource())
app.add_route('/choosepassword', ChoosePasswordResource())
app.add_route('/stats/{item}', StatsResource())
# TODO add change password functionality
logger.success('falcon app initialized')
return app
else:
logger.critical("could not initialize falcon app")
else:
logger.critical(f"could not start database {environ['DATABASE_FILE']}")