forked from sh-edraft.de/sh_discord_bot
		
	Added auth user controller #70
This commit is contained in:
		| @@ -4,6 +4,8 @@ from cpl_query.extension import List | ||||
|  | ||||
| from bot_api.filter.auth_user_select_criteria import AuthUserSelectCriteria | ||||
| from bot_api.model.auth_user_dto import AuthUserDTO | ||||
| from bot_api.model.auth_user_filtered_result_dto import AuthUserFilteredResultDTO | ||||
| from bot_api.model.email_string_dto import EMailStringDTO | ||||
| from bot_api.model.reset_password_dto import ResetPasswordDTO | ||||
| from bot_api.model.token_dto import TokenDTO | ||||
| from bot_api.model.update_auth_user_dto import UpdateAuthUserDTO | ||||
| @@ -19,7 +21,7 @@ class AuthServiceABC(ABC): | ||||
|     async def get_all_auth_users_async(self) -> List[AuthUser]: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def get_filtered_auth_users_async(self, criteria: AuthUserSelectCriteria) -> List[AuthUser]: pass | ||||
|     async def get_filtered_auth_users_async(self, criteria: AuthUserSelectCriteria) -> AuthUserFilteredResultDTO: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def get_auth_user_by_email_async(self, email: str) -> AuthUser: pass | ||||
| @@ -28,37 +30,37 @@ class AuthServiceABC(ABC): | ||||
|     async def find_auth_user_by_email_async(self, email: str) -> AuthUser: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def add_auth_user_async(self, user_dto: AuthUserDTO) -> AuthUser: pass | ||||
|     async def add_auth_user_async(self, user_dto: AuthUserDTO) -> int: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def confirm_email_async(self, id: str) -> AuthUser: pass | ||||
|     async def confirm_email_async(self, id: str) -> bool: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def login_async(self, user_dto: AuthUserDTO) -> AuthUser: pass | ||||
|     async def login_async(self, user_dto: AuthUserDTO) -> TokenDTO: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def forgot_password_async(self, email: str) -> AuthUser: pass | ||||
|     async def forgot_password_async(self, email: str): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def confirm_forgot_password_async(self, id: str) -> AuthUser: pass | ||||
|     async def confirm_forgot_password_async(self, id: str) -> EMailStringDTO: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def reset_password_async(self, rp_dto: ResetPasswordDTO) -> AuthUser: pass | ||||
|     async def reset_password_async(self, rp_dto: ResetPasswordDTO): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def update_user_async(self, update_user_dto: UpdateAuthUserDTO) -> AuthUser: pass | ||||
|     async def update_user_async(self, update_user_dto: UpdateAuthUserDTO): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def update_user_as_admin_async(self, update_user_dto: UpdateAuthUserDTO) -> AuthUser: pass | ||||
|     async def update_user_as_admin_async(self, update_user_dto: UpdateAuthUserDTO): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def refresh_async(self, token_dto: TokenDTO) -> AuthUser: pass | ||||
|     async def refresh_async(self, token_dto: TokenDTO) -> TokenDTO: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def revoke_async(self, token_dto: TokenDTO) -> AuthUser: pass | ||||
|     async def revoke_async(self, token_dto: TokenDTO): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def delete_auth_user_by_email_async(self, email: str) -> AuthUser: pass | ||||
|     async def delete_auth_user_by_email_async(self, email: str): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def delete_auth_user_async(self, user_dto: AuthUserDTO) -> AuthUser: pass | ||||
|     async def delete_auth_user_async(self, user_dto: AuthUserDTO): pass | ||||
|   | ||||
| @@ -54,7 +54,6 @@ class Api(Flask): | ||||
|         self._logger.debug(__name__, f'Received GET @{request.url}') | ||||
|         headers = str(request.headers).replace("\n", "\n\t") | ||||
|         self._logger.trace(__name__, f'Headers: \n\t{headers}') | ||||
|         self._logger.trace(__name__, f'Body: {request.get_json(force=True, silent=True)}') | ||||
|  | ||||
|     def start(self): | ||||
|         self._logger.info(__name__, f'Starting API {self._apt_settings.host}:{self._apt_settings.port}') | ||||
|   | ||||
| @@ -7,10 +7,12 @@ from cpl_core.mailing import EMailClientABC, EMailClient | ||||
| from cpl_discord.service.discord_collection_abc import DiscordCollectionABC | ||||
| from flask import Flask | ||||
|  | ||||
| from bot_api.abc.auth_service_abc import AuthServiceABC | ||||
| from bot_api.api import Api | ||||
| from bot_api.api_thread import ApiThread | ||||
| from bot_api.controller.api_controller import ApiController | ||||
| from bot_api.controller.auth_controller import AuthController | ||||
| from bot_api.service.auth_service import AuthService | ||||
| from bot_core.abc.module_abc import ModuleABC | ||||
| from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum | ||||
|  | ||||
| @@ -34,5 +36,6 @@ class ApiModule(ModuleABC): | ||||
|         services.add_singleton(ApiThread) | ||||
|         services.add_singleton(Flask, Api) | ||||
|  | ||||
|         services.add_transient(AuthServiceABC, AuthService) | ||||
|         services.add_transient(AuthController) | ||||
|         services.add_transient(ApiController) | ||||
|   | ||||
| @@ -1,19 +1,22 @@ | ||||
| from cpl_core.configuration import ConfigurationABC | ||||
| from cpl_core.environment import ApplicationEnvironmentABC | ||||
| from cpl_core.mailing import EMailClientABC, EMailClientSettings | ||||
| from cpl_query.extension import List | ||||
| from cpl_translation import TranslatePipe | ||||
| from flask import request | ||||
| from flask_cors import cross_origin | ||||
| from flask import request, jsonify, Response | ||||
|  | ||||
| from bot_api.abc.auth_service_abc import AuthServiceABC | ||||
| from bot_api.api import Api | ||||
| from bot_api.filter.auth_user_select_criteria import AuthUserSelectCriteria | ||||
| from bot_api.json_processor import JSONProcessor | ||||
| from bot_api.logging.api_logger import ApiLogger | ||||
| from bot_api.model.auth_user_dto import AuthUserDTO | ||||
| from bot_api.model.token_dto import TokenDTO | ||||
| from bot_api.model.update_auth_user_dto import UpdateAuthUserDTO | ||||
| from bot_api.route.route import Route | ||||
| from bot_data.model.auth_user import AuthUser | ||||
|  | ||||
|  | ||||
| class AuthController: | ||||
|     BasePath = '/api/auth' | ||||
|  | ||||
|     def __init__( | ||||
|             self, | ||||
| @@ -23,7 +26,8 @@ class AuthController: | ||||
|             t: TranslatePipe, | ||||
|             api: Api, | ||||
|             mail_settings: EMailClientSettings, | ||||
|             mailer: EMailClientABC | ||||
|             mailer: EMailClientABC, | ||||
|             auth_service: AuthServiceABC | ||||
|     ): | ||||
|         self._config = config | ||||
|         self._env = env | ||||
| @@ -32,16 +36,79 @@ class AuthController: | ||||
|         self._api = api | ||||
|         self._mail_settings = mail_settings | ||||
|         self._mailer = mailer | ||||
|         self._auth_service = auth_service | ||||
|  | ||||
|     @Route.route('/api/auth/get-all-users') | ||||
|     async def get_all_users(self) -> List[AuthUser]: | ||||
|         pass | ||||
|     @Route.get(f'{BasePath}/users') | ||||
|     async def get_all_users(self) -> Response: | ||||
|         return jsonify(await self._auth_service.get_all_auth_users_async()) | ||||
|  | ||||
|     @Route.route('/api/auth/get-filtered-users', methods=['POST']) | ||||
|     async def get_filtered_users(self) -> List[AuthUser]: | ||||
|         pass | ||||
|     @Route.post(f'{BasePath}/users/get/filtered') | ||||
|     async def get_filtered_users(self) -> Response: | ||||
|         dto: AuthUserSelectCriteria = JSONProcessor.process(AuthUserSelectCriteria, request.get_json(force=True, silent=True)) | ||||
|         result = await self._auth_service.get_filtered_auth_users_async(dto) | ||||
|         return jsonify(result.to_dict()) | ||||
|  | ||||
|     @Route.route('/api/auth/login', methods=['POST']) | ||||
|     async def login(self) -> dict: | ||||
|         self._logger.warn(__name__, f'Received {request.json}') | ||||
|         return TokenDTO().to_dict() | ||||
|     @Route.get(f'{BasePath}/users/get/<email>') | ||||
|     async def get_user_from_email(self, email: str) -> Response: | ||||
|         return jsonify(await self._auth_service.get_auth_user_by_email_async(email)) | ||||
|  | ||||
|     @Route.get(f'{BasePath}/users/find/<email>') | ||||
|     async def find_user_from_email(self, email: str) -> Response: | ||||
|         return jsonify(await self._auth_service.find_auth_user_by_email_async(email)) | ||||
|  | ||||
|     @Route.post(f'{BasePath}/register') | ||||
|     async def register(self): | ||||
|         dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True)) | ||||
|         await self._auth_service.add_auth_user_async(dto) | ||||
|         return '', 200 | ||||
|  | ||||
|     @Route.post(f'{BasePath}/login') | ||||
|     async def login(self) -> Response: | ||||
|         dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True)) | ||||
|         result = await self._auth_service.login_async(dto) | ||||
|         return jsonify(result.to_dict()) | ||||
|  | ||||
|     @Route.post(f'{BasePath}/forgot-password/<email>') | ||||
|     async def forgot_password(self, email: str): | ||||
|         await self._auth_service.forgot_password_async(email) | ||||
|         return '', 200 | ||||
|  | ||||
|     @Route.post(f'{BasePath}/confirm-forgot-password/<id>') | ||||
|     async def confirm_forgot_password(self, id: str): | ||||
|         await self._auth_service.confirm_forgot_password_async(id) | ||||
|         return '', 200 | ||||
|  | ||||
|     @Route.post(f'{BasePath}/update-user') | ||||
|     async def update_user(self): | ||||
|         dto: UpdateAuthUserDTO = JSONProcessor.process(UpdateAuthUserDTO, request.get_json(force=True, silent=True)) | ||||
|         await self._auth_service.update_user_async(dto) | ||||
|         return '', 200 | ||||
|  | ||||
|     @Route.post(f'{BasePath}/update-user-as-admin') | ||||
|     async def update_user_as_admin(self): | ||||
|         dto: UpdateAuthUserDTO = JSONProcessor.process(UpdateAuthUserDTO, request.get_json(force=True, silent=True)) | ||||
|         await self._auth_service.update_user_async(dto) | ||||
|         return '', 200 | ||||
|  | ||||
|     @Route.post(f'{BasePath}/refresh') | ||||
|     async def refresh(self) -> Response: | ||||
|         dto: TokenDTO = JSONProcessor.process(TokenDTO, request.get_json(force=True, silent=True)) | ||||
|         result = await self._auth_service.refresh_async(dto) | ||||
|         return jsonify(result.to_dict()) | ||||
|  | ||||
|     @Route.post(f'{BasePath}/revoke') | ||||
|     async def revoke(self): | ||||
|         dto: TokenDTO = JSONProcessor.process(TokenDTO, request.get_json(force=True, silent=True)) | ||||
|         await self._auth_service.revoke_async(dto) | ||||
|         return '', 200 | ||||
|  | ||||
|     @Route.post(f'{BasePath}/delete-user') | ||||
|     async def delete_user(self): | ||||
|         dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True)) | ||||
|         await self._auth_service.delete_auth_user_async(dto) | ||||
|         return '', 200 | ||||
|  | ||||
|     @Route.post(f'{BasePath}/delete-user-by-mail/<email>') | ||||
|     async def delete_user_by_mail(self, email: str): | ||||
|         await self._auth_service.delete_auth_user_by_email_async(email) | ||||
|         return '', 200 | ||||
|   | ||||
							
								
								
									
										32
									
								
								src/bot_api/json_processor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/bot_api/json_processor.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| from inspect import signature, Parameter | ||||
