-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0bdfff7
Showing
5 changed files
with
237 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
<?php | ||
// This file is part of the qrexamlock plugin for Moodle - http://moodle.org/ | ||
// | ||
// qrexamlock is a plugin to enhance exam security using QR code-based access control. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
defined('MOODLE_INTERNAL') || die(); | ||
|
||
$capabilities = [ | ||
// Capability for managing the plugin settings. | ||
'local/qrexamlock:manage' => [ | ||
'riskbitmask' => RISK_CONFIG, | ||
'captype' => 'write', | ||
'contextlevel' => CONTEXT_SYSTEM, | ||
'archetypes' => [ | ||
'manager' => CAP_ALLOW, | ||
], | ||
], | ||
|
||
// Capability for viewing QR codes for exams. | ||
'local/qrexamlock:viewqrcode' => [ | ||
'riskbitmask' => RISK_PERSONAL, | ||
'captype' => 'read', | ||
'contextlevel' => CONTEXT_COURSE, | ||
'archetypes' => [ | ||
'teacher' => CAP_ALLOW, | ||
'student' => CAP_ALLOW, | ||
], | ||
], | ||
|
||
// Capability for scanning and validating QR codes. | ||
'local/qrexamlock:validateqrcode' => [ | ||
'riskbitmask' => RISK_PERSONAL, | ||
'captype' => 'read', | ||
'contextlevel' => CONTEXT_MODULE, | ||
'archetypes' => [ | ||
'teacher' => CAP_ALLOW, | ||
], | ||
], | ||
|
||
// Capability for generating reports about QR code scans. | ||
'local/qrexamlock:generatereports' => [ | ||
'riskbitmask' => RISK_PERSONAL, | ||
'captype' => 'read', | ||
'contextlevel' => CONTEXT_COURSE, | ||
'archetypes' => [ | ||
'manager' => CAP_ALLOW, | ||
'teacher' => CAP_ALLOW, | ||
], | ||
], | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?php | ||
// General plugin information. | ||
$string['pluginname'] = 'QR Exam Lock'; | ||
|
||
// Settings fields. | ||
$string['enabled'] = 'Enable QR Exam Lock'; | ||
$string['enabled_desc'] = 'Enable or disable the QR Exam Lock plugin for secure exam access.'; | ||
|
||
$string['qrcodeexpiry'] = 'QR Code Expiry Time'; | ||
$string['qrcodeexpiry_desc'] = 'Set the expiry time (in minutes) for each QR code generated for an exam session.'; | ||
|
||
$string['requiredeviceverification'] = 'Require Device Verification'; | ||
$string['requiredeviceverification_desc'] = 'If enabled, students must use a verified device to scan the QR code for exam access.'; | ||
|
||
$string['logging'] = 'Enable Logging'; | ||
$string['logging_desc'] = 'Enable logging of all QR code scans and exam access attempts for audit purposes.'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
<?php | ||
// This file is part of the qrexamlock plugin for Moodle - http://moodle.org/ | ||
// | ||
// qrexamlock is a plugin to enhance exam security using QR code-based access control. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
defined('MOODLE_INTERNAL') || die(); | ||
|
||
/** | ||
* Generates a QR code for a given quiz session. | ||
* | ||
* @param int $quizid The ID of the quiz activity. | ||
* @param int $userid The ID of the user. | ||
* @return string Path to the generated QR code image. | ||
*/ | ||
function local_qrexamlock_generate_qr_code($quizid, $userid) { | ||
global $CFG; | ||
|
||
require_once($CFG->libdir . '/filelib.php'); // Load file library. | ||
require_once($CFG->dirroot . '/local/qrexamlock/phpqrcode/qrlib.php'); // Include QR library. | ||
|
||
// Define the data to encode in the QR code. | ||
$data = json_encode([ | ||
'quizid' => $quizid, | ||
'userid' => $userid, | ||
'timestamp' => time() | ||
]); | ||
|
||
// Define the output file path. | ||
$outputdir = $CFG->dataroot . '/qrexamlock/qrcodes/'; | ||
make_temp_directory('qrexamlock/qrcodes'); // Ensure the directory exists. | ||
$filename = $outputdir . "qr_{$quizid}_{$userid}.png"; | ||
|
||
// Generate the QR code. | ||
QRcode::png($data, $filename, QR_ECLEVEL_H, 6); | ||
|
||
return $filename; | ||
} | ||
|
||
/** | ||
* Validates the QR code scan data. | ||
* | ||
* @param string $qrdata The scanned QR code data (JSON format). | ||
* @return bool True if valid, false otherwise. | ||
*/ | ||
function local_qrexamlock_validate_qr_code($qrdata) { | ||
global $DB; | ||
|
||
// Decode the QR data. | ||
$data = json_decode($qrdata, true); | ||
if (!$data || !isset($data['quizid']) || !isset($data['userid']) || !isset($data['timestamp'])) { | ||
return false; | ||
} | ||
|
||
// Check if the quiz and user exist in the database. | ||
$quizid = $data['quizid']; | ||
$userid = $data['userid']; | ||
$timestamp = $data['timestamp']; | ||
|
||
if (!$DB->record_exists('quiz', ['id' => $quizid])) { | ||
return false; // Quiz does not exist. | ||
} | ||
if (!$DB->record_exists('user', ['id' => $userid])) { | ||
return false; // User does not exist. | ||
} | ||
|
||
// Verify that the QR code is still valid based on expiry time. | ||
$expirytime = get_config('local_qrexamlock', 'qrcodeexpiry') * 60; // Convert to seconds. | ||
if ((time() - $timestamp) > $expirytime) { | ||
return false; // QR code has expired. | ||
} | ||
|
||
return true; // Valid QR code. | ||
} | ||
|
||
/** | ||
* Restricts access to the quiz based on QR code validation. | ||
* | ||
* @param stdClass $quiz The quiz activity object. | ||
* @param stdClass $user The user object. | ||
* @return bool True if access is granted, false otherwise. | ||
*/ | ||
function local_qrexamlock_restrict_quiz_access($quiz, $user) { | ||
// Generate a QR code for the current user and quiz. | ||
$qrcodefile = local_qrexamlock_generate_qr_code($quiz->id, $user->id); | ||
|
||
// Display the QR code to the user. | ||
echo html_writer::tag('div', get_string('scanqrcode', 'local_qrexamlock'), ['class' => 'qrexamlock-message']); | ||
echo html_writer::empty_tag('img', ['src' => new moodle_url('/local/qrexamlock/qrcodes/' . basename($qrcodefile))]); | ||
|
||
// Wait for QR code validation. | ||
// This can be implemented using AJAX to validate the scan in real-time. | ||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<?php | ||
// This file is part of the qrexamlock plugin for Moodle - http://moodle.org/ | ||
// | ||
// qrexamlock is a plugin to enhance exam security using QR code-based access control. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
defined('MOODLE_INTERNAL') || die(); | ||
|
||
if ($hassiteconfig) { // Ensure the user has site administration permissions. | ||
$settings = new admin_settingpage('local_qrexamlock', get_string('pluginname', 'local_qrexamlock')); | ||
|
||
// Enable/Disable the plugin. | ||
$settings->add(new admin_setting_configcheckbox( | ||
'local_qrexamlock/enabled', | ||
get_string('enabled', 'local_qrexamlock'), | ||
get_string('enabled_desc', 'local_qrexamlock'), | ||
1 // Default: Enabled. | ||
)); | ||
|
||
// QR Code Expiry Time (in minutes). | ||
$settings->add(new admin_setting_configtext( | ||
'local_qrexamlock/qrcodeexpiry', | ||
get_string('qrcodeexpiry', 'local_qrexamlock'), | ||
get_string('qrcodeexpiry_desc', 'local_qrexamlock'), | ||
5, // Default: 5 minutes. | ||
PARAM_INT | ||
)); | ||
|
||
// Require device verification. | ||
$settings->add(new admin_setting_configcheckbox( | ||
'local_qrexamlock/requiredeviceverification', | ||
get_string('requiredeviceverification', 'local_qrexamlock'), | ||
get_string('requiredeviceverification_desc', 'local_qrexamlock'), | ||
1 // Default: Enabled. | ||
)); | ||
|
||
// Logging enabled/disabled. | ||
$settings->add(new admin_setting_configcheckbox( | ||
'local_qrexamlock/logging', | ||
get_string('logging', 'local_qrexamlock'), | ||
get_string('logging_desc', 'local_qrexamlock'), | ||
1 // Default: Enabled. | ||
)); | ||
|
||
// Add the settings page to the "Local plugins" category. | ||
$ADMIN->add('localplugins', $settings); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
// This file is part of the qrexamlock plugin for Moodle - http://moodle.org/ | ||
// | ||
// qrexamlock is a plugin to enhance exam security using QR code-based access control. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
defined('MOODLE_INTERNAL') || die(); | ||
|
||
$plugin->component = 'local_qrexamlock'; // Full name of the plugin (used for diagnostics). | ||
$plugin->version = 2024112300; // The current plugin version (date-based YYYYMMDDXX). | ||
$plugin->release = 'v1.0'; // Human-readable version name. | ||
$plugin->requires = 2022041900; // Requires this Moodle version (e.g., Moodle 4.0). | ||
$plugin->maturity = MATURITY_STABLE; // Maturity level: MATURITY_ALPHA, MATURITY_BETA, or MATURITY_STABLE. | ||
$plugin->author = 'Your Name or Organization'; // Author of the plugin. | ||
$plugin->license = 'GPLv3 or later'; // License type. | ||
$plugin->supported = [401, 402]; // Supported Moodle versions (e.g., Moodle 4.1 and 4.2). | ||
|
||
// Optional: Dependencies | ||
// $plugin->dependencies = [ | ||
// 'mod_quiz' => ANY_VERSION, // Requires the Quiz module. | ||
// ]; |