summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDevaev Maxim <[email protected]>2020-05-29 06:44:28 +0300
committerDevaev Maxim <[email protected]>2020-05-29 06:44:28 +0300
commitd79ed9f1be494d019543bd531bbe09e57946f438 (patch)
tree9a4731b2878652608e4abd08a48309042c883a54
parentcf5bf8e14732e7c0bdc67a08a0e410b81b2d4572 (diff)
refactoring
-rw-r--r--kvmd/apps/kvmd/api/auth.py95
-rw-r--r--kvmd/apps/kvmd/server.py65
2 files changed, 100 insertions, 60 deletions
diff --git a/kvmd/apps/kvmd/api/auth.py b/kvmd/apps/kvmd/api/auth.py
new file mode 100644
index 00000000..80996e7e
--- /dev/null
+++ b/kvmd/apps/kvmd/api/auth.py
@@ -0,0 +1,95 @@
+# ========================================================================== #
+# #
+# KVMD - The main Pi-KVM daemon. #
+# #
+# Copyright (C) 2018 Maxim Devaev <[email protected]> #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <https://www.gnu.org/licenses/>. #
+# #
+# ========================================================================== #
+
+
+from aiohttp.web import Request
+from aiohttp.web import Response
+
+from ....validators.auth import valid_user
+from ....validators.auth import valid_passwd
+from ....validators.auth import valid_auth_token
+
+from ..http import UnauthorizedError
+from ..http import ForbiddenError
+from ..http import HttpExposed
+from ..http import exposed_http
+from ..http import make_json_response
+from ..http import set_request_auth_info
+
+from ..auth import AuthManager
+
+
+# =====
+_COOKIE_AUTH_TOKEN = "auth_token"
+
+
+async def check_request_auth(auth_manager: AuthManager, exposed: HttpExposed, request: Request) -> None:
+ if exposed.auth_required and auth_manager.is_auth_enabled():
+ user = request.headers.get("X-KVMD-User", "")
+ passwd = request.headers.get("X-KVMD-Passwd", "")
+ token = request.cookies.get(_COOKIE_AUTH_TOKEN, "")
+
+ if user:
+ user = valid_user(user)
+ set_request_auth_info(request, f"{user} (xhdr)")
+ if not (await auth_manager.authorize(user, valid_passwd(passwd))):
+ raise ForbiddenError()
+
+ elif token:
+ user = auth_manager.check(valid_auth_token(token))
+ if not user:
+ set_request_auth_info(request, "- (token)")
+ raise ForbiddenError()
+ set_request_auth_info(request, f"{user} (token)")
+
+ else:
+ raise UnauthorizedError()
+
+
+class AuthApi:
+ def __init__(self, auth_manager: AuthManager) -> None:
+ self.__auth_manager = auth_manager
+
+ # =====
+
+ @exposed_http("POST", "/auth/login", auth_required=False)
+ async def __login_handler(self, request: Request) -> Response:
+ if self.__auth_manager.is_auth_enabled():
+ credentials = await request.post()
+ token = await self.__auth_manager.login(
+ user=valid_user(credentials.get("user", "")),
+ passwd=valid_passwd(credentials.get("passwd", "")),
+ )
+ if token:
+ return make_json_response(set_cookies={_COOKIE_AUTH_TOKEN: token})
+ raise ForbiddenError()
+ return make_json_response()
+
+ @exposed_http("POST", "/auth/logout")
+ async def __logout_handler(self, request: Request) -> Response:
+ if self.__auth_manager.is_auth_enabled():
+ token = valid_auth_token(request.cookies.get(_COOKIE_AUTH_TOKEN, ""))
+ self.__auth_manager.logout(token)
+ return make_json_response()
+
+ @exposed_http("GET", "/auth/check")
+ async def __check_handler(self, _: Request) -> Response:
+ return make_json_response()
diff --git a/kvmd/apps/kvmd/server.py b/kvmd/apps/kvmd/server.py
index 2c63cb0b..9392c826 100644
--- a/kvmd/apps/kvmd/server.py
+++ b/kvmd/apps/kvmd/server.py
@@ -52,10 +52,6 @@ from ...plugins.msd import BaseMsd
from ...validators import ValidatorError
-from ...validators.auth import valid_user
-from ...validators.auth import valid_passwd
-from ...validators.auth import valid_auth_token
-
from ...validators.kvm import valid_stream_quality
from ...validators.kvm import valid_stream_fps
@@ -78,9 +74,11 @@ from .http import get_exposed_http
from .http import get_exposed_ws
from .http import make_json_response
from .http import make_json_exception
-from .http import set_request_auth_info
from .http import HttpServer
+from .api.auth import AuthApi
+from .api.auth import check_request_auth
+
from .api.log import LogApi
from .api.wol import WolApi
from .api.hid import HidApi
@@ -89,12 +87,6 @@ from .api.msd import MsdApi
# =====
-_HEADER_AUTH_USER = "X-KVMD-User"
-_HEADER_AUTH_PASSWD = "X-KVMD-Passwd"
-
-_COOKIE_AUTH_TOKEN = "auth_token"
-
-
class _Events(Enum):
INFO_STATE = "info_state"
WOL_STATE = "wol_state"
@@ -136,6 +128,7 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
self.__apis: List[object] = [
self,
+ AuthApi(auth_manager),
LogApi(log_reader),
WolApi(wol),
HidApi(hid, keymap_path),
@@ -166,32 +159,6 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
"extras": await self.__info_manager.get_extras(),
}
- # ===== AUTH
-
- @exposed_http("POST", "/auth/login", auth_required=False)
- async def __auth_login_handler(self, request: aiohttp.web.Request) -> aiohttp.web.Response:
- if self.__auth_manager.is_auth_enabled():
- credentials = await request.post()
- token = await self.__auth_manager.login(
- user=valid_user(credentials.get("user", "")),
- passwd=valid_passwd(credentials.get("passwd", "")),
- )
- if token:
- return make_json_response(set_cookies={_COOKIE_AUTH_TOKEN: token})
- raise ForbiddenError()
- return make_json_response()
-
- @exposed_http("POST", "/auth/logout")
- async def __auth_logout_handler(self, request: aiohttp.web.Request) -> aiohttp.web.Response:
- if self.__auth_manager.is_auth_enabled():
- token = valid_auth_token(request.cookies.get(_COOKIE_AUTH_TOKEN, ""))
- self.__auth_manager.logout(token)
- return make_json_response()
-
- @exposed_http("GET", "/auth/check")
- async def __auth_check_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response:
- return make_json_response()
-
# ===== SYSTEM
@exposed_http("GET", "/info")
@@ -307,29 +274,8 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
def __add_app_route(self, app: aiohttp.web.Application, exposed: HttpExposed) -> None:
async def wrapper(request: aiohttp.web.Request) -> aiohttp.web.Response:
try:
- if exposed.auth_required and self.__auth_manager.is_auth_enabled():
- user = request.headers.get(_HEADER_AUTH_USER, "")
- passwd = request.headers.get(_HEADER_AUTH_PASSWD, "")
- token = request.cookies.get(_COOKIE_AUTH_TOKEN, "")
-
- if user:
- user = valid_user(user)
- set_request_auth_info(request, f"{user} (xhdr)")
- if not (await self.__auth_manager.authorize(user, valid_passwd(passwd))):
- raise ForbiddenError()
-
- elif token:
- user = self.__auth_manager.check(valid_auth_token(token))
- if not user:
- set_request_auth_info(request, "- (token)")
- raise ForbiddenError()
- set_request_auth_info(request, f"{user} (token)")
-
- else:
- raise UnauthorizedError()
-
+ await check_request_auth(self.__auth_manager, exposed, request)
return (await exposed.handler(request))
-
except IsBusyError as err:
return make_json_exception(err, 409)
except (ValidatorError, OperationError) as err:
@@ -338,7 +284,6 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
return make_json_exception(err, 401)
except ForbiddenError as err:
return make_json_exception(err, 403)
-
app.router.add_route(exposed.method, exposed.path, wrapper)
async def __on_shutdown(self, _: aiohttp.web.Application) -> None: