diff --git a/kdb-bot/src/bot_api/controller/discord/server_controller.py b/kdb-bot/src/bot_api/controller/discord/server_controller.py index 394338699e..35a3fa9c96 100644 --- a/kdb-bot/src/bot_api/controller/discord/server_controller.py +++ b/kdb-bot/src/bot_api/controller/discord/server_controller.py @@ -2,9 +2,11 @@ from cpl_core.configuration import ConfigurationABC from cpl_core.environment import ApplicationEnvironmentABC from cpl_core.mailing import EMailClientABC, EMailClientSettings from cpl_translation import TranslatePipe -from flask import Response, jsonify +from flask import Response, jsonify, request from bot_api.api import Api +from bot_api.filter.discord.server_select_criteria import ServerSelectCriteria +from bot_api.json_processor import JSONProcessor from bot_api.logging.api_logger import ApiLogger from bot_api.route.route import Route from bot_api.service.discord_service import DiscordService @@ -41,6 +43,14 @@ class ServerController: result = result.select(lambda x: x.to_dict()) return jsonify(result) + @Route.get(f'{BasePath}/servers/get/filtered') + @Route.authorize + async def get_all_servers_by_user(self) -> Response: + dto: ServerSelectCriteria = JSONProcessor.process(ServerSelectCriteria, request.get_json(force=True, silent=True)) + result = await self._discord_service.get_filtered_servers_async(dto) + result.result = result.result.select(lambda x: x.to_dict()) + return jsonify(result.to_dict()) + @Route.get(f'{BasePath}/servers-by-user') @Route.authorize async def get_all_servers_by_user(self) -> Response: diff --git a/kdb-bot/src/bot_api/filter/discord/__init__.py b/kdb-bot/src/bot_api/filter/discord/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/kdb-bot/src/bot_api/filter/discord/server_select_criteria.py b/kdb-bot/src/bot_api/filter/discord/server_select_criteria.py new file mode 100644 index 0000000000..f1454a8c95 --- /dev/null +++ b/kdb-bot/src/bot_api/filter/discord/server_select_criteria.py @@ -0,0 +1,17 @@ +from bot_api.abc.select_criteria_abc import SelectCriteriaABC + + +class ServerSelectCriteria(SelectCriteriaABC): + + def __init__( + self, + page_index: int, + page_size: int, + sort_direction: str, + sort_column: str, + + name: str, + ): + SelectCriteriaABC.__init__(self, page_index, page_size, sort_direction, sort_column) + + self.name = name diff --git a/kdb-bot/src/bot_api/model/discord/server_filtered_result_dto.py b/kdb-bot/src/bot_api/model/discord/server_filtered_result_dto.py new file mode 100644 index 0000000000..eceb642ca0 --- /dev/null +++ b/kdb-bot/src/bot_api/model/discord/server_filtered_result_dto.py @@ -0,0 +1,21 @@ +from cpl_query.extension import List + +from bot_api.abc.dto_abc import DtoABC +from bot_data.filtered_result import FilteredResult + + +class ServerFilteredResultDTO(DtoABC, FilteredResult): + + def __init__(self, result: List = None, total_count: int = 0): + DtoABC.__init__(self) + FilteredResult.__init__(self, result, total_count) + + def from_dict(self, values: dict): + self._result = values['servers'] + self._total_count = values['totalCount'] + + def to_dict(self) -> dict: + return { + 'servers': self.result, + 'totalCount': self.total_count + } diff --git a/kdb-bot/src/bot_api/service/discord_service.py b/kdb-bot/src/bot_api/service/discord_service.py index e6b3056c4e..e00e5b8486 100644 --- a/kdb-bot/src/bot_api/service/discord_service.py +++ b/kdb-bot/src/bot_api/service/discord_service.py @@ -7,7 +7,9 @@ from flask import jsonify from bot_api.abc.auth_service_abc import AuthServiceABC from bot_api.exception.service_error_code_enum import ServiceErrorCode from bot_api.exception.service_exception import ServiceException +from bot_api.filter.discord.server_select_criteria import ServerSelectCriteria from bot_api.model.discord.server_dto import ServerDTO +from bot_api.model.discord.server_filtered_result_dto import ServerFilteredResultDTO from bot_api.model.error_dto import ErrorDTO from bot_api.transformer.server_transformer import ServerTransformer from bot_data.abc.server_repository_abc import ServerRepositoryABC @@ -35,6 +37,29 @@ class DiscordService: lambda x: ServerTransformer.to_dto(x, self._bot.get_guild(x.discord_server_id).name, self._bot.get_guild(x.discord_server_id).member_count) ) + async def get_filtered_servers_async(self, criteria: ServerSelectCriteria) -> ServerFilteredResultDTO: + token = self._auth.get_decoded_token_from_request() + if token is None or 'email' not in token or 'role' not in token: + raise ServiceException(ServiceErrorCode.InvalidData, 'Token invalid') + + role = AuthRoleEnum(token['role']) + role = AuthRoleEnum(token['role']) + filtered_result = self._servers.get_filtered_servers(criteria) + servers = filtered_result.result + if role != AuthRoleEnum.admin: + user = await self._auth.find_auth_user_by_email_async(token['email']) + user_from_db = self._users.find_user_by_id(0 if user.user_id is None else user.user_id) + servers = servers.where(lambda x: user_from_db is not None and x.server_id == user_from_db.server.server_id) + + result = servers.select( + lambda x: ServerTransformer.to_dto(x, self._bot.get_guild(x.discord_server_id).name, self._bot.get_guild(x.discord_server_id).member_count) + ) + + return ServerFilteredResultDTO( + List(ServerDTO, result), + servers.total_count + ) + async def get_all_servers_by_user(self) -> List[ServerDTO]: token = self._auth.get_decoded_token_from_request() if token is None or 'email' not in token or 'role' not in token: diff --git a/kdb-bot/src/bot_data/abc/server_repository_abc.py b/kdb-bot/src/bot_data/abc/server_repository_abc.py index d1ab13fe63..f3eea75a9d 100644 --- a/kdb-bot/src/bot_data/abc/server_repository_abc.py +++ b/kdb-bot/src/bot_data/abc/server_repository_abc.py @@ -3,6 +3,8 @@ from typing import Optional from cpl_query.extension import List +from bot_api.filter.discord.server_select_criteria import ServerSelectCriteria +from bot_data.filtered_result import FilteredResult from bot_data.model.server import Server @@ -13,6 +15,9 @@ class ServerRepositoryABC(ABC): @abstractmethod def get_servers(self) -> List[Server]: pass + + @abstractmethod + def get_filtered_servers(self, criteria: ServerSelectCriteria) -> FilteredResult: pass @abstractmethod def get_server_by_id(self, id: int) -> Server: pass diff --git a/kdb-bot/src/bot_data/service/server_repository_service.py b/kdb-bot/src/bot_data/service/server_repository_service.py index 728d2bc679..37b2918e2c 100644 --- a/kdb-bot/src/bot_data/service/server_repository_service.py +++ b/kdb-bot/src/bot_data/service/server_repository_service.py @@ -3,8 +3,10 @@ from typing import Optional from cpl_core.database.context import DatabaseContextABC from cpl_query.extension import List +from bot_api.filter.discord.server_select_criteria import ServerSelectCriteria from bot_core.logging.database_logger import DatabaseLogger from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.filtered_result import FilteredResult from bot_data.model.server import Server @@ -28,6 +30,29 @@ class ServerRepositoryService(ServerRepositoryABC): return servers + def get_filtered_servers(self, criteria: ServerSelectCriteria) -> FilteredResult: + servers = self.get_servers() + self._logger.trace(__name__, f'Send SQL command: {Server.get_select_all_string()}') + query = servers + + if criteria.name is not None and criteria.name != '': + query = query.where(lambda x: criteria.name in x.first_name or x.first_name == criteria.name) + + # sort + if criteria.sort_column is not None and criteria.sort_column != '' and criteria.sort_direction is not None and criteria.sort_direction: + crit_sort_direction = criteria.sort_direction.lower() + if crit_sort_direction == "desc" or crit_sort_direction == "descending": + query = query.order_by_descending(lambda x: getattr(x, criteria.sort_column)) + else: + query = query.order_by(lambda x: getattr(x, criteria.sort_column)) + + result = FilteredResult() + result.total_count = query.count() + skip = criteria.page_size * criteria.page_index + result.result = query.skip(skip).take(criteria.page_size) + + return result + def get_server_by_id(self, server_id: int) -> Server: self._logger.trace(__name__, f'Send SQL command: {Server.get_select_by_id_string(server_id)}') result = self._context.select(Server.get_select_by_id_string(server_id))[0]