Restrict global system memory viewing and tabs strictly to admin users
This commit is contained in:
Submodule
+1
Submodule projects/8896969833/blog added at 98e0e41b22
Submodule
+1
Submodule projects/8896969833/lt-project_name-gt added at 7f1496ce51
+51
-10
@@ -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.
@@ -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
Reference in New Issue
Block a user