From 91b054fdca1ccd677c952d4ecc97b09f71e32edf Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Fri, 14 Oct 2022 07:51:30 +0200 Subject: [PATCH] Added auth service abc #70 --- src/bot_api/abc/auth_service_abc.py | 64 ++++++++++ src/bot_api/abc/select_criteria_abc.py | 17 +++ src/bot_api/filter/__init__.py | 0 .../filter/auth_user_select_criteria.py | 23 ++++ src/bot_api/model/auth_user_dto.py | 18 +++ src/bot_api/model/reset_password_dto.py | 18 +++ src/bot_api/model/settings_dto.py | 28 ++--- src/bot_api/model/token_dto.py | 18 +++ src/bot_api/model/update_auth_user_dto.py | 18 +++ src/bot_api/service/__init__.py | 1 + src/bot_api/service/auth_service.py | 4 + src/bot_data/migration/api_migration.py | 38 ++++++ src/bot_data/model/auth_role_enum.py | 7 ++ src/bot_data/model/auth_user.py | 109 ++++++++++++++++++ 14 files changed, 347 insertions(+), 16 deletions(-) create mode 100644 src/bot_api/abc/auth_service_abc.py create mode 100644 src/bot_api/abc/select_criteria_abc.py create mode 100644 src/bot_api/filter/__init__.py create mode 100644 src/bot_api/filter/auth_user_select_criteria.py create mode 100644 src/bot_api/model/auth_user_dto.py create mode 100644 src/bot_api/model/reset_password_dto.py create mode 100644 src/bot_api/model/token_dto.py create mode 100644 src/bot_api/model/update_auth_user_dto.py create mode 100644 src/bot_api/service/__init__.py create mode 100644 src/bot_api/service/auth_service.py create mode 100644 src/bot_data/migration/api_migration.py create mode 100644 src/bot_data/model/auth_role_enum.py create mode 100644 src/bot_data/model/auth_user.py diff --git a/src/bot_api/abc/auth_service_abc.py b/src/bot_api/abc/auth_service_abc.py new file mode 100644 index 0000000000..0141103e4e --- /dev/null +++ b/src/bot_api/abc/auth_service_abc.py @@ -0,0 +1,64 @@ +from abc import ABC, abstractmethod + +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.reset_password_dto import ResetPasswordDTO +from bot_api.model.token_dto import TokenDTO +from bot_api.model.update_auth_user_dto import UpdateAuthUserDTO +from bot_data.model.auth_user import AuthUser + + +class AuthABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + 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 + + @abstractmethod + async def get_auth_user_by_email_async(self, email: str) -> AuthUser: pass + + @abstractmethod + 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 + + @abstractmethod + async def confirm_email_async(self, id: str) -> AuthUser: pass + + @abstractmethod + async def login_async(self, user_dto: AuthUserDTO) -> AuthUser: pass + + @abstractmethod + async def forgot_password_async(self, email: str) -> AuthUser: pass + + @abstractmethod + async def confirm_forgot_password_async(self, id: str) -> AuthUser: pass + + @abstractmethod + async def reset_password_async(self, rp_dto: ResetPasswordDTO) -> AuthUser: pass + + @abstractmethod + async def update_user_async(self, update_user_dto: UpdateAuthUserDTO) -> AuthUser: pass + + @abstractmethod + async def update_user_as_admin_async(self, update_user_dto: UpdateAuthUserDTO) -> AuthUser: pass + + @abstractmethod + async def refresh_async(self, token_dto: TokenDTO) -> AuthUser: pass + + @abstractmethod + async def revoke_async(self, token_dto: TokenDTO) -> AuthUser: pass + + @abstractmethod + async def delete_auth_user_by_email_async(self, email: str) -> AuthUser: pass + + @abstractmethod + async def delete_auth_user_async(self, user_dto: AuthUserDTO) -> AuthUser: pass diff --git a/src/bot_api/abc/select_criteria_abc.py b/src/bot_api/abc/select_criteria_abc.py new file mode 100644 index 0000000000..234f7865b3 --- /dev/null +++ b/src/bot_api/abc/select_criteria_abc.py @@ -0,0 +1,17 @@ +from abc import ABC, abstractmethod + + +class SelectCriteriaABC(ABC): + + @abstractmethod + def __init__( + self, + page_index: int, + page_size: int, + sort_direction: str, + sort_column: str + ): + self.page_index = page_index + self.page_size = page_size + self.sort_direction = sort_direction + self.sort_column = sort_column diff --git a/src/bot_api/filter/__init__.py b/src/bot_api/filter/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/bot_api/filter/auth_user_select_criteria.py b/src/bot_api/filter/auth_user_select_criteria.py new file mode 100644 index 0000000000..497f5eaa18 --- /dev/null +++ b/src/bot_api/filter/auth_user_select_criteria.py @@ -0,0 +1,23 @@ +from bot_api.abc.select_criteria_abc import SelectCriteriaABC + + +class AuthUserSelectCriteria(SelectCriteriaABC): + + def __init__( + self, + page_index: int, + page_size: int, + sort_direction: str, + sort_column: str, + + first_name: str, + last_name: str, + email: str, + auth_role=0 + ): + SelectCriteriaABC.__init__(self, page_index, page_size, sort_direction, sort_column) + + self.first_name = first_name + self.last_name = last_name + self.email = email + self.auth_role = auth_role diff --git a/src/bot_api/model/auth_user_dto.py b/src/bot_api/model/auth_user_dto.py new file mode 100644 index 0000000000..f43dde4e0e --- /dev/null +++ b/src/bot_api/model/auth_user_dto.py @@ -0,0 +1,18 @@ +import traceback + +from cpl_core.console import Console + +from bot_api.abc.dto_abc import DtoABC + + +class AuthUserDTO(DtoABC): + + def __init__(self): + DtoABC.__init__(self) + + def from_dict(self, values: dict): + pass + + def to_dict(self) -> dict: + return { + } diff --git a/src/bot_api/model/reset_password_dto.py b/src/bot_api/model/reset_password_dto.py new file mode 100644 index 0000000000..240437cdfa --- /dev/null +++ b/src/bot_api/model/reset_password_dto.py @@ -0,0 +1,18 @@ +import traceback + +from cpl_core.console import Console + +from bot_api.abc.dto_abc import DtoABC + + +class ResetPasswordDTO(DtoABC): + + def __init__(self): + DtoABC.__init__(self) + + def from_dict(self, values: dict): + pass + + def to_dict(self) -> dict: + return { + } diff --git a/src/bot_api/model/settings_dto.py b/src/bot_api/model/settings_dto.py index 6d72245ba2..ce3ec436cc 100644 --- a/src/bot_api/model/settings_dto.py +++ b/src/bot_api/model/settings_dto.py @@ -1,7 +1,3 @@ -import traceback - -from cpl_core.console import Console - from bot_api.abc.dto_abc import DtoABC from bot_api.model.version_dto import VersionDTO @@ -25,20 +21,20 @@ class SettingsDTO(DtoABC): ): DtoABC.__init__(self) - self._web_version = '' - self._api_version = VersionDTO() - self._config_path = '' - self._web_base_url = '' - self._api_base_url = '' + self._web_version = web_version + self._api_version = api_version + self._config_path = config_path + self._web_base_url = web_base_url + self._api_base_url = api_base_url - self._token_expire_time = 0 - self._refresh_token_expire_time = 0 + self._token_expire_time = token_expire_time + self._refresh_token_expire_time = refresh_token_expire_time - self._mail_user = '' - self._mail_port = 0 - self._mail_host = '' - self._mail_transceiver = '' - self._mail_transceiver_address = '' + self._mail_user = mail_user + self._mail_port = mail_port + self._mail_host = mail_host + self._mail_transceiver = mail_transceiver + self._mail_transceiver_address = mail_transceiver_address def from_dict(self, values: dict): self._web_version = values['WebVersion'] diff --git a/src/bot_api/model/token_dto.py b/src/bot_api/model/token_dto.py new file mode 100644 index 0000000000..445943c248 --- /dev/null +++ b/src/bot_api/model/token_dto.py @@ -0,0 +1,18 @@ +import traceback + +from cpl_core.console import Console + +from bot_api.abc.dto_abc import DtoABC + + +class TokenDTO(DtoABC): + + def __init__(self): + DtoABC.__init__(self) + + def from_dict(self, values: dict): + pass + + def to_dict(self) -> dict: + return { + } diff --git a/src/bot_api/model/update_auth_user_dto.py b/src/bot_api/model/update_auth_user_dto.py new file mode 100644 index 0000000000..b7d501f587 --- /dev/null +++ b/src/bot_api/model/update_auth_user_dto.py @@ -0,0 +1,18 @@ +import traceback + +from cpl_core.console import Console + +from bot_api.abc.dto_abc import DtoABC + + +class UpdateAuthUserDTO(DtoABC): + + def __init__(self): + DtoABC.__init__(self) + + def from_dict(self, values: dict): + pass + + def to_dict(self) -> dict: + return { + } diff --git a/src/bot_api/service/__init__.py b/src/bot_api/service/__init__.py new file mode 100644 index 0000000000..425ab6c146 --- /dev/null +++ b/src/bot_api/service/__init__.py @@ -0,0 +1 @@ +# imports diff --git a/src/bot_api/service/auth_service.py b/src/bot_api/service/auth_service.py new file mode 100644 index 0000000000..cc9ecbbd75 --- /dev/null +++ b/src/bot_api/service/auth_service.py @@ -0,0 +1,4 @@ +class AuthService: + + def __init__(self): + pass diff --git a/src/bot_data/migration/api_migration.py b/src/bot_data/migration/api_migration.py new file mode 100644 index 0000000000..187dc5fcbe --- /dev/null +++ b/src/bot_data/migration/api_migration.py @@ -0,0 +1,38 @@ +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.migration_abc import MigrationABC +from bot_data.db_context import DBContext + + +class ApiMigration(MigrationABC): + name = '0.3_ApiMigration' + + def __init__(self, logger: DatabaseLogger, db: DBContext): + MigrationABC.__init__(self) + self._logger = logger + self._db = db + self._cursor = db.cursor + + def upgrade(self): + self._logger.debug(__name__, 'Running upgrade') + + self._cursor.execute( + str(f""" + CREATE TABLE IF NOT EXISTS `AuthUsers` ( + `Id` bigint NOT NULL, + `FirstName` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci, + `LastName` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci, + `EMail` varchar(255) DEFAULT NULL, + `Password` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci, + `RefreshToken` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci, + `ConfirmationId` varchar(255) DEFAULT NULL, + `ForgotPasswordId` varchar(255) DEFAULT NULL, + `RefreshTokenExpiryTime` datetime(6) NOT NULL, + `AuthRole` int NOT NULL DEFAULT '0' + `CreatedOn` datetime(6) NOT NULL, + `LastModifiedOn` datetime(6) NOT NULL, + ) + """) + ) + + def downgrade(self): + self._cursor.execute('DROP TABLE `AuthUsers`;') diff --git a/src/bot_data/model/auth_role_enum.py b/src/bot_data/model/auth_role_enum.py new file mode 100644 index 0000000000..8b03232577 --- /dev/null +++ b/src/bot_data/model/auth_role_enum.py @@ -0,0 +1,7 @@ +from enum import Enum + + +class AuthRoleEnum(Enum): + + Normal = 0 + Admin = 1 diff --git a/src/bot_data/model/auth_user.py b/src/bot_data/model/auth_user.py new file mode 100644 index 0000000000..37b50d99c9 --- /dev/null +++ b/src/bot_data/model/auth_user.py @@ -0,0 +1,109 @@ +from datetime import datetime +from typing import Optional +from cpl_core.database import TableABC + +from bot_data.model.auth_role_enum import AuthRoleEnum +from bot_data.model.server import Server + + +class AuthUser(TableABC): + + def __init__( + self, + first_name: str, + last_name: str, + email: str, + password: str, + refresh_token: str, + confirmation_id: str, + forgot_password_id: str, + refresh_token_expire_time: datetime, + auth_role: AuthRoleEnum, + created_at: datetime = None, + modified_at: datetime = None, + id=0 + ): + self._auth_user_id = id + self._first_name = first_name + self._last_name = last_name + self._email = email + self._password = password + self._refresh_token = refresh_token + self._confirmation_id = confirmation_id + self._forgot_password_id = forgot_password_id + self._refresh_token_expire_time = refresh_token_expire_time + + self._auth_role_id = auth_role.value + + TableABC.__init__(self) + self._created_at = created_at if created_at is not None else self._created_at + self._modified_at = modified_at if modified_at is not None else self._modified_at + + @staticmethod + def get_select_all_string() -> str: + return str(f""" + SELECT * FROM `AuthUsers`; + """) + + @staticmethod + def get_select_by_id_string(id: int) -> str: + return str(f""" + SELECT * FROM `AuthUsers` + WHERE `Id` = {id}; + """) + + @property + def insert_string(self) -> str: + return str(f""" + INSERT INTO `AuthUsers` ( + `Id`, + `FirstName`, + `LastName`, + `EMail`, + `Password`, + `RefreshToken`, + `ConfirmationId`, + `ForgotPasswordId`, + `RefreshTokenExpiryTime`, + `AuthRole`, + `CreatedOn`, + `LastModifiedOn` + ) VALUES ( + {self._auth_user_id}, + {self._first_name}, + {self._last_name}, + {self._email}, + {self._password}, + {self._refresh_token}, + {self._confirmation_id}, + {self._forgot_password_id}, + {self._refresh_token_expire_time}, + {self._auth_role_id} + {self._created_at}, + {self._modified_at} + ) + """) + + @property + def udpate_string(self) -> str: + return str(f""" + UPDATE `AuthUsers` + SET `FirstName` = '{self._first_name}', + `LastName` = '{self._last_name}', + `EMail` = '{self._email}', + `Password` = '{self._password}', + `RefreshToken` = '{self._refresh_token}', + `ConfirmationId` = '{self._confirmation_id}', + `ForgotPasswordId` = '{self._forgot_password_id}', + `RefreshTokenExpiryTime` = '{self._refresh_token_expire_time}', + `AutoRole` = {self._auth_role_id}, + `LastModifiedAt` = '{self._modified_at}' + WHERE `AuthUsers`.`Id` = {self._auth_user_id}; + """) + + @property + def delete_string(self) -> str: + return str(f""" + DELETE FROM `AuthUsers` + WHERE `Id` = {self._auth_user_id}; + """)