From 1a388229e830d9f23b94882fa6553a2a4c5c2aca Mon Sep 17 00:00:00 2001 From: Alexei Date: Sun, 8 Oct 2023 23:34:33 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B0=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0?= =?UTF-8?q?=20=D1=81=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- auth_docs/test_doc.odt | 273 +++++++++++++++++++++++++++++++++++++++ bot_modules/authorize.py | 128 ++++++++++++++++-- bot_modules/mod_table_operate.py | 11 +- bot_sys/bot_bd.py | 1 + bot_sys/user_access.py | 2 + config_auth_docs | 1 + requirements.txt | 1 + template/docs_message.py | 77 +++++++++++ template/file_message.py | 2 +- 9 files changed, 480 insertions(+), 16 deletions(-) create mode 100644 auth_docs/test_doc.odt create mode 100644 config_auth_docs create mode 100644 template/docs_message.py diff --git a/auth_docs/test_doc.odt b/auth_docs/test_doc.odt new file mode 100644 index 0000000..6047b4a --- /dev/null +++ b/auth_docs/test_doc.odt @@ -0,0 +1,273 @@ + + + + 2023-10-08T23:17:27.894126099PT46S2LibreOffice/7.3.6.2$Linux_X86_64 LibreOffice_project/30$Build-2 + + + 0 + 0 + 35588 + 13813 + true + false + + + view2 + 22826 + 5909 + 0 + 0 + 35586 + 13811 + 0 + 1 + false + 100 + false + false + false + + + + + false + false + false + true + true + true + true + true + false + 0 + false + false + false + true + false + false + true + false + false + false + false + true + true + true + false + false + false + false + false + false + false + true + false + false + true + false + false + false + true + 0 + 1 + true + false + + high-resolution + true + + + false + false + true + false + true + true + false + true + + true + 820887 + + true + false + true + true + 0 + + false + false + false + true + false + true + false + false + false + false + true + false + false + + false + false + true + false + false + false + false + false + false + false + false + false + 820887 + false + false + false + false + false + true + false + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bd_table.TableFieldDestiny.USER_NAME: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_FAMILY_NAME: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_MIDDLE_NAME: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_BIRTHDAY: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_ADDRESS: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_CONTACTS: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_CONFIRM: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.ACCESS: user_access.AccessMode.NONE, + + + \ No newline at end of file diff --git a/bot_modules/authorize.py b/bot_modules/authorize.py index 2831c0a..e2f515e 100644 --- a/bot_modules/authorize.py +++ b/bot_modules/authorize.py @@ -3,8 +3,9 @@ # Авторизация или регистрация в кооперативе или другой организации -from bot_sys import bot_bd, keyboard, user_access, bd_table, bot_subscribes +from bot_sys import bot_bd, keyboard, user_access, bd_table, bot_subscribes, config from bot_modules import mod_table_operate, mod_simple_message +from template import docs_message from enum import Enum from enum import auto @@ -50,6 +51,12 @@ table = bd_table.Table(table_name, [ init_access = f'{user_access.user_access_group_new}=va' +def GetAuthorizeItem(a_Bot, a_UserID): + items = bd_item.GetBDItemsTemplate(a_Bot, table_name, user_id_field)(a_UserID) + if len(items) == 1: + return items[0] + return None + # --------------------------------------------------------- # Сообщения и кнопки @@ -60,24 +67,35 @@ button_names = { mod_simple_message.ButtonNames.START: "🔑 Авторизация", mod_table_operate.ButtonNames.LIST: "≣ Список авторизаций пользователей", mod_table_operate.ButtonNames.ADD: "📨 Заявка на вступление", + ButtonNames.LIST_AUTH_DOCS: "📨 Регистрационные документы", mod_table_operate.ButtonNames.EDIT: "🛠 Редактировать свои данные", - mod_table_operate.EditButton(bd_table.TableFieldDestiny.USER_ID): "☐ Изменить id пользователя", - mod_table_operate.EditButton(bd_table.TableFieldDestiny.USER_NAME): "☐ Изменить имя пользователя", - mod_table_operate.EditButton(bd_table.TableFieldDestiny.USER_FAMILY_NAME): "☐ Изменить фамилию пользователя", - mod_table_operate.EditButton(bd_table.TableFieldDestiny.USER_MIDDLE_NAME): "☐ Изменить отчество пользователя", - mod_table_operate.EditButton(bd_table.TableFieldDestiny.USER_BIRTHDAY): "☐ Изменить дату рождения пользователя", - mod_table_operate.EditButton(bd_table.TableFieldDestiny.USER_ADDRESS): "☐ Изменить адрес пользователя", - mod_table_operate.EditButton(bd_table.TableFieldDestiny.USER_CONTACTS): "☐ Изменить контакты пользователя", - mod_table_operate.EditButton(bd_table.TableFieldDestiny.USER_CONFIRM): "☐ Изменить подтверждение пользователя", -# mod_table_operate.EditButton(bd_table.TableFieldDestiny.USER_ID): "☐ Изменить id пользователя", - mod_table_operate.EditButton(bd_table.TableFieldDestiny.ACCESS): "✋ Доступ к авторизации пользователя", mod_table_operate.ButtonNames.DEL: "❌ Удалить авторизацию пользователя", + bd_table.TableFieldDestiny.USER_ID): "☐ Изменить id пользователя", + bd_table.TableFieldDestiny.USER_NAME): "☐ Изменить имя пользователя", + bd_table.TableFieldDestiny.USER_FAMILY_NAME): "☐ Изменить фамилию пользователя", + bd_table.TableFieldDestiny.USER_MIDDLE_NAME): "☐ Изменить отчество пользователя", + bd_table.TableFieldDestiny.USER_BIRTHDAY): "☐ Изменить дату рождения пользователя", + bd_table.TableFieldDestiny.USER_ADDRESS): "☐ Изменить адрес пользователя", + bd_table.TableFieldDestiny.USER_CONTACTS): "☐ Изменить контакты пользователя", + bd_table.TableFieldDestiny.USER_CONFIRM): "☐ Изменить подтверждение пользователя", +# bd_table.TableFieldDestiny.USER_ID): "☐ Изменить id пользователя", + bd_table.TableFieldDestiny.ACCESS): "✋ Доступ к авторизации пользователя", mod_table_operate.ButtonNames.DEL: "❌ Удалить авторизацию пользователя", } +class Messages(Enum): + LIST_AUTH_DOCS = auto() + LIST_AUTH_DOCS_ERROR = auto() + messages = { mod_simple_message.Messages.START: f''' {button_names[mod_simple_message.ButtonNames.START]} ''', + Messages.LIST_AUTH_DOCS: ''' +ваши регистрационные документы: +''', + Messages.LIST_AUTH_DOCS_ERROR: ''' +Ошибка получения документов. Обратитесь в техподдержку. +''', mod_table_operate.Messages.SELECT: ''' Пожалуйста, выберите пользователя: ''', @@ -229,3 +247,91 @@ class ModuleAuthorize(mod_table_operate.TableOperateModule): def GetName(self): return module_name + def GetAccessForEditKeyboardButtons(self, a_Field): + cur_dict = { + bd_table.TableFieldDestiny.USER_ID: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_NAME: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_FAMILY_NAME: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_MIDDLE_NAME: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_BIRTHDAY: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_ADDRESS: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_CONTACTS: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_CONFIRM: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.ACCESS: user_access.AccessMode.NONE, + } + return cur_dict.get(a_Field.m_Destiny, super().GetAccessForEditKeyboardButtons(a_Field)) + + def GetButtonNameAndKeyValueAndAccess(self, a_Item): + key_name_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.USER_ID) + name_field_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.USER_NAME) + fam_name_field_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.USER_FAMILY_NAME) + access_field_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.ACCESS) + assert key_name_id != None + assert name_field_id != None + assert fam_name_field_id != None + assert access_field_id != None + return \ + a_Item[name_field_id] + ' ' + a_Item[fam_name_field_id] + '(' + a_Item[key_name_id] +')',\ + a_Item[key_name_id],\ + a_Item[access_field_id] + + def GetStartKeyboardButtons(self, a_Message, a_UserGroups): + parent_buttons = super().GetStartKeyboardButtons(a_Message, a_UserGroups) + user_id = str(a_Message.from_user.id) + item = GetAuthorizeItem(self.m_Bot, user_id) + user_confirm_field_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.USER_CONFIRM) + cur_buttons = [] + if item and item[user_confirm_field_id] == str(ConfirmStatus.YES): + cur_buttons += [ + keyboard.ButtonWithAccess(self.GetButton(ButtonNames.LIST_AUTH_DOCS), user_access.AccessMode.VIEW, self.GetAccess()), + ] + return parent_buttons + keyboard.MakeButtons(self.m_Bot, cur_buttons, a_UserGroups) + + def RegisterHandlers(self): + super().RegisterHandlers() + + def GetFilesFunc(a_user_id): + files = GetAuthDocs() + cur_dict = GetReplaceDictFunc(self.m_Bot, a_user_id) + result = {} + for f in files: + result.update({f, cur_dict}) + return result + + button_name = self.GetButton(ButtonNames.LIST_AUTH_DOCS) + if button_name: + self.m_Bot.RegisterMessageHandler( + docs_message.BackupFileTemplate( + self.m_Bot, + GetFilesFunc, + self.GetMessage(Messages.LIST_AUTH_DOCS), + self.m_GetAccessFunc, + self.m_GetStartKeyboardButtonsFunc, + None, + self.GetMessage(Messages.LIST_AUTH_DOCS_ERROR), + access_mode = user_access.AccessMode.VIEW + ), + bd_item.GetCheckForTextFunc(button_name) + ) + +def GetReplaceDictFunc(a_Bot, a_user_id): + item = GetAuthorizeItem(self.m_Bot, user_id) + if not item: + return None + result = {} + i = 0 + for f in table: + result.update({str(f.m_Destiny), item[i]}) + i += 1 + return result + +auth_docs_file_name = 'config_auth_docs' + +def GetAuthDocs(): + global g_auth_docs + if len(g_auth_docs) == 0: + root_ids = config.GetAllLinesFromFile(auth_docs_file_name) + for i in root_ids: + g_auth_docs += [config.ClearReadLine(i)] + + return g_auth_docs diff --git a/bot_modules/mod_table_operate.py b/bot_modules/mod_table_operate.py index acff162..e927b0d 100644 --- a/bot_modules/mod_table_operate.py +++ b/bot_modules/mod_table_operate.py @@ -126,13 +126,16 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule): ] return mod_buttons + keyboard.MakeButtons(self.m_Bot, cur_buttons, a_UserGroups) + def GetAccessForEditKeyboardButtons(self, a_Field): + if a_Field.m_Destiny == bd_table.TableFieldDestiny.ACCESS or a_Field.m_Destiny == bd_table.TableFieldDestiny.DEFAULT_ACCESS: + return user_access.AccessMode.ACCEES_EDIT + return user_access.AccessMode.EDIT + def GetEditKeyboardButtons(self, a_Message, a_UserGroups): mod_buttons = keyboard.MakeButtons(self.m_Bot, self.GetButtons(self.m_EditModuleNameList), a_UserGroups) cur_buttons = [] for f in self.m_Table.GetFields(): - access = user_access.AccessMode.EDIT - if f.m_Destiny == bd_table.TableFieldDestiny.ACCESS or f.m_Destiny == bd_table.TableFieldDestiny.DEFAULT_ACCESS: - access = user_access.AccessMode.ACCEES_EDIT + access = self.GetAccessForEditKeyboardButtons(f) cur_buttons += [keyboard.ButtonWithAccess(self.GetButton(EditButton(f.m_Destiny)), access, self.GetAccess()),] return mod_buttons + keyboard.MakeButtons(self.m_Bot, cur_buttons, a_UserGroups) @@ -185,7 +188,7 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule): def ShowMessageTemplate(self, a_Message, Inline_keyboard_template_func = None, a_EnablePhoto = False): async def ShowMessage(a_CallbackQuery, a_Item): msg = a_Message.StaticCopy() - # TODO: добавить поддержку языка в a_MessageName + # TODO: добавить поддержку языков в a_MessageName Inline_keyboard_func = None item_access = None if a_Item: diff --git a/bot_sys/bot_bd.py b/bot_sys/bot_bd.py index ec81174..47583b2 100644 --- a/bot_sys/bot_bd.py +++ b/bot_sys/bot_bd.py @@ -9,6 +9,7 @@ from bot_sys import log def GetBDDateTimeNow(): return 'datetime(\'now\')' +# TODO: Удалить что-то из SelectBDTemplate RequestSelectTemplate def SelectBDTemplate(a_Bot, a_TableName): def SelectBD(): return a_Bot.SQLRequest(f'SELECT * FROM {a_TableName}') diff --git a/bot_sys/user_access.py b/bot_sys/user_access.py index abe3127..29750ca 100644 --- a/bot_sys/user_access.py +++ b/bot_sys/user_access.py @@ -32,11 +32,13 @@ ACCEES_EDIT = 'r' - изменение прав доступа # Типы уровня доступа class AccessMode(Enum): + NONE = '-' VIEW = 'v' ADD = 'a' EDIT = 'e' DELETE = 'd' ACCEES_EDIT = 'r' + ALL = '+' class UserGroups: def __init__(self, a_UserID : str, a_GroupNamesList : [str]): diff --git a/config_auth_docs b/config_auth_docs new file mode 100644 index 0000000..7822470 --- /dev/null +++ b/config_auth_docs @@ -0,0 +1 @@ +auth_docs/test_doc.odt diff --git a/requirements.txt b/requirements.txt index e99a1ef..9e91223 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ aiogram==2.20 colorama==0.4.5 +odfpy diff --git a/template/docs_message.py b/template/docs_message.py new file mode 100644 index 0000000..7544125 --- /dev/null +++ b/template/docs_message.py @@ -0,0 +1,77 @@ +# -*- coding: utf8 -*- +# Общественное достояние 2023, Алексей Безбородов (Alexei Bezborodov) + +# Сообщения для работы с документами + +from bot_sys import log, config, user_access +from bot_modules import groups_utils +from template import simple_message +import odf + +def DocFilesTemplate(a_Bot, a_FilesFunc, a_CaptionMessage, a_AccessFunc, a_GetButtonsFunc, a_GetInlineButtonsFunc, a_ErrorMessage, access_mode = user_access.AccessMode.EDIT): + async def DocFiles(a_Message): + user_id = str(a_Message.from_user.id) + user_groups= groups_utils.GetUserGroupData(a_Bot, user_id) + if not user_access.CheckAccess(a_Bot.GetRootIDs(), a_AccessFunc(), user_groups, access_mode): + return await simple_message.AccessDeniedMessage(a_Bot, a_GetButtonsFunc, user_id, a_Message, user_groups) + + msg = a_CaptionMessage.GetDesc() + msg = msg.replace('@time', a_Bot.GetLog().GetTime()) + + files = a_FilesFunc(user_id) + if not files: + await simple_message.SendMessage(a_Bot, a_ErrorMessage, a_GetButtonsFunc, None, user_id, a_Message, user_groups) + return + + for file_path, dict_replace in files.values(): + if not dict_replace: + continue + new_file = await MakeDocFile(a_Bot, file_path, dict_replace, user_id) + document = await GetFile(a_Bot, file_path) + if document is None: + await simple_message.SendMessage(a_Bot, a_ErrorMessage, a_GetButtonsFunc, None, user_id, a_Message, user_groups) + else: + await a_Bot.SendDocument( + user_id, + document, + msg, + simple_message.ProxyGetButtonsTemplate(a_GetButtonsFunc)(a_Message, user_groups), + simple_message.ProxyGetButtonsTemplate(a_GetInlineButtonsFunc)(a_Message, user_groups) + ) + return DocFiles + +async def MakeDocFile(a_Bot, a_FilePath, a_DictReplace, a_user_id): + document = odf.opendocument.load(a_FilePath) + if document == None: + a_Bot.GetLog().Error(f'Не удалось загрузить файл {a_FilePath}.') + return None + + for element in document.getElementsByType(text.Span): + extracted_text = odf.teletype.extractText(element) + + for file_path, dict_replace in a_DictReplace.values(): + if extracted_text.find('Replace this') != -1: + extracted_text = extracted_text.replace('Replace this', 'to this') + + new_element = odf.text.Span() + new_element.setAttribute('stylename', element.getAttribute('stylename')) + new_element.addText(extracted_text) + + element.parentNode.insertBefore(new_element, element) + element.parentNode.removeChild(element) + + new_file_path = a_FilePath[:-4] + new_file_path += f"{a_user_id}.odt" + document.save(new_file_path) + return new_file_path + +async def GetFile(a_Bot, a_Path): + if not a_Path: + return None + try: + document = open(a_Path, 'rb') + a_Bot.GetLog().Success(f'Загружен файл {a_Path}') + return document + except Exception as e: + a_Bot.GetLog().Error(f'Не удалось загрузить файл {a_Path}. Ошибка {str(e)}') + return None diff --git a/template/file_message.py b/template/file_message.py index fe7e6a7..0159aa3 100644 --- a/template/file_message.py +++ b/template/file_message.py @@ -16,7 +16,7 @@ def BackupFileTemplate(a_Bot, a_Path, a_CaptionMessage, a_AccessFunc, a_GetButto document = await GetFile(a_Bot, a_Path) if document is None: - return simple_message.SendMessage(a_Bot, a_ErrorMessage, a_GetButtonsFunc, None, user_id, a_Message, user_groups) + return await simple_message.SendMessage(a_Bot, a_ErrorMessage, a_GetButtonsFunc, None, user_id, a_Message, user_groups) msg = a_CaptionMessage.GetDesc() msg = msg.replace('@time', a_Bot.GetLog().GetTime())