Moodle Queries (SQL) Series #1

Student aktif per course

Banyaknya student aktif per course pada bulan Oktober 2025, hanya untuk course dengan lebih dari 100 student aktif.

SELECT 
    c.id AS courseid,
    c.fullname AS coursename,
    COUNT(DISTINCT l.userid) AS active_students
FROM mdl_logstore_standard_log l
JOIN mdl_course c ON c.id = l.courseid
JOIN mdl_role_assignments ra ON ra.userid = l.userid
JOIN mdl_context ctx ON ctx.id = ra.contextid
WHERE 
    ctx.contextlevel = 50  -- contextlevel 50 = course
    AND ctx.instanceid = c.id
    AND ra.roleid = 5       -- roleid 5 = student
    AND l.timecreated BETWEEN UNIX_TIMESTAMP('2025-10-01 00:00:00')
                           AND UNIX_TIMESTAMP('2025-10-31 23:59:59')
GROUP BY c.id, c.fullname
HAVING active_students > 100
ORDER BY active_students DESC;

Active users menggunakan tabel mdl_users_lastaccess

“active” = enrolled + accessed the course recently

SELECT 
    c.id AS courseid,
    c.fullname AS coursename,
    COUNT(DISTINCT CASE 
        WHEN ula.timeaccess BETWEEN UNIX_TIMESTAMP('2025-10-01 00:00:00')
                               AND UNIX_TIMESTAMP('2025-10-31 23:59:59')
        THEN ula.userid END) AS active_students,
    COUNT(DISTINCT ra.userid) AS total_students,
    ROUND(
        (COUNT(DISTINCT CASE 
            WHEN ula.timeaccess BETWEEN UNIX_TIMESTAMP('2025-10-01 00:00:00')
                                   AND UNIX_TIMESTAMP('2025-10-31 23:59:59')
            THEN ula.userid END)
         / COUNT(DISTINCT ra.userid)) * 100, 2
    ) AS active_percentage
FROM mdl_course c
JOIN mdl_context ctx 
    ON ctx.contextlevel = 50 AND ctx.instanceid = c.id
JOIN mdl_role_assignments ra 
    ON ra.contextid = ctx.id AND ra.roleid = 5  -- 5 = student
LEFT JOIN mdl_user_lastaccess ula 
    ON ula.courseid = c.id AND ula.userid = ra.userid
GROUP BY c.id, c.fullname
HAVING active_students > 100
ORDER BY active_students DESC;

Ganti Sessions File system ke Database

Secara default sessions pada moodle diletakkan pada file system di moodledata dengan nama folder */[moodledata]/sessions* . Ada kalanya kita perlu meletakkan sessions tersebut di database untuk beberapa alasan:

  1. Kemudahan pemeliharaan
  2. Kecepatan

Kita bisa menggunakan database table, yaitu mdl_sessions menggunakan memory database seperti Memcache dan Redis

Yang paling mudah adalah konversi ke tabel database, yaitu tinggal meletakkan parameter baru di config.php

$CFG->sessionhandler = ‘database’;

Bila table mdl_sessions belum ada, maka moodle akan membuatkannya untuk Anda

Untuk menggunakan redis dan memcache akan saya tuangkan pada tulisan yang berbeda.

Selamat mencoba

Menambahkan File JavaScript eksternal (.js) ke Moodle

Terkadang kita perlu menambahkan file javascript (*.js) ke dalam LMS Moodle yang sedang kita kembangkan. Berikut adalah langkah-langkahnya:

Masuk ke Folder Theme Anda
Pertama-tama , masuklah ke direktori /theme/Nama_Theme_Anda. Jika di dalamnya belum ada folder bernama javascript, buatlah folder baru dengan nama tersebut.

Unggah File JavaScript
Letakkan file .js yang ingin ditambahkan ke dalam folder javascript yang baru dibuat.

Edit File config.php
Buka file config.php yang berada di dalam folder theme Anda (/theme/Nama_Theme_Anda/config.php). Di bagian paling bawah file tersebut, tambahkan baris kode berikut untuk menyertakan file JavaScript Anda:

