mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2024-11-14 00:35:41 +00:00
Simplify Config setup and move some functions to dedicated files
This commit is contained in:
parent
8a69d6364a
commit
52c25fd563
22
.env.tpl
22
.env.tpl
@ -91,9 +91,8 @@ MAIL_USERNAME=
|
|||||||
# Flask-SQLAlchemy #
|
# Flask-SQLAlchemy #
|
||||||
# https://flask-sqlalchemy.palletsprojects.com/en/2.x/config/ #
|
# https://flask-sqlalchemy.palletsprojects.com/en/2.x/config/ #
|
||||||
################################################################################
|
################################################################################
|
||||||
# DEFAULT with development config: postgresql://nopaque:nopaque@db/nopaque_dev
|
# DEFAULT: 'sqlite:///<nopaque-root-dir>/app.db'
|
||||||
# DEFAULT with production config: postgresql://nopaque:nopaque@db/nopaque
|
# NOTE: Use `.` as <nopaque-root-dir>
|
||||||
# DEFAULT with testing config: postgresql://nopaque:nopaque@db/nopaque_test
|
|
||||||
# SQLALCHEMY_DATABASE_URI=
|
# SQLALCHEMY_DATABASE_URI=
|
||||||
|
|
||||||
|
|
||||||
@ -105,10 +104,6 @@ MAIL_USERNAME=
|
|||||||
# EXAMPLE: admin.nopaque@example.com
|
# EXAMPLE: admin.nopaque@example.com
|
||||||
NOPAQUE_ADMIN=
|
NOPAQUE_ADMIN=
|
||||||
|
|
||||||
# DEFAULT: development
|
|
||||||
# CHOOSE ONE: development, production, testing
|
|
||||||
# NOPAQUE_CONFIG=
|
|
||||||
|
|
||||||
# This email adress is used for the contact button in the nopaque footer. If
|
# This email adress is used for the contact button in the nopaque footer. If
|
||||||
# not set, no contact button is displayed.
|
# not set, no contact button is displayed.
|
||||||
# DEFAULT: None
|
# DEFAULT: None
|
||||||
@ -124,24 +119,13 @@ NOPAQUE_ADMIN=
|
|||||||
# DEFAULT: True
|
# DEFAULT: True
|
||||||
# NOPAQUE_DAEMON_ENABLED=
|
# NOPAQUE_DAEMON_ENABLED=
|
||||||
|
|
||||||
# The hostname or IP address for the server to listen on.
|
|
||||||
# DEFAULT: 0.0.0.0
|
|
||||||
# NOTES: To use a domain locally, add any names that should route to the app to your hosts file.
|
|
||||||
# If nopaque is running in a Docker container, you propably want to use the default value.
|
|
||||||
# NOPAQUE_HOST=
|
|
||||||
|
|
||||||
# The port number for the server to listen on.
|
|
||||||
# DEFAULT: 5000
|
|
||||||
# NOTE: If nopaque is running in a Docker container, you propably want to use the default value.
|
|
||||||
# NOPAQUE_PORT=
|
|
||||||
|
|
||||||
# transport://[userid:password]@hostname[:port]/[virtual_host]
|
# transport://[userid:password]@hostname[:port]/[virtual_host]
|
||||||
NOPAQUE_SOCKETIO_MESSAGE_QUEUE_URI=
|
NOPAQUE_SOCKETIO_MESSAGE_QUEUE_URI=
|
||||||
|
|
||||||
# DEFAULT: %Y-%m-%d %H:%M:%S
|
# DEFAULT: %Y-%m-%d %H:%M:%S
|
||||||
# NOPAQUE_LOG_DATE_FORMAT=
|
# NOPAQUE_LOG_DATE_FORMAT=
|
||||||
|
|
||||||
# DEFAULT: <nopaque-root-dir>/nopaque.log ~ /home/nopaque/nopaque.log
|
# DEFAULT: <nopaque-root-dir>/nopaque.log
|
||||||
# NOTE: Use `.` as <nopaque-root-dir>
|
# NOTE: Use `.` as <nopaque-root-dir>
|
||||||
# NOPAQUE_LOG_FILE=
|
# NOPAQUE_LOG_FILE=
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
from config import config
|
from config import Config
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from flask_login import LoginManager
|
from flask_login import LoginManager
|
||||||
from flask_mail import Mail
|
from flask_mail import Mail
|
||||||
|
from flask_migrate import Migrate
|
||||||
from flask_paranoid import Paranoid
|
from flask_paranoid import Paranoid
|
||||||
from flask_socketio import SocketIO
|
from flask_socketio import SocketIO
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
@ -10,23 +11,26 @@ import flask_assets
|
|||||||
|
|
||||||
assets = flask_assets.Environment()
|
assets = flask_assets.Environment()
|
||||||
db = SQLAlchemy()
|
db = SQLAlchemy()
|
||||||
login_manager = LoginManager()
|
login = LoginManager()
|
||||||
login_manager.login_view = 'auth.login'
|
login.login_view = 'auth.login'
|
||||||
|
login.login_message = 'Please log in to access this page.'
|
||||||
mail = Mail()
|
mail = Mail()
|
||||||
|
migrate = Migrate()
|
||||||
paranoid = Paranoid()
|
paranoid = Paranoid()
|
||||||
paranoid.redirect_view = '/'
|
paranoid.redirect_view = '/'
|
||||||
socketio = SocketIO()
|
socketio = SocketIO()
|
||||||
|
|
||||||
|
|
||||||
def create_app(config_name):
|
def create_app(config_class=Config):
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.config.from_object(config[config_name])
|
app.config.from_object(config_class)
|
||||||
|
|
||||||
assets.init_app(app)
|
assets.init_app(app)
|
||||||
config[config_name].init_app(app)
|
config_class.init_app(app)
|
||||||
db.init_app(app)
|
db.init_app(app)
|
||||||
login_manager.init_app(app)
|
login.init_app(app)
|
||||||
mail.init_app(app)
|
mail.init_app(app)
|
||||||
|
migrate.init_app(app, db)
|
||||||
paranoid.init_app(app)
|
paranoid.init_app(app)
|
||||||
socketio.init_app(
|
socketio.init_app(
|
||||||
app, message_queue=app.config['NOPAQUE_SOCKETIO_MESSAGE_QUEUE_URI'])
|
app, message_queue=app.config['NOPAQUE_SOCKETIO_MESSAGE_QUEUE_URI'])
|
||||||
|
25
app/cli.py
Normal file
25
app/cli.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
from .models import Role
|
||||||
|
from flask_migrate import upgrade
|
||||||
|
|
||||||
|
|
||||||
|
def register(app):
|
||||||
|
@app.cli.command()
|
||||||
|
def deploy():
|
||||||
|
"""Run deployment tasks."""
|
||||||
|
# migrate database to latest revision
|
||||||
|
upgrade()
|
||||||
|
# create or update user roles
|
||||||
|
Role.insert_roles()
|
||||||
|
|
||||||
|
@app.cli.command()
|
||||||
|
def tasks():
|
||||||
|
from app.tasks import TaskRunner
|
||||||
|
task_runner = TaskRunner()
|
||||||
|
task_runner.run()
|
||||||
|
|
||||||
|
@app.cli.command()
|
||||||
|
def test():
|
||||||
|
"""Run the unit tests."""
|
||||||
|
import unittest
|
||||||
|
tests = unittest.TestLoader().discover('tests')
|
||||||
|
unittest.TextTestRunner(verbosity=2).run(tests)
|
@ -1,11 +1,11 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from flask import current_app, url_for
|
from flask import current_app, url_for
|
||||||
from flask_login import UserMixin, AnonymousUserMixin
|
from flask_login import UserMixin
|
||||||
from itsdangerous import BadSignature, TimedJSONWebSignatureSerializer
|
from itsdangerous import BadSignature, TimedJSONWebSignatureSerializer
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from werkzeug.security import generate_password_hash, check_password_hash
|
from werkzeug.security import generate_password_hash, check_password_hash
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
from . import db, login_manager
|
from . import db, login
|
||||||
import base64
|
import base64
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
@ -285,18 +285,6 @@ class User(UserMixin, db.Model):
|
|||||||
return user
|
return user
|
||||||
|
|
||||||
|
|
||||||
class AnonymousUser(AnonymousUserMixin):
|
|
||||||
'''
|
|
||||||
Model replaces the default AnonymousUser.
|
|
||||||
'''
|
|
||||||
|
|
||||||
def can(self, permissions):
|
|
||||||
return False
|
|
||||||
|
|
||||||
def is_administrator(self):
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class JobInput(db.Model):
|
class JobInput(db.Model):
|
||||||
'''
|
'''
|
||||||
Class to define JobInputs.
|
Class to define JobInputs.
|
||||||
@ -722,13 +710,6 @@ class QueryResult(db.Model):
|
|||||||
return '<QueryResult {}>'.format(self.title)
|
return '<QueryResult {}>'.format(self.title)
|
||||||
|
|
||||||
|
|
||||||
'''
|
@login.user_loader
|
||||||
' Flask-Login is told to use the application’s custom anonymous user by setting
|
|
||||||
' its class in the login_manager.anonymous_user attribute.
|
|
||||||
'''
|
|
||||||
login_manager.anonymous_user = AnonymousUser
|
|
||||||
|
|
||||||
|
|
||||||
@login_manager.user_loader
|
|
||||||
def load_user(user_id):
|
def load_user(user_id):
|
||||||
return User.query.get(int(user_id))
|
return User.query.get(int(user_id))
|
||||||
|
44
config.py
44
config.py
@ -1,9 +1,11 @@
|
|||||||
|
from dotenv import load_dotenv
|
||||||
from werkzeug.middleware.proxy_fix import ProxyFix
|
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
ROOT_DIR = os.path.abspath(os.path.dirname(__file__))
|
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
load_dotenv(os.path.join(basedir, '.env'))
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
@ -33,6 +35,10 @@ class Config:
|
|||||||
MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS', 'false').lower() == 'true'
|
MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS', 'false').lower() == 'true'
|
||||||
|
|
||||||
''' # Flask-SQLAlchemy # '''
|
''' # Flask-SQLAlchemy # '''
|
||||||
|
SQLALCHEMY_DATABASE_URI = os.environ.get(
|
||||||
|
'SQLALCHEMY_DATABASE_URI',
|
||||||
|
'sqlite:///' + os.path.join(basedir, 'app.db')
|
||||||
|
)
|
||||||
SQLALCHEMY_RECORD_QUERIES = True
|
SQLALCHEMY_RECORD_QUERIES = True
|
||||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||||
|
|
||||||
@ -52,7 +58,7 @@ class Config:
|
|||||||
'datefmt': os.environ.get('NOPAQUE_LOG_DATE_FORMAT',
|
'datefmt': os.environ.get('NOPAQUE_LOG_DATE_FORMAT',
|
||||||
'%Y-%m-%d %H:%M:%S'),
|
'%Y-%m-%d %H:%M:%S'),
|
||||||
'filename': os.environ.get('NOPAQUE_LOG_FILE',
|
'filename': os.environ.get('NOPAQUE_LOG_FILE',
|
||||||
os.path.join(ROOT_DIR, 'nopaque.log')),
|
os.path.join(basedir, 'nopaque.log')),
|
||||||
'format': os.environ.get(
|
'format': os.environ.get(
|
||||||
'NOPAQUE_LOG_FORMAT',
|
'NOPAQUE_LOG_FORMAT',
|
||||||
'[%(asctime)s] %(levelname)s in '
|
'[%(asctime)s] %(levelname)s in '
|
||||||
@ -72,37 +78,3 @@ class Config:
|
|||||||
'x_proto': int(os.environ.get('NOPAQUE_PROXY_FIX_X_PROTO', '0'))
|
'x_proto': int(os.environ.get('NOPAQUE_PROXY_FIX_X_PROTO', '0'))
|
||||||
}
|
}
|
||||||
app.wsgi_app = ProxyFix(app.wsgi_app, **proxy_fix_kwargs)
|
app.wsgi_app = ProxyFix(app.wsgi_app, **proxy_fix_kwargs)
|
||||||
|
|
||||||
|
|
||||||
class DevelopmentConfig(Config):
|
|
||||||
''' # Flask # '''
|
|
||||||
DEBUG = True
|
|
||||||
|
|
||||||
''' # Flask-SQLAlchemy # '''
|
|
||||||
SQLALCHEMY_DATABASE_URI = os.environ.get(
|
|
||||||
'SQLALCHEMY_DATABASE_URI',
|
|
||||||
'postgresql://nopaque:nopaque@db/nopaque_dev'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ProductionConfig(Config):
|
|
||||||
''' # Flask-SQLAlchemy # '''
|
|
||||||
SQLALCHEMY_DATABASE_URI = os.environ.get(
|
|
||||||
'SQLALCHEMY_DATABASE_URI', 'postgresql://nopaque:nopaque@db/nopaque')
|
|
||||||
|
|
||||||
|
|
||||||
class TestingConfig(Config):
|
|
||||||
''' # Flask # '''
|
|
||||||
TESTING = True
|
|
||||||
WTF_CSRF_ENABLED = False
|
|
||||||
|
|
||||||
''' # Flask-SQLAlchemy # '''
|
|
||||||
SQLALCHEMY_DATABASE_URI = os.environ.get(
|
|
||||||
'SQLALCHEMY_DATABASE_URI',
|
|
||||||
'postgresql://nopaque:nopaque@db/nopaque_test'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
config = {'development': DevelopmentConfig,
|
|
||||||
'production': ProductionConfig,
|
|
||||||
'testing': TestingConfig}
|
|
||||||
|
45
nopaque.py
45
nopaque.py
@ -6,23 +6,13 @@ import eventlet
|
|||||||
eventlet.monkey_patch()
|
eventlet.monkey_patch()
|
||||||
|
|
||||||
|
|
||||||
from dotenv import load_dotenv # noqa
|
from app import db, cli, create_app, socketio # noqa
|
||||||
import os # noqa
|
|
||||||
|
|
||||||
# Load environment variables
|
|
||||||
DOTENV_FILE = os.path.join(os.path.dirname(__file__), '.env')
|
|
||||||
if os.path.exists(DOTENV_FILE):
|
|
||||||
load_dotenv(DOTENV_FILE)
|
|
||||||
|
|
||||||
|
|
||||||
from app import create_app, db, socketio # noqa
|
|
||||||
from app.models import (Corpus, CorpusFile, Job, JobInput, JobResult,
|
from app.models import (Corpus, CorpusFile, Job, JobInput, JobResult,
|
||||||
QueryResult, Role, User) # noqa
|
QueryResult, Role, User) # noqa
|
||||||
from flask_migrate import Migrate, upgrade # noqa
|
|
||||||
|
|
||||||
|
|
||||||
app = create_app(os.environ.get('NOPAQUE_CONFIG', 'development'))
|
app = create_app()
|
||||||
migrate = Migrate(app, db, compare_type=True)
|
cli.register(app)
|
||||||
|
|
||||||
|
|
||||||
@app.shell_context_processor
|
@app.shell_context_processor
|
||||||
@ -38,32 +28,7 @@ def make_shell_context():
|
|||||||
'User': User}
|
'User': User}
|
||||||
|
|
||||||
|
|
||||||
@app.cli.command()
|
|
||||||
def deploy():
|
|
||||||
"""Run deployment tasks."""
|
|
||||||
# migrate database to latest revision
|
|
||||||
upgrade()
|
|
||||||
|
|
||||||
# create or update user roles
|
|
||||||
Role.insert_roles()
|
|
||||||
|
|
||||||
|
|
||||||
@app.cli.command()
|
|
||||||
def tasks():
|
|
||||||
from app.tasks import TaskRunner
|
|
||||||
task_runner = TaskRunner()
|
|
||||||
task_runner.run()
|
|
||||||
|
|
||||||
|
|
||||||
@app.cli.command()
|
|
||||||
def test():
|
|
||||||
"""Run the unit tests."""
|
|
||||||
import unittest
|
|
||||||
tests = unittest.TestLoader().discover('tests')
|
|
||||||
unittest.TextTestRunner(verbosity=2).run(tests)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
host = os.environ.get('NOPAQUE_HOST', '0.0.0.0')
|
host = '0.0.0.0'
|
||||||
port = int(os.environ.get('NOPAQUE_PORT', '5000'))
|
port = 5000
|
||||||
socketio.run(app, host=host, port=port)
|
socketio.run(app, host=host, port=port)
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
from config import Config
|
||||||
|
|
||||||
|
|
||||||
|
class TestConfig(Config):
|
||||||
|
TESTING = True
|
||||||
|
SQLALCHEMY_DATABASE_URI = 'sqlite://'
|
@ -1,11 +1,12 @@
|
|||||||
import unittest
|
|
||||||
from flask import current_app
|
|
||||||
from app import create_app, db
|
from app import create_app, db
|
||||||
|
from flask import current_app
|
||||||
|
from . import TestConfig
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
class BasicsTestCase(unittest.TestCase):
|
class BasicsTestCase(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.app = create_app('testing')
|
self.app = create_app(TestConfig)
|
||||||
self.app_context = self.app.app_context()
|
self.app_context = self.app.app_context()
|
||||||
self.app_context.push()
|
self.app_context.push()
|
||||||
db.create_all()
|
db.create_all()
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import unittest
|
|
||||||
from app import create_app, db
|
from app import create_app, db
|
||||||
|
from . import TestConfig
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
class FlaskClientTestCase(unittest.TestCase):
|
class FlaskClientTestCase(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.app = create_app('testing')
|
self.app = create_app(TestConfig)
|
||||||
self.app_context = self.app.app_context()
|
self.app_context = self.app.app_context()
|
||||||
self.app_context.push()
|
self.app_context.push()
|
||||||
db.create_all()
|
db.create_all()
|
||||||
@ -48,7 +49,8 @@ class FlaskClientTestCase(unittest.TestCase):
|
|||||||
'password2': 'cat'
|
'password2': 'cat'
|
||||||
})
|
})
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertTrue('Usernames must have only letters, numbers, dots or underscores' in response.get_data(as_text=True))
|
self.assertTrue(
|
||||||
|
'Usernames must have only letters, numbers, dots or underscores' in response.get_data(as_text=True))
|
||||||
|
|
||||||
def test_register_false_email(self):
|
def test_register_false_email(self):
|
||||||
# register a new account with wrong username
|
# register a new account with wrong username
|
||||||
@ -59,7 +61,8 @@ class FlaskClientTestCase(unittest.TestCase):
|
|||||||
'password2': 'cat'
|
'password2': 'cat'
|
||||||
})
|
})
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertTrue('Invalid email address.' in response.get_data(as_text=True))
|
self.assertTrue(
|
||||||
|
'Invalid email address.' in response.get_data(as_text=True))
|
||||||
|
|
||||||
def test_duplicates(self):
|
def test_duplicates(self):
|
||||||
# tries to register an account that has already been registered
|
# tries to register an account that has already been registered
|
||||||
@ -78,7 +81,8 @@ class FlaskClientTestCase(unittest.TestCase):
|
|||||||
'password2': 'cat'
|
'password2': 'cat'
|
||||||
})
|
})
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertTrue('Username already in use.' in response.get_data(as_text=True))
|
self.assertTrue(
|
||||||
|
'Username already in use.' in response.get_data(as_text=True))
|
||||||
response = self.client.post('/auth/register', data={
|
response = self.client.post('/auth/register', data={
|
||||||
'email': 'john@example.com',
|
'email': 'john@example.com',
|
||||||
'username': 'johnsmith',
|
'username': 'johnsmith',
|
||||||
@ -86,7 +90,8 @@ class FlaskClientTestCase(unittest.TestCase):
|
|||||||
'password2': 'cat'
|
'password2': 'cat'
|
||||||
})
|
})
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertTrue('Email already registered.' in response.get_data(as_text=True))
|
self.assertTrue(
|
||||||
|
'Email already registered.' in response.get_data(as_text=True))
|
||||||
|
|
||||||
def test_admin_forbidden(self):
|
def test_admin_forbidden(self):
|
||||||
response = self.client.post('/auth/login', data={
|
response = self.client.post('/auth/login', data={
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import unittest
|
|
||||||
import time
|
|
||||||
from app import create_app, db
|
from app import create_app, db
|
||||||
from app.models import User, AnonymousUser, Role, Permission
|
from app.models import User, AnonymousUser, Role, Permission
|
||||||
|
from . import TestConfig
|
||||||
|
import time
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
class UserModelTestCase(unittest.TestCase):
|
class UserModelTestCase(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.app = create_app('testing')
|
self.app = create_app(TestConfig)
|
||||||
self.app_context = self.app.app_context()
|
self.app_context = self.app.app_context()
|
||||||
self.app_context.push()
|
self.app_context.push()
|
||||||
db.create_all()
|
db.create_all()
|
||||||
|
Loading…
Reference in New Issue
Block a user