mirror of
https://github.com/LibreTranslate/LibreTranslate.git
synced 2024-11-21 23:41:01 +00:00
Programmatic api keys access
This commit is contained in:
parent
29c1f2cd2e
commit
24c77ede19
3 changed files with 31 additions and 4 deletions
|
@ -115,6 +115,7 @@ docker-compose up -d --build
|
||||||
| --frontend-language-target | Set frontend default language - target | `es` |
|
| --frontend-language-target | Set frontend default language - target | `es` |
|
||||||
| --frontend-timeout | Set frontend translation timeout | `500` |
|
| --frontend-timeout | Set frontend translation timeout | `500` |
|
||||||
| --api-keys | Enable API keys database for per-user rate limits lookup | `Don't use API keys` |
|
| --api-keys | Enable API keys database for per-user rate limits lookup | `Don't use API keys` |
|
||||||
|
| --require-api-key-origin | Require use of an API key for programmatic access to the API, unless the request origin matches this domain | `No restrictions on domain origin` |
|
||||||
| --load-only | Set available languages | `all from argostranslate` |
|
| --load-only | Set available languages | `all from argostranslate` |
|
||||||
|
|
||||||
## Manage API Keys
|
## Manage API Keys
|
||||||
|
|
32
app/app.py
32
app/app.py
|
@ -6,6 +6,7 @@ from pkg_resources import resource_filename
|
||||||
from .api_keys import Database
|
from .api_keys import Database
|
||||||
from app.language import detect_languages, transliterate
|
from app.language import detect_languages, transliterate
|
||||||
from app import flood
|
from app import flood
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
def get_json_dict(request):
|
def get_json_dict(request):
|
||||||
d = request.get_json()
|
d = request.get_json()
|
||||||
|
@ -50,6 +51,7 @@ def get_routes_limits(default_req_limit, daily_req_limit, api_keys_db):
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
def create_app(args):
|
def create_app(args):
|
||||||
from app.init import boot
|
from app.init import boot
|
||||||
boot(args.load_only)
|
boot(args.load_only)
|
||||||
|
@ -77,12 +79,16 @@ def create_app(args):
|
||||||
if frontend_argos_language_target is None:
|
if frontend_argos_language_target is None:
|
||||||
raise AttributeError(f"{args.frontend_language_target} as frontend target language is not supported.")
|
raise AttributeError(f"{args.frontend_language_target} as frontend target language is not supported.")
|
||||||
|
|
||||||
|
api_keys_db = None
|
||||||
|
|
||||||
if args.req_limit > 0 or args.api_keys or args.daily_req_limit > 0:
|
if args.req_limit > 0 or args.api_keys or args.daily_req_limit > 0:
|
||||||
|
api_keys_db = Database() if args.api_keys else None
|
||||||
|
|
||||||
from flask_limiter import Limiter
|
from flask_limiter import Limiter
|
||||||
limiter = Limiter(
|
limiter = Limiter(
|
||||||
app,
|
app,
|
||||||
key_func=get_remote_address,
|
key_func=get_remote_address,
|
||||||
default_limits=get_routes_limits(args.req_limit, args.daily_req_limit, Database() if args.api_keys else None)
|
default_limits=get_routes_limits(args.req_limit, args.daily_req_limit, api_keys_db)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
from .no_limiter import Limiter
|
from .no_limiter import Limiter
|
||||||
|
@ -91,6 +97,25 @@ def create_app(args):
|
||||||
if args.req_flood_threshold > 0:
|
if args.req_flood_threshold > 0:
|
||||||
flood.setup(args.req_flood_threshold)
|
flood.setup(args.req_flood_threshold)
|
||||||
|
|
||||||
|
def access_check(f):
|
||||||
|
@wraps(f)
|
||||||
|
def func(*a, **kw):
|
||||||
|
if flood.is_banned(get_remote_address()):
|
||||||
|
abort(403, description="Too many request limits violations")
|
||||||
|
|
||||||
|
if args.api_keys and args.require_api_key_origin:
|
||||||
|
if request.is_json:
|
||||||
|
json = get_json_dict(request)
|
||||||
|
ak = json.get("api_key")
|
||||||
|
else:
|
||||||
|
ak = request.values.get("api_key")
|
||||||
|
|
||||||
|
if api_keys_db.lookup(ak) is None and request.headers.get("Origin") != args.require_api_key_origin:
|
||||||
|
abort(403, description="Please contact the server operator to obtain an API key")
|
||||||
|
|
||||||
|
return f(*a, **kw)
|
||||||
|
return func
|
||||||
|
|
||||||
@app.errorhandler(400)
|
@app.errorhandler(400)
|
||||||
def invalid_api(e):
|
def invalid_api(e):
|
||||||
return jsonify({"error": str(e.description)}), 400
|
return jsonify({"error": str(e.description)}), 400
|
||||||
|
@ -167,6 +192,7 @@ def create_app(args):
|
||||||
|
|
||||||
|
|
||||||
@app.route("/translate", methods=['POST'])
|
@app.route("/translate", methods=['POST'])
|
||||||
|
@access_check
|
||||||
def translate():
|
def translate():
|
||||||
"""
|
"""
|
||||||
Translate text from a language to another
|
Translate text from a language to another
|
||||||
|
@ -254,9 +280,6 @@ def create_app(args):
|
||||||
type: string
|
type: string
|
||||||
description: Error message
|
description: Error message
|
||||||
"""
|
"""
|
||||||
if flood.is_banned(get_remote_address()):
|
|
||||||
abort(403, description="Too many request limits violations")
|
|
||||||
|
|
||||||
if request.is_json:
|
if request.is_json:
|
||||||
json = get_json_dict(request)
|
json = get_json_dict(request)
|
||||||
q = json.get('q')
|
q = json.get('q')
|
||||||
|
@ -320,6 +343,7 @@ def create_app(args):
|
||||||
abort(500, description="Cannot translate text: %s" % str(e))
|
abort(500, description="Cannot translate text: %s" % str(e))
|
||||||
|
|
||||||
@app.route("/detect", methods=['POST'])
|
@app.route("/detect", methods=['POST'])
|
||||||
|
@access_check
|
||||||
def detect():
|
def detect():
|
||||||
"""
|
"""
|
||||||
Detect the language of a single text
|
Detect the language of a single text
|
||||||
|
|
|
@ -32,6 +32,8 @@ def main():
|
||||||
help='Set frontend translation timeout (%(default)s)')
|
help='Set frontend translation timeout (%(default)s)')
|
||||||
parser.add_argument('--api-keys', default=False, action="store_true",
|
parser.add_argument('--api-keys', default=False, action="store_true",
|
||||||
help="Enable API keys database for per-user rate limits lookup")
|
help="Enable API keys database for per-user rate limits lookup")
|
||||||
|
parser.add_argument('--require-api-key-origin', type=str, default="",
|
||||||
|
help="Require use of an API key for programmatic access to the API, unless the request origin matches this domain")
|
||||||
parser.add_argument('--load-only', type=operator.methodcaller('split', ','),
|
parser.add_argument('--load-only', type=operator.methodcaller('split', ','),
|
||||||
metavar='<comma-separated language codes>',
|
metavar='<comma-separated language codes>',
|
||||||
help='Set available languages (ar,de,en,es,fr,ga,hi,it,ja,ko,pt,ru,zh)')
|
help='Set available languages (ar,de,en,es,fr,ga,hi,it,ja,ko,pt,ru,zh)')
|
||||||
|
|
Loading…
Reference in a new issue