diff --git a/.env_example b/.env_example new file mode 100644 index 00000000..f328a3ed --- /dev/null +++ b/.env_example @@ -0,0 +1,17 @@ +### Flask ### +FLASK_CONFIG=production +# SECRET_KEY= + +### Flask-Mail ### +MAIL_SERVER=smtp.example.com +MAIL_PORT=587 +MAIL_USE_TLS=true +MAIL_USERNAME=username@example.com +MAIL_PASSWORD=password +MAIL_DEFAULT_SENDER=username@example.com + +### Opaque ### +OPAQUE_ADMIN=admin.opaque@example.com + +### Flask-SQLAlchemy ### +# SQLALCHEMY_DATABASE_URI= diff --git a/.flaskenv b/.flaskenv index f88b6e5b..47093cda 100644 --- a/.flaskenv +++ b/.flaskenv @@ -1,2 +1,2 @@ +### Flask ### FLASK_APP=opaque.py -FLASK_ENV=development diff --git a/Dockerfile b/Dockerfile index e6a7ea0b..e588a372 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,18 +1,30 @@ -# pull official base image -FROM python:3.6.9 +FROM python:3.6-alpine -# set environment varibles -ENV PYTHONDONTWRITEBYTECODE 1 -ENV PYTHONUNBUFFERED 1 -# set work directory -WORKDIR /opaque +RUN apk add build-base -# Copy the current directory contents into the container at /daemon -COPY . /opaque -# Install requirements -RUN pip install --trusted-host pypi.python.org -r requirements.txt +RUN adduser -D opaque +USER opaque -# set permissions for entrypoint -RUN chmod a+x flask-entrypoint.sh + +WORKDIR /home/opaque + + +COPY app app +COPY migrations migrations +COPY opaque.py config.py ./ +COPY requirements.txt requirements.txt + + +RUN python -m venv venv && \ + venv/bin/pip install -r requirements.txt + + +COPY docker-entrypoint.sh /usr/local/bin/ + + +EXPOSE 5000 + + +ENTRYPOINT ["docker-entrypoint.sh"] diff --git a/app/email.py b/app/email.py index 1e3fb3ab..072b7bc3 100644 --- a/app/email.py +++ b/app/email.py @@ -10,11 +10,7 @@ def send_async_email(app, msg): def send_email(to, subject, template, **kwargs): - subject = '{} {}'.format(current_app.config['OPAQUE_MAIL_SUBJECT_PREFIX'], - subject) - msg = Message(subject, - sender=current_app.config['OPAQUE_MAIL_SENDER'], - recipients=[to]) + msg = Message('[Opaque] {}'.format(subject), recipients=[to]) msg.body = render_template(template + '.txt.j2', **kwargs) msg.html = render_template(template + '.html.j2', **kwargs) thr = Thread(target=send_async_email, diff --git a/app/main/views.py b/app/main/views.py index efb2b0bd..9acc9061 100644 --- a/app/main/views.py +++ b/app/main/views.py @@ -21,7 +21,7 @@ def corpus(corpus_id): print('Corpus not found.') abort(404) - dir = os.path.join(current_app.config['OPAQUE_STORAGE'], + dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'], str(current_user.id), 'corpora', str(corpus.id)) @@ -44,7 +44,7 @@ def corpus_download(corpus_id): if not file or not corpus: print('File not found.') abort(404) - dir = os.path.join(current_app.config['OPAQUE_STORAGE'], + dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'], str(current_user.id), 'corpora', str(corpus.id)) @@ -66,7 +66,7 @@ def dashboard(): db.session.add(corpus) db.session.commit() - dir = os.path.join(app.config['OPAQUE_STORAGE'], + dir = os.path.join(app.config['OPAQUE_STORAGE_DIRECTORY'], str(corpus.user_id), 'corpora', str(corpus.id)) @@ -96,7 +96,7 @@ def job(job_id): print('Job not found.') abort(404) - dir = os.path.join(current_app.config['OPAQUE_STORAGE'], + dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'], str(current_user.id), 'jobs', str(job.id)) @@ -130,7 +130,7 @@ def job_download(job_id): if not file or not job: print('File not found.') abort(404) - dir = os.path.join(current_app.config['OPAQUE_STORAGE'], + dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'], str(current_user.id), 'jobs', str(job.id)) diff --git a/app/services/views.py b/app/services/views.py index 96247d57..52c36084 100644 --- a/app/services/views.py +++ b/app/services/views.py @@ -26,7 +26,7 @@ def nlp(): db.session.add(nlp_job) db.session.commit() - dir = os.path.join(current_app.config['OPAQUE_STORAGE'], + dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'], str(nlp_job.user_id), 'jobs', str(nlp_job.id)) @@ -72,7 +72,7 @@ def ocr(): db.session.add(ocr_job) db.session.commit() - dir = os.path.join(current_app.config['OPAQUE_STORAGE'], + dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'], str(ocr_job.user_id), 'jobs', str(ocr_job.id)) diff --git a/app/templates/main/jobs/job.html.j2 b/app/templates/main/jobs/job.html.j2 index a9bfd2b5..12865aa2 100644 --- a/app/templates/main/jobs/job.html.j2 +++ b/app/templates/main/jobs/job.html.j2 @@ -161,11 +161,12 @@ + Files - - + + @@ -179,8 +180,6 @@ {% for result in files[file]['results'] %} {{ result }} {% endfor %} - {% else %} - None {% endif %} diff --git a/app/templates/services/nlp.html.j2 b/app/templates/services/nlp.html.j2 index 1ba9550b..8e394f08 100644 --- a/app/templates/services/nlp.html.j2 +++ b/app/templates/services/nlp.html.j2 @@ -13,56 +13,32 @@
- - layers - Tokenisierung - -

