Compare commits
67 Commits
1.1.7
...
dd6b609094
Author | SHA1 | Date | |
---|---|---|---|
dd6b609094 | |||
3810dec927 | |||
a87380f6f8 | |||
98ac7835b6 | |||
0a76068604 | |||
f9caf59180 | |||
284318bb10 | |||
6130cac6fe | |||
3a64c51600 | |||
90fce5a79a | |||
d448ad7707 | |||
19791ff9d8 | |||
3cba8de675 | |||
b7ff070676 | |||
c88e07d743 | |||
f5b978b231 | |||
0e2b7d03fc | |||
c7f5ab0161 | |||
01e8e4256d | |||
75adc2285e | |||
9e12d84ba0 | |||
d3b503d3ef | |||
dd86c3a657 | |||
aba6e48e2b | |||
73848c3141 | |||
33d6015088 | |||
7e962e05f6 | |||
c73c6876b2 | |||
8e949c3e1a | |||
472a76d563 | |||
f5d88ec94c | |||
2182c021b9 | |||
a9c9880fd4 | |||
d91c76467d | |||
2f10ace27f | |||
3b79a61bb6 | |||
ef0fab1178 | |||
189b6370a9 | |||
0ed93c56d0 | |||
4d18dd3845 | |||
7b7cbb20db | |||
84c2f5c2c4 | |||
c85c6df784 | |||
d5d898fa07 | |||
ef5ebabf81 | |||
f89b4c4ef5 | |||
8b277a2d19 | |||
a84e77e055 | |||
892c983e1e | |||
1d3809c986 | |||
3117f617d9 | |||
7e6053768f | |||
3d9cd0a2fc | |||
8d90768594 | |||
7e8a9482d4 | |||
bf7d29e6ab | |||
608001e0e1 | |||
0dd9558f33 | |||
7acd850e68 | |||
ecd3ea96b1 | |||
d869bcfd3a | |||
818e021761 | |||
b286322247 | |||
661b057e85 | |||
25137c6923 | |||
74f3ee2f08 | |||
2e0c1babe4 |
17
.gitea/issue_template.md
Normal file
17
.gitea/issue_template.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#### Beschreibung
|
||||||
|
|
||||||
|
Als Produktmanager muss ich nun dieses Ticket ausfüllen.
|
||||||
|
|
||||||
|
#### Aktuelles Verhalten
|
||||||
|
|
||||||
|
* Was macht die Software aktuell?
|
||||||
|
|
||||||
|
#### Gewünschtes Verhalten
|
||||||
|
|
||||||
|
* Was soll die Software anders machen?
|
||||||
|
|
||||||
|
#### Akzeptanzkriterien
|
||||||
|
|
||||||
|
* Was muss erfüllt sein, damit das Ticket als abgeschlossen angesehen werden kann?
|
||||||
|
|
||||||
|
#### Anmerkungen
|
7
.gitea/pull_request_template.md
Normal file
7
.gitea/pull_request_template.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#### Ticket Referenz:
|
||||||
|
|
||||||
|
#1
|
||||||
|
|
||||||
|
#### Gibt es etwas beim Review zu beachten?
|
||||||
|
|
||||||
|
Nein
|
@@ -3,7 +3,7 @@ run-name: Deploy dev on push
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- support
|
- dev
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
on-push-deploy_sh-edraft:
|
on-push-deploy_sh-edraft:
|
18
.gitmodules
vendored
18
.gitmodules
vendored
@@ -1,9 +1,9 @@
|
|||||||
[submodule "kdb-bot/src/bot/config"]
|
[submodule "bot/src/bot/config"]
|
||||||
path = kdb-bot/src/bot/config
|
path = bot/src/bot/config
|
||||||
url = https://git.sh-edraft.de/sh-edraft.de/kd_discord_bot.config.git
|
url = https://git.sh-edraft.de/sh-edraft.de/sh_discord_bot.config.git
|
||||||
[submodule "kdb-bot/src/bot_api/config"]
|
[submodule "bot/src/bot_api/config"]
|
||||||
path = kdb-bot/src/bot_api/config
|
path = bot/src/bot_api/config
|
||||||
url = https://git.sh-edraft.de/sh-edraft.de/kd_discord_bot.api.config.git
|
url = https://git.sh-edraft.de/sh-edraft.de/sh_discord_bot.api.config.git
|
||||||
[submodule "kdb-bot/docker"]
|
[submodule "bot/docker"]
|
||||||
path = kdb-bot/docker
|
path = bot/docker
|
||||||
url = https://git.sh-edraft.de/sh-edraft.de/kd_discord_bot.docker.git
|
url = https://git.sh-edraft.de/sh-edraft.de/sh_discord_bot.docker.git
|
||||||
|
@@ -16,7 +16,8 @@
|
|||||||
"level": "src/modules/level/level.json",
|
"level": "src/modules/level/level.json",
|
||||||
"permission": "src/modules/permission/permission.json",
|
"permission": "src/modules/permission/permission.json",
|
||||||
"technician": "src/modules/technician/technician.json",
|
"technician": "src/modules/technician/technician.json",
|
||||||
"short-role-name": "src/modules/_short_role_name/modules/short-role-name.json",
|
"short-role-name": "src/modules/short_role_name/short-role-name.json",
|
||||||
|
"special-offers": "src/modules/special_offers/special-offers.json",
|
||||||
"checks": "tools/checks/checks.json",
|
"checks": "tools/checks/checks.json",
|
||||||
"get-version": "tools/get_version/get-version.json",
|
"get-version": "tools/get_version/get-version.json",
|
||||||
"post-build": "tools/post_build/post-build.json",
|
"post-build": "tools/post_build/post-build.json",
|
@@ -15,7 +15,7 @@ __title__ = "bot"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -8,6 +8,7 @@ from cpl_discord.service import DiscordBotServiceABC, DiscordBotService
|
|||||||
from cpl_translation import TranslatePipe, TranslationServiceABC, TranslationSettings
|
from cpl_translation import TranslatePipe, TranslationServiceABC, TranslationSettings
|
||||||
|
|
||||||
from bot_api.api_thread import ApiThread
|
from bot_api.api_thread import ApiThread
|
||||||
|
from bot_core.abc.task_abc import TaskABC
|
||||||
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
||||||
from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings
|
from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings
|
||||||
from bot_core.service.data_integrity_service import DataIntegrityService
|
from bot_core.service.data_integrity_service import DataIntegrityService
|
||||||
@@ -22,15 +23,25 @@ class Application(DiscordBotApplicationABC):
|
|||||||
|
|
||||||
# cpl-core
|
# cpl-core
|
||||||
self._logger: LoggerABC = services.get_service(LoggerABC)
|
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
|
# cpl-discord
|
||||||
self._bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC)
|
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
|
# cpl-translation
|
||||||
self._translation: TranslationServiceABC = services.get_service(TranslationServiceABC)
|
self._translation: TranslationServiceABC = services.get_service(
|
||||||
|
TranslationServiceABC
|
||||||
|
)
|
||||||
self._t: TranslatePipe = services.get_service(TranslatePipe)
|
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
|
# api
|
||||||
if self._feature_flags.get_flag(FeatureFlagsEnum.api_module):
|
if self._feature_flags.get_flag(FeatureFlagsEnum.api_module):
|
||||||
@@ -39,7 +50,9 @@ class Application(DiscordBotApplicationABC):
|
|||||||
self._is_stopping = False
|
self._is_stopping = False
|
||||||
|
|
||||||
async def configure(self):
|
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):
|
async def main(self):
|
||||||
try:
|
try:
|
||||||
@@ -55,6 +68,9 @@ class Application(DiscordBotApplicationABC):
|
|||||||
return
|
return
|
||||||
|
|
||||||
self._logger.info(__name__, f"Try to start {DiscordBotService.__name__}")
|
self._logger.info(__name__, f"Try to start {DiscordBotService.__name__}")
|
||||||
|
for task in self._tasks:
|
||||||
|
await self._bot.add_cog(task)
|
||||||
|
|
||||||
await self._bot.start_async()
|
await self._bot.start_async()
|
||||||
await self._bot.stop_async()
|
await self._bot.stop_async()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -79,4 +95,8 @@ class Application(DiscordBotApplicationABC):
|
|||||||
Console.write_line()
|
Console.write_line()
|
||||||
|
|
||||||
def is_restart(self):
|
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
|
||||||
|
)
|
@@ -3,8 +3,8 @@
|
|||||||
"Name": "bot",
|
"Name": "bot",
|
||||||
"Version": {
|
"Version": {
|
||||||
"Major": "1",
|
"Major": "1",
|
||||||
"Minor": "1",
|
"Minor": "2",
|
||||||
"Micro": "7"
|
"Micro": "0"
|
||||||
},
|
},
|
||||||
"Author": "Sven Heidemann",
|
"Author": "Sven Heidemann",
|
||||||
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
||||||
@@ -16,22 +16,22 @@
|
|||||||
"LicenseName": "MIT",
|
"LicenseName": "MIT",
|
||||||
"LicenseDescription": "MIT, see LICENSE for more details.",
|
"LicenseDescription": "MIT, see LICENSE for more details.",
|
||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"cpl-core==2023.4.0.post5",
|
"cpl-core==2023.10.0",
|
||||||
"cpl-translation==2023.4.0.post1",
|
"cpl-translation==2023.4.0.post1",
|
||||||
"cpl-query==2023.4.0.post1",
|
"cpl-query==2023.10.0",
|
||||||
"cpl-discord==2023.4.0.post3",
|
"cpl-discord==2023.10.0.post1",
|
||||||
"Flask==2.3.2",
|
"Flask==3.0.0",
|
||||||
"Flask-Classful==0.14.2",
|
"Flask-Classful==0.16.0",
|
||||||
"Flask-Cors==4.0.0",
|
"Flask-Cors==4.0.0",
|
||||||
"PyJWT==2.8.0",
|
"PyJWT==2.8.0",
|
||||||
"waitress==2.1.2",
|
"waitress==2.1.2",
|
||||||
"Flask-SocketIO==5.3.4",
|
"Flask-SocketIO==5.3.6",
|
||||||
"eventlet==0.33.3",
|
"eventlet==0.33.3",
|
||||||
"requests-oauthlib==1.3.1",
|
"requests-oauthlib==1.3.1",
|
||||||
"icmplib==3.0.3",
|
"icmplib==3.0.4",
|
||||||
"ariadne==0.20.1",
|
"ariadne==0.20.1",
|
||||||
"cryptography==41.0.2",
|
"cryptography==41.0.4",
|
||||||
"discord>=2.3.2"
|
"discord==2.3.2"
|
||||||
],
|
],
|
||||||
"DevDependencies": [
|
"DevDependencies": [
|
||||||
"cpl-cli==2023.4.0.post3",
|
"cpl-cli==2023.4.0.post3",
|
||||||
@@ -69,6 +69,7 @@
|
|||||||
"../modules/level/level.json",
|
"../modules/level/level.json",
|
||||||
"../modules/permission/permission.json",
|
"../modules/permission/permission.json",
|
||||||
"../modules/short_role_name/short-role-name.json",
|
"../modules/short_role_name/short-role-name.json",
|
||||||
|
"../modules/special_offers/special-offers.json",
|
||||||
"../modules/technician/technician.json"
|
"../modules/technician/technician.json"
|
||||||
]
|
]
|
||||||
}
|
}
|
@@ -15,7 +15,7 @@ __title__ = "bot.extension"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -13,4 +13,6 @@ class InitBotExtension(ApplicationExtensionABC):
|
|||||||
async def run(self, config: ConfigurationABC, services: ServiceProviderABC):
|
async def run(self, config: ConfigurationABC, services: ServiceProviderABC):
|
||||||
settings = config.get_configuration(TechnicianConfig)
|
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
|
||||||
|
)
|
@@ -14,6 +14,7 @@ from modules.database.database_module import DatabaseModule
|
|||||||
from modules.level.level_module import LevelModule
|
from modules.level.level_module import LevelModule
|
||||||
from modules.permission.permission_module import PermissionModule
|
from modules.permission.permission_module import PermissionModule
|
||||||
from modules.short_role_name.short_role_name_module import ShortRoleNameModule
|
from modules.short_role_name.short_role_name_module import ShortRoleNameModule
|
||||||
|
from modules.special_offers.special_offers_module import SteamSpecialOffersModule
|
||||||
from modules.technician.technician_module import TechnicianModule
|
from modules.technician.technician_module import TechnicianModule
|
||||||
|
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@ class ModuleList:
|
|||||||
TechnicianModule,
|
TechnicianModule,
|
||||||
AchievementsModule,
|
AchievementsModule,
|
||||||
ShortRoleNameModule,
|
ShortRoleNameModule,
|
||||||
|
SteamSpecialOffersModule,
|
||||||
# has to be last!
|
# has to be last!
|
||||||
BootLogModule,
|
BootLogModule,
|
||||||
CoreExtensionModule,
|
CoreExtensionModule,
|
@@ -16,6 +16,7 @@ from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings
|
|||||||
from bot_core.logging.command_logger import CommandLogger
|
from bot_core.logging.command_logger import CommandLogger
|
||||||
from bot_core.logging.database_logger import DatabaseLogger
|
from bot_core.logging.database_logger import DatabaseLogger
|
||||||
from bot_core.logging.message_logger import MessageLogger
|
from bot_core.logging.message_logger import MessageLogger
|
||||||
|
from bot_core.logging.task_logger import TaskLogger
|
||||||
from bot_data.db_context import DBContext
|
from bot_data.db_context import DBContext
|
||||||
|
|
||||||
|
|
||||||
@@ -43,12 +44,15 @@ class Startup(StartupABC):
|
|||||||
services.add_singleton(CustomFileLoggerABC, CommandLogger)
|
services.add_singleton(CustomFileLoggerABC, CommandLogger)
|
||||||
services.add_singleton(CustomFileLoggerABC, DatabaseLogger)
|
services.add_singleton(CustomFileLoggerABC, DatabaseLogger)
|
||||||
services.add_singleton(CustomFileLoggerABC, MessageLogger)
|
services.add_singleton(CustomFileLoggerABC, MessageLogger)
|
||||||
|
services.add_singleton(CustomFileLoggerABC, TaskLogger)
|
||||||
|
|
||||||
if self._feature_flags.get_flag(FeatureFlagsEnum.api_module):
|
if self._feature_flags.get_flag(FeatureFlagsEnum.api_module):
|
||||||
services.add_singleton(CustomFileLoggerABC, ApiLogger)
|
services.add_singleton(CustomFileLoggerABC, ApiLogger)
|
||||||
|
|
||||||
services.add_translation()
|
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()
|
provider = services.build_service_provider()
|
||||||
# instantiate custom logger
|
# instantiate custom logger
|
@@ -9,9 +9,13 @@ class StartupDiscordExtension(StartupExtensionABC):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
|
def configure_configuration(
|
||||||
|
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
|
||||||
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
def configure_services(
|
||||||
|
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
|
||||||
|
):
|
||||||
services.add_discord()
|
services.add_discord()
|
||||||
dcc = get_discord_collection(services)
|
dcc = get_discord_collection(services)
|
106
bot/src/bot/startup_migration_extension.py
Normal file
106
bot/src/bot/startup_migration_extension.py
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
from cpl_core.application import StartupExtensionABC
|
||||||
|
from cpl_core.configuration import ConfigurationABC
|
||||||
|
from cpl_core.dependency_injection import ServiceCollectionABC
|
||||||
|
from cpl_core.environment import ApplicationEnvironmentABC
|
||||||
|
|
||||||
|
from bot_data.abc.migration_abc import MigrationABC
|
||||||
|
from bot_data.migration.achievements_migration import AchievementsMigration
|
||||||
|
from bot_data.migration.api_key_migration import ApiKeyMigration
|
||||||
|
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_migration import ConfigMigration
|
||||||
|
from bot_data.migration.db_history_migration import DBHistoryMigration
|
||||||
|
from bot_data.migration.default_role_migration import DefaultRoleMigration
|
||||||
|
from bot_data.migration.fix_updates_migration import FixUpdatesMigration
|
||||||
|
from bot_data.migration.fix_user_history_migration import FixUserHistoryMigration
|
||||||
|
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.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_message_count_per_hour_migration import (
|
||||||
|
UserMessageCountPerHourMigration,
|
||||||
|
)
|
||||||
|
from bot_data.migration.user_warning_migration import UserWarningMigration
|
||||||
|
from bot_data.service.migration_service import MigrationService
|
||||||
|
|
||||||
|
|
||||||
|
class StartupMigrationExtension(StartupExtensionABC):
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def configure_configuration(
|
||||||
|
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
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, 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, 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, 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
|
@@ -18,11 +18,15 @@ class StartupModuleExtension(StartupExtensionABC):
|
|||||||
|
|
||||||
self._modules = ModuleList.get_modules()
|
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._config = config
|
||||||
self._feature_flags = config.get_configuration(FeatureFlagsSettings)
|
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()
|
provider = services.build_service_provider()
|
||||||
dc_collection: DiscordCollectionABC = provider.get_service(DiscordCollectionABC)
|
dc_collection: DiscordCollectionABC = provider.get_service(DiscordCollectionABC)
|
||||||
|
|
@@ -14,26 +14,38 @@ class StartupSettingsExtension(StartupExtensionABC):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._start_time = datetime.now()
|
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
|
# 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__)))
|
environment.set_working_directory(os.path.dirname(os.path.realpath(__file__)))
|
||||||
configuration.add_environment_variables("KDB_")
|
configuration.add_environment_variables("KDB_")
|
||||||
configuration.add_environment_variables("DISCORD_")
|
configuration.add_environment_variables("DISCORD_")
|
||||||
|
|
||||||
configuration.add_json_file(f"config/appsettings.json", optional=False)
|
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(
|
||||||
configuration.add_json_file(f"config/appsettings.{environment.host_name}.json", optional=True)
|
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
|
# load feature-flags
|
||||||
configuration.add_json_file(f"config/feature-flags.json", optional=False)
|
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(
|
||||||
configuration.add_json_file(f"config/feature-flags.{environment.host_name}.json", optional=True)
|
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))
|
configuration.add_configuration("Startup_StartTime", str(self._start_time))
|
||||||
self._configure_settings_with_sub_settings(
|
self._configure_settings_with_sub_settings(
|
||||||
configuration, BotLoggingSettings, lambda x: x.files, lambda x: x.key
|
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
|
pass
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -45,4 +57,6 @@ class StartupSettingsExtension(StartupExtensionABC):
|
|||||||
return
|
return
|
||||||
|
|
||||||
for sub_settings in list_atr(settings):
|
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
|
||||||
|
)
|
@@ -21,7 +21,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
"feature_not_activated": "Diese Funktion ist deaktiviert",
|
|
||||||
"bot_has_no_permission_message": "Ey!!!\nWas soll das?\nIch habe keine Berechtigungen :(\nScheiß System...",
|
"bot_has_no_permission_message": "Ey!!!\nWas soll das?\nIch habe keine Berechtigungen :(\nScheiß System...",
|
||||||
"colors": {
|
"colors": {
|
||||||
"blue": "Blau",
|
"blue": "Blau",
|
||||||
@@ -83,6 +82,7 @@
|
|||||||
"unexpected_quote_error": "Fehler: Unerwarteter Fehler beim Anführungszeichen!",
|
"unexpected_quote_error": "Fehler: Unerwarteter Fehler beim Anführungszeichen!",
|
||||||
"user_input_error": "Fehler: Eingabefehler!"
|
"user_input_error": "Fehler: Eingabefehler!"
|
||||||
},
|
},
|
||||||
|
"feature_not_activated": "Diese Funktion ist deaktiviert",
|
||||||
"hello_world": "Hallo Welt",
|
"hello_world": "Hallo Welt",
|
||||||
"no_permission_message": "Nein!\nIch höre nicht auf dich ¯\\_(ツ)_/¯",
|
"no_permission_message": "Nein!\nIch höre nicht auf dich ¯\\_(ツ)_/¯",
|
||||||
"not_implemented_yet": "Ey Alter, das kann ich noch nicht...",
|
"not_implemented_yet": "Ey Alter, das kann ich noch nicht...",
|
||||||
@@ -94,11 +94,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"modules": {
|
"modules": {
|
||||||
|
"special_offers": {
|
||||||
|
"price": "Preis",
|
||||||
|
"discount": "Rabatt",
|
||||||
|
"discount_price": "Neuer Preis"
|
||||||
|
},
|
||||||
"achievements": {
|
"achievements": {
|
||||||
"got_new_achievement": "{} hat die Errungenschaft {} freigeschaltet :D",
|
|
||||||
"commands": {
|
"commands": {
|
||||||
"check": "Alles klar, ich schaue eben nach... nom nom"
|
"check": "Alles klar, ich schaue eben nach... nom nom"
|
||||||
}
|
},
|
||||||
|
"got_new_achievement": "{} hat die Errungenschaft {} freigeschaltet :D"
|
||||||
},
|
},
|
||||||
"auto_role": {
|
"auto_role": {
|
||||||
"add": {
|
"add": {
|
||||||
@@ -123,6 +128,9 @@
|
|||||||
},
|
},
|
||||||
"success": "auto-role {} wurde entfernt :D"
|
"success": "auto-role {} wurde entfernt :D"
|
||||||
},
|
},
|
||||||
|
"react": {
|
||||||
|
"success": "Alle Reaktionen wurden hinzugefügt"
|
||||||
|
},
|
||||||
"rule": {
|
"rule": {
|
||||||
"add": {
|
"add": {
|
||||||
"error": {
|
"error": {
|
||||||
@@ -152,38 +160,37 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"base": {
|
"base": {
|
||||||
"member_left_message": "{} hat uns leider verlassen :(",
|
|
||||||
"complaints": {
|
|
||||||
"title": "Beschwerde einreichen",
|
|
||||||
"label": "Beschwerde",
|
|
||||||
"message": "{} hat eine Beschwerde eingereicht:\n{}",
|
|
||||||
"response": "Danke für deine Beschwerde"
|
|
||||||
},
|
|
||||||
"bug": {
|
|
||||||
"title": "Bug melden",
|
|
||||||
"label": "Bug",
|
|
||||||
"message": "{} meldet einen Bug:\n{}",
|
|
||||||
"response": "Danke für dein Feedback :D"
|
|
||||||
},
|
|
||||||
"afk_command_channel_missing_message": "Zu unfähig einem Sprachkanal beizutreten?",
|
"afk_command_channel_missing_message": "Zu unfähig einem Sprachkanal beizutreten?",
|
||||||
"afk_command_move_message": "Ich verschiebe dich ja schon... (◔_◔)",
|
"afk_command_move_message": "Ich verschiebe dich ja schon... (◔_◔)",
|
||||||
|
"bug": {
|
||||||
|
"label": "Bug",
|
||||||
|
"message": "{} meldet einen Bug:\n{}",
|
||||||
|
"response": "Danke für dein Feedback :D",
|
||||||
|
"title": "Bug melden"
|
||||||
|
},
|
||||||
|
"complaints": {
|
||||||
|
"label": "Beschwerde",
|
||||||
|
"message": "{} hat eine Beschwerde eingereicht:\n{}",
|
||||||
|
"response": "Danke für deine Beschwerde",
|
||||||
|
"title": "Beschwerde einreichen"
|
||||||
|
},
|
||||||
"game_server": {
|
"game_server": {
|
||||||
|
"add": {
|
||||||
|
"success": "Gameserver {} wurde hinzugefügt :)"
|
||||||
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"nothing_found": "Keine Gameserver gefunden."
|
"nothing_found": "Keine Gameserver gefunden."
|
||||||
},
|
},
|
||||||
"list_members": {
|
|
||||||
"title": "Mitglieder",
|
|
||||||
"description": "Konfigurierte Mitglieder:",
|
|
||||||
"users": "Mitglieder"
|
|
||||||
},
|
|
||||||
"list": {
|
"list": {
|
||||||
"title": "Gameserver",
|
"api_key": "API Key",
|
||||||
"description": "Konfigurierte Gameserver:",
|
"description": "Konfigurierte Gameserver:",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"api_key": "API Key"
|
"title": "Gameserver"
|
||||||
},
|
},
|
||||||
"add": {
|
"list_members": {
|
||||||
"success": "Gameserver {} wurde hinzugefügt :)"
|
"description": "Konfigurierte Mitglieder:",
|
||||||
|
"title": "Mitglieder",
|
||||||
|
"users": "Mitglieder"
|
||||||
},
|
},
|
||||||
"remove": {
|
"remove": {
|
||||||
"success": "Gameserver wurde entfernt :D"
|
"success": "Gameserver wurde entfernt :D"
|
||||||
@@ -210,6 +217,7 @@
|
|||||||
"moved": "Alle Personen aus {} wurden nach {} verschoben."
|
"moved": "Alle Personen aus {} wurden nach {} verschoben."
|
||||||
},
|
},
|
||||||
"member_joined_help_voice_channel": "{} braucht Hilfe, bitte kümmere dich drum :D",
|
"member_joined_help_voice_channel": "{} braucht Hilfe, bitte kümmere dich drum :D",
|
||||||
|
"member_left_message": "{} hat uns leider verlassen :(",
|
||||||
"pong": "Pong",
|
"pong": "Pong",
|
||||||
"presence": {
|
"presence": {
|
||||||
"changed": "Presence wurde geändert.",
|
"changed": "Presence wurde geändert.",
|
||||||
@@ -226,6 +234,11 @@
|
|||||||
"success": "Verlinkung wurde entfernt :D"
|
"success": "Verlinkung wurde entfernt :D"
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
|
"birthday": {
|
||||||
|
"has_birthday": "Alles Gute zum Geburtag {} :D",
|
||||||
|
"success": "Dein Geburtstag wurde eingetragen.",
|
||||||
|
"success_team": "{} hat seinen Geburtstag eingetragen: {}"
|
||||||
|
},
|
||||||
"add": {
|
"add": {
|
||||||
"xp": "Die {} von {} wurden um {} erhöht"
|
"xp": "Die {} von {} wurden um {} erhöht"
|
||||||
},
|
},
|
||||||
@@ -346,6 +359,9 @@
|
|||||||
"moderator": {
|
"moderator": {
|
||||||
"purge_message": "Na gut..., ich lösche alle Nachrichten wenns sein muss."
|
"purge_message": "Na gut..., ich lösche alle Nachrichten wenns sein muss."
|
||||||
},
|
},
|
||||||
|
"short_role_name": {
|
||||||
|
"checked_message": "Die Rollen Kürzel wurden überprüft"
|
||||||
|
},
|
||||||
"technician": {
|
"technician": {
|
||||||
"api_key": {
|
"api_key": {
|
||||||
"add": {
|
"add": {
|
||||||
@@ -357,10 +373,10 @@
|
|||||||
"success": "API-Schlüssel wurde entfernt :D"
|
"success": "API-Schlüssel wurde entfernt :D"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"synced_message": "Der Sync wurde abgeschlossen.",
|
|
||||||
"log_message": "Hier sind deine Logdateien! :)",
|
"log_message": "Hier sind deine Logdateien! :)",
|
||||||
"restart_message": "Bin gleich wieder da :D",
|
"restart_message": "Bin gleich wieder da :D",
|
||||||
"shutdown_message": "Trauert nicht um mich, es war eine logische Entscheidung. Das Wohl von Vielen, es wiegt schwerer als das Wohl von Wenigen oder eines Einzelnen. Ich war es und ich werde es immer sein, euer Freund. Lebt lange und in Frieden :)"
|
"shutdown_message": "Trauert nicht um mich, es war eine logische Entscheidung. Das Wohl von Vielen, es wiegt schwerer als das Wohl von Wenigen oder eines Einzelnen. Ich war es und ich werde es immer sein, euer Freund. Lebt lange und in Frieden :)",
|
||||||
|
"synced_message": "Der Sync wurde abgeschlossen."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -15,7 +15,7 @@ __title__ = "bot_api"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.abc"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -40,11 +40,15 @@ class AuthServiceABC(ABC):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def get_filtered_auth_users_async(self, criteria: AuthUserSelectCriteria) -> AuthUserFilteredResultDTO:
|
async def get_filtered_auth_users_async(
|
||||||
|
self, criteria: AuthUserSelectCriteria
|
||||||
|
) -> AuthUserFilteredResultDTO:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@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
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
@@ -3,7 +3,9 @@ from abc import ABC, abstractmethod
|
|||||||
|
|
||||||
class SelectCriteriaABC(ABC):
|
class SelectCriteriaABC(ABC):
|
||||||
@abstractmethod
|
@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_index = page_index
|
||||||
self.page_size = page_size
|
self.page_size = page_size
|
||||||
self.sort_direction = sort_direction
|
self.sort_direction = sort_direction
|
@@ -57,7 +57,9 @@ class Api(Flask):
|
|||||||
# Added async_mode see link below
|
# Added async_mode see link below
|
||||||
# https://github.com/miguelgrinberg/Flask-SocketIO/discussions/1849
|
# https://github.com/miguelgrinberg/Flask-SocketIO/discussions/1849
|
||||||
# https://stackoverflow.com/questions/39370848/flask-socket-io-sometimes-client-calls-freeze-the-server
|
# 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("connect", self.on_connect)
|
||||||
self._socketio.on_event("disconnect", self.on_disconnect)
|
self._socketio.on_event("disconnect", self.on_disconnect)
|
||||||
|
|
||||||
@@ -143,19 +145,26 @@ class Api(Flask):
|
|||||||
data = request.get_data()
|
data = request.get_data()
|
||||||
data = "" if len(data) == 0 else str(data.decode(encoding="utf-8"))
|
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)
|
self._logger.trace(__name__, text)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def start(self):
|
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._register_routes()
|
||||||
self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key)
|
self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key)
|
||||||
# from waitress import serve
|
# from waitress import serve
|
||||||
# https://docs.pylonsproject.org/projects/waitress/en/stable/arguments.html
|
# 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)
|
# 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)
|
wsgi.server(self._socket, self, log_output=False)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
@@ -26,15 +26,21 @@ class ApiModule(ModuleABC):
|
|||||||
def __init__(self, dc: DiscordCollectionABC):
|
def __init__(self, dc: DiscordCollectionABC):
|
||||||
ModuleABC.__init__(self, dc, FeatureFlagsEnum.api_module)
|
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
|
cwd = env.working_directory
|
||||||
env.set_working_directory(os.path.dirname(os.path.realpath(__file__)))
|
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.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)
|
config.add_json_file(f"config/apisettings.{env.host_name}.json", optional=True)
|
||||||
env.set_working_directory(cwd)
|
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(EMailClientABC, EMailClient)
|
||||||
|
|
||||||
services.add_singleton(ApiThread)
|
services.add_singleton(ApiThread)
|
||||||
@@ -48,4 +54,4 @@ class ApiModule(ModuleABC):
|
|||||||
services.add_transient(GraphQLController)
|
services.add_transient(GraphQLController)
|
||||||
|
|
||||||
# cpl-discord
|
# cpl-discord
|
||||||
self._dc.add_event(DiscordEventTypesEnum.on_ready.value, BotApiOnReadyEvent)
|
services.add_transient(DiscordEventTypesEnum.on_ready.value, BotApiOnReadyEvent)
|
@@ -12,7 +12,9 @@ class AppApiExtension(ApplicationExtensionABC):
|
|||||||
ApplicationExtensionABC.__init__(self)
|
ApplicationExtensionABC.__init__(self)
|
||||||
|
|
||||||
async def run(self, config: ConfigurationABC, services: ServiceProviderABC):
|
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):
|
if not feature_flags.get_flag(FeatureFlagsEnum.api_module):
|
||||||
return
|
return
|
||||||
|
|
@@ -3,8 +3,8 @@
|
|||||||
"Name": "bot-api",
|
"Name": "bot-api",
|
||||||
"Version": {
|
"Version": {
|
||||||
"Major": "1",
|
"Major": "1",
|
||||||
"Minor": "1",
|
"Minor": "2",
|
||||||
"Micro": "7"
|
"Micro": "0"
|
||||||
},
|
},
|
||||||
"Author": "",
|
"Author": "",
|
||||||
"AuthorEmail": "",
|
"AuthorEmail": "",
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.configuration"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports
|
# imports
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -16,7 +16,9 @@ class AuthenticationSettings(ConfigurationModelABC):
|
|||||||
self._issuer = "" if issuer is None else issuer
|
self._issuer = "" if issuer is None else issuer
|
||||||
self._audience = "" if audience is None else audience
|
self._audience = "" if audience is None else audience
|
||||||
self._token_expire_time = 0 if token_expire_time is None else token_expire_time
|
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
|
@property
|
||||||
def secret_key(self) -> str:
|
def secret_key(self) -> str:
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.controller"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -70,7 +70,9 @@ class AuthController:
|
|||||||
|
|
||||||
@Route.post(f"{BasePath}/register")
|
@Route.post(f"{BasePath}/register")
|
||||||
async def register(self):
|
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)
|
self._auth_service.add_auth_user(dto)
|
||||||
return "", 200
|
return "", 200
|
||||||
|
|
||||||
@@ -81,7 +83,9 @@ class AuthController:
|
|||||||
|
|
||||||
@Route.post(f"{BasePath}/login")
|
@Route.post(f"{BasePath}/login")
|
||||||
async def login(self) -> Response:
|
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)
|
result = await self._auth_service.login_async(dto)
|
||||||
return jsonify(result.to_dict())
|
return jsonify(result.to_dict())
|
||||||
|
|
||||||
@@ -110,40 +114,52 @@ class AuthController:
|
|||||||
|
|
||||||
@Route.post(f"{BasePath}/reset-password")
|
@Route.post(f"{BasePath}/reset-password")
|
||||||
async def reset_password(self):
|
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)
|
await self._auth_service.reset_password_async(dto)
|
||||||
return "", 200
|
return "", 200
|
||||||
|
|
||||||
@Route.post(f"{BasePath}/update-user")
|
@Route.post(f"{BasePath}/update-user")
|
||||||
@Route.authorize
|
@Route.authorize
|
||||||
async def update_user(self):
|
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)
|
await self._auth_service.update_user_async(dto)
|
||||||
return "", 200
|
return "", 200
|
||||||
|
|
||||||
@Route.post(f"{BasePath}/update-user-as-admin")
|
@Route.post(f"{BasePath}/update-user-as-admin")
|
||||||
@Route.authorize(role=AuthRoleEnum.admin)
|
@Route.authorize(role=AuthRoleEnum.admin)
|
||||||
async def update_user_as_admin(self):
|
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)
|
await self._auth_service.update_user_as_admin_async(dto)
|
||||||
return "", 200
|
return "", 200
|
||||||
|
|
||||||
@Route.post(f"{BasePath}/refresh")
|
@Route.post(f"{BasePath}/refresh")
|
||||||
async def refresh(self) -> Response:
|
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)
|
result = await self._auth_service.refresh_async(dto)
|
||||||
return jsonify(result.to_dict())
|
return jsonify(result.to_dict())
|
||||||
|
|
||||||
@Route.post(f"{BasePath}/revoke")
|
@Route.post(f"{BasePath}/revoke")
|
||||||
async def revoke(self):
|
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)
|
await self._auth_service.revoke_async(dto)
|
||||||
return "", 200
|
return "", 200
|
||||||
|
|
||||||
@Route.post(f"{BasePath}/delete-user")
|
@Route.post(f"{BasePath}/delete-user")
|
||||||
@Route.authorize(role=AuthRoleEnum.admin)
|
@Route.authorize(role=AuthRoleEnum.admin)
|
||||||
async def delete_user(self):
|
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)
|
await self._auth_service.delete_auth_user_async(dto)
|
||||||
return "", 200
|
return "", 200
|
||||||
|
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.event"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.exception"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.filter"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -13,7 +13,9 @@ class AuthUserSelectCriteria(SelectCriteriaABC):
|
|||||||
email: str,
|
email: str,
|
||||||
auth_role: int,
|
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.first_name = first_name
|
||||||
self.last_name = last_name
|
self.last_name = last_name
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.filter.discord"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -10,6 +10,8 @@ class ServerSelectCriteria(SelectCriteriaABC):
|
|||||||
sort_column: str,
|
sort_column: str,
|
||||||
name: 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
|
self.name = name
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.logging"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.model"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.model.discord"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -11,7 +11,9 @@ class ErrorDTO(DtoABC):
|
|||||||
def __init__(self, error_code: Optional[ServiceErrorCode], message: str):
|
def __init__(self, error_code: Optional[ServiceErrorCode], message: str):
|
||||||
DtoABC.__init__(self)
|
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
|
self._message = message
|
||||||
|
|
||||||
@property
|
@property
|
@@ -27,4 +27,8 @@ class TokenDTO(DtoABC):
|
|||||||
self._first_login = values["firstLogin"]
|
self._first_login = values["firstLogin"]
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
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,
|
||||||
|
}
|
@@ -34,7 +34,9 @@ class UpdateAuthUserDTO(DtoABC):
|
|||||||
def from_dict(self, values: dict):
|
def from_dict(self, values: dict):
|
||||||
self._auth_user = AuthUserDTO().from_dict(values["authUser"])
|
self._auth_user = AuthUserDTO().from_dict(values["authUser"])
|
||||||
self._new_auth_user = AuthUserDTO().from_dict(values["newAuthUser"])
|
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:
|
def to_dict(self) -> dict:
|
||||||
return {
|
return {
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.route"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -25,7 +25,12 @@ class Route:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ServiceProviderABC.inject
|
@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_users = auth_users
|
||||||
cls._auth = auth
|
cls._auth = auth
|
||||||
cls._env = env.environment_name
|
cls._env = env.environment_name
|
||||||
@@ -52,9 +57,17 @@ class Route:
|
|||||||
return user
|
return user
|
||||||
|
|
||||||
@classmethod
|
@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:
|
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)
|
@wraps(f)
|
||||||
async def decorator(*args, **kwargs):
|
async def decorator(*args, **kwargs):
|
||||||
@@ -65,7 +78,9 @@ class Route:
|
|||||||
api_key = None
|
api_key = None
|
||||||
if "Authorization" in request.headers:
|
if "Authorization" in request.headers:
|
||||||
if " " not in request.headers.get("Authorization"):
|
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)
|
error = ErrorDTO(ex.error_code, ex.message)
|
||||||
return jsonify(error.to_dict()), 401
|
return jsonify(error.to_dict()), 401
|
||||||
|
|
||||||
@@ -87,7 +102,9 @@ class Route:
|
|||||||
return jsonify(e), 500
|
return jsonify(e), 500
|
||||||
|
|
||||||
if not valid:
|
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)
|
error = ErrorDTO(ex.error_code, ex.message)
|
||||||
return jsonify(error.to_dict()), 401
|
return jsonify(error.to_dict()), 401
|
||||||
|
|
||||||
@@ -99,7 +116,9 @@ class Route:
|
|||||||
return jsonify(error.to_dict()), 401
|
return jsonify(error.to_dict()), 401
|
||||||
|
|
||||||
if cls._auth_users is None or cls._auth is None:
|
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)
|
error = ErrorDTO(ex.error_code, ex.message)
|
||||||
return jsonify(error.to_dict()), 401
|
return jsonify(error.to_dict()), 401
|
||||||
|
|
||||||
@@ -121,7 +140,9 @@ class Route:
|
|||||||
return jsonify(error.to_dict()), 401
|
return jsonify(error.to_dict()), 401
|
||||||
|
|
||||||
if role is not None and user.auth_role.value < role.value:
|
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)
|
error = ErrorDTO(ex.error_code, ex.message)
|
||||||
return jsonify(error.to_dict()), 403
|
return jsonify(error.to_dict()), 403
|
||||||
|
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.service"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports
|
# imports
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -90,7 +90,9 @@ class AuthService(AuthServiceABC):
|
|||||||
|
|
||||||
def _get_api_key_str(self, api_key: ApiKey) -> str:
|
def _get_api_key_str(self, api_key: ApiKey) -> str:
|
||||||
return hashlib.sha256(
|
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()
|
).hexdigest()
|
||||||
|
|
||||||
def generate_token(self, user: AuthUser) -> str:
|
def generate_token(self, user: AuthUser) -> str:
|
||||||
@@ -99,7 +101,8 @@ class AuthService(AuthServiceABC):
|
|||||||
"user_id": user.id,
|
"user_id": user.id,
|
||||||
"email": user.email,
|
"email": user.email,
|
||||||
"role": user.auth_role.value,
|
"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,
|
"iss": self._auth_settings.issuer,
|
||||||
"aud": self._auth_settings.audience,
|
"aud": self._auth_settings.audience,
|
||||||
},
|
},
|
||||||
@@ -155,7 +158,9 @@ class AuthService(AuthServiceABC):
|
|||||||
def _create_and_save_refresh_token(self, user: AuthUser) -> str:
|
def _create_and_save_refresh_token(self, user: AuthUser) -> str:
|
||||||
token = str(uuid.uuid4())
|
token = str(uuid.uuid4())
|
||||||
user.refresh_token = token
|
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._auth_users.update_auth_user(user)
|
||||||
self._db.save_changes()
|
self._db.save_changes()
|
||||||
return token
|
return token
|
||||||
@@ -188,8 +193,12 @@ class AuthService(AuthServiceABC):
|
|||||||
|
|
||||||
self._send_link_mail(
|
self._send_link_mail(
|
||||||
user.email,
|
user.email,
|
||||||
self._t.transform("api.auth.confirmation.subject").format(user.first_name, user.last_name),
|
self._t.transform("api.auth.confirmation.subject").format(
|
||||||
self._t.transform("api.auth.confirmation.message").format(url, user.confirmation_id),
|
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):
|
def _send_forgot_password_id_to_user(self, user: AuthUser):
|
||||||
@@ -199,28 +208,38 @@ class AuthService(AuthServiceABC):
|
|||||||
|
|
||||||
self._send_link_mail(
|
self._send_link_mail(
|
||||||
user.email,
|
user.email,
|
||||||
self._t.transform("api.auth.forgot_password.subject").format(user.first_name, user.last_name),
|
self._t.transform("api.auth.forgot_password.subject").format(
|
||||||
self._t.transform("api.auth.forgot_password.message").format(url, user.forgot_password_id),
|
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]:
|
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))
|
result = self._auth_users.get_all_auth_users().select(lambda x: AUT.to_dto(x))
|
||||||
return List(AuthUserDTO, result)
|
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)
|
users = self._auth_users.get_filtered_auth_users(criteria)
|
||||||
result = users.result.select(lambda x: AUT.to_dto(x))
|
result = users.result.select(lambda x: AUT.to_dto(x))
|
||||||
|
|
||||||
return AuthUserFilteredResultDTO(List(AuthUserDTO, result), users.total_count)
|
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:
|
try:
|
||||||
# todo: check if logged in user is admin then send mail
|
# todo: check if logged in user is admin then send mail
|
||||||
user = self._auth_users.get_auth_user_by_email(email)
|
user = self._auth_users.get_auth_user_by_email(email)
|
||||||
return AUT.to_dto(user, password=user.password if with_password else None)
|
return AUT.to_dto(user, password=user.password if with_password else None)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._logger.error(__name__, f"AuthUser not found", 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]:
|
async def find_auth_user_by_email_async(self, email: str) -> Optional[AuthUser]:
|
||||||
user = self._auth_users.find_auth_user_by_email(email)
|
user = self._auth_users.find_auth_user_by_email(email)
|
||||||
@@ -238,16 +257,22 @@ class AuthService(AuthServiceABC):
|
|||||||
user.password_salt = uuid.uuid4()
|
user.password_salt = uuid.uuid4()
|
||||||
user.password = self._hash_sha256(user_dto.password, user.password_salt)
|
user.password = self._hash_sha256(user_dto.password, user.password_salt)
|
||||||
if not self._is_email_valid(user.email):
|
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:
|
try:
|
||||||
user.confirmation_id = uuid.uuid4()
|
user.confirmation_id = uuid.uuid4()
|
||||||
self._auth_users.add_auth_user(user)
|
self._auth_users.add_auth_user(user)
|
||||||
self._send_confirmation_id_to_user(user)
|
self._send_confirmation_id_to_user(user)
|
||||||
self._db.save_changes()
|
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:
|
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")
|
raise ServiceException(ServiceErrorCode.UnableToAdd, "Invalid E-Mail")
|
||||||
|
|
||||||
async def add_auth_user_by_oauth_async(self, dto: OAuthDTO):
|
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.first_name = dto.user.first_name
|
||||||
db_user.last_name = dto.user.last_name
|
db_user.last_name = dto.user.last_name
|
||||||
db_user.password_salt = uuid.uuid4()
|
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.oauth_id = None
|
||||||
db_user.confirmation_id = uuid.uuid4()
|
db_user.confirmation_id = uuid.uuid4()
|
||||||
self._send_confirmation_id_to_user(db_user)
|
self._send_confirmation_id_to_user(db_user)
|
||||||
self._auth_users.update_auth_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:
|
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")
|
raise ServiceException(ServiceErrorCode.UnableToAdd, "Invalid E-Mail")
|
||||||
|
|
||||||
self._db.save_changes()
|
self._db.save_changes()
|
||||||
@@ -280,14 +311,16 @@ class AuthService(AuthServiceABC):
|
|||||||
raise ServiceException(ServiceErrorCode.InvalidData, f"User is empty")
|
raise ServiceException(ServiceErrorCode.InvalidData, f"User is empty")
|
||||||
|
|
||||||
if update_user_dto.auth_user is None:
|
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:
|
if update_user_dto.new_auth_user is None:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, f"New user is empty")
|
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(
|
if not self._is_email_valid(
|
||||||
update_user_dto.new_auth_user.email
|
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")
|
raise ServiceException(ServiceErrorCode.InvalidData, f"Invalid E-Mail")
|
||||||
|
|
||||||
user = self._auth_users.find_auth_user_by_email(update_user_dto.auth_user.email)
|
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
|
# update first name
|
||||||
if (
|
if (
|
||||||
update_user_dto.new_auth_user.first_name is not None
|
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
|
user.first_name = update_user_dto.new_auth_user.first_name
|
||||||
|
|
||||||
@@ -308,7 +342,8 @@ class AuthService(AuthServiceABC):
|
|||||||
if (
|
if (
|
||||||
update_user_dto.new_auth_user.last_name is not None
|
update_user_dto.new_auth_user.last_name is not None
|
||||||
and update_user_dto.new_auth_user.last_name != ""
|
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
|
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.new_auth_user.email != ""
|
||||||
and update_user_dto.auth_user.email != 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:
|
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
|
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:
|
if update_user_dto.auth_user.password != user.password:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidUser, "Wrong password")
|
raise ServiceException(ServiceErrorCode.InvalidUser, "Wrong password")
|
||||||
|
|
||||||
# update password
|
# update password
|
||||||
if (
|
if (
|
||||||
update_user_dto.new_auth_user.password is not None
|
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_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._auth_users.update_auth_user(user)
|
||||||
self._db.save_changes()
|
self._db.save_changes()
|
||||||
@@ -343,23 +389,31 @@ class AuthService(AuthServiceABC):
|
|||||||
raise ServiceException(ServiceErrorCode.InvalidData, f"User is empty")
|
raise ServiceException(ServiceErrorCode.InvalidData, f"User is empty")
|
||||||
|
|
||||||
if update_user_dto.auth_user is None:
|
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:
|
if update_user_dto.new_auth_user is None:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, f"New user is empty")
|
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(
|
if not self._is_email_valid(
|
||||||
update_user_dto.new_auth_user.email
|
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")
|
raise ServiceException(ServiceErrorCode.InvalidData, f"Invalid E-Mail")
|
||||||
|
|
||||||
user = self._auth_users.find_auth_user_by_email(update_user_dto.auth_user.email)
|
user = self._auth_users.find_auth_user_by_email(update_user_dto.auth_user.email)
|
||||||
if user is None:
|
if user is None:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidUser, "User not found")
|
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
|
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()
|
user.confirmation_id = uuid.uuid4()
|
||||||
# else
|
# else
|
||||||
# raise ServiceException(ServiceErrorCode.InvalidUser, 'E-Mail not confirmed')
|
# raise ServiceException(ServiceErrorCode.InvalidUser, 'E-Mail not confirmed')
|
||||||
@@ -367,7 +421,8 @@ class AuthService(AuthServiceABC):
|
|||||||
# update first name
|
# update first name
|
||||||
if (
|
if (
|
||||||
update_user_dto.new_auth_user.first_name is not None
|
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
|
user.first_name = update_user_dto.new_auth_user.first_name
|
||||||
|
|
||||||
@@ -375,7 +430,8 @@ class AuthService(AuthServiceABC):
|
|||||||
if (
|
if (
|
||||||
update_user_dto.new_auth_user.last_name is not None
|
update_user_dto.new_auth_user.last_name is not None
|
||||||
and update_user_dto.new_auth_user.last_name != ""
|
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
|
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.new_auth_user.email != ""
|
||||||
and update_user_dto.auth_user.email != 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:
|
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
|
user.email = update_user_dto.new_auth_user.email
|
||||||
|
|
||||||
# update password
|
# update password
|
||||||
if (
|
if (
|
||||||
update_user_dto.new_auth_user.password is not None
|
update_user_dto.new_auth_user.password is not None
|
||||||
and update_user_dto.change_password
|
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_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
|
# update role
|
||||||
if (
|
if (
|
||||||
@@ -416,7 +481,9 @@ class AuthService(AuthServiceABC):
|
|||||||
self._db.save_changes()
|
self._db.save_changes()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._logger.error(__name__, f"Cannot delete user", 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):
|
async def delete_auth_user_async(self, user_dto: AuthUser):
|
||||||
try:
|
try:
|
||||||
@@ -500,7 +567,9 @@ class AuthService(AuthServiceABC):
|
|||||||
if user.id in user_ids:
|
if user.id in user_ids:
|
||||||
continue
|
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:
|
if db_user.confirmation_id is not None and not added_user:
|
||||||
raise ServiceException(ServiceErrorCode.Forbidden, "E-Mail not verified")
|
raise ServiceException(ServiceErrorCode.Forbidden, "E-Mail not verified")
|
||||||
@@ -530,13 +599,19 @@ class AuthService(AuthServiceABC):
|
|||||||
):
|
):
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, "Token expired")
|
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:
|
except Exception as e:
|
||||||
self._logger.error(__name__, f"Refreshing token failed", e)
|
self._logger.error(__name__, f"Refreshing token failed", e)
|
||||||
return TokenDTO("", "")
|
return TokenDTO("", "")
|
||||||
|
|
||||||
async def revoke_async(self, token_dto: 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")
|
raise ServiceException(ServiceErrorCode.InvalidData, "Token not set")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -589,7 +664,9 @@ class AuthService(AuthServiceABC):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if user.confirmation_id is not None:
|
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 == "":
|
if user.password is None or rp_dto.password == "":
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, f"Password not set")
|
raise ServiceException(ServiceErrorCode.InvalidData, f"Password not set")
|
@@ -53,13 +53,17 @@ class DiscordService:
|
|||||||
if role != AuthRoleEnum.admin:
|
if role != AuthRoleEnum.admin:
|
||||||
auth_user = self._auth_users.find_auth_user_by_email(token["email"])
|
auth_user = self._auth_users.find_auth_user_by_email(token["email"])
|
||||||
if auth_user is not None:
|
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 = servers.where(lambda x: x.id in user_ids)
|
||||||
|
|
||||||
servers = List(ServerDTO, servers)
|
servers = List(ServerDTO, servers)
|
||||||
return servers.select(self._to_dto).where(lambda x: x.name != "")
|
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()
|
token = self._auth.get_decoded_token_from_request()
|
||||||
if token is None or "email" not in token or "role" not in token:
|
if token is None or "email" not in token or "role" not in token:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, "Token invalid")
|
raise ServiceException(ServiceErrorCode.InvalidData, "Token invalid")
|
||||||
@@ -70,15 +74,22 @@ class DiscordService:
|
|||||||
if role != AuthRoleEnum.admin:
|
if role != AuthRoleEnum.admin:
|
||||||
auth_user = self._auth_users.find_auth_user_by_email(token["email"])
|
auth_user = self._auth_users.find_auth_user_by_email(token["email"])
|
||||||
if auth_user is not None:
|
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(
|
||||||
filtered_result.result = filtered_result.result.where(lambda x: x.id in user_ids)
|
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)
|
result = List(ServerDTO, servers)
|
||||||
|
|
||||||
if criteria.name is not None and criteria.name != "":
|
if criteria.name is not None and criteria.name != "":
|
||||||
result = result.where(
|
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())
|
return ServerFilteredResultDTO(List(ServerDTO, result), servers.count())
|
||||||
@@ -87,5 +98,7 @@ class DiscordService:
|
|||||||
server = self._servers.get_server_by_id(id)
|
server = self._servers.get_server_by_id(id)
|
||||||
guild = self._bot.get_guild(server.discord_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
|
return server_dto
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.transformer"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -27,27 +27,35 @@ class AuthUserTransformer(TransformerABC):
|
|||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
datetime.now(),
|
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,
|
auth_user_id=0 if dto.id is None else dto.id,
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ServiceProviderABC.inject
|
@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)
|
guild = bot.get_guild(user.server.discord_id)
|
||||||
member = guild.get_member(user.discord_id)
|
member = guild.get_member(user.discord_id)
|
||||||
return permissions.is_member_technician(member)
|
return permissions.is_member_technician(member)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ServiceProviderABC.inject
|
@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)
|
guild = bot.get_guild(user.server.discord_id)
|
||||||
member = guild.get_member(user.discord_id)
|
member = guild.get_member(user.discord_id)
|
||||||
return permissions.is_member_admin(member)
|
return permissions.is_member_admin(member)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ServiceProviderABC.inject
|
@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)
|
guild = bot.get_guild(user.server.discord_id)
|
||||||
member = guild.get_member(user.discord_id)
|
member = guild.get_member(user.discord_id)
|
||||||
return permissions.is_member_moderator(member)
|
return permissions.is_member_moderator(member)
|
@@ -13,7 +13,9 @@ class ServerTransformer(TransformerABC):
|
|||||||
return Server(dto.discord_id)
|
return Server(dto.discord_id)
|
||||||
|
|
||||||
@staticmethod
|
@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(
|
return ServerDTO(
|
||||||
db.id,
|
db.id,
|
||||||
db.discord_id,
|
db.discord_id,
|
@@ -15,7 +15,7 @@ __title__ = "bot_core"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports
|
# imports
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -15,7 +15,7 @@ __title__ = "bot_core.abc"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -45,7 +45,9 @@ class ClientUtilsABC(ABC):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@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
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
@@ -64,7 +66,11 @@ class ClientUtilsABC(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def react_to_message_by_auto_role_rule(
|
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
|
pass
|
||||||
|
|
@@ -18,7 +18,9 @@ class CustomFileLoggerABC(Logger, ABC):
|
|||||||
env: ApplicationEnvironmentABC,
|
env: ApplicationEnvironmentABC,
|
||||||
):
|
):
|
||||||
self._key = key
|
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)
|
Logger.__init__(self, self._settings, time_format, env)
|
||||||
self._begin_log()
|
self._begin_log()
|
||||||
|
|
||||||
@@ -32,7 +34,9 @@ class CustomFileLoggerABC(Logger, ABC):
|
|||||||
self.info(__name__, f"Starting...")
|
self.info(__name__, f"Starting...")
|
||||||
self._console = LoggingLevelEnum(console_level)
|
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(" ")
|
names = name_list_as_str.split(" ")
|
||||||
log_level = level.name
|
log_level = level.name
|
||||||
string = f"<{self._get_datetime_now()}> [ {log_level} ]"
|
string = f"<{self._get_datetime_now()}> [ {log_level} ]"
|
@@ -13,7 +13,9 @@ class MessageServiceABC(ABC):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@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
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
30
bot/src/bot_core/abc/task_abc.py
Normal file
30
bot/src/bot_core/abc/task_abc.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import asyncio
|
||||||
|
from abc import abstractmethod
|
||||||
|
|
||||||
|
from cpl_core.configuration import ConfigurationABC
|
||||||
|
from cpl_core.dependency_injection import ServiceProviderABC
|
||||||
|
from cpl_discord.service import DiscordBotServiceABC
|
||||||
|
from discord.ext import commands
|
||||||
|
|
||||||
|
from bot_core.logging.task_logger import TaskLogger
|
||||||
|
|
||||||
|
|
||||||
|
class TaskABC(commands.Cog):
|
||||||
|
@abstractmethod
|
||||||
|
def __init__(self):
|
||||||
|
commands.Cog.__init__(self)
|
||||||
|
|
||||||
|
@ServiceProviderABC.inject
|
||||||
|
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()
|
||||||
|
|
||||||
|
async def wait():
|
||||||
|
is_ready = config.get_configuration("IS_READY")
|
||||||
|
if is_ready != "true":
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
await wait()
|
||||||
|
|
||||||
|
await wait()
|
@@ -3,8 +3,8 @@
|
|||||||
"Name": "bot-core",
|
"Name": "bot-core",
|
||||||
"Version": {
|
"Version": {
|
||||||
"Major": "1",
|
"Major": "1",
|
||||||
"Minor": "1",
|
"Minor": "2",
|
||||||
"Micro": "7"
|
"Micro": "0"
|
||||||
},
|
},
|
||||||
"Author": "Sven Heidemann",
|
"Author": "Sven Heidemann",
|
||||||
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
@@ -15,7 +15,7 @@ __title__ = "bot_core.configuration"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -17,6 +17,7 @@ class FeatureFlagsEnum(Enum):
|
|||||||
moderator_module = "ModeratorModule"
|
moderator_module = "ModeratorModule"
|
||||||
permission_module = "PermissionModule"
|
permission_module = "PermissionModule"
|
||||||
short_role_name_module = "ShortRoleNameModule"
|
short_role_name_module = "ShortRoleNameModule"
|
||||||
|
steam_special_offers_module = "SteamSpecialOffersModule"
|
||||||
# features
|
# features
|
||||||
api_only = "ApiOnly"
|
api_only = "ApiOnly"
|
||||||
presence = "Presence"
|
presence = "Presence"
|
||||||
@@ -24,3 +25,5 @@ class FeatureFlagsEnum(Enum):
|
|||||||
game_server = "GameServer"
|
game_server = "GameServer"
|
||||||
sync_xp = "SyncXp"
|
sync_xp = "SyncXp"
|
||||||
short_role_name = "ShortRoleName"
|
short_role_name = "ShortRoleName"
|
||||||
|
technician_full_access = "TechnicianFullAccess"
|
||||||
|
steam_special_offers = "SteamSpecialOffers"
|
@@ -19,6 +19,7 @@ class FeatureFlagsSettings(ConfigurationModelABC):
|
|||||||
FeatureFlagsEnum.permission_module.value: True, # 02.10.2022 #48
|
FeatureFlagsEnum.permission_module.value: True, # 02.10.2022 #48
|
||||||
FeatureFlagsEnum.config_module.value: True, # 19.07.2023 #127
|
FeatureFlagsEnum.config_module.value: True, # 19.07.2023 #127
|
||||||
FeatureFlagsEnum.short_role_name_module.value: True, # 28.09.2023 #378
|
FeatureFlagsEnum.short_role_name_module.value: True, # 28.09.2023 #378
|
||||||
|
FeatureFlagsEnum.steam_special_offers_module.value: True, # 11.10.2023 #188
|
||||||
# features
|
# features
|
||||||
FeatureFlagsEnum.api_only.value: False, # 13.10.2022 #70
|
FeatureFlagsEnum.api_only.value: False, # 13.10.2022 #70
|
||||||
FeatureFlagsEnum.presence.value: True, # 03.10.2022 #56
|
FeatureFlagsEnum.presence.value: True, # 03.10.2022 #56
|
||||||
@@ -26,6 +27,8 @@ class FeatureFlagsSettings(ConfigurationModelABC):
|
|||||||
FeatureFlagsEnum.game_server.value: False, # 25.09.2023 #366
|
FeatureFlagsEnum.game_server.value: False, # 25.09.2023 #366
|
||||||
FeatureFlagsEnum.sync_xp.value: False, # 25.09.2023 #366
|
FeatureFlagsEnum.sync_xp.value: False, # 25.09.2023 #366
|
||||||
FeatureFlagsEnum.short_role_name.value: False, # 28.09.2023 #378
|
FeatureFlagsEnum.short_role_name.value: False, # 28.09.2023 #378
|
||||||
|
FeatureFlagsEnum.technician_full_access.value: False, # 03.10.2023 #393
|
||||||
|
FeatureFlagsEnum.steam_special_offers.value: False, # 11.10.2023 #188
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, **kwargs: dict):
|
def __init__(self, **kwargs: dict):
|
@@ -10,7 +10,9 @@ class FileLoggingSettings(LoggingSettings):
|
|||||||
console_log_level: LoggingLevelEnum = None,
|
console_log_level: LoggingLevelEnum = None,
|
||||||
file_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
|
self._key = key
|
||||||
|
|
@@ -15,7 +15,7 @@ __title__ = "bot_core.core_extension"
|
|||||||
__author__ = "Sven Heidemann"
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = "1.1.7"
|
__version__ = "1.2.0"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
|||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major="1", minor="1", micro="7")
|
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -17,7 +17,9 @@ class CoreExtension(ApplicationExtensionABC):
|
|||||||
ApplicationExtensionABC.__init__(self)
|
ApplicationExtensionABC.__init__(self)
|
||||||
|
|
||||||
async def run(self, config: ConfigurationABC, services: ServiceProviderABC):
|
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):
|
if not feature_flags.get_flag(FeatureFlagsEnum.core_module):
|
||||||
return
|
return
|
||||||
|
|
@@ -15,8 +15,14 @@ class CoreExtensionModule(ModuleABC):
|
|||||||
def __init__(self, dc: DiscordCollectionABC):
|
def __init__(self, dc: DiscordCollectionABC):
|
||||||
ModuleABC.__init__(self, dc, FeatureFlagsEnum.core_extension_module)
|
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
|
pass
|
||||||
|
|
||||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
def configure_services(
|
||||||
self._dc.add_event(DiscordEventTypesEnum.on_ready.value, CoreExtensionOnReadyEvent)
|
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
|
||||||
|
):
|
||||||
|
services.add_transient(
|
||||||
|
DiscordEventTypesEnum.on_ready.value, CoreExtensionOnReadyEvent
|
||||||
|
)
|
@@ -20,10 +20,14 @@ class CoreModule(ModuleABC):
|
|||||||
def __init__(self, dc: DiscordCollectionABC):
|
def __init__(self, dc: DiscordCollectionABC):
|
||||||
ModuleABC.__init__(self, dc, FeatureFlagsEnum.core_module)
|
ModuleABC.__init__(self, dc, FeatureFlagsEnum.core_module)
|
||||||
|
|
||||||
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
|
def configure_configuration(
|
||||||
|
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
|
||||||
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
def configure_services(
|
||||||
|
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
|
||||||
|
):
|
||||||
services.add_transient(ConfigService)
|
services.add_transient(ConfigService)
|
||||||
services.add_transient(MessageServiceABC, MessageService)
|
services.add_transient(MessageServiceABC, MessageService)
|
||||||
services.add_transient(ClientUtilsABC, ClientUtilsService)
|
services.add_transient(ClientUtilsABC, ClientUtilsService)
|
||||||
@@ -32,4 +36,4 @@ class CoreModule(ModuleABC):
|
|||||||
# pipes
|
# pipes
|
||||||
services.add_transient(DateTimeOffsetPipe)
|
services.add_transient(DateTimeOffsetPipe)
|
||||||
|
|
||||||
self._dc.add_event(DiscordEventTypesEnum.on_ready.value, CoreOnReadyEvent)
|
services.add_transient(DiscordEventTypesEnum.on_ready.value, CoreOnReadyEvent)
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user