نقش‌های وردپرس در سایت‌های آموزش برنامه‌نویسی به‌دلیل ماهیت تعاملی و نیاز به اجرای کد، اشکال‌زدایی، و کنترل نسخه، تنظیمات کدی اختصاصی می‌خواهند. یک دانشجوی برنامه‌نویسی نباید فقط خواننده محتوا باشد؛ باید به محیط اجرای کد، مخزن گیت اختصاصی، و ابزارهای تست دسترسی داشته باشد. بدون تنظیمات کدی، یا دانشجو به کد سایرین دسترسی پیدا می‌کند، یا نمی‌تواند تمرین واقعی انجام دهد. این دوگانه، ریشه اصلی نیاز به معماری نقش مبتنی بر کد است.

وقتی اولین پلتفرم آموزش برنامه‌نویسی را روی وردپرس بنا کردم، تصور می‌کردم نقش Author و Editor کفایت می‌کند. اما در نخستین دوره، دانشجویان نیاز داشتند کد خود را در محیطی امن اجرا کنند، نتیجه را ببینند، و از کد سایرین جدا بمانند. اینجا بود که فهمیدم نقش‌های وردپرس برای محتوا طراحی شده‌اند، نه برای کد.

چرا نقش‌های پیش‌فرض وردپرس کافی نیستند؟

وردپرس شش نقش پیش‌فرض دارد که حول «مدیریت محتوا» ساخته شده‌اند. در سایت آموزش برنامه‌نویسی، این نقش‌ها با شکاف‌های زیر روبه‌رو می‌شوند:

  • نبود قابلیت اجرای کد: هیچ نقش پیش‌فرضی مجوز اجرای کد PHP یا JavaScript را در محیط ایزوله ندارد.
  • نبود کنترل نسخه: دسترسی به مخزن Git اختصاصی هر دانشجو با نقش‌های پیش‌فرض قابل تعریف نیست.
  • عدم تفکیک داده کد: کد هر دانشجو یک دارایی خصوصی است، اما نقش Subscriber فقط read دارد.
  • ریسک اجرای کد مخرب: اگر مجوز اجرا بدون ایزوله‌سازی داده شود، دانشجو می‌تواند به سرور آسیب بزند.

در سایت آموزش برنامه‌نویسی، مجوز اجرای کد بدون ایزوله‌سازی، یک آسیب‌پذیری باز است، نه یک قابلیت آموزشی.

اگر با مفاهیم پایه نقش و دسترسی آشنا نیستید، مطلب مدیریت نقش‌ها و دسترسی‌ها در وردپرس را ببینید. برای انتخاب افزونه مناسب مدیریت کاربران، مطلب انتخاب افزونه مدیریت کاربران وردپرس را مطالعه کنید.

نقش‌ها در سایت آموزش برنامه‌نویسی

دانشجو (Coding Student)

ساخت پروژه کدی، اجرا در محیط ایزوله، دسترسی به مخزن Git شخصی، مشاهده خروجی تست.

مدرس (Coding Instructor)

مشاهده همه پروژه‌ها، اجرای تست‌های خودکار، ثبت بازخورد، بدون دسترسی به سرور اصلی.

دستیار (Coding TA)

مشاهده کد دانشجویان دوره، ثبت یادداشت، بدون تغییر نمره نهایی.

داور کد (Code Reviewer)

دسترسی به کد برای بازبینی، ثبت کامنت در خطوط کد، بدون اجرا.

مدیر محیط (Environment Manager)

مدیریت Docker Containerها، تنظیم سهمیه اجرا، و پایش مصرف منابع.

چالش‌های کدی و محیط اجرا

۱. ایزوله‌سازی اجرای کد

کد دانشجو هرگز نباید روی سرور اصلی اجرا شود. باید در Container ایزوله با منابع محدود اجرا شود. این یعنی نقش دانشجو باید به یک REST Endpoint دسترسی داشته باشد، نه به Shell اصلی.

۲. محدودیت منابع

هر اجرا باید سهمیه CPU، RAM و زمان داشته باشد. بدون این محدودیت، یک حلقه بی‌نهایت می‌تواند کل سرور را بخواباند.

۳. تفکیک مخزن Git

هر دانشجو مخزن اختصاصی دارد. دسترسی به مخزن باید از طریق توکن اختصاصی و با دامنه محدود انجام شود. برای مطالعه بیشتر، مطلب GitHub در پروژه‌های تیمی را ببینید.

