mirror of
https://github.com/morpheus65535/bazarr.git
synced 2025-02-23 22:35:33 +08:00
Added API Key to secure future API endpoint.
This commit is contained in:
parent
3cdff1dd9f
commit
990d7e812c
4 changed files with 60 additions and 2 deletions
|
@ -50,6 +50,14 @@ if not os.path.exists(os.path.join(args.config_dir, 'cache')):
|
|||
configure_logging(settings.general.getboolean('debug') or args.debug)
|
||||
import logging
|
||||
|
||||
# create random api_key if there's none in config.ini
|
||||
if not settings.auth.apikey:
|
||||
from binascii import hexlify
|
||||
from six import text_type
|
||||
settings.auth.apikey = text_type(hexlify(os.urandom(16)))
|
||||
with open(os.path.join(args.config_dir, 'config', 'config.ini'), 'w+') as handle:
|
||||
settings.write(handle)
|
||||
|
||||
# create database file
|
||||
if not os.path.exists(os.path.join(args.config_dir, 'db', 'bazarr.db')):
|
||||
import sqlite3
|
||||
|
|
|
@ -147,6 +147,16 @@ def authorize():
|
|||
aaa.require(fail_redirect=(base_url + 'login'))
|
||||
|
||||
|
||||
def api_authorize():
|
||||
if 'apikey' in request.GET.dict:
|
||||
if request.GET.dict['apikey'][0] == settings.auth.apikey:
|
||||
return
|
||||
else:
|
||||
abort(401, 'Unauthorized')
|
||||
else:
|
||||
abort(401, 'Unauthorized')
|
||||
|
||||
|
||||
def post_get(name, default=''):
|
||||
return request.POST.get(name, default).strip()
|
||||
|
||||
|
@ -1429,6 +1439,7 @@ def save_settings():
|
|||
pass
|
||||
else:
|
||||
aaa._beaker_session.delete()
|
||||
settings.auth.apikey = request.forms.get('settings_auth_apikey')
|
||||
|
||||
settings_sonarr_ip = request.forms.get('settings_sonarr_ip')
|
||||
settings_sonarr_port = request.forms.get('settings_sonarr_port')
|
||||
|
@ -2230,6 +2241,17 @@ def movie_history(no):
|
|||
return dict(data=movie_history)
|
||||
|
||||
|
||||
# Don't put any route under this one
|
||||
@route(base_url + 'api/help')
|
||||
def api_help():
|
||||
endpoints = []
|
||||
for route in app.app.routes:
|
||||
if '/api/' in route.rule:
|
||||
endpoints.append(route.rule)
|
||||
|
||||
return dict(endpoints=endpoints)
|
||||
|
||||
|
||||
# Mute DeprecationWarning
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
server = CherryPyWSGIServer((str(settings.general.ip), (int(args.port) if args.port else int(settings.general.port))), app)
|
||||
|
|
|
@ -116,7 +116,7 @@
|
|||
.tab()
|
||||
;
|
||||
|
||||
$('a:not(.tabs), button:not(.cancel, .test)').on('click', function(){
|
||||
$('a:not(.tabs), button:not(.cancel, .test, .no_loader)').on('click', function(){
|
||||
$('#loader').addClass('active');
|
||||
});
|
||||
|
||||
|
|
|
@ -328,6 +328,22 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>API Key</label>
|
||||
</div>
|
||||
<div class="six wide column">
|
||||
<div class='field'>
|
||||
<div class="ui action input">
|
||||
<input id="settings_auth_apikey" name="settings_auth_apikey" type="text" readonly value="{{settings.auth.apikey}}">
|
||||
<button class="no_loader ui red icon button" type="button" onclick="generate_apikey()">
|
||||
<i class="sync icon"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -866,3 +882,15 @@
|
|||
|
||||
|
||||
</script>
|
||||
|
||||
<script>
|
||||
function generate_apikey() {
|
||||
var result = '';
|
||||
var characters = 'abcdef0123456789';
|
||||
var charactersLength = characters.length;
|
||||
for ( var i = 0; i < 32; i++ ) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
$( "#settings_auth_apikey" ).val( result );
|
||||
}
|
||||
</script>
|
Loading…
Reference in a new issue