- Aufteilung eines Textes in Sätze und Wörter. Dies - ist zur weiteren Verarbeitung notwendig. -

+ layersTokenisierung +

Aufteilung eines Textes in Sätze und Wörter. Dies ist zur weiteren Verarbeitung notwendig.

- - layers - Lemmatisierung - -

- Reduktion der Flexionsformen eines Wortes auf dessen - Grundform. -

+ layersLemmatisierung +

Reduktion der Flexionsformen eines Wortes auf dessen Grundform.

- - layers - Part-of-speech-Tagging - -

- Kontext- und definitionsbezogene Zuordnung von Wörtern - und Satzzeichen zu Wortarten. -

+ layersPart-of-speech-Tagging +

Kontext- und definitionsbezogene Zuordnung von Wörtern und Satzzeichen zu Wortarten.

- - layers - Eigennamenerkennung - -

- Identifikation von Wörtern, die eine Entität - beschreiben, wie Firmen- und Personennamen. -

+ layersEigennamenerkennung +

Identifikation von Wörtern, die eine Entitätbeschreiben, wie Firmen- und Personennamen.

diff --git a/app/templates/services/ocr.html.j2 b/app/templates/services/ocr.html.j2 index 2fc3198c..3e272898 100644 --- a/app/templates/services/ocr.html.j2 +++ b/app/templates/services/ocr.html.j2 @@ -14,56 +14,32 @@
- - layers - Eingabe von Bilddaten - -

- Über ein Auftragsformular können Bilddaten in Form von - PDF-Dateien hochgeladen werden. -

+ layersEingabe von Bilddaten +

Über ein Auftragsformular können Bilddaten in Form von PDF-Dateien hochgeladen werden.

- - layers - Optische Zeichenerkennung - -

- Die optische Zeichenerkennung erfolgt in der - Recheninfrastruktur der Plattform. -

+ layersOptische Zeichenerkennung +

Die optische Zeichenerkennung erfolgt in der Recheninfrastruktur der Plattform.

- - layers - Fehlerkorrektur - -

- Je nach Qualität der Eingabedaten kann es zu - Fehlern kommen, die korrigiert werden sollten. -

+ layersFehlerkorrektur +

Je nach Qualität der Eingabedaten kann es zu Fehlern kommen, die korrigiert werden sollten.

- - layers - Weiterverarbeitung - -

- Die Textdaten können weiterverarbeitet[*] - oder in dieser Form bereits genutzt[*] werden. -

+ layersWeiterverarbeitung +

Die Textdaten können weiterverarbeitet[*] oder in dieser Form bereits genutzt[*] werden.