۴. اشکال‌زدایی

دانشجو باید بتواند خطاها را ببیند، اما نه لاگ‌های سرور. یعنی خروجی اجرای کد باید فیلتر شود. برای مطالعه بیشتر درباره دیباگ، مطلب فعال‌سازی حالت Debug وردپرس را ببینید.

۵. کنترل نسخه تمرین

هر تمرین باید یک نسخه مبنا داشته باشد. دانشجو نسخه خودش را می‌سازد. این نیازمند یک لایه Version Control سبک است.

تنظیمات کدی هر نقش

نقش قابلیت کدی محدودیت
دانشجو run_code, edit_own_project سهمیه ۶۰ ثانیه، ۵۱۲MB RAM
مدرس run_test, read_all_projects بدون دسترسی به Shell
دستیار read_assigned_projects بدون اجرا
داور review_code, comment_code بدون اجرا
مدیر محیط manage_containers بدون دسترسی به کد دانشجو

پیاده‌سازی با PHP

ابتدا CPT پروژه کدی را می‌سازیم. برای مطالعه بیشتر درباره CPT، مطلب پیاده‌سازی درست Custom Post Type را ببینید.

function wk_register_code_project_cpt() {
    register_post_type('wk_code_project', array(
        'label' => 'پروژه‌های کدی',
        'public' => false,
        'show_ui' => true,
        'capability_type' => 'wk_code_project',
        'capabilities' => array(
            'read_post' => 'read_wk_code_project',
            'edit_post' => 'edit_wk_code_project',
            'edit_posts' => 'edit_wk_code_projects',
            'edit_others_posts' => 'edit_others_wk_code_projects',
        ),
        'map_meta_cap' => true,
        'supports' => array('title', 'editor', 'author', 'custom-fields'),
    ));
}
add_action('init', 'wk_register_code_project_cpt');

سپس نقش‌های سفارشی را می‌سازیم. برای درک بهتر هوک‌ها، مطلب هوک‌های وردپرس را ببینید.

function wk_register_code_roles() {
    add_role('wk_code_student', 'دانشجوی کد', array(
        'read' => true,
        'edit_wk_code_projects' => true,
        'publish_wk_code_projects' => true,
        'run_wk_code' => true,
        'upload_files' => true,
    ));

    add_role('wk_code_instructor', 'مدرس کد', array(
        'read' => true,
        'edit_wk_code_projects' => true,
        'edit_others_wk_code_projects' => true,
        'run_wk_tests' => true,
        'read_wk_code_feedback' => true,
        'edit_wk_code_feedback' => true,
    ));

    add_role('wk_code_reviewer', 'داور کد', array(
        'read' => true,
        'edit_wk_code_projects' => true,
        'read_wk_code_feedback' => true,
    ));

    add_role('wk_env_manager', 'مدیر محیط', array(
        'read' => true,
        'manage_wk_containers' => true,
        'read_wk_resource_quotas' => true,
    ));
}
add_action('init', 'wk_register_code_roles');

برای اعتبارسنجی و پاک‌سازی داده‌های ورودی، مطلب اعتبارسنجی داده‌ها و پاک‌سازی داده‌ها را مطالعه کنید.

محیط اجرای ایزوله

اجرای کد دانشجو باید در یک Docker Container با محدودیت‌های سخت‌گیرانه انجام شود. الگوی پیشنهادی:

function wk_run_student_code($user_id, $code, $language) {
    if (!current_user_can('run_wk_code')) {
        return new WP_Error('forbidden', 'دسترسی غیرمجاز');
    }
    $quota = wk_get_user_quota($user_id);
    if ($quota['used'] >= $quota['limit']) {
        return new WP_Error('quota_exceeded', 'سهمیه اجرا تمام شد');
    }
    $result = wk_execute_in_sandbox($code, $language, array(
        'timeout' => 60,
        'memory' => '512m',
        'network' => false,
        'readonly' => true,
    ));
    wk_increment_quota($user_id);
    return $result;
}

نکته کلیدی: پارامتر network => false باید حتماً فعال باشد تا کد دانشجو نتواند به اینترنت دسترسی داشته باشد. بدون این تنظیم، کد می‌تواند به منابع خارجی درخواست بفرستد یا داده‌ای را استخراج کند.

یکپارچگی با Git

هر دانشجو باید یک مخزن اختصاصی داشته باشد. دسترسی از طریق توکن شخصی انجام می‌شود، نه با SSH Key مشترک.

