Added auth user controller #70

This commit is contained in:
Sven Heidemann 2022-10-14 15:37:52 +02:00
parent 126637306d
commit 1defe29406
10 changed files with 232 additions and 45 deletions

View File

@ -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

View File

@ -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}')

View File

@ -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)

View File

@ -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

View 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)

View File

@ -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']

View 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
}

View 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 {
}

View File

@ -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)

View File

@ -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: