mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2025-12-13 01:30:31 +08:00
refactoring
This commit is contained in:
parent
cf5bf8e147
commit
d79ed9f1be
95
kvmd/apps/kvmd/api/auth.py
Normal file
95
kvmd/apps/kvmd/api/auth.py
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
# ========================================================================== #
|
||||||
|
# #
|
||||||
|
# KVMD - The main Pi-KVM daemon. #
|
||||||
|
# #
|
||||||
|
# Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com> #
|
||||||
|
# #
|
||||||
|
# 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()
|
||||||
@ -52,10 +52,6 @@ from ...plugins.msd import BaseMsd
|
|||||||
|
|
||||||
from ...validators import ValidatorError
|
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_quality
|
||||||
from ...validators.kvm import valid_stream_fps
|
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 get_exposed_ws
|
||||||
from .http import make_json_response
|
from .http import make_json_response
|
||||||
from .http import make_json_exception
|
from .http import make_json_exception
|
||||||
from .http import set_request_auth_info
|
|
||||||
from .http import HttpServer
|
from .http import HttpServer
|
||||||
|
|
||||||
|
from .api.auth import AuthApi
|
||||||
|
from .api.auth import check_request_auth
|
||||||
|
|
||||||
from .api.log import LogApi
|
from .api.log import LogApi
|
||||||
from .api.wol import WolApi
|
from .api.wol import WolApi
|
||||||
from .api.hid import HidApi
|
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):
|
class _Events(Enum):
|
||||||
INFO_STATE = "info_state"
|
INFO_STATE = "info_state"
|
||||||
WOL_STATE = "wol_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.__apis: List[object] = [
|
||||||
self,
|
self,
|
||||||
|
AuthApi(auth_manager),
|
||||||
LogApi(log_reader),
|
LogApi(log_reader),
|
||||||
WolApi(wol),
|
WolApi(wol),
|
||||||
HidApi(hid, keymap_path),
|
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(),
|
"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
|
# ===== SYSTEM
|
||||||
|
|
||||||
@exposed_http("GET", "/info")
|
@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:
|
def __add_app_route(self, app: aiohttp.web.Application, exposed: HttpExposed) -> None:
|
||||||
async def wrapper(request: aiohttp.web.Request) -> aiohttp.web.Response:
|
async def wrapper(request: aiohttp.web.Request) -> aiohttp.web.Response:
|
||||||
try:
|
try:
|
||||||
if exposed.auth_required and self.__auth_manager.is_auth_enabled():
|
await check_request_auth(self.__auth_manager, exposed, request)
|
||||||
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()
|
|
||||||
|
|
||||||
return (await exposed.handler(request))
|
return (await exposed.handler(request))
|
||||||
|
|
||||||
except IsBusyError as err:
|
except IsBusyError as err:
|
||||||
return make_json_exception(err, 409)
|
return make_json_exception(err, 409)
|
||||||
except (ValidatorError, OperationError) as err:
|
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)
|
return make_json_exception(err, 401)
|
||||||
except ForbiddenError as err:
|
except ForbiddenError as err:
|
||||||
return make_json_exception(err, 403)
|
return make_json_exception(err, 403)
|
||||||
|
|
||||||
app.router.add_route(exposed.method, exposed.path, wrapper)
|
app.router.add_route(exposed.method, exposed.path, wrapper)
|
||||||
|
|
||||||
async def __on_shutdown(self, _: aiohttp.web.Application) -> None:
|
async def __on_shutdown(self, _: aiohttp.web.Application) -> None:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user