function wk_provision_student_repo($user_id, $course_id) {
    $token = wp_generate_password(40, false, false);
    update_user_meta($user_id, 'wk_git_token_hash', wp_hash_password($token));
    update_user_meta($user_id, 'wk_git_repo', sprintf('repo-course-%d-user-%d', $course_id, $user_id));
    return $token;
}

توکن فقط یک بار نمایش داده می‌شود و هش آن ذخیره می‌شود. برای مطالعه بیشتر درباره User Meta، مطلب کار با User Meta را ببینید.

امنیت و اعتبارسنجی

سه لایه امنیتی ضروری است:

  1. اعتبارسنجی کد ورودی از نظر طول و نوع (Language Whitelist).
  2. اجرای ایزوله با Network Isolation و Read-Only Filesystem.
  3. لاگ کامل هر اجرا برای ممیزی.

برای مطالعه بیشتر درباره کدنویسی امن، مطلب نوشتن کد PHP امن برای وردپرس را ببینید.

استاندارد OWASP چارچوب کاملی برای اجرای امن کد کاربر ارائه می‌دهد و برای این نوع سایت‌ها مرجع اصلی است.

پرسش‌های پرتکرار

آیا اجرای کد روی همان سرور وردپرس امن است؟

خیر. باید در سرور جدا یا Container ایزوله اجرا شود. اجرای مستقیم روی سرور اصلی، ریسک بالایی دارد.

بهترین زبان برای محیط Sandbox چیست؟

Docker استاندارد صنعتی است. گزینه‌های سبک‌تر مثل gVisor برای پروژه‌های کوچک‌تر مناسب‌اند.

چگونه از مصرف بی‌رویه منابع جلوگیری کنم؟

سهمیه روزانه برای هر کاربر، محدودیت زمان اجرا، و محدودیت حافظه. مطلب کاهش مصرف منابع هاست را ببینید.

آیا باید کد دانشجو در دیتابیس ذخیره شود؟

بهتر است کد در فایل‌سیستم ذخیره شود و فقط متادیتا در دیتابیس. برای مطالعه بیشتر، مطلب توابع وردپرس برای کار با فایل‌ها را ببینید.

اشتباهات رایج

اشتباه پیامد راه‌حل
اجرای کد روی سرور اصلی خواب سرور یا نفوذ Docker ایزوله
دسترسی شبکه در Sandbox استخراج داده یا SSRF Network Isolation
توکن Git مشترک دسترسی بین دانشجویان توکن اختصاصی هر کاربر
نبود سهمیه اجرا مصرف بی‌رویه CPU Quota روزانه
عدم لاگ اجرا عدم امکان ممیزی ثبت هر اجرا با کاربر و زمان

نگاه مهندسی سطح‌بالا

در معماری یک پلتفرم آموزش کد، بزرگ‌ترین چالش «ایزوله‌سازی چند-مستأجری» (Multi-Tenant Isolation) است. هر دانشجو در واقع یک مستأجر است که باید منابع اختصاصی داشته باشد. سیستم نقش وردپرس برای این سطح از جداسازی طراحی نشده و باید یک لایه Orchestration بالای آن قرار بگیرد.

رویکرد پیشنهادی، معماری «Control Plane / Data Plane» است. Control Plane در وردپرس می‌ماند و مسئول احراز هویت، مجوزدهی و مدیریت سهمیه است. Data Plane در یک سرویس جدا (مثلاً یک سرویس Go یا Python) قرار می‌گیرد و مسئول اجرای واقعی کد است. این جداسازی، هم امنیت را بالا می‌برد و هم مقیاس‌پذیری را.

نکته دوم، بحث Observability است. هر اجرا باید با Trace ID یکتا ثبت شود تا در صورت بروز مشکل، بتوان مسیر کامل اجرا را بازسازی کرد. این سطح از لاگ‌گیری برای ممیزی امنیتی و رفع اشکال ضروری است.

نکته سوم، مدیریت هزینه است. اجرای کد در Container برای هر درخواست، هزینه محاسباتی بالایی دارد. راه‌حل، استفاده از Container Pool آماده و Warm Start است تا تأخیر راه‌اندازی حذف شود.

اگر این چالش را در پروژه‌ای تجربه کرده‌اید، برای من جالب است بدانم کدام بخش بیشترین زمان را گرفت: طراحی Sandbox، مدیریت سهمیه، یا یکپارچگی با Git. تجربه خود را در دیدگاه‌ها بنویسید.