dev into staging #414

Merged
edraft merged 58 commits from dev into staging 2023-11-04 17:47:24 +01:00
807 changed files with 3801 additions and 1297 deletions
Showing only changes of commit f435d3dd48 - Show all commits

18
.gitmodules vendored
View File

@ -1,9 +1,9 @@
[submodule "kdb-bot/src/bot/config"]
path = kdb-bot/src/bot/config
url = https://git.sh-edraft.de/sh-edraft.de/kd_discord_bot.config.git
[submodule "kdb-bot/src/bot_api/config"]
path = kdb-bot/src/bot_api/config
url = https://git.sh-edraft.de/sh-edraft.de/kd_discord_bot.api.config.git
[submodule "kdb-bot/docker"]
path = kdb-bot/docker
url = https://git.sh-edraft.de/sh-edraft.de/kd_discord_bot.docker.git
[submodule "shd-bot/src/bot/config"]
path = shd-bot/src/bot/config
url = https://git.sh-edraft.de/sh-edraft.de/sh_discord_bot.config.git
[submodule "shb-bot/src/bot_api/config"]
path = shb-bot/src/bot_api/config
url = https://git.sh-edraft.de/sh-edraft.de/sh_discord_bot.api.config.git
[submodule "shb-bot/bot/docker"]
path = shb-bot/bot/docker
url = https://git.sh-edraft.de/sh-edraft.de/sh_discord_bot.docker.git

View File

@ -23,17 +23,25 @@ class Application(DiscordBotApplicationABC):
# cpl-core
self._logger: LoggerABC = services.get_service(LoggerABC)
self._data_integrity: DataIntegrityService = services.get_service(DataIntegrityService)
self._data_integrity: DataIntegrityService = services.get_service(
DataIntegrityService
)
# cpl-discord
self._bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC)
self._bot_settings: DiscordBotSettings = config.get_configuration(DiscordBotSettings)
self._bot_settings: DiscordBotSettings = config.get_configuration(
DiscordBotSettings
)
# cpl-translation
self._translation: TranslationServiceABC = services.get_service(TranslationServiceABC)
self._translation: TranslationServiceABC = services.get_service(
TranslationServiceABC
)
self._t: TranslatePipe = services.get_service(TranslatePipe)
# internal stuff
self._tasks = services.get_services(TaskABC)
self._feature_flags: FeatureFlagsSettings = config.get_configuration(FeatureFlagsSettings)
self._feature_flags: FeatureFlagsSettings = config.get_configuration(
FeatureFlagsSettings
)
# api
if self._feature_flags.get_flag(FeatureFlagsEnum.api_module):
@ -42,7 +50,9 @@ class Application(DiscordBotApplicationABC):
self._is_stopping = False
async def configure(self):
self._translation.load_by_settings(self._configuration.get_configuration(TranslationSettings))
self._translation.load_by_settings(
self._configuration.get_configuration(TranslationSettings)
)
async def main(self):
try:
@ -85,4 +95,8 @@ class Application(DiscordBotApplicationABC):
Console.write_line()
def is_restart(self):
return True if self._configuration.get_configuration("IS_RESTART") == "true" else False
return (
True
if self._configuration.get_configuration("IS_RESTART") == "true"
else False
)

View File

@ -13,4 +13,6 @@ class InitBotExtension(ApplicationExtensionABC):
async def run(self, config: ConfigurationABC, services: ServiceProviderABC):
settings = config.get_configuration(TechnicianConfig)
bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC, max_messages=settings.cache_max_messages)
bot: DiscordBotServiceABC = services.get_service(
DiscordBotServiceABC, max_messages=settings.cache_max_messages
)

View File

@ -50,7 +50,9 @@ class Startup(StartupABC):
services.add_singleton(CustomFileLoggerABC, ApiLogger)
services.add_translation()
services.add_db_context(DBContext, self._config.get_configuration(DatabaseSettings))
services.add_db_context(
DBContext, self._config.get_configuration(DatabaseSettings)
)
provider = services.build_service_provider()
# instantiate custom logger

View File

@ -9,9 +9,13 @@ class StartupDiscordExtension(StartupExtensionABC):
def __init__(self):
pass
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
def configure_configuration(
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
):
pass
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
def configure_services(
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
):
services.add_discord()
dcc = get_discord_collection(services)

View File