diff --git a/config.py b/config.py index 1b340301..f80e8f27 100644 --- a/config.py +++ b/config.py @@ -1,29 +1,34 @@ import os -basedir = os.path.abspath(os.path.dirname(__file__)) - - class Config: + ''' ### Flask ### ''' + SECRET_KEY = os.environ.get('SECRET_KEY') or 'hard to guess string' + + ''' ### Flask-Mail ### ''' MAIL_SERVER = os.environ.get('MAIL_SERVER') MAIL_PORT = int(os.environ.get('MAIL_PORT')) MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS').lower() == 'true' MAIL_USERNAME = os.environ.get('MAIL_USERNAME') MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD') - OPAQUE_ADMIN = os.environ.get('OPAQUE_ADMIN') - OPAQUE_STORAGE = os.environ.get('OPAQUE_STORAGE') - OPAQUE_MAIL_SUBJECT_PREFIX = '[Opaque]' - OPAQUE_MAIL_SENDER = 'Opaque' - SECRET_KEY = os.environ.get('SECRET_KEY') or 'hard to guess string' + MAIL_DEFAULT_SENDER = os.environ.get('MAIL_DEFAULT_SENDER') + + ''' ### Flask-SQLAlchemy ### ''' SQLALCHEMY_TRACK_MODIFICATIONS = False + ''' ### Opaque ### ''' + OPAQUE_ADMIN = os.environ.get('OPAQUE_ADMIN') + OPAQUE_STORAGE_DIRECTORY = '/opaque_storage' + @staticmethod def init_app(app): pass class DevelopmentConfig(Config): + ''' ### Flask ### ''' DEBUG = True +<<<<<<< HEAD # SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, # 'data_dev.sqlite') SQLALCHEMY_DATABASE_URI = \ @@ -34,22 +39,29 @@ class DevelopmentConfig(Config): port=os.environ.get('POSTGRES_PORT'), db=os.environ.get('POSTGRES_DB_NAME')) print(SQLALCHEMY_DATABASE_URI) +======= +>>>>>>> e3db2ecd1e52b4993b91e1a1c3501c0fc775de1d + + ''' ### Flask-SQLAlchemy ### ''' + SQLALCHEMY_DATABASE_URI = 'sqlite:///{}'.format( + os.path.join(os.path.dirname(os.path.abspath(__file__)), + 'data_dev.sqlite') + ) -class TestingConfig(Config): - TESTING = True - SQLALCHEMY_DATABASE_URI = os.environ.get('TEST_DATABASE_URL') or \ - 'sqlite://' - WTF_CSRF_ENABLED = False - - -# class ProductionConfig(Config): +class ProductionConfig(Config): + ''' ### Flask-SQLAlchemy ### ''' + SQLALCHEMY_DATABASE_URI = os.environ.get('SQLALCHEMY_DATABASE_URI') config = { 'development': DevelopmentConfig, +<<<<<<< HEAD 'testing': TestingConfig, #'production': ProductionConfig, +======= + 'production': ProductionConfig, +>>>>>>> e3db2ecd1e52b4993b91e1a1c3501c0fc775de1d 'default': DevelopmentConfig } diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100755 index 00000000..535d86a0 --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# If no argument is given, start Opaque +if [ $# -eq 0 ] +then + venv/bin/python opaque.py +else + if [[ $1 == "--create-db" ]] + then + flask db init + flask db upgrade + fi +fi diff --git a/flask-entrypoint.sh b/flask-entrypoint.sh deleted file mode 100644 index ed4b193f..00000000 --- a/flask-entrypoint.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -x - -python opaque.py diff --git a/opaque.py b/opaque.py index 3f8483af..8d4b0101 100644 --- a/opaque.py +++ b/opaque.py @@ -1,7 +1,5 @@ import eventlet eventlet.monkey_patch() -from dotenv import load_dotenv -load_dotenv() from app import create_app, db, socketio from app.models import Corpus, User, Role, Permission, Job from flask_migrate import Migrate diff --git a/requirements.txt b/requirements.txt index 3fce165f..a36d129c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,6 +8,9 @@ Flask-SQLAlchemy Flask-Table Flask-WTF jsonpatch +<<<<<<< HEAD psycopg2 python-dotenv +======= +>>>>>>> e3db2ecd1e52b4993b91e1a1c3501c0fc775de1d redis
InputsResultsInputsResults