summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLASER-Yi <[email protected]>2021-04-21 22:29:25 +0800
committerLASER-Yi <[email protected]>2021-04-21 22:29:25 +0800
commita742e3c5e3336c2d3e56410bad5eb432d07da056 (patch)
tree85c28db6b0fb87c4edda1ba8026c706b44dcb28e
parent53039f855c205b5397d15cccb35c0f3250d6fa25 (diff)
downloadbazarr-a742e3c5e3336c2d3e56410bad5eb432d07da056.tar.gz
bazarr-a742e3c5e3336c2d3e56410bad5eb432d07da056.zip
Fix auth issues by only check auth when requesting webui
-rw-r--r--bazarr/api.py29
-rw-r--r--bazarr/main.py47
-rw-r--r--bazarr/utils.py5
-rw-r--r--frontend/src/@redux/actions/site.ts3
-rw-r--r--frontend/src/@redux/constants/index.ts1
-rw-r--r--frontend/src/@redux/reducers/site.ts19
-rw-r--r--frontend/src/@types/window.d.ts2
-rw-r--r--frontend/src/App/Header.tsx2
-rw-r--r--frontend/src/Auth/index.tsx5
-rw-r--r--frontend/src/apis/index.ts8
-rw-r--r--frontend/src/apis/utils.ts27
11 files changed, 69 insertions, 79 deletions
diff --git a/bazarr/api.py b/bazarr/api.py
index 8e7957064..d794c20a8 100644
--- a/bazarr/api.py
+++ b/bazarr/api.py
@@ -31,7 +31,7 @@ from list_subtitles import store_subtitles, store_subtitles_movie, series_scan_s
list_missing_subtitles, list_missing_subtitles_movies
from utils import history_log, history_log_movie, blacklist_log, blacklist_delete, blacklist_delete_all, \
blacklist_log_movie, blacklist_delete_movie, blacklist_delete_all_movie, get_sonarr_version, get_radarr_version, \
- delete_subtitles, subtitles_apply_mods, translate_subtitles_file
+ delete_subtitles, subtitles_apply_mods, translate_subtitles_file, check_credentials
from get_providers import get_providers, get_providers_auth, list_throttled_providers, reset_throttled_providers, \
get_throttled_providers, set_throttled_providers
from event_handler import event_stream
@@ -52,27 +52,9 @@ api = Api(api_bp)
None_Keys = ['null', 'undefined', '']
-def check_credentials(user, pw):
- username = settings.auth.username
- password = settings.auth.password
- if hashlib.md5(pw.encode('utf-8')).hexdigest() == password and user == username:
- return True
- return False
-
-
def authenticate(actual_method):
@wraps(actual_method)
def wrapper(*args, **kwargs):
- if settings.auth.type == 'basic':
- auth = request.authorization
- if not (auth and check_credentials(request.authorization.username, request.authorization.password)):
- return ('Unauthorized', 401, {
- 'WWW-Authenticate': 'Basic realm="Login Required"'
- })
- elif settings.auth.type == 'form':
- if 'logged_in' not in session:
- return abort(401, message="Unauthorized")
-
apikey_settings = settings.auth.apikey
apikey_get = request.args.get('apikey')
apikey_post = request.form.get('apikey')
@@ -314,12 +296,9 @@ class SystemAccount(Resource):
session['logged_in'] = True
return '', 204
elif action == 'logout':
- if settings.auth.type == 'basic':
- return abort(401)
- elif settings.auth.type == 'form':
- session.clear()
- gc.collect()
- return '', 204
+ session.clear()
+ gc.collect()
+ return '', 204
return '', 401
diff --git a/bazarr/main.py b/bazarr/main.py
index bd23d6058..b1b147f3c 100644
--- a/bazarr/main.py
+++ b/bazarr/main.py
@@ -39,6 +39,7 @@ from get_movies import *
from check_update import apply_update, check_if_new_update, check_releases
from server import app, webserver
from functools import wraps
+from utils import check_credentials
# Install downloaded update
if bazarr_version != '':
@@ -57,44 +58,68 @@ login_auth = settings.auth.type
update_notifier()
+
+def check_login(actual_method):
+ @wraps(actual_method)
+ def wrapper(*args, **kwargs):
+ if settings.auth.type == 'basic':
+ auth = request.authorization
+ if not (auth and check_credentials(request.authorization.username, request.authorization.password)):
+ return ('Unauthorized', 401, {
+ 'WWW-Authenticate': 'Basic realm="Login Required"'
+ })
+ elif settings.auth.type == 'form':
+ if 'logged_in' not in session:
+ return abort(401, message="Unauthorized")
+ actual_method(*args, **kwargs)
+
+
@app.errorhandler(404)
def page_not_found(e):
return redirect(base_url, code=302)
+
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def catch_all(path):
- return render_template("index.html")
+ auth = True
+ if settings.auth.type == 'basic':
+ auth = request.authorization
+ if not (auth and check_credentials(request.authorization.username, request.authorization.password)):
+ return ('Unauthorized', 401, {
+ 'WWW-Authenticate': 'Basic realm="Login Required"'
+ })
+ elif settings.auth.type == 'form':
+ if 'logged_in' not in session:
+ auth = False
-
-def template_variable_processor():
- updated = False
try:
updated = database.execute("SELECT updated FROM system", only_one=True)['updated']
except:
- pass
+ updated = False
inject = dict()
- inject["apiKey"] = settings.auth.apikey
inject["baseUrl"] = base_url
inject["canUpdate"] = not args.no_update
inject["hasUpdate"] = updated != '0'
+ if auth:
+ inject["apiKey"] = settings.auth.apikey
+
template_url = base_url
if not template_url.endswith("/"):
template_url += "/"
- return dict(BAZARR_SERVER_INJECT=inject, baseUrl=template_url)
-
+ return render_template("index.html", BAZARR_SERVER_INJECT=inject, baseUrl=template_url)
+@check_login
@app.route('/bazarr.log')
def download_log():
-
return send_file(os.path.join(args.config_dir, 'log', 'bazarr.log'), cache_timeout=0, as_attachment=True)
+@check_login
@app.route('/images/series/<path:url>', methods=['GET'])
def series_images(url):
url = url.strip("/")
@@ -109,6 +134,7 @@ def series_images(url):
return Response(stream_with_context(req.iter_content(2048)), content_type=req.headers['content-type'])
+@check_login
@app.route('/images/movies/<path:url>', methods=['GET'])
def movies_images(url):
apikey = settings.radarr.apikey
@@ -135,6 +161,7 @@ def configured():
database.execute("UPDATE system SET configured = 1")
+@check_login
@app.route('/test', methods=['GET'])
@app.route('/test/<protocol>/<path:url>', methods=['GET'])
def proxy(protocol, url):
diff --git a/bazarr/utils.py b/bazarr/utils.py
index 9dc15b11e..ede3cc2d1 100644
--- a/bazarr/utils.py
+++ b/bazarr/utils.py
@@ -398,3 +398,8 @@ def translate_subtitles_file(video_path, source_srt_file, to_lang, forced, hi):
subs.save(dest_srt_file)
return dest_srt_file
+
+def check_credentials(user, pw):
+ username = settings.auth.username
+ password = settings.auth.password
+ return hashlib.md5(pw.encode('utf-8')).hexdigest() == password and user == username \ No newline at end of file
diff --git a/frontend/src/@redux/actions/site.ts b/frontend/src/@redux/actions/site.ts
index b0f6a0938..9ea9e6af5 100644
--- a/frontend/src/@redux/actions/site.ts
+++ b/frontend/src/@redux/actions/site.ts
@@ -1,7 +1,6 @@
import { createAction } from "redux-actions";
import { BadgesApi } from "../../apis";
import {
- SITE_AUTH_SUCCESS,
SITE_BADGE_UPDATE,
SITE_INITIALIZED,
SITE_INITIALIZE_FAILED,
@@ -28,8 +27,6 @@ const siteInitialized = createAction(SITE_INITIALIZED);
export const siteRedirectToAuth = createAction(SITE_NEED_AUTH);
-export const siteAuthSuccess = createAction(SITE_AUTH_SUCCESS);
-
export const badgeUpdateAll = createAsyncAction(SITE_BADGE_UPDATE, () =>
BadgesApi.all()
);
diff --git a/frontend/src/@redux/constants/index.ts b/frontend/src/@redux/constants/index.ts
index 494841f5e..d4be20f04 100644
--- a/frontend/src/@redux/constants/index.ts
+++ b/frontend/src/@redux/constants/index.ts
@@ -31,7 +31,6 @@ export const MOVIES_UPDATE_RANGE = "MOVIES_UPDATE_RANGE";
export const MOVIES_UPDATE_BLACKLIST = "UPDATE_MOVIES_BLACKLIST";
// Site Action
-export const SITE_AUTH_SUCCESS = "SITE_AUTH_SUCCESS";
export const SITE_NEED_AUTH = "SITE_NEED_AUTH";
export const SITE_INITIALIZED = "SITE_SYSTEM_INITIALIZED";
export const SITE_INITIALIZE_FAILED = "SITE_INITIALIZE_FAILED";
diff --git a/frontend/src/@redux/reducers/site.ts b/frontend/src/@redux/reducers/site.ts
index 0d6f761dd..78191908a 100644
--- a/frontend/src/@redux/reducers/site.ts
+++ b/frontend/src/@redux/reducers/site.ts
@@ -1,7 +1,7 @@
import { Action, handleActions } from "redux-actions";
import { storage } from "../../@storage/local";
+import apis from "../../apis";
import {
- SITE_AUTH_SUCCESS,
SITE_BADGE_UPDATE,
SITE_INITIALIZED,
SITE_INITIALIZE_FAILED,
@@ -23,14 +23,15 @@ function updateLocalStorage(): Partial<ReduxStore.Site> {
const reducer = handleActions<ReduxStore.Site, any>(
{
- [SITE_NEED_AUTH]: (state) => ({
- ...state,
- auth: false,
- }),
- [SITE_AUTH_SUCCESS]: (state) => ({
- ...state,
- auth: true,
- }),
+ [SITE_NEED_AUTH]: (state) => {
+ if (process.env.NODE_ENV !== "development") {
+ apis.danger_resetApi("NEED_AUTH");
+ }
+ return {
+ ...state,
+ auth: false,
+ };
+ },
[SITE_INITIALIZED]: (state) => ({
...state,
initialized: true,
diff --git a/frontend/src/@types/window.d.ts b/frontend/src/@types/window.d.ts
index 234052902..ab5f39761 100644
--- a/frontend/src/@types/window.d.ts
+++ b/frontend/src/@types/window.d.ts
@@ -6,7 +6,7 @@ declare global {
export interface BazarrServer {
baseUrl: string;
- apiKey: string;
+ apiKey?: string;
canUpdate: boolean;
hasUpdate: boolean;
}
diff --git a/frontend/src/App/Header.tsx b/frontend/src/App/Header.tsx
index 0786cd35d..27a6c5c1f 100644
--- a/frontend/src/App/Header.tsx
+++ b/frontend/src/App/Header.tsx
@@ -58,7 +58,7 @@ const Header: FunctionComponent<Props> = () => {
const [settings] = useSystemSettings();
- const canLogout = (settings.data?.auth.type ?? "none") !== "none";
+ const canLogout = (settings.data?.auth.type ?? "none") === "form";
const toggleSidebar = useContext(SidebarToggleContext);
diff --git a/frontend/src/Auth/index.tsx b/frontend/src/Auth/index.tsx
index 50b756daa..0293b1fa2 100644
--- a/frontend/src/Auth/index.tsx
+++ b/frontend/src/Auth/index.tsx
@@ -9,8 +9,7 @@ import {
Spinner,
} from "react-bootstrap";
import { Redirect } from "react-router-dom";
-import { siteAuthSuccess } from "../@redux/actions";
-import { useReduxAction, useReduxStore } from "../@redux/hooks/base";
+import { useReduxStore } from "../@redux/hooks/base";
import logo from "../@static/logo128.png";
import { SystemApi } from "../apis";
import "./style.scss";
@@ -29,7 +28,7 @@ const AuthPage: FunctionComponent<Props> = () => {
setTimeout(() => setError(""), 2000);
}, []);
- const onSuccess = useReduxAction(siteAuthSuccess);
+ const onSuccess = useCallback(() => window.location.reload(), []);
const authState = useReduxStore((s) => s.site.auth);
diff --git a/frontend/src/apis/index.ts b/frontend/src/apis/index.ts
index 3707b9bab..b583d3a84 100644
--- a/frontend/src/apis/index.ts
+++ b/frontend/src/apis/index.ts
@@ -17,13 +17,13 @@ class Api {
}
}
- initialize(url: string, apikey: string) {
+ initialize(url: string, apikey?: string) {
this.axios = Axios.create({
baseURL: url,
});
this.axios.defaults.headers.post["Content-Type"] = "application/json";
- this.axios.defaults.headers.common["X-API-KEY"] = apikey;
+ this.axios.defaults.headers.common["X-API-KEY"] = apikey ?? "AUTH_NEEDED";
this.source = Axios.CancelToken.source();
@@ -56,6 +56,10 @@ class Api {
);
}
+ danger_resetApi(apikey: string) {
+ this.axios.defaults.headers.common["X-API-KEY"] = apikey;
+ }
+
onOnline() {
const offline = reduxStore.getState().site.offline;
if (offline) {
diff --git a/frontend/src/apis/utils.ts b/frontend/src/apis/utils.ts
index 2ea911de6..9601a692b 100644
--- a/frontend/src/apis/utils.ts
+++ b/frontend/src/apis/utils.ts
@@ -1,4 +1,4 @@
-import Axios, { AxiosInstance } from "axios";
+import apis from ".";
type UrlTestResponse =
| {
@@ -11,35 +11,14 @@ type UrlTestResponse =
};
class RequestUtils {
- private axios!: AxiosInstance;
-
- constructor() {
- if (process.env.NODE_ENV === "development") {
- this.recreateAxios("/", process.env.REACT_APP_APIKEY!);
- } else {
- const baseUrl =
- window.Bazarr.baseUrl === "/" ? "/" : `${window.Bazarr.baseUrl}/`;
- this.recreateAxios(baseUrl, window.Bazarr.apiKey);
- }
- }
-
- private recreateAxios(url: string, apikey: string) {
- this.axios = Axios.create({
- baseURL: url,
- });
-
- this.axios.defaults.headers.post["Content-Type"] = "application/json";
- this.axios.defaults.headers.common["x-api-key"] = apikey;
- }
-
urlTest(
protocol: string,
url: string,
params?: any
): Promise<UrlTestResponse> {
return new Promise<UrlTestResponse>((resolve, reject) => {
- this.axios
- .get(`test/${protocol}/${url}api/system/status`, { params })
+ apis.axios
+ .get(`../test/${protocol}/${url}api/system/status`, { params })
.then((result) => resolve(result.data))
.catch(reject);
});