@ -10,7 +10,9 @@ from bot_data.migration.api_migration import ApiMigration
from bot_data.migration.auto_role_fix1_migration import AutoRoleFix1Migration
from bot_data.migration.auto_role_migration import AutoRoleMigration
from bot_data.migration.birthday_migration import BirthdayMigration
from bot_data.migration.config_feature_flags_migration import ConfigFeatureFlagsMigration
from bot_data.migration.config_feature_flags_migration import (
ConfigFeatureFlagsMigration,
)
from bot_data.migration.config_migration import ConfigMigration
from bot_data.migration.db_history_migration import DBHistoryMigration
from bot_data.migration.default_role_migration import DefaultRoleMigration
@ -20,10 +22,14 @@ from bot_data.migration.initial_migration import InitialMigration
from bot_data.migration.level_migration import LevelMigration
from bot_data.migration.remove_stats_migration import RemoveStatsMigration
from bot_data.migration.short_role_name_migration import ShortRoleNameMigration
from bot_data.migration.short_role_name_only_highest_migration import ShortRoleNameOnlyHighestMigration
from bot_data.migration.short_role_name_only_highest_migration import (
ShortRoleNameOnlyHighestMigration,
)
from bot_data.migration.stats_migration import StatsMigration
from bot_data.migration.steam_special_offer_migration import SteamSpecialOfferMigration
from bot_data.migration.user_joined_game_server_migration import UserJoinedGameServerMigration
from bot_data.migration.user_joined_game_server_migration import (
UserJoinedGameServerMigration,
)
from bot_data.migration.user_message_count_per_hour_migration import (
UserMessageCountPerHourMigration,
)
@ -35,30 +41,66 @@ class StartupMigrationExtension(StartupExtensionABC):
def __init__(self):
pass
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
def configure_configuration(
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
):
pass
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
def configure_services(
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
):
services.add_transient(MigrationService)
services.add_transient(MigrationABC, InitialMigration)
services.add_transient(MigrationABC, AutoRoleMigration) # 03.10.2022 #54 - 0.2.2
services.add_transient(
MigrationABC, AutoRoleMigration
) # 03.10.2022 #54 - 0.2.2
services.add_transient(MigrationABC, ApiMigration) # 15.10.2022 #70 - 0.3.0
services.add_transient(MigrationABC, LevelMigration) # 06.11.2022 #25 - 0.3.0
services.add_transient(MigrationABC, StatsMigration) # 09.11.2022 #46 - 0.3.0
services.add_transient(MigrationABC, AutoRoleFix1Migration) # 30.12.2022 #151 - 0.3.0
services.add_transient(MigrationABC, UserMessageCountPerHourMigration) # 11.01.2023 #168 - 0.3.1
services.add_transient(
MigrationABC, AutoRoleFix1Migration
) # 30.12.2022 #151 - 0.3.0
services.add_transient(
MigrationABC, UserMessageCountPerHourMigration
) # 11.01.2023 #168 - 0.3.1
services.add_transient(MigrationABC, ApiKeyMigration) # 09.02.2023 #162 - 1.0.0
services.add_transient(MigrationABC, UserJoinedGameServerMigration) # 12.02.2023 #181 - 1.0.0
services.add_transient(MigrationABC, RemoveStatsMigration) # 19.02.2023 #190 - 1.0.0
services.add_transient(MigrationABC, UserWarningMigration) # 21.02.2023 #35 - 1.0.0
services.add_transient(MigrationABC, DBHistoryMigration) # 06.03.2023 #246 - 1.0.0
services.add_transient(MigrationABC, AchievementsMigration) # 14.06.2023 #268 - 1.1.0
services.add_transient(
MigrationABC, UserJoinedGameServerMigration
) # 12.02.2023 #181 - 1.0.0
services.add_transient(
MigrationABC, RemoveStatsMigration
) # 19.02.2023 #190 - 1.0.0
services.add_transient(
MigrationABC, UserWarningMigration
) # 21.02.2023 #35 - 1.0.0
services.add_transient(
MigrationABC, DBHistoryMigration
) # 06.03.2023 #246 - 1.0.0
services.add_transient(
MigrationABC, AchievementsMigration
) # 14.06.2023 #268 - 1.1.0
services.add_transient(MigrationABC, ConfigMigration) # 19.07.2023 #127 - 1.1.0
services.add_transient(MigrationABC, ConfigFeatureFlagsMigration) # 15.08.2023 #334 - 1.1.0
services.add_transient(MigrationABC, DefaultRoleMigration) # 24.09.2023 #360 - 1.1.3
services.add_transient(MigrationABC, ShortRoleNameMigration) # 28.09.2023 #378 - 1.1.7
services.add_transient(MigrationABC, FixUpdatesMigration) # 28.09.2023 #378 - 1.1.7
services.add_transient(MigrationABC, ShortRoleNameOnlyHighestMigration) # 02.10.2023 #391 - 1.1.9
services.add_transient(MigrationABC, FixUserHistoryMigration) # 10.10.2023 #401 - 1.2.0
services.add_transient(MigrationABC, BirthdayMigration) # 10.10.2023 #401 - 1.2.0
services.add_transient(MigrationABC, SteamSpecialOfferMigration) # 10.10.2023 #188 - 1.2.0
services.add_transient(
MigrationABC, ConfigFeatureFlagsMigration
) # 15.08.2023 #334 - 1.1.0
services.add_transient(
MigrationABC, DefaultRoleMigration
) # 24.09.2023 #360 - 1.1.3
services.add_transient(
MigrationABC, ShortRoleNameMigration
) # 28.09.2023 #378 - 1.1.7
services.add_transient(
MigrationABC, FixUpdatesMigration
) # 28.09.2023 #378 - 1.1.7
services.add_transient(
MigrationABC, ShortRoleNameOnlyHighestMigration
) # 02.10.2023 #391 - 1.1.9
services.add_transient(
MigrationABC, FixUserHistoryMigration
) # 10.10.2023 #401 - 1.2.0
services.add_transient(
MigrationABC, BirthdayMigration
) # 10.10.2023 #401 - 1.2.0
services.add_transient(
MigrationABC, SteamSpecialOfferMigration
) # 10.10.2023 #188 - 1.2.0

View File

@ -18,11 +18,15 @@ class StartupModuleExtension(StartupExtensionABC):
self._modules = ModuleList.get_modules()
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
def configure_configuration(
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
):
self._config = config
self._feature_flags = config.get_configuration(FeatureFlagsSettings)
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
def configure_services(
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
):
provider = services.build_service_provider()
dc_collection: DiscordCollectionABC = provider.get_service(DiscordCollectionABC)

View File

@ -14,26 +14,38 @@ class StartupSettingsExtension(StartupExtensionABC):
def __init__(self):
self._start_time = datetime.now()
def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironmentABC):
def configure_configuration(
self, configuration: ConfigurationABC, environment: ApplicationEnvironmentABC
):
# this shit has to be done here because we need settings in subsequent startup extensions
environment.set_working_directory(os.path.dirname(os.path.realpath(__file__)))
configuration.add_environment_variables("KDB_")
configuration.add_environment_variables("DISCORD_")
configuration.add_json_file(f"config/appsettings.json", optional=False)
configuration.add_json_file(f"config/appsettings.{environment.environment_name}.json", optional=True)
configuration.add_json_file(f"config/appsettings.{environment.host_name}.json", optional=True)
configuration.add_json_file(
f"config/appsettings.{environment.environment_name}.json", optional=True
)
configuration.add_json_file(
f"config/appsettings.{environment.host_name}.json", optional=True
)
# load feature-flags
configuration.add_json_file(f"config/feature-flags.json", optional=False)
configuration.add_json_file(f"config/feature-flags.{environment.environment_name}.json", optional=True)
configuration.add_json_file(f"config/feature-flags.{environment.host_name}.json", optional=True)
configuration.add_json_file(
f"config/feature-flags.{environment.environment_name}.json", optional=True
)
configuration.add_json_file(
f"config/feature-flags.{environment.host_name}.json", optional=True
)
configuration.add_configuration("Startup_StartTime", str(self._start_time))
self._configure_settings_with_sub_settings(
configuration, BotLoggingSettings, lambda x: x.files, lambda x: x.key
)
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
def configure_services(
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
):
pass
@staticmethod
@ -45,4 +57,6 @@ class StartupSettingsExtension(StartupExtensionABC):
return
for sub_settings in list_atr(settings):
config.add_configuration(f"{type(sub_settings).__name__}_{atr(sub_settings)}", sub_settings)
config.add_configuration(
f"{type(sub_settings).__name__}_{atr(sub_settings)}", sub_settings
)

