divid_teacher / admin_office_app_patch.py
Asem75's picture
Upload 2 files
1494df9 verified
Raw
History Blame Contribute Delete
8.16 kB
# admin_office_app_patch.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Divid Teacher — Bridge لمكتب الإدارة V10.
الإصدار:
admin_office_app_patch_v5_admin_office_v10_unified_diagnostics
المهام:
- استخدام admin_access_manager لتسجيل دخول owner / manager_1 / manager_2.
- تركيب admin_office_ui.py داخل admin_panel الحالي.
- تمرير حقل كلمة مرور المدير نفسه حتى يفحص كل زر الصلاحية على السيرفر.
- إبقاء مكونات الفحص القديمة في الخلف للتوافق مع callbacks القديمة،
بينما الفحوص المرئية أصبحت مجتمعة داخل تبويب «الفحص» في Admin Office V10.
- لا يحتاج تعديل app.py يدويًا طالما أن app.py يستدعي apply_admin_office_patch().
"""
from __future__ import annotations
import re
VERSION = "admin_office_app_patch_v5_admin_office_v10_unified_diagnostics"
REQUIRED_ADMIN_OFFICE_VERSION = (
"admin_office_ui_v10_repository_browser_"
"flexible_audit_unified_diagnostics"
)
def _patch_admin_login(source: str) -> str:
new_login = r'''def ui_admin_login(password):
password = str(password or "").strip()
try:
from admin_access_manager import get_manager as get_admin_access_manager
access = get_admin_access_manager()
result = access.authenticate(password)
except Exception as exc:
return (
markdown_error(f"تعذر تحميل نظام صلاحيات المدراء: {exc}"),
gr.update(visible=False),
)
if isinstance(result, dict) and result.get("success"):
display_name = str(result.get("display_name") or "المدير").strip()
admin_id = str(result.get("admin_id") or "").strip()
return (
markdown_success(
f"تم فتح لوحة المدير: {display_name}"
+ (f" — {admin_id}" if admin_id else "")
),
gr.update(visible=True),
)
message = (
str(result.get("message") or "كلمة مرور المدير غير صحيحة.")
if isinstance(result, dict)
else "كلمة مرور المدير غير صحيحة."
)
return (
markdown_error(message),
gr.update(visible=False),
)'''
pattern = r'''def ui_admin_login\(password\):.*?(?=\n\ndef ui_admin_list_students\()'''
patched, count = re.subn(
pattern,
new_login,
source,
count=1,
flags=re.DOTALL,
)
if count != 1:
raise RuntimeError(
"لم أجد دالة ui_admin_login الحالية بصورة آمنة؛ "
"لم يتم تطبيق Patch حتى لا نكسر التطبيق."
)
return patched
def _hide_legacy_admin_tools(source: str) -> str:
"""
لا يحذف الوظائف القديمة ولا callbacks الخاصة بها.
يخفي واجهتها فقط لأن Admin Office V10 يعرض الفحوص في تبويب واحد.
"""
replacements = {
' gr.Markdown("## أدوات المدير والفحص")':
' gr.Markdown("## أدوات المدير والفحص القديمة - نُقلت إلى تبويب الفحص", visible=False)',
' check = gr.Button("فحص النظام")':
' check = gr.Button("فحص النظام", visible=False)',
' queue_center_btn = gr.Button("عرض الحصص العلاجية")':
' queue_center_btn = gr.Button("عرض الحصص العلاجية", visible=False)',
' process_task_btn = gr.Button("معالجة مهمة واحدة")':
' process_task_btn = gr.Button("معالجة مهمة واحدة", visible=False)',
' queue_test_btn = gr.Button("اختبار نظام الحصص المؤجلة")':
' queue_test_btn = gr.Button("اختبار نظام الحصص المؤجلة", visible=False)',
' media_test_btn = gr.Button("اختبار فيديو الحصة العلاجية")':
' media_test_btn = gr.Button("اختبار فيديو الحصة العلاجية", visible=False)',
' admin_media_html = gr.HTML("")':
' admin_media_html = gr.HTML("", visible=False)',
' admin_out = gr.Markdown("")':
' admin_out = gr.Markdown("", visible=False)',
' with gr.Accordion("فحص دخول الطالب", open=False):':
' with gr.Accordion("فحص دخول الطالب", open=False, visible=False):',
}
for old, new in replacements.items():
if old in source:
source = source.replace(old, new, 1)
return source
def apply_admin_office_patch(source: str) -> str:
if not isinstance(source, str) or not source.strip():
raise RuntimeError("مصدر app.py فارغ.")
source = _patch_admin_login(source)
source = _hide_legacy_admin_tools(source)
marker = ' with gr.Accordion("إدارة تسجيل الطلاب", open=True):'
if marker in source:
indent = " "
else:
marker = 'with gr.Accordion("إدارة تسجيل الطلاب", open=True):'
if marker not in source:
raise RuntimeError(
"لم أجد واجهة إدارة تسجيل الطلاب القديمة داخل المصدر. "
"لم يتم تطبيق Patch حتى لا نكسر التطبيق."
)
pos = source.find(marker)
indent = source[source.rfind("\n", 0, pos) + 1:pos]
replacement = (
indent + "# مكتب الإدارة V10 متعدد المديرين والصلاحيات والفحص الموحد\n"
+ indent + "try:\n"
+ indent + " from admin_office_ui import build_admin_office\n"
+ indent + " _ADMIN_OFFICE_COMPONENTS = build_admin_office(\n"
+ indent + " get_admin_manager=get_admin_manager,\n"
+ indent + " get_student_manager=get_student_manager,\n"
+ indent + " admin_key=ADMIN_PANEL_KEY,\n"
+ indent + " admin_password_component=admin_password,\n"
+ indent + " )\n"
+ indent + "except Exception as _admin_office_error:\n"
+ indent + " gr.Markdown(\n"
+ indent + ' "### تعذر تحميل Admin Office V10\\n\\n"\n'
+ indent + " + str(_admin_office_error)\n"
+ indent + " )\n\n"
+ indent + "# واجهة التسجيل القديمة مخفية للتوافق فقط\n"
+ indent + 'with gr.Accordion("إدارة تسجيل الطلاب القديمة - توافق", open=False, visible=False):'
)
patched = source.replace(marker, replacement, 1)
required = [
"from admin_access_manager import get_manager as get_admin_access_manager",
"from admin_office_ui import build_admin_office",
"admin_password_component=admin_password",
"_ADMIN_OFFICE_COMPONENTS = build_admin_office(",
"Admin Office V10",
]
missing = [item for item in required if item not in patched]
if missing:
raise RuntimeError(
"فشل التحقق من Patch مكتب الإدارة V10: " + repr(missing)
)
# إذا كان مصدر التطبيق كاملاً وصالحًا، نتحقق من الصياغة قبل التنفيذ.
compile(patched, "<patched_app_admin_office_v10>", "exec")
return patched
def summary():
return {
"success": True,
"ready": True,
"version": VERSION,
"admin_office_required_version": REQUIRED_ADMIN_OFFICE_VERSION,
"multi_admin": True,
"unified_diagnostics": True,
"legacy_diagnostics_deleted": False,
"legacy_diagnostics_hidden_for_compatibility": True,
"app_py_manual_change_required": False,
}