feat: add Trueconf access request flow with intermediate prompt and existing ticket check
This commit is contained in:
+45
-17
@@ -14,6 +14,7 @@ from utils.texts import (
|
|||||||
INSTRUCT_MAIN_MENU_TEXT,
|
INSTRUCT_MAIN_MENU_TEXT,
|
||||||
INSTRUCT_TRUECONF_TEXT,
|
INSTRUCT_TRUECONF_TEXT,
|
||||||
INSTRUCT_TRUECONF_WITH_AD,
|
INSTRUCT_TRUECONF_WITH_AD,
|
||||||
|
INSTRUCT_TRUECONF_PENDING_TEXT,
|
||||||
INSTRUCT_EMAIL_TEXT,
|
INSTRUCT_EMAIL_TEXT,
|
||||||
)
|
)
|
||||||
from utils.states import get_state, set_state, clear_state
|
from utils.states import get_state, set_state, clear_state
|
||||||
@@ -275,37 +276,41 @@ async def instruct_router_handler(msg: Message):
|
|||||||
await msg.answer(MENU_TEXT, parse_mode="html")
|
await msg.answer(MENU_TEXT, parse_mode="html")
|
||||||
elif cmd == "1":
|
elif cmd == "1":
|
||||||
log_menu_stats(user_id, "Инструкции", "Trueconf")
|
log_menu_stats(user_id, "Инструкции", "Trueconf")
|
||||||
set_state(user_id, "INSTRUCT_TRUECONF_VIEW")
|
|
||||||
|
|
||||||
# Получаем CN пользователя
|
# Получаем CN пользователя
|
||||||
cn = get_user_cn(user_id)
|
cn = get_user_cn(user_id)
|
||||||
if cn is None:
|
if cn is None:
|
||||||
cn = user_id # fallback
|
cn = user_id # fallback
|
||||||
|
|
||||||
# Проверяем наличие группы 2FA в AD перед созданием заявки
|
# Проверяем наличие группы 2FA в AD
|
||||||
from utils.ad_checker import check_group_membership
|
from utils.ad_checker import check_group_membership
|
||||||
ad_check = check_group_membership(cn, "2FA")
|
ad_check = check_group_membership(cn, "2FA")
|
||||||
|
|
||||||
ticket_id = None
|
if ad_check.get("in_group", False):
|
||||||
# Создаём заявку в SD ТОЛЬКО если у пользователя НЕТ группы 2FA (или он не найден)
|
# Есть доступ — сразу показываем инструкцию
|
||||||
if not ad_check.get("in_group", False):
|
set_state(user_id, "INSTRUCT_TRUECONF_VIEW")
|
||||||
ticket_id = await create_sd_ticket_for_trueconf(user_id, cn)
|
text = INSTRUCT_TRUECONF_WITH_AD(EMOJI_DIGITS, cn, None)
|
||||||
else:
|
if os.path.isfile(TRUECONF_INSTRUCT_PATH):
|
||||||
logger.info(f"User {cn} already has 2FA group. SD ticket creation skipped.")
|
|
||||||
|
|
||||||
# Показываем текст с результатом
|
|
||||||
text = INSTRUCT_TRUECONF_WITH_AD(EMOJI_DIGITS, cn, ticket_id)
|
|
||||||
if ticket_id is not None:
|
|
||||||
# Нет доступа — отправляем текст без документа
|
|
||||||
await msg.answer(text, parse_mode="html")
|
|
||||||
elif os.path.isfile(TRUECONF_INSTRUCT_PATH):
|
|
||||||
# Есть доступ — отправляем документ с caption
|
|
||||||
await msg.bot.send_document(
|
await msg.bot.send_document(
|
||||||
chat_id=msg.chat_id,
|
chat_id=msg.chat_id,
|
||||||
file=FSInputFile(TRUECONF_INSTRUCT_PATH, file_name="Инструкция.docx"),
|
file=FSInputFile(TRUECONF_INSTRUCT_PATH, file_name="Инструкция.docx"),
|
||||||
caption=text,
|
caption=text,
|
||||||
parse_mode="html"
|
parse_mode="html"
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
await msg.answer(text, parse_mode="html")
|
||||||
|
else:
|
||||||
|
# Нет доступа — проверяем, есть ли уже открытая заявка
|
||||||
|
ticket_id = await create_sd_ticket_for_trueconf(user_id, cn)
|
||||||
|
if ticket_id:
|
||||||
|
# Заявка уже существует — показываем информацию
|
||||||
|
set_state(user_id, "INSTRUCT_TRUECONF_VIEW")
|
||||||
|
text = INSTRUCT_TRUECONF_WITH_AD(EMOJI_DIGITS, cn, ticket_id)
|
||||||
|
await msg.answer(text, parse_mode="html")
|
||||||
|
else:
|
||||||
|
# Заявки нет — показываем промпт с запросом
|
||||||
|
set_state(user_id, "INSTRUCT_TRUECONF_PENDING")
|
||||||
|
text = INSTRUCT_TRUECONF_PENDING_TEXT(EMOJI_DIGITS, cn)
|
||||||
|
await msg.answer(text, parse_mode="html")
|
||||||
elif cmd == "2":
|
elif cmd == "2":
|
||||||
log_menu_stats(user_id, "Инструкции", "Почта")
|
log_menu_stats(user_id, "Инструкции", "Почта")
|
||||||
set_state(user_id, "INSTRUCT_EMAIL_VIEW")
|
set_state(user_id, "INSTRUCT_EMAIL_VIEW")
|
||||||
@@ -313,6 +318,29 @@ async def instruct_router_handler(msg: Message):
|
|||||||
else:
|
else:
|
||||||
await msg.answer(UNKNOWN_MAIN_CMD_TEXT, parse_mode="html")
|
await msg.answer(UNKNOWN_MAIN_CMD_TEXT, parse_mode="html")
|
||||||
|
|
||||||
|
elif current_state == "INSTRUCT_TRUECONF_PENDING":
|
||||||
|
msg.handled = True
|
||||||
|
if cmd == "0":
|
||||||
|
clear_state(user_id)
|
||||||
|
from utils.menu import MENU_TEXT
|
||||||
|
await msg.answer(MENU_TEXT, parse_mode="html")
|
||||||
|
elif cmd == "9":
|
||||||
|
set_state(user_id, "INSTRUCT_MODE")
|
||||||
|
await msg.answer(INSTRUCT_MAIN_MENU_TEXT, parse_mode="html")
|
||||||
|
elif cmd == "1":
|
||||||
|
# Запросить доступ
|
||||||
|
cn = get_user_cn(user_id)
|
||||||
|
if cn is None:
|
||||||
|
cn = user_id
|
||||||
|
ticket_id = await create_sd_ticket_for_trueconf(user_id, cn)
|
||||||
|
if ticket_id:
|
||||||
|
text = INSTRUCT_TRUECONF_WITH_AD(EMOJI_DIGITS, cn, ticket_id)
|
||||||
|
await msg.answer(text, parse_mode="html")
|
||||||
|
else:
|
||||||
|
await msg.answer("❌ Не удалось создать заявку. Попробуйте позже.", parse_mode="html")
|
||||||
|
else:
|
||||||
|
await msg.answer(UNKNOWN_MAIN_CMD_TEXT, parse_mode="html")
|
||||||
|
|
||||||
elif current_state in ["INSTRUCT_TRUECONF_VIEW", "INSTRUCT_EMAIL_VIEW"]:
|
elif current_state in ["INSTRUCT_TRUECONF_VIEW", "INSTRUCT_EMAIL_VIEW"]:
|
||||||
msg.handled = True
|
msg.handled = True
|
||||||
if cmd == "0":
|
if cmd == "0":
|
||||||
|
|||||||
+20
-5
@@ -606,6 +606,25 @@ def _instruct_trueconf(emojis: dict) -> str:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _instruct_trueconf_pending(emojis: dict, cn: str) -> str:
|
||||||
|
"""Промпт для запроса доступа к Trueconf (когда нет заявки)."""
|
||||||
|
return (
|
||||||
|
f"ℹ У вас отсутствует доступ к TrueConf с мобильных устройств.\n\n"
|
||||||
|
f"Если Вам требуется доступ, то напишите цифру {emojis['1']}, либо выберите другие пункты меню.\n\n"
|
||||||
|
f"{emojis['1']} — Запросить доступ\n"
|
||||||
|
f"<i>{emojis['9']} — Назад\n{emojis['0']} — В главное меню</i>"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _instruct_trueconf_no_ticket(emojis: dict, cn: str) -> str:
|
||||||
|
"""Текст Trueconf когда пользователь не найден в AD."""
|
||||||
|
return (
|
||||||
|
f"🖥 <b>Инструкция по Trueconf</b>\n\n"
|
||||||
|
f"Пользователь {cn} не найден в Active Directory.\n\n"
|
||||||
|
f"<i>{emojis['9']} — Назад\n{emojis['0']} — В главное меню</i>"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _instruct_trueconf_with_ad(emojis: dict, cn: str, ticket_id: str = None) -> str:
|
def _instruct_trueconf_with_ad(emojis: dict, cn: str, ticket_id: str = None) -> str:
|
||||||
"""
|
"""
|
||||||
Текст Trueconf с проверкой группы 2FA.
|
Текст Trueconf с проверкой группы 2FA.
|
||||||
@@ -618,11 +637,7 @@ def _instruct_trueconf_with_ad(emojis: dict, cn: str, ticket_id: str = None) ->
|
|||||||
|
|
||||||
if not result["found"]:
|
if not result["found"]:
|
||||||
ticket_part = f"\n\n🎫 <b>Заявка #{ticket_id} создана!</b>" if ticket_id else ""
|
ticket_part = f"\n\n🎫 <b>Заявка #{ticket_id} создана!</b>" if ticket_id else ""
|
||||||
return (
|
return _instruct_trueconf_no_ticket(emojis, cn)
|
||||||
f"🖥 <b>Инструкция по Trueconf</b>\n\n"
|
|
||||||
f"Пользователь {cn} не найден в Active Directory.{ticket_part}\n\n"
|
|
||||||
f"<i>{emojis['9']} — Назад\n{emojis['0']} — В главное меню</i>"
|
|
||||||
)
|
|
||||||
|
|
||||||
if result["in_group"]:
|
if result["in_group"]:
|
||||||
body = (
|
body = (
|
||||||
|
|||||||
Reference in New Issue
Block a user