View File

@ -40,11 +40,15 @@ class AuthServiceABC(ABC):
pass
@abstractmethod
async def get_filtered_auth_users_async(self, criteria: AuthUserSelectCriteria) -> AuthUserFilteredResultDTO:
async def get_filtered_auth_users_async(
self, criteria: AuthUserSelectCriteria
) -> AuthUserFilteredResultDTO:
pass
@abstractmethod
async def get_auth_user_by_email_async(self, email: str, with_password: bool = False) -> AuthUserDTO:
async def get_auth_user_by_email_async(
self, email: str, with_password: bool = False
) -> AuthUserDTO:
pass
@abstractmethod

View File

@ -3,7 +3,9 @@ from abc import ABC, abstractmethod
class SelectCriteriaABC(ABC):
@abstractmethod
def __init__(self, page_index: int, page_size: int, sort_direction: str, sort_column: str):
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

View File

@ -57,7 +57,9 @@ class Api(Flask):
# Added async_mode see link below
# https://github.com/miguelgrinberg/Flask-SocketIO/discussions/1849
# https://stackoverflow.com/questions/39370848/flask-socket-io-sometimes-client-calls-freeze-the-server
self._socketio = SocketIO(self, cors_allowed_origins="*", path="/api/socket.io", async_mode="eventlet")
self._socketio = SocketIO(
self, cors_allowed_origins="*", path="/api/socket.io", async_mode="eventlet"
)
self._socketio.on_event("connect", self.on_connect)
self._socketio.on_event("disconnect", self.on_disconnect)
@ -143,19 +145,26 @@ class Api(Flask):
data = request.get_data()
data = "" if len(data) == 0 else str(data.decode(encoding="utf-8"))
text = textwrap.dedent(f"Request: {request_id}:\n\tHeader:\n\t\t{headers}\n\tResponse: {data}")
text = textwrap.dedent(
f"Request: {request_id}:\n\tHeader:\n\t\t{headers}\n\tResponse: {data}"
)
self._logger.trace(__name__, text)
return response
def start(self):
self._logger.info(__name__, f"Starting API {self._api_settings.host}:{self._api_settings.port}")
self._logger.info(
__name__,
f"Starting API {self._api_settings.host}:{self._api_settings.port}",
)
self._register_routes()
self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key)
# from waitress import serve
# https://docs.pylonsproject.org/projects/waitress/en/stable/arguments.html
# serve(self, host=self._apt_settings.host, port=self._apt_settings.port, threads=10, connection_limit=1000, channel_timeout=10)
self._socket = eventlet.listen((self._api_settings.host, self._api_settings.port))
self._socket = eventlet.listen(
(self._api_settings.host, self._api_settings.port)
)
wsgi.server(self._socket, self, log_output=False)
def stop(self):

View File

@ -26,15 +26,21 @@ class ApiModule(ModuleABC):
def __init__(self, dc: DiscordCollectionABC):
ModuleABC.__init__(self, dc, FeatureFlagsEnum.api_module)
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
def configure_configuration(
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
):
cwd = env.working_directory
env.set_working_directory(os.path.dirname(os.path.realpath(__file__)))
config.add_json_file(f"config/apisettings.json", optional=False)
config.add_json_file(f"config/apisettings.{env.environment_name}.json", optional=True)
config.add_json_file(
f"config/apisettings.{env.environment_name}.json", optional=True
)
config.add_json_file(f"config/apisettings.{env.host_name}.json", optional=True)
env.set_working_directory(cwd)
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
def configure_services(
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
):
services.add_singleton(EMailClientABC, EMailClient)
services.add_singleton(ApiThread)

View File

@ -12,7 +12,9 @@ class AppApiExtension(ApplicationExtensionABC):
ApplicationExtensionABC.__init__(self)
async def run(self, config: ConfigurationABC, services: ServiceProviderABC):
feature_flags: FeatureFlagsSettings = config.get_configuration(FeatureFlagsSettings)
feature_flags: FeatureFlagsSettings = config.get_configuration(
FeatureFlagsSettings
)
if not feature_flags.get_flag(FeatureFlagsEnum.api_module):
return

View File

@ -16,7 +16,9 @@ class AuthenticationSettings(ConfigurationModelABC):
self._issuer = "" if issuer is None else issuer
self._audience = "" if audience is None else audience
self._token_expire_time = 0 if token_expire_time is None else token_expire_time
self._refresh_token_expire_time = 0 if refresh_token_expire_time is None else refresh_token_expire_time
self._refresh_token_expire_time = (
0 if refresh_token_expire_time is None else refresh_token_expire_time
)
@property
def secret_key(self) -> str:

View File