#To load the js files in your header:
$THEME->javascripts = array(‘yourfirstjsfile’,’yoursecondjsfile’); 

#To load the js files in your footer:
$THEME->javascripts_footer = array(‘yourfirstjsfile’,’yoursecondjsfile’);

Perlu dicatat bahwa: Pada saat menambahkan nama file JavaScript dalam konfigurasi, jangan sertakan ekstensi .js. Contohnya, gunakan’youfirstjsfile’ bukan ‘yourfirstjsfile.js’.

Agar perubahan tersebut berlaku, maka kita perlu membersihkan cache situs Moodle, kemudian bersihkan cache browser dan reload.

Referensi: https://dzone.com/articles/adding-external-javascript-files-js-into-moodle

Mengenal Plugin Block: Filtered course list

Saat tulisan ini dibuat block ini dapat digunakan pada Moodle versi 3.8 hingga versi 4.3

Plugin ini dapat ditemukan di: https://moodle.org/plugins/block_filtered_course_list

Blok Filtered course list menampilkan daftar course yang dapat dikonfigurasi. Hal ini dimaksudkan sebagai pengganti blok My Course, meskipun keduanya tetap dapat digunakan bersama-sama. Plugin ini dikelola oleh Collaborative Liberal Arts Moodle Project (CLAMP).

Administrator dapat menerapkan berbagai filter yang digunakan untuk mengatur daftar course di blok. Course dapat diurutkan berdasarkan:

  1. kategori,
  2. kecocokan nama pendek,
  3. atau status penyelesaian.
  4. Mendukung Pencocokan regex. Jika semua mata kuliah dalam suatu semester mempunyai nama pendek yang diakhiri dengan kode semester, misalnya, maka administrator dapat menetapkan mata kuliah tersebut untuk muncul di bawah “Mata kuliah saat ini”, “Mata kuliah mendatang” atau judul lainnya.

Administrator dapat menetapkan beberapa judul yang dapat diciutkan dan memilih judul mana, jika ada, yang harus diperluas secara default.

Pilihan lainnya mencakup kemampuan untuk menyembunyikan blokir dari tamu atau pengunjung anonim, untuk memilih apakah admin melihat semua kursus atau miliknya sendiri, dan untuk menyembunyikan atau menampilkan tautan ke pencarian kursus yang lebih komprehensif.

Pengamanan Situs dengan menggunakan headers pada server Nginx

Secure Nginx from Clickjacking with X-FRAME-OPTIONS

Clickjacking

https://owasp.org/www-community/attacks/Clickjacking

X-Frame Options

Header add_header X-Frame-Options “SAMEORIGIN”;

Reference: here

Header X-XSS-Protection

When this header is being sent along with a response and the website contains an XSS attack, the browser will see this XSS attack and stop it from loading. This protection knows 3 levels:

  • X-XSS-Protection: 0; Disables the filter entirely.
  • X-XSS-Protection: 1; Enables the filter but only sanitizes the malicious script
  • X-XSS-Protection: 1; mode=block Enables the filter and completely blocks the page

Example:

add_header X-XSS-Protection "1; mode=block";
atau
add_header X-XSS-Protection "1;";

Reference

https://youtu.be/pV_uX0jDAh4?si=W6gbBjvpvniVDSDB

X-XSS-Protection headers. Protection or vulnerability?

https://webdock.io/en/docs/how-guides/security-guides/how-to-configure-security-headers-in-nginx-and-apache

Tips untuk mengamankan server Moodle

Berikut beberapa tips untuk mengamankan sebuah Moodle Server. Pendekatannya dapat dari arah Operating System, Server-server (web server, db server, cache, dll), Instalasi Moodle, server setup dan configuration

#1 Anti clickjacking

Menambahkan X-Frame-Options dalam HTTP header berguna untuk mengamankan NGINX dari serangan Clickjacking

The X-Frame-Options pada HTTP response header dapat digunakan untuk mengindikasikan apakah browser diizinkan untuk membuka sebuah halaman web luar ke dalam sebuah frame atau iframe .

Apakah anda pernah mencoba untuk meng”embed” situs Google.com di website anda dalam sebuah frame ? Dipasikan itu tidak bisa Anda lakukan karena memang di protect, dan hal yang sama dapat Anda lakukan juga pada website Anda. 

