Restrict global system memory viewing and tabs strictly to admin users

This commit is contained in:
Antigravity Bot
2026-08-30 10:45:36 +03:30
parent 6d78424ebd
commit 5fa08bcbb7
6 changed files with 136 additions and 44 deletions
Submodule projects/8896969833/blog added at 98e0e41b22
Submodule projects/8896969833/lt-project_name-gt added at 7f1496ce51
+51 -10
View File
@@ -1115,6 +1115,10 @@ def build_memory_menu(chat_id: int, view_type: str = "project", page: int = 0) -
proj_name = curr_proj.name if curr_proj else "default" proj_name = curr_proj.name if curr_proj else "default"
# Non-admin users are strictly forbidden from viewing global memory
if view_type == "global" and not is_admin_user:
view_type = "project" if curr_proj else "user"
# Validate view_type # Validate view_type
if view_type not in ("project", "user", "global"): if view_type not in ("project", "user", "global"):
view_type = "project" if curr_proj else "user" view_type = "project" if curr_proj else "user"
@@ -1123,8 +1127,11 @@ def build_memory_menu(chat_id: int, view_type: str = "project", page: int = 0) -
memories = memory_manager.get_project_memories(user_id=chat_id, project_name=proj_name, limit=100) memories = memory_manager.get_project_memories(user_id=chat_id, project_name=proj_name, limit=100)
elif view_type == "user": elif view_type == "user":
memories = memory_manager.get_user_memories(user_id=chat_id, limit=100) memories = memory_manager.get_user_memories(user_id=chat_id, limit=100)
else: # global elif view_type == "global" and is_admin_user:
memories = memory_manager.get_global_memories(limit=100) memories = memory_manager.get_global_memories(limit=100)
else:
memories = memory_manager.get_user_memories(user_id=chat_id, limit=100)
view_type = "user"
total_cnt = len(memories) total_cnt = len(memories)
page_size = 5 page_size = 5
@@ -1145,11 +1152,15 @@ def build_memory_menu(chat_id: int, view_type: str = "project", page: int = 0) -
tab_name = "🌐 قوانین و خاطرات عمومی (کل سرور و کاربران)" tab_name = "🌐 قوانین و خاطرات عمومی (کل سرور و کاربران)"
tab_desc = "این قوانین برای <b>همه کاربران</b> تزریق می‌شوند (ویرایش و حذف فقط توسط مدیر)." tab_desc = "این قوانین برای <b>همه کاربران</b> تزریق می‌شوند (ویرایش و حذف فقط توسط مدیر)."
stats_str = f"<code>{stats['current_project_memories']}</code> پروژه | <code>{stats['current_user_memories']}</code> کاربر"
if is_admin_user:
stats_str += f" | <code>{stats['global_memories']}</code> عمومی"
header = ( header = (
f"🧠 <b>کنترل‌پنل حافظه هوشمند ۳ لایه (AI Memory Dashboard)</b>\n\n" f"🧠 <b>کنترل‌پنل حافظه هوشمند (AI Memory Dashboard)</b>\n\n"
f"• 📂 <b>بخش فعال:</b> {tab_name}\n" f"• 📂 <b>بخش فعال:</b> {tab_name}\n"
f"{tab_desc}\n" f"{tab_desc}\n"
f"• 📊 <b>آمار:</b> <code>{stats['current_project_memories']}</code> پروژه | <code>{stats['current_user_memories']}</code> کاربر | <code>{stats['global_memories']}</code> عمومی\n\n" f"• 📊 <b>آمار:</b> {stats_str}\n\n"
) )
if not memories: if not memories:
body = ( body = (
@@ -1176,11 +1187,15 @@ def build_memory_menu(chat_id: int, view_type: str = "project", page: int = 0) -
tab_name = "🌐 Global System Memory" tab_name = "🌐 Global System Memory"
tab_desc = "Applies to all users (admin-managed)." tab_desc = "Applies to all users (admin-managed)."
stats_str = f"<code>{stats['current_project_memories']}</code> project | <code>{stats['current_user_memories']}</code> user"
if is_admin_user:
stats_str += f" | <code>{stats['global_memories']}</code> global"
header = ( header = (
f"🧠 <b>3-Tier AI Memory Dashboard</b>\n\n" f"🧠 <b>AI Memory Dashboard</b>\n\n"
f"• 📂 <b>Active Tab:</b> {tab_name}\n" f"• 📂 <b>Active Tab:</b> {tab_name}\n"
f"{tab_desc}\n" f"{tab_desc}\n"
f"• 📊 <b>Stats:</b> <code>{stats['current_project_memories']}</code> project | <code>{stats['current_user_memories']}</code> user | <code>{stats['global_memories']}</code> global\n\n" f"• 📊 <b>Stats:</b> {stats_str}\n\n"
) )
if not memories: if not memories:
body = "️ <i>No memories recorded in this section yet.</i>" body = "️ <i>No memories recorded in this section yet.</i>"
@@ -1199,7 +1214,7 @@ def build_memory_menu(chat_id: int, view_type: str = "project", page: int = 0) -
# Build keyboard # Build keyboard
keyboard = [] keyboard = []
# 1. 3 Tab buttons # 1. Tab buttons (Global tab only visible to admin)
t_proj = f"📁 پروژه ({proj_name[:10]}) ✓" if view_type == "project" else f"📁 پروژه ({proj_name[:10]})" t_proj = f"📁 پروژه ({proj_name[:10]}) ✓" if view_type == "project" else f"📁 پروژه ({proj_name[:10]})"
t_user = "👤 کاربر (من) ✓" if view_type == "user" else "👤 کاربر (من)" t_user = "👤 کاربر (من) ✓" if view_type == "user" else "👤 کاربر (من)"
t_glob = "🌐 عمومی ✓" if view_type == "global" else "🌐 عمومی" t_glob = "🌐 عمومی ✓" if view_type == "global" else "🌐 عمومی"
@@ -1208,11 +1223,13 @@ def build_memory_menu(chat_id: int, view_type: str = "project", page: int = 0) -
t_user = "👤 User ✓" if view_type == "user" else "👤 User" t_user = "👤 User ✓" if view_type == "user" else "👤 User"
t_glob = "🌐 Global ✓" if view_type == "global" else "🌐 Global" t_glob = "🌐 Global ✓" if view_type == "global" else "🌐 Global"
keyboard.append([ tab_row = [
InlineKeyboardButton(t_proj, callback_data="mem_tab:project:0"), InlineKeyboardButton(t_proj, callback_data="mem_tab:project:0"),
InlineKeyboardButton(t_user, callback_data="mem_tab:user:0"), InlineKeyboardButton(t_user, callback_data="mem_tab:user:0"),
InlineKeyboardButton(t_glob, callback_data="mem_tab:global:0"), ]
]) if is_admin_user:
tab_row.append(InlineKeyboardButton(t_glob, callback_data="mem_tab:global:0"))
keyboard.append(tab_row)
# 2. Item delete buttons # 2. Item delete buttons
can_delete_current = (view_type in ("project", "user")) or (view_type == "global" and is_admin_user) can_delete_current = (view_type in ("project", "user")) or (view_type == "global" and is_admin_user)
@@ -3438,6 +3455,13 @@ async def memory_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
return return
if subcmd in ("global", "g", "public", "system"): if subcmd in ("global", "g", "public", "system"):
if not is_admin_user:
await update.message.reply_html(
"🚫 <b>خطای دسترسی: مشاهده و مدیریت حافظه عمومی سیستم فقط مختص مدیر است.</b>"
if is_fa
else "🚫 <b>Access Denied: Viewing global system memory is restricted to administrators.</b>"
)
return
text, markup = build_memory_menu(chat_id, view_type="global", page=0) text, markup = build_memory_menu(chat_id, view_type="global", page=0)
await update.message.reply_html(text, reply_markup=markup) await update.message.reply_html(text, reply_markup=markup)
return return
@@ -5197,8 +5221,12 @@ async def callback_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
elif data == "btn_memory_menu" or data.startswith("mem_tab:"): elif data == "btn_memory_menu" or data.startswith("mem_tab:"):
parts = data.split(":") parts = data.split(":")
v_type = parts[1] if len(parts) > 1 else "private" v_type = parts[1] if len(parts) > 1 else "project"
page_num = int(parts[2]) if len(parts) > 2 and parts[2].isdigit() else 0 page_num = int(parts[2]) if len(parts) > 2 and parts[2].isdigit() else 0
if v_type == "global" and not is_admin_user:
await query.answer("🚫 مشاهده حافظه عمومی فقط برای مدیر سیستم مجاز است." if is_fa else "🚫 Global memory access restricted to administrators.", show_alert=True)
v_type = "project" if session_manager.get_current_project(chat_id) else "user"
page_num = 0
text, markup = build_memory_menu(chat_id, view_type=v_type, page=page_num) text, markup = build_memory_menu(chat_id, view_type=v_type, page=page_num)
try: try:
await query.edit_message_text(text, parse_mode=constants.ParseMode.HTML, reply_markup=markup) await query.edit_message_text(text, parse_mode=constants.ParseMode.HTML, reply_markup=markup)
@@ -5215,6 +5243,9 @@ async def callback_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
await query.answer("❌ خاطره یافت نشد." if is_fa else "❌ Memory not found.", show_alert=True) await query.answer("❌ خاطره یافت نشد." if is_fa else "❌ Memory not found.", show_alert=True)
text, markup = build_memory_menu(chat_id, view_type=v_type, page=p_num) text, markup = build_memory_menu(chat_id, view_type=v_type, page=p_num)
await query.edit_message_text(text, parse_mode=constants.ParseMode.HTML, reply_markup=markup) await query.edit_message_text(text, parse_mode=constants.ParseMode.HTML, reply_markup=markup)
elif mem.is_global and not is_admin_user:
await query.answer("🚫 دسترسی غیرمجاز!" if is_fa else "🚫 Permission denied!", show_alert=True)
return
else: else:
confirm_text = ( confirm_text = (
f"🗑️ <b>آیا از حذف این خاطره اطمینان دارید؟</b>\n\n" f"🗑️ <b>آیا از حذف این خاطره اطمینان دارید؟</b>\n\n"
@@ -5239,6 +5270,10 @@ async def callback_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
m_id = int(m_id_str) m_id = int(m_id_str)
p_num = int(page_str) p_num = int(page_str)
from memory_manager import memory_manager from memory_manager import memory_manager
mem = memory_manager.get_by_id(m_id)
if mem and mem.is_global and not is_admin_user:
await query.answer("🚫 دسترسی غیرمجاز!" if is_fa else "🚫 Permission denied!", show_alert=True)
return
try: try:
ok = memory_manager.delete_by_id(m_id, user_id=chat_id, is_admin=is_admin_user) ok = memory_manager.delete_by_id(m_id, user_id=chat_id, is_admin=is_admin_user)
if ok: if ok:
@@ -5258,6 +5293,9 @@ async def callback_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
elif data.startswith("mem_clear_conf:"): elif data.startswith("mem_clear_conf:"):
v_type = data.split(":")[1] v_type = data.split(":")[1]
if v_type == "global" and not is_admin_user:
await query.answer("🚫 دسترسی غیرمجاز!" if is_fa else "🚫 Permission denied!", show_alert=True)
return
type_label = "عمومی سیستم" if v_type == "global" else "اختصاصی خودتان" type_label = "عمومی سیستم" if v_type == "global" else "اختصاصی خودتان"
confirm_text = ( confirm_text = (
f"⚠️ <b>هشدار پاک‌سازی حافظه</b>\n\n" f"⚠️ <b>هشدار پاک‌سازی حافظه</b>\n\n"
@@ -5277,6 +5315,9 @@ async def callback_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
elif data.startswith("mem_clear_do:"): elif data.startswith("mem_clear_do:"):
v_type = data.split(":")[1] v_type = data.split(":")[1]
if v_type == "global" and not is_admin_user:
await query.answer("🚫 دسترسی غیرمجاز!" if is_fa else "🚫 Permission denied!", show_alert=True)
return
from memory_manager import memory_manager from memory_manager import memory_manager
curr_p = session_manager.get_current_project(chat_id) curr_p = session_manager.get_current_project(chat_id)
p_name = curr_p.name if curr_p else "default" p_name = curr_p.name if curr_p else "default"
Binary file not shown.
+16
View File
@@ -421,10 +421,13 @@ class MemoryManager:
project_name: Optional[str] = None, project_name: Optional[str] = None,
type_: Optional[str] = None, type_: Optional[str] = None,
limit: int = 50, limit: int = 50,
is_admin: bool = False,
) -> List[MemoryItem]: ) -> List[MemoryItem]:
q = f"%{query.strip().lower()}%" q = f"%{query.strip().lower()}%"
with self._get_connection() as conn: with self._get_connection() as conn:
if type_ == "global": if type_ == "global":
if not is_admin:
return []
cur = conn.execute( cur = conn.execute(
""" """
SELECT * FROM memories SELECT * FROM memories
@@ -452,6 +455,7 @@ class MemoryManager:
(user_id, project_name, q, q, q, limit), (user_id, project_name, q, q, q, limit),
) )
elif user_id is not None: elif user_id is not None:
if is_admin:
cur = conn.execute( cur = conn.execute(
""" """
SELECT * FROM memories SELECT * FROM memories
@@ -462,6 +466,18 @@ class MemoryManager:
(user_id, user_id, project_name or "", q, q, q, limit), (user_id, user_id, project_name or "", q, q, q, limit),
) )
else: else:
cur = conn.execute(
"""
SELECT * FROM memories
WHERE ((type IN ('user', 'private') AND user_id = ?) OR (type = 'project' AND user_id = ? AND project_name = ?))
AND (key LIKE ? OR content LIKE ? OR category LIKE ?)
ORDER BY importance DESC, updated_at DESC LIMIT ?
""",
(user_id, user_id, project_name or "", q, q, q, limit),
)
else:
if not is_admin:
return []
cur = conn.execute( cur = conn.execute(
""" """
SELECT * FROM memories SELECT * FROM memories
File diff suppressed because one or more lines are too long