@ -70,7 +70,9 @@ class AuthController:
@Route.post(f"{BasePath}/register")
async def register(self):
dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True))
dto: AuthUserDTO = JSONProcessor.process(
AuthUserDTO, request.get_json(force=True, silent=True)
)
self._auth_service.add_auth_user(dto)
return "", 200
@ -81,7 +83,9 @@ class AuthController:
@Route.post(f"{BasePath}/login")
async def login(self) -> Response:
dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True))
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())
@ -110,40 +114,52 @@ class AuthController:
@Route.post(f"{BasePath}/reset-password")
async def reset_password(self):
dto: ResetPasswordDTO = JSONProcessor.process(ResetPasswordDTO, request.get_json(force=True, silent=True))
dto: ResetPasswordDTO = JSONProcessor.process(
ResetPasswordDTO, request.get_json(force=True, silent=True)
)
await self._auth_service.reset_password_async(dto)
return "", 200
@Route.post(f"{BasePath}/update-user")
@Route.authorize
async def update_user(self):
dto: UpdateAuthUserDTO = JSONProcessor.process(UpdateAuthUserDTO, request.get_json(force=True, silent=True))
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")
@Route.authorize(role=AuthRoleEnum.admin)
async def update_user_as_admin(self):
dto: UpdateAuthUserDTO = JSONProcessor.process(UpdateAuthUserDTO, request.get_json(force=True, silent=True))
dto: UpdateAuthUserDTO = JSONProcessor.process(
UpdateAuthUserDTO, request.get_json(force=True, silent=True)
)
await self._auth_service.update_user_as_admin_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))
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))
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")
@Route.authorize(role=AuthRoleEnum.admin)
async def delete_user(self):
dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True))
dto: AuthUserDTO = JSONProcessor.process(
AuthUserDTO, request.get_json(force=True, silent=True)
)
await self._auth_service.delete_auth_user_async(dto)
return "", 200

View File

@ -13,7 +13,9 @@ class AuthUserSelectCriteria(SelectCriteriaABC):
email: str,
auth_role: int,
):
SelectCriteriaABC.__init__(self, page_index, page_size, sort_direction, sort_column)
SelectCriteriaABC.__init__(
self, page_index, page_size, sort_direction, sort_column
)
self.first_name = first_name
self.last_name = last_name

View File

@ -10,6 +10,8 @@ class ServerSelectCriteria(SelectCriteriaABC):
sort_column: str,
name: str,
):
SelectCriteriaABC.__init__(self, page_index, page_size, sort_direction, sort_column)
SelectCriteriaABC.__init__(
self, page_index, page_size, sort_direction, sort_column
)
self.name = name

View File

@ -11,7 +11,9 @@ class ErrorDTO(DtoABC):
def __init__(self, error_code: Optional[ServiceErrorCode], message: str):
DtoABC.__init__(self)
self._error_code = ServiceErrorCode.Unknown if error_code is None else error_code
self._error_code = (
ServiceErrorCode.Unknown if error_code is None else error_code
)
self._message = message
@property

View File

@ -27,4 +27,8 @@ class TokenDTO(DtoABC):
self._first_login = values["firstLogin"]
def to_dict(self) -> dict:
return {"token": self._token, "refreshToken": self._refresh_token, "firstLogin": self._first_login}
return {
"token": self._token,
"refreshToken": self._refresh_token,
"firstLogin": self._first_login,
}

View File

