Improved permission handling
This commit is contained in:
		| @@ -71,12 +71,10 @@ class Startup(StartupABC): | ||||
|          | ||||
|         services.add_db_context(DBContext, self._config.get_configuration(DatabaseSettings)) | ||||
|          | ||||
|         # modules | ||||
|         # general services | ||||
|         services.add_singleton(ModuleServiceABC, ModuleService) | ||||
|         services.add_singleton(BotServiceABC, BotService) | ||||
|         services.add_transient(MessageServiceABC, MessageService) | ||||
|          | ||||
|         # general services | ||||
|         services.add_transient(MigrationService) | ||||
|  | ||||
|         # data services | ||||
| @@ -87,14 +85,15 @@ class Startup(StartupABC): | ||||
|         services.add_transient(UserJoinedServerRepositoryABC, UserJoinedServerRepositoryService) | ||||
|         services.add_transient(UserJoinedVoiceChannelRepositoryABC, UserJoinedVoiceChannelRepositoryService) | ||||
|  | ||||
|         # module services | ||||
|         services.add_singleton(PermissionServiceABC, PermissionService) | ||||
|          | ||||
|         # modules | ||||
|         services.add_transient(ModuleABC, Permission) | ||||
|         services.add_transient(ModuleABC, Database) | ||||
|         services.add_transient(ModuleABC, Base) | ||||
|         services.add_transient(ModuleABC, BootLog) | ||||
|  | ||||
|         # permission module services | ||||
|         services.add_transient(PermissionServiceABC, PermissionService) | ||||
|         services.add_singleton(ModuleABC, Permission) | ||||
|         services.add_singleton(ModuleABC, Base) | ||||
|          | ||||
|  | ||||
|         # migrations | ||||
|         services.add_transient(MigrationABC, InitialMigration) | ||||
|   | ||||
| @@ -20,6 +20,7 @@ from gismo_data.model.user import User | ||||
| from gismo_data.model.user_joined_server import UserJoinedServer | ||||
| from gismo_data.model.user_joined_voice_channel import UserJoinedVoiceChannel | ||||
| from modules.base.base_settings import BaseSettings | ||||
| from modules.permission.abc.permission_service_abc import PermissionServiceABC | ||||
| from modules_core.abc.events.on_member_join_abc import OnMemberJoinABC | ||||
| from modules_core.abc.events.on_member_remove_abc import OnMemberRemoveABC | ||||
| from modules_core.abc.events.on_message_abc import OnMessageABC | ||||
| @@ -42,7 +43,8 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS | ||||
|         user_joins_vc: UserJoinedVoiceChannelRepositoryABC, | ||||
|         bot: BotServiceABC, | ||||
|         db: DatabaseContextABC, | ||||
|         messenger: MessageServiceABC | ||||
|         messenger: MessageServiceABC, | ||||
|         permission_service: PermissionServiceABC | ||||
|     ): | ||||
|         self._config = config | ||||
|         self._logger = logger | ||||
| @@ -55,6 +57,7 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS | ||||
|         self._bot = bot | ||||
|         self._db = db | ||||
|         self._messenger = messenger | ||||
|         self._permission_service = permission_service | ||||
|  | ||||
|         ModuleABC.__init__( | ||||
|             self, | ||||
| @@ -66,7 +69,7 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS | ||||
|             }, | ||||
|             BaseSettings | ||||
|         ) | ||||
|         self._logger.trace(__name__, f'Module {type(self)} loaded') | ||||
|         self._logger.info(__name__, f'Module {type(self)} loaded') | ||||
|  | ||||
|     def _get_config(self, g_id: int) -> BaseSettings: | ||||
|         return self._config.get_configuration(f'{type(self).__name__}_{g_id}') | ||||
| @@ -100,21 +103,14 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS | ||||
|  | ||||
|     async def _add_if_not_exists_user(self, member: Union[discord.User, discord.Member]): | ||||
|         self._logger.debug(__name__, f'Check if user exists {member}') | ||||
|         # todo: user permission service | ||||
|         settings: BaseSettings = self._get_config() | ||||
|         await self._messenger.send_dm_message(settings.welcome_message.format(member.guild.name), member) | ||||
|  | ||||
|         for roleId in settings.admin_roles: | ||||
|             g: discord.Guild = member.guild  | ||||
|             role: discord.Role = g.get_role(roleId) | ||||
|             for admin in role.members: | ||||
|                 await self._messenger.send_dm_message(settings.welcome_message_for_team.format(member.name), admin) | ||||
|         for admin in self._permission_service.get_admins(): | ||||
|             await self._messenger.send_dm_message(settings.welcome_message_for_team.format(member.name), admin) | ||||
|  | ||||
|         for roleId in settings.moderator_roles: | ||||
|             g: discord.Guild = member.guild  | ||||
|             role: discord.Role = g.get_role(roleId) | ||||
|             for mod in role.members: | ||||
|                 await self._messenger.send_dm_message(settings.welcome_message_for_team.format(member.name), mod) | ||||
|         for moderator in self._permission_service.get_moderators(): | ||||
|             await self._messenger.send_dm_message(settings.welcome_message_for_team.format(member.name), moderator) | ||||
|  | ||||
|         try: | ||||
|             server = self._servers.get_server_by_discord_id(member.guild.id) | ||||
|   | ||||
| @@ -35,7 +35,7 @@ class BootLog(ModuleABC, OnReadyABC): | ||||
|             }, | ||||
|             BootLogSettings | ||||
|         ) | ||||
|         self._logger.trace(__name__, f'Module {type(self)} loaded') | ||||
|         self._logger.info(__name__, f'Module {type(self)} loaded') | ||||
|  | ||||
|     async def on_ready(self): | ||||
|         self._logger.debug(__name__, f'Module {type(self)} started') | ||||
|   | ||||
| @@ -57,7 +57,7 @@ class Database(ModuleABC, OnReadyABC): | ||||
|             { OnReadyABC: 0 }, | ||||
|             None | ||||
|         ) | ||||
|         self._logger.trace(__name__, f'Module {type(self)} loaded') | ||||
|         self._logger.info(__name__, f'Module {type(self)} loaded') | ||||
|      | ||||
|     def _validate_init_time(self): | ||||
|         try: | ||||
|   | ||||
| @@ -1,7 +1,32 @@ | ||||
| from abc import ABC, abstractmethod | ||||
|  | ||||
| import discord | ||||
|  | ||||
| class PermissionServiceABC(ABC): | ||||
|  | ||||
|     @abstractmethod | ||||
|     def __init__(self): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def on_ready(self): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def on_member_update(self, before: discord.Member, after: discord.Member): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_admin_role_ids(self, g_id: int) -> list[int]: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_admin_roles(self, g_id: int) -> list[discord.Role]: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_admins(self, g_id: int) -> list[discord.Member]: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_moderator_role_ids(self, g_id: int) -> list[int]: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_moderator_roles(self, g_id: int) -> list[discord.Role]: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_moderators(self, g_id: int) -> list[discord.Member]: pass | ||||
|   | ||||
| @@ -12,7 +12,6 @@ class PermissionSettings(ConfigurationModelABC): | ||||
|         self._admin_roles: list[int] = [] | ||||
|         self._moderator_roles: list[int] = [] | ||||
|  | ||||
|  | ||||
|     @property | ||||
|     def admin_roles(self) -> list[int]: | ||||
|         return self._admin_roles | ||||
|   | ||||
| @@ -1,41 +1,37 @@ | ||||
| from ctypes import Union | ||||
| from datetime import datetime | ||||
|  | ||||
| import discord | ||||
| from cpl_core.configuration import ConfigurationABC | ||||
| from cpl_core.database.context import DatabaseContextABC | ||||
| from cpl_core.logging import LoggerABC | ||||
|  | ||||
| from gismo_core.abc.bot_service_abc import BotServiceABC | ||||
| from gismo_core.configuration.server_settings import ServerSettings | ||||
| from gismo_data.abc.client_repository_abc import ClientRepositoryABC | ||||
| from gismo_data.abc.known_user_repository_abc import KnownUserRepositoryABC | ||||
| from gismo_data.abc.user_joined_server_repository_abc import \ | ||||
|     UserJoinedServerRepositoryABC | ||||
| from gismo_data.abc.user_joined_voice_channel_abc import UserJoinedVoiceChannelRepositoryABC | ||||
| from gismo_data.abc.user_repository_abc import UserRepositoryABC | ||||
| from gismo_data.model.client import Client | ||||
| from gismo_data.model.known_user import KnownUser | ||||
| from gismo_data.model.server import Server | ||||
| from gismo_data.model.user import User | ||||
| from gismo_data.model.user_joined_server import UserJoinedServer | ||||
| from gismo_data.model.user_joined_voice_channel import UserJoinedVoiceChannel | ||||
| from gismo_data.service.user_repository_service import ServerRepositoryABC | ||||
| from modules.permission.configuration.permission_settings import PermissionSettings | ||||
| from cpl_core.logging import LoggerABC | ||||
| from modules.permission.abc.permission_service_abc import PermissionServiceABC | ||||
| from modules.permission.configuration.permission_settings import \ | ||||
|     PermissionSettings | ||||
| from modules_core.abc.events.on_member_update_abc import OnMemberUpdateABC | ||||
| from modules_core.abc.events.on_ready_abc import OnReadyABC | ||||
| from modules_core.abc.module_abc import ModuleABC | ||||
|  | ||||
|  | ||||
| class Permission(ModuleABC): | ||||
| class Permission(ModuleABC, OnReadyABC, OnMemberUpdateABC): | ||||
|  | ||||
|     def __init__( | ||||
|         self, | ||||
|         logger: LoggerABC, | ||||
|         permission_service: PermissionServiceABC | ||||
|     ): | ||||
|         self._logger = logger | ||||
|         self._permission_service = permission_service | ||||
|  | ||||
|         ModuleABC.__init__( | ||||
|             self, | ||||
|             { OnReadyABC: 0 }, | ||||
|             { OnReadyABC: 1, OnMemberUpdateABC: 0 }, | ||||
|             PermissionSettings | ||||
|         ) | ||||
|         self._logger.trace(__name__, f'Module {type(self)} loaded') | ||||
|         self._logger.info(__name__, f'Module {type(self)} loaded') | ||||
|  | ||||
|     async def on_ready(self): | ||||
|         self._logger.debug(__name__, f'Module {type(self)} started') | ||||
|         self._permission_service.on_ready() | ||||
|  | ||||
|     async def on_member_update(self, before: discord.Member, after: discord.Member): | ||||
|         self._logger.debug(__name__, f'Module {type(self)} started') | ||||
|  | ||||
|         if before.roles != after.roles: | ||||
|             self._permission_service.on_member_update(before, after) | ||||
| @@ -1,4 +1,88 @@ | ||||
| class PermissionService: | ||||
| import discord | ||||
| from cpl_core.logging import LoggerABC | ||||
| from cpl_core.configuration import ConfigurationABC | ||||
| from gismo_core.abc.bot_service_abc import BotServiceABC | ||||
| from modules.permission.abc.permission_service_abc import PermissionServiceABC | ||||
| from modules.permission.configuration.permission_settings import PermissionSettings | ||||
|  | ||||
|     def __init__(self): | ||||
|         pass | ||||
|  | ||||
| class PermissionService(PermissionServiceABC): | ||||
|  | ||||
|     def __init__(self, logger: LoggerABC, bot: BotServiceABC, config: ConfigurationABC): | ||||
|         PermissionServiceABC.__init__(self) | ||||
|         self._logger = logger | ||||
|         self._bot = bot | ||||
|         self._config = config | ||||
|  | ||||
|         self._admin_role_ids: dict[str, list[int]] = {} | ||||
|         self._admin_roles: dict[list[discord.Role]] = {} | ||||
|         self._admins: dict[list[discord.Member]] = {} | ||||
|          | ||||
|         self._moderator_role_ids: dict[list[int]] = {} | ||||
|         self._moderator_roles: dict[list[discord.Role]] = {} | ||||
|         self._moderators: dict[list[discord.Member]] = {} | ||||
|  | ||||
|     def on_ready(self):  | ||||
|         for guild in self._bot.guilds: | ||||
|             guild: discord.Guild = guild | ||||
|  | ||||
|             settings: PermissionSettings = self._config.get_configuration(f'Permission_{guild.id}') | ||||
|             if settings is None: | ||||
|                 self._logger.error(__name__, 'Permission settings not found') | ||||
|                 return | ||||
|              | ||||
|             self._admin_role_ids[guild.id] = settings.admin_roles | ||||
|             self._admin_roles[guild.id] = [] | ||||
|             self._admins[guild.id] = [] | ||||
|              | ||||
|             self._moderator_role_ids[guild.id] = settings.moderator_roles | ||||
|             self._moderator_roles[guild.id] = [] | ||||
|             self._moderators[guild.id] = [] | ||||
|  | ||||
|             for role in guild.roles: | ||||
|                 role: discord.Role = role | ||||
|  | ||||
|                 if role.id in self._admin_role_ids: | ||||
|                     self._admin_roles[guild.id].append(role) | ||||
|  | ||||
|                     for member in role.members: | ||||
|                         self._admins[guild.id].append(member) | ||||
|  | ||||
|                 if role.id in self._moderator_role_ids: | ||||
|                     self._moderator_roles[guild.id].append(role) | ||||
|  | ||||
|                     for member in role.members: | ||||
|                         self._moderators[guild.id].append(member) | ||||
|  | ||||
|     def on_member_update(self, before: discord.Member, after: discord.Member): | ||||
|         g_id = after.guild.id | ||||
|          | ||||
|         if before in self._admin_roles[g_id] and after not in self._admin_roles[g_id]: | ||||
|             self._admins[g_id].remove(after) | ||||
|          | ||||
|         elif before not in self._admin_roles[g_id] and after in self._admin_roles[g_id]: | ||||
|             self._admins[g_id].append(after) | ||||
|  | ||||
|         if before in self._moderator_roles[g_id] and after not in self._moderator_roles[g_id]: | ||||
|             self._moderators[g_id].remove(after) | ||||
|          | ||||
|         elif before not in self._moderator_roles[g_id] and after in self._moderator_roles[g_id]: | ||||
|             self._moderators[g_id].append(after)    | ||||
|  | ||||
|     def get_admin_role_ids(self, g_id: int) -> list[int]: | ||||
|         return self._admin_role_ids[g_id] | ||||
|  | ||||
|     def get_admin_roles(self, g_id: int) -> list[discord.Role]: | ||||
|         return self._admin_roles[g_id] | ||||
|  | ||||
|     def get_admins(self, g_id: int) -> list[discord.Member]: | ||||
|         return self._admins[g_id] | ||||
|  | ||||
|     def get_moderator_role_ids(self, g_id: int) -> list[int]: | ||||
|         return self._moderator_role_ids[g_id] | ||||
|  | ||||
|     def get_moderator_roles(self, g_id: int) -> list[discord.Role]: | ||||
|         return self._moderator_roles[g_id] | ||||
|  | ||||
|     def get_moderators(self, g_id: int) -> list[discord.Member]: | ||||
|         return self._moderators[g_id] | ||||
|   | ||||
| @@ -90,7 +90,7 @@ class ModuleService(ModuleServiceABC, commands.Cog, metaclass=_MetaCogABC): | ||||
|                         settings: ConfigurationModelABC = module.settings_type() | ||||
|                         settings.from_dict(json_cfg[id]) | ||||
|                         self._config.add_configuration(f'{type(module).__name__}_{id}', settings) | ||||
|                         self._logger.debug(__name__, f'Added config: {type(module).__name__}_{id}') | ||||
|                         self._logger.info(__name__, f'Added config: {type(module).__name__}_{id}') | ||||
|  | ||||
|             modules.append(module) | ||||
|          | ||||
| @@ -103,14 +103,18 @@ class ModuleService(ModuleServiceABC, commands.Cog, metaclass=_MetaCogABC): | ||||
|         if modules.count() < 1: | ||||
|             self._logger.debug(__name__, f'Stopped {event} modules') | ||||
|             return | ||||
|              | ||||
|         func_name = String.convert_to_snake_case(event.__name__.split('ABC')[0]) | ||||
|         for module in modules: | ||||
|             func = getattr(module, func_name) | ||||
|             await func(*args) | ||||
|             if not module.success: | ||||
|                 self._logger.debug(__name__, f'Stopped propagation for {event} from {type(module)}') | ||||
|                 break | ||||
|          | ||||
|         try: | ||||
|             func_name = String.convert_to_snake_case(event.__name__.split('ABC')[0]) | ||||
|             for module in modules: | ||||
|                 self._logger.trace(__name__, f'Start {type(module)} module') | ||||
|                 func = getattr(module, func_name) | ||||
|                 await func(*args) | ||||
|                 if not module.success: | ||||
|                     self._logger.debug(__name__, f'Stopped propagation for {event} from {type(module)}') | ||||
|                     break | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f'Start {event} modules failed', e) | ||||
|          | ||||
|         self._logger.debug(__name__, f'Stopped {event} modules') | ||||
|      | ||||
|   | ||||
		Reference in New Issue
	
	Block a user