diff --git a/app/app.py b/app/app.py index 6a78a1d..0bbe02a 100644 --- a/app/app.py +++ b/app/app.py @@ -3,18 +3,20 @@ import os import tempfile import uuid from functools import wraps +from html import unescape import argostranslatefiles from argostranslatefiles import get_supported_formats -from flask import Flask, abort, jsonify, render_template, request, url_for, send_file +from flask import (Flask, abort, jsonify, render_template, request, send_file, + url_for) from flask_swagger import swagger from flask_swagger_ui import get_swaggerui_blueprint from translatehtml import translate_html from werkzeug.utils import secure_filename -from html import unescape from app import flood, remove_translated_files, security from app.language import detect_languages, transliterate + from .api_keys import Database from .suggestions import Database as SuggestionsDatabase @@ -140,7 +142,6 @@ def create_app(args): else: frontend_argos_language_target = languages[0] - api_keys_db = None if args.req_limit > 0 or args.api_keys or args.daily_req_limit > 0: @@ -174,11 +175,19 @@ def create_app(args): if flood.has_violation(ip): flood.decrease(ip) - if args.api_keys and args.require_api_key_origin: + if args.api_keys: ak = get_req_api_key() - if ( - api_keys_db.lookup(ak) is None and request.headers.get("Origin") != args.require_api_key_origin + ak and api_keys_db.lookup(ak) is None + ): + abort( + 403, + description="Invalid API key", + ) + elif ( + args.require_api_key_origin + and api_keys_db.lookup(ak) is None + and request.headers.get("Origin") != args.require_api_key_origin ): abort( 403, diff --git a/app/default_values.py b/app/default_values.py index b6fff3f..9161aa6 100644 --- a/app/default_values.py +++ b/app/default_values.py @@ -2,16 +2,19 @@ import os _prefix = 'LT_' + def _get_value_str(name, default_value): env_value = os.environ.get(name) return default_value if env_value is None else env_value + def _get_value_int(name, default_value): try: return int(os.environ[name]) except: return default_value + def _get_value_bool(name, default_value): env_value = os.environ.get(name) if env_value in ['FALSE', 'False', 'false', '0']: @@ -20,6 +23,7 @@ def _get_value_bool(name, default_value): return True return default_value + def _get_value(name, default_value, value_type): env_name = _prefix + name if value_type == 'str': @@ -30,6 +34,7 @@ def _get_value(name, default_value, value_type): return _get_value_bool(env_name, default_value) return default_value + _default_options_objects = [ { 'name': 'HOST', @@ -114,7 +119,7 @@ _default_options_objects = [ { 'name': 'SUGGESTIONS', 'default_value': False, - 'value_type': 'bool' + 'value_type': 'bool' }, { 'name': 'DISABLE_FILES_TRANSLATION', @@ -129,4 +134,4 @@ _default_options_objects = [ ] -DEFAULT_ARGUMENTS = { obj['name']:_get_value(**obj) for obj in _default_options_objects} +DEFAULT_ARGUMENTS = {obj['name']: _get_value(**obj) for obj in _default_options_objects} diff --git a/app/flood.py b/app/flood.py index 3aa2c74..bc7fc1d 100644 --- a/app/flood.py +++ b/app/flood.py @@ -22,6 +22,7 @@ def forgive_banned(): for ip in clear_list: del banned[ip] + def setup(violations_threshold=100): global active global threshold diff --git a/app/main.py b/app/main.py index ab0e61c..62d4d6e 100644 --- a/app/main.py +++ b/app/main.py @@ -1,6 +1,6 @@ import argparse -import sys import operator +import sys from app.app import create_app from app.default_values import DEFAULT_ARGUMENTS as DEFARGS diff --git a/app/security.py b/app/security.py index 56913ce..99415da 100644 --- a/app/security.py +++ b/app/security.py @@ -1,8 +1,10 @@ import os + class SuspiciousFileOperation(Exception): pass + def path_traversal_check(unsafe_path, known_safe_path): known_safe_path = os.path.abspath(known_safe_path) unsafe_path = os.path.abspath(unsafe_path) diff --git a/app/suggestions.py b/app/suggestions.py index 28b943a..281ca38 100644 --- a/app/suggestions.py +++ b/app/suggestions.py @@ -1,5 +1,4 @@ import sqlite3 -import uuid from expiringdict import ExpiringDict