@ -34,7 +34,9 @@ class UpdateAuthUserDTO(DtoABC):
def from_dict(self, values: dict):
self._auth_user = AuthUserDTO().from_dict(values["authUser"])
self._new_auth_user = AuthUserDTO().from_dict(values["newAuthUser"])
self._change_password = False if "changePassword" not in values else bool(values["changePassword"])
self._change_password = (
False if "changePassword" not in values else bool(values["changePassword"])
)
def to_dict(self) -> dict:
return {

View File

@ -25,7 +25,12 @@ class Route:
@classmethod
@ServiceProviderABC.inject
def init_authorize(cls, env: ApplicationEnvironmentABC, auth_users: AuthUserRepositoryABC, auth: AuthServiceABC):
def init_authorize(
cls,
env: ApplicationEnvironmentABC,
auth_users: AuthUserRepositoryABC,
auth: AuthServiceABC,
):
cls._auth_users = auth_users
cls._auth = auth
cls._env = env.environment_name
@ -52,9 +57,17 @@ class Route:
return user
@classmethod
def authorize(cls, f: Callable = None, role: AuthRoleEnum = None, skip_in_dev=False, by_api_key=False):
def authorize(
cls,
f: Callable = None,
role: AuthRoleEnum = None,
skip_in_dev=False,
by_api_key=False,
):
if f is None:
return functools.partial(cls.authorize, role=role, skip_in_dev=skip_in_dev, by_api_key=by_api_key)
return functools.partial(
cls.authorize, role=role, skip_in_dev=skip_in_dev, by_api_key=by_api_key
)
@wraps(f)
async def decorator(*args, **kwargs):
@ -65,7 +78,9 @@ class Route:
api_key = None
if "Authorization" in request.headers:
if " " not in request.headers.get("Authorization"):
ex = ServiceException(ServiceErrorCode.Unauthorized, f"Token not set")
ex = ServiceException(
ServiceErrorCode.Unauthorized, f"Token not set"
)
error = ErrorDTO(ex.error_code, ex.message)
return jsonify(error.to_dict()), 401
@ -87,7 +102,9 @@ class Route:
return jsonify(e), 500
if not valid:
ex = ServiceException(ServiceErrorCode.Unauthorized, f"API-Key invalid")
ex = ServiceException(
ServiceErrorCode.Unauthorized, f"API-Key invalid"
)
error = ErrorDTO(ex.error_code, ex.message)
return jsonify(error.to_dict()), 401
@ -99,7 +116,9 @@ class Route:
return jsonify(error.to_dict()), 401
if cls._auth_users is None or cls._auth is None:
ex = ServiceException(ServiceErrorCode.Unauthorized, f"Authorize is not initialized")
ex = ServiceException(
ServiceErrorCode.Unauthorized, f"Authorize is not initialized"
)
error = ErrorDTO(ex.error_code, ex.message)
return jsonify(error.to_dict()), 401
@ -121,7 +140,9 @@ class Route:
return jsonify(error.to_dict()), 401
if role is not None and user.auth_role.value < role.value:
ex = ServiceException(ServiceErrorCode.Unauthorized, f"Role {role} required")
ex = ServiceException(
ServiceErrorCode.Unauthorized, f"Role {role} required"
)
error = ErrorDTO(ex.error_code, ex.message)
return jsonify(error.to_dict()), 403

View File

@ -90,7 +90,9 @@ class AuthService(AuthServiceABC):
def _get_api_key_str(self, api_key: ApiKey) -> str:
return hashlib.sha256(
f"{api_key.identifier}:{api_key.key}+{self._auth_settings.secret_key}".encode("utf-8")
f"{api_key.identifier}:{api_key.key}+{self._auth_settings.secret_key}".encode(
"utf-8"
)
).hexdigest()
def generate_token(self, user: AuthUser) -> str:
@ -99,7 +101,8 @@ class AuthService(AuthServiceABC):
"user_id": user.id,
"email": user.email,
"role": user.auth_role.value,
"exp": datetime.now(tz=timezone.utc) + timedelta(days=self._auth_settings.token_expire_time),
"exp": datetime.now(tz=timezone.utc)
+ timedelta(days=self._auth_settings.token_expire_time),
"iss": self._auth_settings.issuer,
"aud": self._auth_settings.audience,
},
@ -155,7 +158,9 @@ class AuthService(AuthServiceABC):
def _create_and_save_refresh_token(self, user: AuthUser) -> str:
token = str(uuid.uuid4())
user.refresh_token = token
user.refresh_token_expire_time = datetime.now() + timedelta(days=self._auth_settings.refresh_token_expire_time)
user.refresh_token_expire_time = datetime.now() + timedelta(
days=self._auth_settings.refresh_token_expire_time
)
self._auth_users.update_auth_user(user)
self._db.save_changes()
return token
@ -188,8 +193,12 @@ class AuthService(AuthServiceABC):
self._send_link_mail(
user.email,
self._t.transform("api.auth.confirmation.subject").format(user.first_name, user.last_name),
self._t.transform("api.auth.confirmation.message").format(url, user.confirmation_id),
self._t.transform("api.auth.confirmation.subject").format(
user.first_name, user.last_name
),
self._t.transform("api.auth.confirmation.message").format(
url, user.confirmation_id
),
)
def _send_forgot_password_id_to_user(self, user: AuthUser):
@ -199,28 +208,38 @@ class AuthService(AuthServiceABC):
self._send_link_mail(
user.email,
self._t.transform("api.auth.forgot_password.subject").format(user.first_name, user.last_name),
self._t.transform("api.auth.forgot_password.message").format(url, user.forgot_password_id),
self._t.transform("api.auth.forgot_password.subject").format(
user.first_name, user.last_name
),
self._t.transform("api.auth.forgot_password.message").format(
url, user.forgot_password_id
),
)
async def get_all_auth_users_async(self) -> List[AuthUserDTO]:
result = self._auth_users.get_all_auth_users().select(lambda x: AUT.to_dto(x))
return List(AuthUserDTO, result)
async def get_filtered_auth_users_async(self, criteria: AuthUserSelectCriteria) -> AuthUserFilteredResultDTO:
async def get_filtered_auth_users_async(
self, criteria: AuthUserSelectCriteria
) -> AuthUserFilteredResultDTO:
users = self._auth_users.get_filtered_auth_users(criteria)
result = users.result.select(lambda x: AUT.to_dto(x))
return AuthUserFilteredResultDTO(List(AuthUserDTO, result), users.total_count)
async def get_auth_user_by_email_async(self, email: str, with_password: bool = False) -> AuthUserDTO:
async def get_auth_user_by_email_async(
self, email: str, with_password: bool = False
) -> AuthUserDTO:
try:
# todo: check if logged in user is admin then send mail
user = self._auth_users.get_auth_user_by_email(email)
return AUT.to_dto(user, password=user.password if with_password else None)
except Exception as e:
self._logger.error(__name__, f"AuthUser not found", e)
raise ServiceException(ServiceErrorCode.InvalidData, f"User not found {email}")
raise ServiceException(
ServiceErrorCode.InvalidData, f"User not found {email}"
)
async def find_auth_user_by_email_async(self, email: str) -> Optional[AuthUser]:
user = self._auth_users.find_auth_user_by_email(email)
@ -238,16 +257,22 @@ class AuthService(AuthServiceABC):
user.password_salt = uuid.uuid4()
user.password = self._hash_sha256(user_dto.password, user.password_salt)
if not self._is_email_valid(user.email):
raise ServiceException(ServiceErrorCode.InvalidData, "Invalid E-Mail address")
raise ServiceException(
ServiceErrorCode.InvalidData, "Invalid E-Mail address"
)
try:
user.confirmation_id = uuid.uuid4()
self._auth_users.add_auth_user(user)
self._send_confirmation_id_to_user(user)
self._db.save_changes()
self._logger.info(__name__, f"Added auth user with E-Mail: {user_dto.email}")
self._logger.info(
__name__, f"Added auth user with E-Mail: {user_dto.email}"
)
except Exception as e:
self._logger.error(__name__, f"Cannot add user with E-Mail {user_dto.email}", e)
self._logger.error(
__name__, f"Cannot add user with E-Mail {user_dto.email}", e
)
raise ServiceException(ServiceErrorCode.UnableToAdd, "Invalid E-Mail")
async def add_auth_user_by_oauth_async(self, dto: OAuthDTO):
@ -263,14 +288,20 @@ class AuthService(AuthServiceABC):
db_user.first_name = dto.user.first_name
db_user.last_name = dto.user.last_name
db_user.password_salt = uuid.uuid4()
db_user.password = self._hash_sha256(dto.user.password, db_user.password_salt)
db_user.password = self._hash_sha256(
dto.user.password, db_user.password_salt
)
db_user.oauth_id = None
db_user.confirmation_id = uuid.uuid4()
self._send_confirmation_id_to_user(db_user)
self._auth_users.update_auth_user(db_user)
self._logger.info(__name__, f"Added auth user with E-Mail: {dto.user.email}")
self._logger.info(
__name__, f"Added auth user with E-Mail: {dto.user.email}"
)
except Exception as e:
self._logger.error(__name__, f"Cannot add user with E-Mail {dto.user.email}", e)
self._logger.error(
__name__, f"Cannot add user with E-Mail {dto.user.email}", e
)
raise ServiceException(ServiceErrorCode.UnableToAdd, "Invalid E-Mail")
self._db.save_changes()
@ -280,14 +311,16 @@ class AuthService(AuthServiceABC):
raise ServiceException(ServiceErrorCode.InvalidData, f"User is empty")
if update_user_dto.auth_user is None:
raise ServiceException(ServiceErrorCode.InvalidData, f"Existing user is empty")
raise ServiceException(
ServiceErrorCode.InvalidData, f"Existing user is empty"
)
if update_user_dto.new_auth_user is None:
raise ServiceException(ServiceErrorCode.InvalidData, f"New user is empty")
if not self._is_email_valid(update_user_dto.auth_user.email) or not self._is_email_valid(
update_user_dto.new_auth_user.email
):
if not self._is_email_valid(
update_user_dto.auth_user.email
) or not self._is_email_valid(update_user_dto.new_auth_user.email):
raise ServiceException(ServiceErrorCode.InvalidData, f"Invalid E-Mail")
user = self._auth_users.find_auth_user_by_email(update_user_dto.auth_user.email)
@ -300,7 +333,8 @@ class AuthService(AuthServiceABC):
# update first name
if (
update_user_dto.new_auth_user.first_name is not None
and update_user_dto.auth_user.first_name != update_user_dto.new_auth_user.first_name
and update_user_dto.auth_user.first_name
!= update_user_dto.new_auth_user.first_name
):
user.first_name = update_user_dto.new_auth_user.first_name
@ -308,7 +342,8 @@ class AuthService(AuthServiceABC):
if (
update_user_dto.new_auth_user.last_name is not None
and update_user_dto.new_auth_user.last_name != ""
and update_user_dto.auth_user.last_name != update_user_dto.new_auth_user.last_name
and update_user_dto.auth_user.last_name
!= update_user_dto.new_auth_user.last_name
):
user.last_name = update_user_dto.new_auth_user.last_name
@ -318,22 +353,33 @@ class AuthService(AuthServiceABC):
and update_user_dto.new_auth_user.email != ""
and update_user_dto.auth_user.email != update_user_dto.new_auth_user.email
):
user_by_new_e_mail = self._auth_users.find_auth_user_by_email(update_user_dto.new_auth_user.email)
user_by_new_e_mail = self._auth_users.find_auth_user_by_email(
update_user_dto.new_auth_user.email
)
if user_by_new_e_mail is not None:
raise ServiceException(ServiceErrorCode.InvalidUser, "User already exists")
raise ServiceException(
ServiceErrorCode.InvalidUser, "User already exists"
)
user.email = update_user_dto.new_auth_user.email
update_user_dto.auth_user.password = self._hash_sha256(update_user_dto.auth_user.password, user.password_salt)
update_user_dto.auth_user.password = self._hash_sha256(
update_user_dto.auth_user.password, user.password_salt
)
if update_user_dto.auth_user.password != user.password:
raise ServiceException(ServiceErrorCode.InvalidUser, "Wrong password")
# update password
if (
update_user_dto.new_auth_user.password is not None
and self._hash_sha256(update_user_dto.new_auth_user.password, user.password_salt) != user.password
and self._hash_sha256(
update_user_dto.new_auth_user.password, user.password_salt
)
!= user.password
):
user.password_salt = uuid.uuid4()
user.password = self._hash_sha256(update_user_dto.new_auth_user.password, user.password_salt)
user.password = self._hash_sha256(
update_user_dto.new_auth_user.password, user.password_salt
)
self._auth_users.update_auth_user(user)
self._db.save_changes()
@ -343,23 +389,31 @@ class AuthService(AuthServiceABC):
raise ServiceException(ServiceErrorCode.InvalidData, f"User is empty")
if update_user_dto.auth_user is None:
raise ServiceException(ServiceErrorCode.InvalidData, f"Existing user is empty")
raise ServiceException(
ServiceErrorCode.InvalidData, f"Existing user is empty"
)
if update_user_dto.new_auth_user is None:
raise ServiceException(ServiceErrorCode.InvalidData, f"New user is empty")
if not self._is_email_valid(update_user_dto.auth_user.email) or not self._is_email_valid(
update_user_dto.new_auth_user.email
):
if not self._is_email_valid(
update_user_dto.auth_user.email
) or not self._is_email_valid(update_user_dto.new_auth_user.email):
raise ServiceException(ServiceErrorCode.InvalidData, f"Invalid E-Mail")
user = self._auth_users.find_auth_user_by_email(update_user_dto.auth_user.email)
if user is None:
raise ServiceException(ServiceErrorCode.InvalidUser, "User not found")
if user.confirmation_id is not None and update_user_dto.new_auth_user.is_confirmed:
if (
user.confirmation_id is not None
and update_user_dto.new_auth_user.is_confirmed
):
user.confirmation_id = None
elif user.confirmation_id is None and not update_user_dto.new_auth_user.is_confirmed:
elif (
user.confirmation_id is None
and not update_user_dto.new_auth_user.is_confirmed
):
user.confirmation_id = uuid.uuid4()
# else
# raise ServiceException(ServiceErrorCode.InvalidUser, 'E-Mail not confirmed')
@ -367,7 +421,8 @@ class AuthService(AuthServiceABC):
# update first name
if (
update_user_dto.new_auth_user.first_name is not None
and update_user_dto.auth_user.first_name != update_user_dto.new_auth_user.first_name
and update_user_dto.auth_user.first_name
!= update_user_dto.new_auth_user.first_name
):
user.first_name = update_user_dto.new_auth_user.first_name
@ -375,7 +430,8 @@ class AuthService(AuthServiceABC):
if (
update_user_dto.new_auth_user.last_name is not None
and update_user_dto.new_auth_user.last_name != ""
and update_user_dto.auth_user.last_name != update_user_dto.new_auth_user.last_name
and update_user_dto.auth_user.last_name
!= update_user_dto.new_auth_user.last_name
):
user.last_name = update_user_dto.new_auth_user.last_name
@ -385,19 +441,28 @@ class AuthService(AuthServiceABC):
and update_user_dto.new_auth_user.email != ""
and update_user_dto.auth_user.email != update_user_dto.new_auth_user.email
):
user_by_new_e_mail = self._auth_users.find_auth_user_by_email(update_user_dto.new_auth_user.email)
user_by_new_e_mail = self._auth_users.find_auth_user_by_email(
update_user_dto.new_auth_user.email
)
if user_by_new_e_mail is not None:
raise ServiceException(ServiceErrorCode.InvalidUser, "User already exists")
raise ServiceException(
ServiceErrorCode.InvalidUser, "User already exists"
)
user.email = update_user_dto.new_auth_user.email
# update password
if (
update_user_dto.new_auth_user.password is not None
and update_user_dto.change_password
and user.password != self._hash_sha256(update_user_dto.new_auth_user.password, user.password_salt)
and user.password
!= self._hash_sha256(
update_user_dto.new_auth_user.password, user.password_salt
)
):
user.password_salt = uuid.uuid4()
user.password = self._hash_sha256(update_user_dto.new_auth_user.password, user.password_salt)
user.password = self._hash_sha256(
update_user_dto.new_auth_user.password, user.password_salt
)
# update role
if (
@ -416,7 +481,9 @@ class AuthService(AuthServiceABC):
self._db.save_changes()
except Exception as e:
self._logger.error(__name__, f"Cannot delete user", e)
raise ServiceException(ServiceErrorCode.UnableToDelete, f"Cannot delete user by mail {email}")
raise ServiceException(
ServiceErrorCode.UnableToDelete, f"Cannot delete user by mail {email}"
)
async def delete_auth_user_async(self, user_dto: AuthUser):
try:
@ -500,7 +567,9 @@ class AuthService(AuthServiceABC):
if user.id in user_ids:
continue
self._auth_users.add_auth_user_user_rel(AuthUserUsersRelation(db_user, user))
self._auth_users.add_auth_user_user_rel(
AuthUserUsersRelation(db_user, user)
)
if db_user.confirmation_id is not None and not added_user:
raise ServiceException(ServiceErrorCode.Forbidden, "E-Mail not verified")
@ -530,13 +599,19 @@ class AuthService(AuthServiceABC):
):
raise ServiceException(ServiceErrorCode.InvalidData, "Token expired")
return TokenDTO(self.generate_token(user), self._create_and_save_refresh_token(user))
return TokenDTO(
self.generate_token(user), self._create_and_save_refresh_token(user)
)
except Exception as e:
self._logger.error(__name__, f"Refreshing token failed", e)
return TokenDTO("", "")
async def revoke_async(self, token_dto: TokenDTO):
if token_dto is None or token_dto.token is None or token_dto.refresh_token is None:
if (
token_dto is None
or token_dto.token is None
or token_dto.refresh_token is None
):
raise ServiceException(ServiceErrorCode.InvalidData, "Token not set")
try:
@ -589,7 +664,9 @@ class AuthService(AuthServiceABC):
)
if user.confirmation_id is not None:
raise ServiceException(ServiceErrorCode.InvalidUser, f"E-Mail not confirmed")
raise ServiceException(
ServiceErrorCode.InvalidUser, f"E-Mail not confirmed"
)
if user.password is None or rp_dto.password == "":
raise ServiceException(ServiceErrorCode.InvalidData, f"Password not set")