Ada tiga pilihan pengaturan untuk X-Frame-Options:

  1. SAMEORIGIN: This setting will allow the page to be displayed in a frame on the same origin as the page itself.
  2. DENY: This setting will prevent a page displaying in a frame or iframe.
  3. ALLOW-FROM URI: This setting will allow a page to be displayed only on the specified origin.

Berikut contoh penulisan pada file konfigurasi nginx di block [server]

add_header X-Frame-Options "SAMEORIGIN";

#2 Mengamankan direktori-direktori yang terbuka

Biasanya direktori yang ada di Moodle kebanyakan di isi dengan file index.html yang kosong untuk memberikan kesan bahwa direktori tersebut walaupun ada, tapi isinya kosong. Untuk itu disaranakn mengahpus semua file index.html dari direktori-direktori dimaksud.

#3 Mengamankan file-file tertentu dari akses melalui browser

Walaupun file-file seperti *.txt, *.md tidak berisi informasi-iinformasi yang sensitif, tapi demi kemanan yang lebih baik, akses terhadap file-file seperti ini sebaiknya tetap dihindari. Karena letak file-file tersebut tersebar di berbagai direktori dibawah direktori utama moodle, maka secara cepat, kita dapat melakukan pembatasan itu dengan cara pengaturan file konfigurasi di Nginx config atau di nginx virtual host configuration file(s)

Konfigirasi berikut ini akan mengamankan file-file dengan ekstensi *.txt|git|md|json. Letakkan kode berikut di file config dari virtualhost config nya, yang biasanya diletakkan di /etc/nginx/site-enable/*

location ~.(git|txt|md|json)$ {
deny all;
return 404;
}

#4 Menutup akses ke direktori-direktori yang di hidden

Demikian pula direktori-direktori yang di hidden, biasanya nama direktori di awalai dengan tanda “.” (titik). Tapi ada juga direktori yang diawalai tanda titik, tapi tidak boleh di block/deny, misalnya direktori .well-known. Direktori ini digunakan oleh Let’s Encrypt

Maka konfigirasi file konfigurasi nginx perlu ditambahkan perintah sebagai berikut:

 location ~ /\.(?!well-known).* {
deny all;
access_log off;
log_not_found off;
}

#5 Menyembunyikan identitas web server yang digunakan yang akan muncul ketika terjadi error

Masih akan berlanjut ….

Reference:

Cross-site Scripting (XSS) in Moodle

https://geekflare.com/add-x-frame-options-nginx/

https://webdock.io/en/docs/how-guides/security-guides/how-to-configure-security-headers-in-nginx-and-apache?irclickid=zw5Xe0R39xyPWxVyFWSd%3AWiYUkH2G4yNqyHQXQ0&irgwc=1&utm_medium=2334778&utm_source=Impact&utm_campaign=Online%20Tracking%20Link#2.-content-security-policy-csp

https://pdfs.semanticscholar.org/1aed/91301bea6030195332a990fd8d666693072c.pdf

https://serverfault.com/questions/755662/nginx-disable-htaccess-and-hidden-files-but-allow-well-known-directory

SQL Injection false positive (https://github.com/zaproxy/zaproxy/issues/3662)

Moodle File Permissions Recomendation

1. moodledata directory dan semua all konten-kontennya (dan subdirectories, termausk sessions):

owner: apache user (apache, httpd, www-data, whatever; see above)
group: apache group (apache, httpd, www-data, whatever; see above)
permissions: 700 on directories, 600 on files

2. moodle directory dan semua konten-kontent nya dan subdirektori (termasuk: config.php):

owner: root
group: root
permissions: 755 on directories, 644 on files.

Jika dimungkinkan login secara lokal oleh user biasa, maka ada 2 (dua) hal yang perlu diatur:

owner: root
group: apache group (apache, httpd, www-data, whatever; see above)
permissions: 750 on directories, 640 on files.

Reference:

https://docs.moodle.org/403/en/Security_recommendations#Most_secure.2Fparanoid_file_permissions

1 2