2 // This file is part of Moodle - http://moodle.org/
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17 namespace quizaccess_seb\external
;
19 defined('MOODLE_INTERNAL') ||
die();
24 use external_function_parameters
;
25 use external_single_structure
;
27 use invalid_parameter_exception
;
29 use quizaccess_seb\event\access_prevented
;
30 use quizaccess_seb\access_manager
;
32 require_once($CFG->dirroot
. '/mod/quiz/attemptlib.php');
33 require_once($CFG->libdir
. '/externallib.php');
36 * Validate browser exam key and config key.
38 * @package quizaccess_seb
39 * @author Andrew Madden <andrewmadden@catalyst-au.net>
40 * @copyright 2021 Catalyst IT
41 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
43 class validate_quiz_keys
extends external_api
{
46 * External function parameters.
48 * @return external_function_parameters
50 public static function execute_parameters(): external_function_parameters
{
51 return new external_function_parameters([
52 'cmid' => new external_value(PARAM_INT
, 'Course module ID',
53 VALUE_REQUIRED
, null, NULL_NOT_ALLOWED
),
54 'url' => new external_value(PARAM_URL
, 'Page URL to check',
55 VALUE_REQUIRED
, null, NULL_NOT_ALLOWED
),
56 'configkey' => new external_value(PARAM_ALPHANUMEXT
, 'SEB config key',
58 'browserexamkey' => new external_value(PARAM_ALPHANUMEXT
, 'SEB browser exam key',
64 * Validate a SEB config key or browser exam key.
66 * @param string $cmid Course module ID.
67 * @param string $url URL of the page on which the SEB JS API generated the keys.
68 * @param string|null $configkey A SEB config key hash. Includes URL in the hash.
69 * @param string|null $browserexamkey A SEB browser exam key hash. Includes the URL in the hash.
72 public static function execute(string $cmid, string $url, ?
string $configkey = null, ?
string $browserexamkey = null): array {
76 'configkey' => $configkey,
77 'browserexamkey' => $browserexamkey
78 ) = self
::validate_parameters(self
::execute_parameters(), [
81 'configkey' => $configkey,
82 'browserexamkey' => $browserexamkey,
85 self
::validate_context(\context_module
::instance($cmid));
87 // At least one SEB key must be provided.
88 if (empty($configkey) && empty($browserexamkey)) {
89 throw new invalid_parameter_exception(get_string('error:ws:nokeyprovided', 'quizaccess_seb'));
92 // Check quiz exists corresponding to cmid.
93 if (($quizid = self
::get_quiz_id($cmid)) === 0) {
94 throw new invalid_parameter_exception(get_string('error:ws:quiznotexists', 'quizaccess_seb', $cmid));
97 $result = ['configkey' => true, 'browserexamkey' => true];
99 $accessmanager = new access_manager(quiz
::create($quizid));
101 // Check if there is a valid config key.
102 if (!$accessmanager->validate_config_key($configkey, $url)) {
103 access_prevented
::create_strict($accessmanager, get_string('invalid_config_key', 'quizaccess_seb'),
104 $configkey, $browserexamkey)->trigger();
105 $result['configkey'] = false;
108 // Check if there is a valid browser exam key.
109 if (!$accessmanager->validate_browser_exam_key($browserexamkey, $url)) {
110 access_prevented
::create_strict($accessmanager, get_string('invalid_browser_key', 'quizaccess_seb'),
111 $configkey, $browserexamkey)->trigger();
112 $result['browserexamkey'] = false;
115 if ($result['configkey'] && $result['browserexamkey']) {
116 // Set the state of the access for this Moodle session.
117 $accessmanager->set_session_access(true);
124 * External function returns.
126 * @return external_single_structure
128 public static function execute_returns(): external_single_structure
{
129 return new external_single_structure([
130 'configkey' => new external_value(PARAM_BOOL
, 'Is a provided config key valid?',
131 VALUE_REQUIRED
, 0, NULL_NOT_ALLOWED
),
132 'browserexamkey' => new external_value(PARAM_BOOL
, 'Is a provided browser exam key valid?',
133 VALUE_REQUIRED
, 0, NULL_NOT_ALLOWED
)
138 * Check if there is a valid quiz corresponding to a course module it.
140 * @param string $cmid Course module ID.
141 * @return int Returns quiz id if cmid matches valid quiz, or 0 if there is no match.
143 private static function get_quiz_id(string $cmid): int {
146 $coursemodule = get_coursemodule_from_id('quiz', $cmid);
147 if (!empty($coursemodule)) {
148 $quizid = $coursemodule->instance
;