View File

@ -53,13 +53,17 @@ class DiscordService:
if role != AuthRoleEnum.admin:
auth_user = self._auth_users.find_auth_user_by_email(token["email"])
if auth_user is not None:
user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.id)
user_ids = auth_user.users.select(
lambda x: x.server is not None and x.server.id
)
servers = servers.where(lambda x: x.id in user_ids)
servers = List(ServerDTO, servers)
return servers.select(self._to_dto).where(lambda x: x.name != "")
async def get_filtered_servers_async(self, criteria: ServerSelectCriteria) -> ServerFilteredResultDTO:
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")
@ -70,15 +74,22 @@ class DiscordService:
if role != AuthRoleEnum.admin:
auth_user = self._auth_users.find_auth_user_by_email(token["email"])
if auth_user is not None:
user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.id)
filtered_result.result = filtered_result.result.where(lambda x: x.id in user_ids)
user_ids = auth_user.users.select(
lambda x: x.server is not None and x.server.id
)
filtered_result.result = filtered_result.result.where(
lambda x: x.id in user_ids
)
servers: List = filtered_result.result.select(self._to_dto).where(lambda x: x.name != "")
servers: List = filtered_result.result.select(self._to_dto).where(
lambda x: x.name != ""
)
result = List(ServerDTO, servers)
if criteria.name is not None and criteria.name != "":
result = result.where(
lambda x: criteria.name.lower() in x.name.lower() or x.name.lower() == criteria.name.lower()
lambda x: criteria.name.lower() in x.name.lower()
or x.name.lower() == criteria.name.lower()
)
return ServerFilteredResultDTO(List(ServerDTO, result), servers.count())
@ -87,5 +98,7 @@ class DiscordService:
server = self._servers.get_server_by_id(id)
guild = self._bot.get_guild(server.discord_id)
server_dto = ServerTransformer.to_dto(server, guild.name, guild.member_count, guild.icon)
server_dto = ServerTransformer.to_dto(
server, guild.name, guild.member_count, guild.icon
)
return server_dto