|  | ||||
| from cpl_core.utils import String | ||||
|  | ||||
|  | ||||
| class JSONProcessor: | ||||
|  | ||||
|     @staticmethod | ||||
|     def process(_t: type, values: dict) -> object: | ||||
|         args = [] | ||||
|  | ||||
|         sig = signature(_t.__init__) | ||||
|         for param in sig.parameters.items(): | ||||
|             parameter = param[1] | ||||
|             if parameter.name == 'self' or parameter.annotation == Parameter.empty: | ||||
|                 continue | ||||
|  | ||||
|             name = String.convert_to_camel_case(parameter.name) | ||||
|             name_first_lower = String.first_to_lower(name) | ||||
|             if name in values or name_first_lower in values: | ||||
|                 if name in values: | ||||
|                     args.append(values[name]) | ||||
|                 else: | ||||
|                     args.append(values[name_first_lower]) | ||||
|  | ||||
|             elif parameter.default != Parameter.empty: | ||||
|                 args.append(parameter.default) | ||||
|  | ||||
|             else: | ||||
|                 args.append(None) | ||||
|  | ||||
|         return _t(*args) | ||||
| @@ -14,7 +14,7 @@ class AuthUserDTO(DtoABC): | ||||
|             id: int, | ||||
|             first_name: str, | ||||
|             last_name: str, | ||||
|             email: str, | ||||
|             e_mail: str, | ||||
|             password: str, | ||||
|             confirmation_id: Optional[str], | ||||
|             auth_role: AuthRoleEnum, | ||||
| @@ -24,20 +24,38 @@ class AuthUserDTO(DtoABC): | ||||
|         self._id = id | ||||
|         self._first_name = first_name | ||||
|         self._last_name = last_name | ||||
|         self._email = email | ||||
|         self._email = e_mail | ||||
|         self._password = password | ||||
|         self._is_confirmed = confirmation_id is None | ||||
|         self._auth_role = auth_role | ||||
|  | ||||
|         """ | ||||
|         long Id { get; set; } | ||||
|         string FirstName { get; set; } | ||||
|         string LastName { get; set; } | ||||
|         string EMail { get; set; } | ||||
|         string Password { get; set; } | ||||
|         bool IsConfirmed { get; set; } | ||||
|         AuthRoles AuthRole { get; set; } | ||||
|         """ | ||||
|          | ||||
|     @property | ||||
|     def id(self) -> int: | ||||
|         return self._id | ||||
|      | ||||
|     @property | ||||
|     def first_name(self) -> str: | ||||
|         return self._first_name | ||||
|      | ||||
|     @property | ||||
|     def last_name(self) -> str: | ||||
|         return self._last_name | ||||
|      | ||||
|     @property | ||||
|     def email(self) -> str: | ||||
|         return self._email | ||||
|      | ||||
|     @property | ||||
|     def password(self) -> str: | ||||
|         return self._password | ||||
|      | ||||
|     @property | ||||
|     def is_confirmed(self) -> bool: | ||||
|         return self._is_confirmed | ||||
|      | ||||
|     @property | ||||
|     def auth_role(self) -> AuthRoleEnum: | ||||
|         return self._auth_role | ||||
|  | ||||
|     def from_dict(self, values: dict): | ||||
|         self._id = values['Id'] | ||||
|   | ||||
							
								
								
									
										21
									
								
								src/bot_api/model/auth_user_filtered_result_dto.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/bot_api/model/auth_user_filtered_result_dto.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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 AuthUserFilteredResultDTO(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['Users'] | ||||
|         self._total_count = values['TotalCount'] | ||||
|  | ||||
|     def to_dict(self) -> dict: | ||||
|         return { | ||||
|             'Users': self.result, | ||||
|             'TotalCount': self.total_count | ||||
|         } | ||||
							
								
								
									
										18
									
								
								src/bot_api/model/email_string_dto.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/bot_api/model/email_string_dto.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| import traceback | ||||
|  | ||||
| from cpl_core.console import Console | ||||
|  | ||||
| from bot_api.abc.dto_abc import DtoABC | ||||
|  | ||||
|  | ||||
| class EMailStringDTO(DtoABC): | ||||
|  | ||||
|     def __init__(self): | ||||
|         DtoABC.__init__(self) | ||||
|  | ||||
|     def from_dict(self, values: dict): | ||||
|         pass | ||||
|  | ||||
|     def to_dict(self) -> dict: | ||||
|         return { | ||||
|         } | ||||
| @@ -9,3 +9,23 @@ class Route: | ||||
|             return fn | ||||
|  | ||||
|         return inner | ||||
|  | ||||
|     @classmethod | ||||
|     def get(cls, path=None, **kwargs): | ||||
|         return cls.route(path, methods=['GET'], **kwargs) | ||||
|  | ||||
|     @classmethod | ||||
|     def post(cls, path=None, **kwargs): | ||||
|         return cls.route(path, methods=['POST'], **kwargs) | ||||
|  | ||||
|     @classmethod | ||||
|     def head(cls, path=None, **kwargs): | ||||
|         return cls.route(path, methods=['HEAD'], **kwargs) | ||||
|  | ||||
|     @classmethod | ||||
|     def put(cls, path=None, **kwargs): | ||||
|         return cls.route(path, methods=['PUT'], **kwargs) | ||||
|  | ||||
|     @classmethod | ||||
|     def delete(cls, path=None, **kwargs): | ||||
|         return cls.route(path, methods=['DELETE'], **kwargs) | ||||
|   | ||||
| @@ -2,7 +2,9 @@ from cpl_query.extension import List | ||||
|  | ||||
| from bot_api.abc.auth_service_abc import AuthServiceABC | ||||
| from bot_api.filter.auth_user_select_criteria import AuthUserSelectCriteria | ||||
| from bot_api.logging.api_logger import ApiLogger | ||||
| from bot_api.model.auth_user_dto import AuthUserDTO | ||||
| from bot_api.model.auth_user_filtered_result_dto import AuthUserFilteredResultDTO | ||||
| from bot_api.model.reset_password_dto import ResetPasswordDTO | ||||
| from bot_api.model.token_dto import TokenDTO | ||||
| from bot_api.model.update_auth_user_dto import UpdateAuthUserDTO | ||||
| @@ -11,13 +13,18 @@ from bot_data.model.auth_user import AuthUser | ||||
|  | ||||
| class AuthService(AuthServiceABC): | ||||
|  | ||||
|     def __init__(self): | ||||
|         pass | ||||
|     def __init__( | ||||
|             self, | ||||
|             logger: ApiLogger, | ||||
|     ): | ||||
|         AuthServiceABC.__init__(self) | ||||
|  | ||||
|         self._logger = logger | ||||
|  | ||||
|     async def get_all_auth_users_async(self) -> List[AuthUser]: | ||||
|         pass | ||||
|  | ||||
|     async def get_filtered_auth_users_async(self, criteria: AuthUserSelectCriteria) -> List[AuthUser]: | ||||
|     async def get_filtered_auth_users_async(self, criteria: AuthUserSelectCriteria) -> AuthUserFilteredResultDTO: | ||||
|         pass | ||||
|  | ||||
|     async def get_auth_user_by_email_async(self, email: str) -> AuthUser: | ||||
| @@ -32,7 +39,7 @@ class AuthService(AuthServiceABC): | ||||
|     async def confirm_email_async(self, id: str) -> AuthUser: | ||||
|         pass | ||||
|  | ||||
|     async def login_async(self, user_dto: AuthUserDTO) -> AuthUser: | ||||
|     async def login_async(self, user_dto: AuthUserDTO) -> TokenDTO: | ||||
|         pass | ||||
|  | ||||
|     async def forgot_password_async(self, email: str) -> AuthUser: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user