235 lines
7.2 KiB
Python
235 lines
7.2 KiB
Python
import logging
|
|
import os
|
|
import configparser
|
|
import re
|
|
from pathlib import Path
|
|
|
|
from flask import Flask, render_template, request
|
|
from flask_dropzone import Dropzone
|
|
from flask_migrate import Migrate, MigrateCommand
|
|
from flask_script import Manager
|
|
from portal.model import db
|
|
|
|
import portal.base
|
|
|
|
|
|
|
|
ENABLED_FILETYPES = ['txt', 'csv', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'xml', 'mxliff', 'tmx']
|
|
REGEX_EMAIL = re.compile('^[a-z0-9]+[\._]?[a-z0-9]+[@]\w+[.]\w{2,3}$')
|
|
|
|
# TODO: make logging level configurable
|
|
logging.basicConfig(level=logging.DEBUG, format='[APP LOGGER] %(asctime)s %(levelname)s: %(message)s')
|
|
|
|
######################
|
|
# Load configuration #
|
|
######################
|
|
config = configparser.ConfigParser()
|
|
config.read('config.ini')
|
|
config = config['DEFAULT']
|
|
|
|
MAIL_HOST = config['MAIL_HOST']
|
|
MAIL_LOGIN = config['MAIL_LOGIN']
|
|
MAIL_PASS = config['MAIL_PASS']
|
|
SMTP_PORT = int(config['SMTP_PORT'])
|
|
IMAP_PORT = int(config['IMAP_PORT'])
|
|
MAX_UPLOAD_SIZE = int(config['MAX_UPLOAD_SIZE']) # Bytes
|
|
MAX_FILES_PER_UPLOAD = int(config['MAX_FILES_PER_UPLOAD'])
|
|
CONTRACT_CLIENT_CONTACT = config['CONTRACT_CLIENT_CONTACT']
|
|
MAIL_SUBJECT = config['MAIL_SUBJECT']
|
|
MAIL_BODY = config['MAIL_BODY']
|
|
SQL_CONN_STR = config['SQL_CONN_STR']
|
|
DESC_PREVODI = config['DESC_PREVODI']
|
|
DESC_GIGAFIDA = config['DESC_GIGAFIDA']
|
|
|
|
if 'UPLOADS_DIR' in config:
|
|
UPLOADS_DIR = Path(config['UPLOADS_DIR'])
|
|
else:
|
|
UPLOADS_DIR = Path(__file__).resolve().parent / 'uploads'
|
|
if not UPLOADS_DIR.exists:
|
|
UPLOADS_DIR.mkdir(parents=True)
|
|
|
|
# Override configs with environment variables, if set
|
|
if 'PORTALDS4DS1_MAIL_HOST' in os.environ:
|
|
MAIL_HOST = os.environ['PORTALDS4DS1_MAIL_HOST']
|
|
if 'PORTALDS4DS1_MAIL_LOGIN' in os.environ:
|
|
MAIL_LOGIN = os.environ['PORTALDS4DS1_MAIL_LOGIN']
|
|
if 'PORTALDS4DS1_MAIL_PASS' in os.environ:
|
|
MAIL_PASS = os.environ['PORTALDS4DS1_MAIL_PASS']
|
|
if 'PORTALDS4DS1_SMTP_PORT' in os.environ:
|
|
SMTP_PORT = int(os.environ['PORTALDS4DS1_SMTP_PORT'])
|
|
if 'PORTALDS4DS1_IMAP_PORT' in os.environ:
|
|
IMAP_PORT = int(os.environ['PORTALDS4DS1_IMAP_PORT'])
|
|
if 'PORTALDS4DS1_MAX_UPLOAD_SIZE' in os.environ:
|
|
MAX_UPLOAD_SIZE = int(os.environ['PORTALDS4DS1_MAX_UPLOAD_SIZE'])
|
|
if 'PORTALDS4DS1_MAX_FILES_PER_UPLOAD' in os.environ:
|
|
MAX_FILES_PER_UPLOAD = int(os.environ['PORTALDS4DS1_MAX_FILES_PER_UPLOAD'])
|
|
if 'PORTALDS4DS1_CONTRACT_CLIENT_CONTACT' in os.environ:
|
|
CONTRACT_CLIENT_CONTACT = os.environ['PORTALDS4DS1_CONTRACT_CLIENT_CONTACT']
|
|
if 'PORTALDS4DS1_UPLOADS_DIR' in os.environ:
|
|
UPLOADS_DIR = os.environ['PORTALDS4DS1_UPLOADS_DIR']
|
|
if 'PORTALDS4DS1_MAIL_SUBJECT' in os.environ:
|
|
MAIL_SUBJECT = os.environ['PORTALDS4DS1_MAIL_SUBJECT']
|
|
if 'PORTALDS4DS1_MAIL_BODY' in os.environ:
|
|
MAIL_BODY = os.environ['PORTALDS4DS1_MAIL_BODY']
|
|
if 'PORTALDS4DS1_SQL_CONN_STR' in os.environ:
|
|
SQL_CONN_STR = os.environ['PORTALDS4DS1_SQL_CONN_STR']
|
|
if 'PORTALDS4DS1_DESC_PREVODI' in os.environ:
|
|
DESC_PREVODI = os.environ['PORTALDS4DS1_DESC_PREVODI']
|
|
if 'PORTALDS4DS1_DESC_GIGAFIDA' in os.environ:
|
|
DESC_GIGAFIDA = os.environ['PORTALDS4DS1_DESC_GIGAFIDA']
|
|
|
|
VALID_CORPUS_NAMES = ['prevodi', 'gigafida', 'solar']
|
|
|
|
|
|
######################
|
|
|
|
app = Flask(__name__)
|
|
|
|
app.config.update(
|
|
UPLOADED_PATH = UPLOADS_DIR,
|
|
MAX_CONTENT_LENGTH = MAX_UPLOAD_SIZE,
|
|
TEMPLATES_AUTO_RELOAD = True,
|
|
SQLALCHEMY_DATABASE_URI = SQL_CONN_STR,
|
|
SQLALCHEMY_ECHO = True
|
|
)
|
|
|
|
# Run "python app.py db -?" to see more info about DB migrations.
|
|
manager = Manager(app)
|
|
db.init_app(app)
|
|
migrate = Migrate(app, db)
|
|
manager.add_command('db', MigrateCommand)
|
|
|
|
# Set up dropzone.js to serve all the stuff for "file dropping" on the web interface.
|
|
dropzone = Dropzone(app)
|
|
|
|
upload_handler = portal.base.UploadHandler(
|
|
UPLOADS_DIR=UPLOADS_DIR,
|
|
MAIL_HOST=MAIL_HOST,
|
|
MAIL_LOGIN=MAIL_LOGIN,
|
|
MAIL_PASS=MAIL_PASS,
|
|
SMTP_PORT=SMTP_PORT,
|
|
IMAP_PORT=IMAP_PORT,
|
|
MAIL_SUBJECT=MAIL_SUBJECT,
|
|
MAIL_BODY=MAIL_BODY,
|
|
CONTRACT_CLIENT_CONTACT=CONTRACT_CLIENT_CONTACT
|
|
)
|
|
|
|
|
|
@app.route('/')
|
|
def index():
|
|
return render_template('index.html')
|
|
|
|
|
|
@app.route('/<corpus_name>')
|
|
def index_corpus(corpus_name):
|
|
if corpus_name not in VALID_CORPUS_NAMES:
|
|
return 'Korpus "{}" ne obstaja.'.format(corpus_name), 404
|
|
|
|
if corpus_name == 'prevodi':
|
|
description = DESC_PREVODI
|
|
elif corpus_name == 'gigafida':
|
|
description = DESC_GIGAFIDA
|
|
elif corpus_name == 'solar':
|
|
return handle_solar(request)
|
|
|
|
return render_template('basic.html',
|
|
corpus_name=corpus_name, description=description, max_files=MAX_FILES_PER_UPLOAD)
|
|
|
|
|
|
def handle_solar(request):
|
|
return 404
|
|
|
|
|
|
@app.route('/<corpus_name>/upload', methods=['POST'])
|
|
def handle_upload(corpus_name):
|
|
if corpus_name not in VALID_CORPUS_NAMES:
|
|
return 404
|
|
|
|
if corpus_name == 'solar':
|
|
return handle_upload_solar(request)
|
|
else:
|
|
return handle_upload_unauthenticated(request, corpus_name)
|
|
|
|
|
|
def handle_upload_solar(request):
|
|
return 404
|
|
|
|
|
|
def handle_upload_unauthenticated(request, corpus_name):
|
|
files = request.files
|
|
if len(files) > MAX_FILES_PER_UPLOAD:
|
|
return 'Naložite lahko do {} datotek hkrati.'.format(MAX_FILES_PER_UPLOAD), 400
|
|
elif len(files) < 1:
|
|
return 'Priložena ni bila nobena datoteka.', 400
|
|
|
|
err = check_suffixes(files)
|
|
if err:
|
|
return err, 400
|
|
|
|
err = check_form(request.form)
|
|
if err:
|
|
return err, 400
|
|
|
|
# Parse request.
|
|
upload_metadata = upload_handler.extract_upload_metadata(corpus_name, request)
|
|
|
|
logging.info('Upload with id "{}" supplied form data: {}'.format(upload_metadata['upload_id'],
|
|
str(upload_metadata['form_data'])))
|
|
|
|
# Generate contract PDF file based on the uploads metadata.
|
|
upload_handler.generate_upload_contract_pdf(upload_metadata)
|
|
|
|
# Store uploaded files to disk.
|
|
upload_handler.store_datafiles(files, upload_metadata)
|
|
|
|
# Store metadata to database.
|
|
upload_handler.store_metadata_unauthenticated(upload_metadata)
|
|
|
|
# Send confirmation mail along with the contract to the submitted email address.
|
|
upload_handler.send_confirm_mail(upload_metadata)
|
|
|
|
return 'Uspešno ste oddali datotek(e). Št. datotek: {}'.format(len(files))
|
|
|
|
|
|
def check_suffixes(files):
|
|
for key, f in files.items():
|
|
if key.startswith('file'):
|
|
suffix = f.filename.split('.')[-1]
|
|
if suffix not in ENABLED_FILETYPES:
|
|
return 'Datoteka "{}" ni pravilnega formata.'.format(f.filename)
|
|
return None
|
|
|
|
|
|
def check_form(form):
|
|
ime = form.get('ime')
|
|
podjetje = form.get('podjetje')
|
|
naslov = form.get('naslov')
|
|
posta = form.get('posta')
|
|
email = form.get('email')
|
|
telefon = form.get('telefon')
|
|
|
|
if len(ime) > 100:
|
|
return 'Predolgo ime.'
|
|
|
|
if len(podjetje) > 100:
|
|
return 'Predolgo ime institucije.'
|
|
|
|
if len(email) > 100:
|
|
return 'Predolgi email naslov'
|
|
elif not re.search(REGEX_EMAIL, email):
|
|
return 'Email napačnega formata.'
|
|
|
|
if len(telefon) > 100:
|
|
return 'Predolga telefonska št.'
|
|
|
|
if len(naslov) > 100:
|
|
return 'Predolg naslov.'
|
|
|
|
if len(posta) > 100:
|
|
return 'Predolga pošta'
|
|
|
|
return None
|
|
|
|
if __name__ == '__main__':
|
|
app.run(debug=True)
|