View File

@ -27,27 +27,35 @@ class AuthUserTransformer(TransformerABC):
None,
None,
datetime.now(),
AuthRoleEnum.normal if dto.auth_role is None else AuthRoleEnum(dto.auth_role),
AuthRoleEnum.normal
if dto.auth_role is None
else AuthRoleEnum(dto.auth_role),
auth_user_id=0 if dto.id is None else dto.id,
)
@staticmethod
@ServiceProviderABC.inject
def _is_technician(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC):
def _is_technician(
user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC
):
guild = bot.get_guild(user.server.discord_id)
member = guild.get_member(user.discord_id)
return permissions.is_member_technician(member)
@staticmethod
@ServiceProviderABC.inject
def _is_admin(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC):
def _is_admin(
user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC
):
guild = bot.get_guild(user.server.discord_id)
member = guild.get_member(user.discord_id)
return permissions.is_member_admin(member)
@staticmethod
@ServiceProviderABC.inject
def _is_moderator(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC):
def _is_moderator(
user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC
):
guild = bot.get_guild(user.server.discord_id)
member = guild.get_member(user.discord_id)
return permissions.is_member_moderator(member)

View File

@ -13,7 +13,9 @@ class ServerTransformer(TransformerABC):
return Server(dto.discord_id)
@staticmethod
def to_dto(db: Server, name: str, member_count: int, icon_url: Optional[discord.Asset]) -> ServerDTO:
def to_dto(
db: Server, name: str, member_count: int, icon_url: Optional[discord.Asset]
) -> ServerDTO:
return ServerDTO(
db.id,
db.discord_id,

View File

@ -45,7 +45,9 @@ class ClientUtilsABC(ABC):
pass
@abstractmethod
def get_auto_complete_list(self, _l: List, current: str, select: Callable = None) -> List:
def get_auto_complete_list(
self, _l: List, current: str, select: Callable = None
) -> List:
pass
@abstractmethod
@ -64,7 +66,11 @@ class ClientUtilsABC(ABC):
@abstractmethod
async def react_to_message_by_auto_role_rule(
self, discord_channel_id: int, discord_message_id: int, rule: AutoRoleRule, guild: discord.Guild
self,
discord_channel_id: int,
discord_message_id: int,
rule: AutoRoleRule,
guild: discord.Guild,
):
pass

View File

@ -18,7 +18,9 @@ class CustomFileLoggerABC(Logger, ABC):
env: ApplicationEnvironmentABC,
):
self._key = key
self._settings: LoggingSettings = config.get_configuration(f"{FileLoggingSettings.__name__}_{key}")
self._settings: LoggingSettings = config.get_configuration(
f"{FileLoggingSettings.__name__}_{key}"
)
Logger.__init__(self, self._settings, time_format, env)
self._begin_log()
@ -32,7 +34,9 @@ class CustomFileLoggerABC(Logger, ABC):
self.info(__name__, f"Starting...")
self._console = LoggingLevelEnum(console_level)
def _get_string(self, name_list_as_str: str, level: LoggingLevelEnum, message: str) -> str:
def _get_string(
self, name_list_as_str: str, level: LoggingLevelEnum, message: str
) -> str:
names = name_list_as_str.split(" ")
log_level = level.name
string = f"<{self._get_datetime_now()}> [ {log_level} ]"

View File

@ -13,7 +13,9 @@ class MessageServiceABC(ABC):
pass
@abstractmethod
async def delete_messages(self, messages: List[discord.Message], guild_id: int, without_tracking=False):
async def delete_messages(
self, messages: List[discord.Message], guild_id: int, without_tracking=False
):
pass
@abstractmethod

View File

@ -15,7 +15,9 @@ class TaskABC(commands.Cog):
commands.Cog.__init__(self)
@ServiceProviderABC.inject
async def _wait_until_ready(self, config: ConfigurationABC, logger: TaskLogger, bot: DiscordBotServiceABC):
async def _wait_until_ready(
self, config: ConfigurationABC, logger: TaskLogger, bot: DiscordBotServiceABC
):
logger.debug(__name__, f"Waiting before {type(self).__name__}")
await bot.wait_until_ready()

View File

@ -10,7 +10,9 @@ class FileLoggingSettings(LoggingSettings):
console_log_level: LoggingLevelEnum = None,
file_log_level: LoggingLevelEnum = None,
):
LoggingSettings.__init__(self, path, filename, console_log_level, file_log_level)
LoggingSettings.__init__(
self, path, filename, console_log_level, file_log_level
)
self._key = key

View File

@ -17,7 +17,9 @@ class CoreExtension(ApplicationExtensionABC):
ApplicationExtensionABC.__init__(self)
async def run(self, config: ConfigurationABC, services: ServiceProviderABC):
feature_flags: FeatureFlagsSettings = config.get_configuration(FeatureFlagsSettings)
feature_flags: FeatureFlagsSettings = config.get_configuration(
FeatureFlagsSettings
)
if not feature_flags.get_flag(FeatureFlagsEnum.core_module):
return

View File

@ -15,8 +15,14 @@ class CoreExtensionModule(ModuleABC):
def __init__(self, dc: DiscordCollectionABC):
ModuleABC.__init__(self, dc, FeatureFlagsEnum.core_extension_module)
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
def configure_configuration(
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
):
pass
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
services.add_transient(DiscordEventTypesEnum.on_ready.value, CoreExtensionOnReadyEvent)
def configure_services(
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
):
services.add_transient(
DiscordEventTypesEnum.on_ready.value, CoreExtensionOnReadyEvent
)

View File

@ -20,10 +20,14 @@ class CoreModule(ModuleABC):
def __init__(self, dc: DiscordCollectionABC):
ModuleABC.__init__(self, dc, FeatureFlagsEnum.core_module)
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
def configure_configuration(
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
):
pass
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
def configure_services(
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
):
services.add_transient(ConfigService)
services.add_transient(MessageServiceABC, MessageService)
services.add_transient(ClientUtilsABC, ClientUtilsService)

View File

@ -44,7 +44,9 @@ class CommandChecks:
async def check_is_member_admin(ctx: Context):
has_permission = cls._permissions.is_member_admin(ctx.author)
if not has_permission:
await cls._message_service.send_ctx_msg(ctx, cls._t.transform("common.no_permission_message"))
await cls._message_service.send_ctx_msg(
ctx, cls._t.transform("common.no_permission_message")
)
raise CheckError(f"Member {ctx.author.name} is not admin")
return has_permission
@ -56,7 +58,9 @@ class CommandChecks:
async def check_is_member_technician(ctx: Context):
has_permission = cls._permissions.is_member_technician(ctx.author)
if not has_permission:
await cls._message_service.send_ctx_msg(ctx, cls._t.transform("common.no_permission_message"))
await cls._message_service.send_ctx_msg(
ctx, cls._t.transform("common.no_permission_message")
)
raise CheckError(f"Member {ctx.author.name} is not technician")
return has_permission
@ -68,7 +72,9 @@ class CommandChecks:
async def check_is_member_moderator(ctx: Context):
has_permission = cls._permissions.is_member_moderator(ctx.author)
if not has_permission:
await cls._message_service.send_ctx_msg(ctx, cls._t.transform("common.no_permission_message"))
await cls._message_service.send_ctx_msg(
ctx, cls._t.transform("common.no_permission_message")
)
raise CheckError(f"Member {ctx.author.name} is not moderator")
return has_permission

Some files were not shown because too many files have changed in this diff Show More