From 5c9710f44d77747473ecec9e11ebb69bc092348d Mon Sep 17 00:00:00 2001 From: ma0048 Date: Tue, 2 Dec 2025 13:49:05 +0100 Subject: [PATCH] externe ueberwachung v1 --- cis/testtool/externeueberwachung.js | 35 +++ cis/testtool/frage.php | 6 +- cis/testtool/index.php | 63 ++++++ cis/testtool/login.php | 19 +- cis/testtool/menu.php | 30 ++- cis/testtool/resetconnection.php | 25 +++ cis/testtool/session_init.php | 11 + cis/testtool/topbar.php | 14 +- composer.json | 3 +- config/cis.config-default.inc.php | 6 + include/externe_ueberwachung.class.php | 203 ++++++++++++++++++ include/reihungstest.class.php | 10 +- system/dbupdate_3.4.php | 3 +- ...hungstest_ueberwachung_mit_constructor.php | 42 ++++ vilesci/stammdaten/reihungstestverwaltung.php | 8 + 15 files changed, 461 insertions(+), 17 deletions(-) create mode 100644 cis/testtool/externeueberwachung.js create mode 100644 cis/testtool/resetconnection.php create mode 100644 cis/testtool/session_init.php create mode 100644 include/externe_ueberwachung.class.php create mode 100644 system/dbupdate_3.4/62889_reihungstest_ueberwachung_mit_constructor.php diff --git a/cis/testtool/externeueberwachung.js b/cis/testtool/externeueberwachung.js new file mode 100644 index 000000000..a40a93e05 --- /dev/null +++ b/cis/testtool/externeueberwachung.js @@ -0,0 +1,35 @@ +(function () { + /* + + const params = new URLSearchParams(location.search); + let expectedOrigin = params.get("examus-client-origin"); + + if (!expectedOrigin) + { + window.top.location.href = 'resetconnection.php'; + return; + } + */ + let proctoringOK = false; + + window.addEventListener("message", function (e) { + /*if (e.origin !== expectedOrigin) { + return; + }*/ + + const data = e.data || {}; + + if (data.proctoringIsActive) + { + proctoringOK = true; + } + }); + + setTimeout(function () { + if (!proctoringOK) + { + console.warn("Constructor nicht aktiv!") + //window.location.href='resetconnection.php'; + } + }, 1000); +})(); \ No newline at end of file diff --git a/cis/testtool/frage.php b/cis/testtool/frage.php index c38229cdf..4267d6a13 100644 --- a/cis/testtool/frage.php +++ b/cis/testtool/frage.php @@ -45,7 +45,7 @@ if (!$db = new basis_db()) $PHP_SELF=$_SERVER["PHP_SELF"]; // Start session -session_start(); +require_once './session_init.php'; // If language is changed by language select menu, reset language variables if (isset($_GET['sprache_user']) && !empty($_GET['sprache_user'])) @@ -182,6 +182,10 @@ echo ' if(!isset($_SESSION['pruefling_id'])) die($p->t('testtool/bitteZuerstAnmelden')); +if (!empty($_SESSION['externe_ueberwachung']) && isset($_SESSION['externe_ueberwachung_verified'])): ?> + +load($_SESSION['pruefling_id']); diff --git a/cis/testtool/index.php b/cis/testtool/index.php index d235e6ce9..9aa6c3f84 100644 --- a/cis/testtool/index.php +++ b/cis/testtool/index.php @@ -1,16 +1,78 @@ TestTool - FH Technikum Wien + + + @@ -26,3 +88,4 @@ if(isset($_GET['prestudent']) && is_numeric($_GET['prestudent'])) + diff --git a/cis/testtool/login.php b/cis/testtool/login.php index 5a2ae0dea..2b4e678fa 100644 --- a/cis/testtool/login.php +++ b/cis/testtool/login.php @@ -40,8 +40,7 @@ if (!$db = new basis_db()) die('Fehler beim Oeffnen der Datenbankverbindung'); // Start session -session_start(); - +require_once './session_init.php'; // Logout (triggered by logout button in menu.php) if (isset($_GET['logout']) && $_GET['logout'] == true) { @@ -173,6 +172,12 @@ if (isset($_REQUEST['prestudent'])) else $reload_menu = true; } + + if ($rt->externe_ueberwachung) + { + $_SESSION['externe_ueberwachung'] = true; + $_SESSION['externe_ueberwachung_verified'] = false; + } } $pruefling = new pruefling(); @@ -339,6 +344,8 @@ if ((isset($_SESSION['prestudent_id']) && !isset($_SESSION['pruefling_id']) && !isset($_SESSION['confirmation_needed']) && !isset($_SESSION['confirmed_code'])) || (isset($_SESSION['confirmation_needed']) && $_SESSION['confirmation_needed'] === true && isset($_SESSION['confirmed_code']) && $_SESSION['confirmed_code'] === true && + isset($_SESSION['externe_ueberwachung']) && $_SESSION['externe_ueberwachung'] === true && + isset($_SESSION['externe_ueberwachung_verified']) && $_SESSION['externe_ueberwachung_verified'] === true && isset($_SESSION['prestudent_id']) && !isset($_SESSION['pruefling_id']))) { $pruefling = new pruefling(); @@ -468,7 +475,13 @@ if (isset($_POST['save']) && isset($_SESSION['prestudent_id'])) top.location.href = 'resetconnection.php';"; + exit; +} +else if (isset($_SESSION['confirmation_needed']) && $_SESSION['confirmation_needed'] === true && isset($_SESSION['confirmed_code']) && $_SESSION['confirmed_code'] === false) { echo ' diff --git a/cis/testtool/menu.php b/cis/testtool/menu.php index 7c8b12b9d..2c027c886 100644 --- a/cis/testtool/menu.php +++ b/cis/testtool/menu.php @@ -34,7 +34,7 @@ if (!$db = new basis_db()) die('Fehler beim Oeffnen der Datenbankverbindung'); // Start session -session_start(); +require_once './session_init.php'; // If language is changed by language select menu, reset language and session variables if(isset($_GET['sprache_user']) && !empty($_GET['sprache_user'])) @@ -73,7 +73,7 @@ if (isset($_SESSION['pruefling_id'])) // Link zur Startseite echo ' - '.$p->t('testtool/startseite').' + '.$p->t('testtool/startseite').' '; // Link zur Einleitung @@ -83,7 +83,7 @@ if (isset($_SESSION['pruefling_id'])) { echo ' - '.$p->t('testtool/einleitung').' + '.$p->t('testtool/einleitung').' '; } @@ -379,10 +379,13 @@ if (isset($_SESSION['pruefling_id'])) } } + echo ' + - '.$gebietbezeichnung.' + '.$gebietbezeichnung.' + '; @@ -401,7 +404,7 @@ if (isset($_SESSION['pruefling_id'])) // Link zum Logout echo ' - Logout + Logout '; echo ''; @@ -461,5 +464,22 @@ else ''); } }); + + function loadContent(url) + { + if (parent && typeof parent.loadInContent === 'function') + { + parent.loadInContent(url); + return false; + } + + let frame = parent?.frames?.["content"]; + if (frame) + { + frame.location.href = url; + return false; + } + } + diff --git a/cis/testtool/resetconnection.php b/cis/testtool/resetconnection.php new file mode 100644 index 000000000..200b3d778 --- /dev/null +++ b/cis/testtool/resetconnection.php @@ -0,0 +1,25 @@ +start($_SESSION['prestudent_id'], $_SESSION['reihungstestID']); + $urlSafe = htmlspecialchars($url, ENT_QUOTES); + + + //var_dump($urlSafe); + + header("Location: $urlSafe"); + //echo ""; + $_SESSION['externe_ueberwachung_verified'] = true; + +} \ No newline at end of file diff --git a/cis/testtool/session_init.php b/cis/testtool/session_init.php new file mode 100644 index 000000000..fd7f0b5f3 --- /dev/null +++ b/cis/testtool/session_init.php @@ -0,0 +1,11 @@ + diff --git a/include/externe_ueberwachung.class.php b/include/externe_ueberwachung.class.php new file mode 100644 index 000000000..0e2e06ec9 --- /dev/null +++ b/include/externe_ueberwachung.class.php @@ -0,0 +1,203 @@ +getSessionByPrestudent($prestudent_id); + return $this->getSessionStatus($session_id); + } + public function start($prestudent_id, $reihungstest_id) + { + $session_id = $this->getSessionByPrestudent($prestudent_id); + + if (!$session_id) + { + $session_id = $this->createSession($prestudent_id); + } + else + { + $status = $this->getSessionStatus($session_id); + + if (in_array($status, array('late_to_start', 'finished'))) + { + $session_id = $this->createSession($prestudent_id); + } + } + + $payload = $this->getPayload($session_id, $prestudent_id, $reihungstest_id); + return $this->getStartUrl($payload); + } + + + private function createSession($prestudent_id) + { + if (is_null($prestudent_id)) + { + $this->errormsg = 'Falsche Parameterübergabe'; + return false; + } + + $uuid = $this->genereateUUID(); + + $qry = "INSERT INTO testtool.tbl_externe_ueberwachung (prestudent_id, session_id, insertvon) + VALUES (". + $this->db_add_param($prestudent_id).",". + $this->db_add_param($uuid).",". + $this->db_add_param(get_uid()).")"; + + if($this->db_query($qry)) + { + return $uuid; + } + else + { + $this->errormsg = 'Fehler beim Speichern der Antwort'; + return false; + } + } + public function getSessionByPrestudent($prestudent_id) + { + if (is_null($prestudent_id)) + { + $this->errormsg = 'Falsche Parameterübergabe'; + return false; + } + + $qry = "SELECT session_id + FROM testtool.tbl_externe_ueberwachung + ORDER BY insertamum DESC + LIMIT 1"; + + if($result = $this->db_query($qry)) + { + if ($row = $this->db_fetch_object($result)) + { + return $row->session_id; + } + else + { + $this->errormsg = 'Daten konnten nicht geladen werden'; + return false; + } + } + else + { + $this->errormsg = 'Fehler bei einer Abfrage'; + return false; + } + } + + public function getSessionStatus($session_id) + { + $payload = $this->getSessionPayload($session_id); + $jwt = $this->createToken($payload); + + $url = $this->getSessionUrl($session_id); + + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + "Authorization: JWT {$jwt}", + "Content-Type: application/json", + ]); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET'); + + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + + curl_close($ch); + + $data = json_decode($response, true); + return isset($data['status']) ? $data['status'] : false; + } + + private function getSessionPayload($session_id) + { + return [ + "session_id" => $session_id, + "iat" => time(), + "exp" => time() + 120, + ]; + } + + private function getPayload($session_id, $prestudent_id, $reihungstest_id) + { + $prestudent = new prestudent($prestudent_id); + $person = new Person($prestudent->person_id); + + $reihungstest = new Reihungstest($reihungstest_id); + + $datetime = new DateTime(); + $today = $datetime->format('Y-m-d'); + + $payload = [ + "userId"=> $prestudent_id, + "lastName"=> $person->nachname, + "firstName"=> $person->vorname, + "language"=> $person->sprache, + "accountName"=> "technikum_wien", + "accountId"=> "technikum_wien", + "examId" => !is_null(trim($reihungstest->anmerkung)) ? $reihungstest->anmerkung : ($today . " RT Test"), + "examName" => !is_null(trim($reihungstest->anmerkung)) ? $reihungstest->anmerkung : ($today . " RT Test"), + "allowMultipleDisplays" => true, + "allowMakingRoomScanSecondCamera" => false, + "duration"=> 120, + "schedule"=> false, + "trial"=> true, + "proctoring"=> "offline", + "identification"=> "skip", + "startDate"=> "2018-03-27T00:00:00Z", //TODO anpassen + "endDate"=> "2027-03-30T12:55:00Z", // TODO anpassen + "sessionId"=> $session_id, + "sessionUrl"=> "https://demo.dev.technikum-wien.at/cis/testtool/index.php" + ]; + return $payload; + } + + private function getSessionUrl($session_id) + { + return EXTERNE_UEBERWACHUNG_PROTOCOL_URL . "/api/v2/integration/simple/". EXTERNE_UEBERWACHUNG_INTEGRATION_NAME . "/sessions/". urlencode($session_id) ."/status/"; + } + + private function getStartUrl($payload) + { + $token = $this->createToken($payload); + $query = http_build_query(['token' => $token]); + + return EXTERNE_UEBERWACHUNG_PROTOCOL_URL . '/integration/simple/'. EXTERNE_UEBERWACHUNG_INTEGRATION_NAME .'/start?' . $query; + } + + private function createToken($payload) + { + return JWT::encode($payload, EXTERNE_UEBERWACHUNG_SECRET_KEY, 'HS256'); + } + + private function genereateUUID() + { + $data = openssl_random_pseudo_bytes(16); + + $data[6] = chr(ord($data[6]) & 0x0f | 0x40); + $data[8] = chr(ord($data[8]) & 0x3f | 0x80); + + return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); + } +} + +?> + + + diff --git a/include/reihungstest.class.php b/include/reihungstest.class.php index df4134ebf..94d064c25 100644 --- a/include/reihungstest.class.php +++ b/include/reihungstest.class.php @@ -63,6 +63,7 @@ class reihungstest extends basis_db public $zugangs_ueberpruefung = false; //boolean public $zugangscode; //smallint + public $externe_ueberwachung = false; //boolean /** @@ -119,6 +120,7 @@ class reihungstest extends basis_db $this->aufnahmegruppe_kurzbz = $row->aufnahmegruppe_kurzbz; $this->zugangs_ueberpruefung = $this->db_parse_bool($row->zugangs_ueberpruefung); $this->zugangscode = $row->zugangscode; + $this->externe_ueberwachung = $this->db_parse_bool($row->externe_ueberwachung); return true; } @@ -234,7 +236,7 @@ class reihungstest extends basis_db $qry = 'BEGIN; INSERT INTO public.tbl_reihungstest (studiengang_kz, ort_kurzbz, anmerkung, datum, uhrzeit, insertamum, insertvon, updateamum, updatevon, max_teilnehmer, oeffentlich, freigeschaltet, - studiensemester_kurzbz, stufe, anmeldefrist, aufnahmegruppe_kurzbz, zugangs_ueberpruefung, zugangscode) VALUES('. + studiensemester_kurzbz, stufe, anmeldefrist, aufnahmegruppe_kurzbz, zugangs_ueberpruefung, zugangscode, externe_ueberwachung) VALUES('. $this->db_add_param($this->studiengang_kz, FHC_INTEGER).', '. $this->db_add_param($this->ort_kurzbz).', '. $this->db_add_param($this->anmerkung).', '. @@ -250,7 +252,8 @@ class reihungstest extends basis_db $this->db_add_param($this->anmeldefrist).','. $this->db_add_param($this->aufnahmegruppe_kurzbz). ',' . $this->db_add_param($this->zugangs_ueberpruefung, FHC_BOOLEAN).','. - $this->db_add_param($this->zugangscode) . ');'; + $this->db_add_param($this->zugangscode) . ','. + $this->db_add_param($this->externe_ueberwachung, FHC_BOOLEAN) . ');'; } else { @@ -270,7 +273,8 @@ class reihungstest extends basis_db 'anmeldefrist='.$this->db_add_param($this->anmeldefrist).', '. 'aufnahmegruppe_kurzbz='.$this->db_add_param($this->aufnahmegruppe_kurzbz).', '. 'zugangs_ueberpruefung='.$this->db_add_param($this->zugangs_ueberpruefung, FHC_BOOLEAN).', '. - 'zugangscode='.$this->db_add_param($this->zugangscode).' '. + 'zugangscode='.$this->db_add_param($this->zugangscode).', '. + 'externe_ueberwachung='.$this->db_add_param($this->externe_ueberwachung, FHC_BOOLEAN).' '. 'WHERE reihungstest_id='.$this->db_add_param($this->reihungstest_id, FHC_INTEGER, false).';'; } diff --git a/system/dbupdate_3.4.php b/system/dbupdate_3.4.php index ed50b0df1..708e69717 100644 --- a/system/dbupdate_3.4.php +++ b/system/dbupdate_3.4.php @@ -86,6 +86,7 @@ require_once('dbupdate_3.4/40314_electronic_onboarding_anbindung_ida.php'); require_once('dbupdate_3.4/47972_pruefungsverwaltung_ects_angabe.php'); require_once('dbupdate_3.4/67490_studstatus_suche_abort_controller_haengt.php'); require_once('dbupdate_3.4/68744_StV_settings.php'); +require_once('dbupdate_3.4/62889_reihungstest_ueberwachung_mit_constructor.php'); // *** Pruefung und hinzufuegen der neuen Attribute und Tabellen echo '

Pruefe Tabellen und Attribute!

'; @@ -358,7 +359,7 @@ $tabellen=array( "public.tbl_profil_update_status" => array("status_kurzbz","beschreibung","bezeichnung_mehrsprachig"), "public.tbl_profil_update_topic" => array("topic_kurzbz","beschreibung","bezeichnung_mehrsprachig"), "public.tbl_raumtyp" => array("raumtyp_kurzbz","beschreibung","kosten","aktiv"), - "public.tbl_reihungstest" => array("reihungstest_id","studiengang_kz","ort_kurzbz","anmerkung","datum","uhrzeit","updateamum","updatevon","insertamum","insertvon","ext_id","freigeschaltet","max_teilnehmer","oeffentlich","studiensemester_kurzbz","aufnahmegruppe_kurzbz","stufe","anmeldefrist","zugangs_ueberpruefung","zugangscode"), + "public.tbl_reihungstest" => array("reihungstest_id","studiengang_kz","ort_kurzbz","anmerkung","datum","uhrzeit","updateamum","updatevon","insertamum","insertvon","ext_id","freigeschaltet","max_teilnehmer","oeffentlich","studiensemester_kurzbz","aufnahmegruppe_kurzbz","stufe","anmeldefrist","zugangs_ueberpruefung","zugangscode", "externe_ueberwachung"), "public.tbl_rueckstellung" => array("rueckstellung_id","person_id","status_kurzbz","datum_bis","insertamum","insertvon"), "public.tbl_rueckstellung_status" => array("status_kurzbz", "bezeichnung_mehrsprachig", "sort", "aktiv"), "public.tbl_rt_ort" => array("rt_id","ort_kurzbz","uid"), diff --git a/system/dbupdate_3.4/62889_reihungstest_ueberwachung_mit_constructor.php b/system/dbupdate_3.4/62889_reihungstest_ueberwachung_mit_constructor.php new file mode 100644 index 000000000..7f306e3d9 --- /dev/null +++ b/system/dbupdate_3.4/62889_reihungstest_ueberwachung_mit_constructor.php @@ -0,0 +1,42 @@ +db_query("SELECT externe_ueberwachung FROM public.tbl_reihungstest LIMIT 1")) +{ + $qry = "ALTER TABLE public.tbl_reihungstest ADD COLUMN externe_ueberwachung boolean NOT NULL DEFAULT false;"; + + if(!$db->db_query($qry)) + echo 'public.tbl_reihungstest: '.$db->db_last_error().'
'; + else + echo '
public.tbl_reihungstest: Spalte externe_ueberwachung hinzugefuegt'; +} + +if(!$result = @$db->db_query("SELECT 1 FROM testtool.tbl_externe_ueberwachung LIMIT 1")) +{ + $qry = "CREATE TABLE testtool.tbl_externe_ueberwachung ( + externe_ueberwachung_id INTEGER NOT NULL, + prestudent_id INTEGER NOT NULL, + session_id UUID NOT NULL, + insertamum TIMESTAMP DEFAULT NOW(), + insertvon VARCHAR(32) NOT NULL, + CONSTRAINT tbl_externe_ueberwachung_pk PRIMARY KEY(externe_ueberwachung_id) + ); + CREATE SEQUENCE testtool.tbl_externe_ueberwachungg_id_seq + INCREMENT BY 1 + NO MAXVALUE + NO MINVALUE + CACHE 1; + ALTER TABLE testtool.tbl_externe_ueberwachung ALTER COLUMN externe_ueberwachung_id SET DEFAULT nextval('testtool.tbl_externe_ueberwachungg_id_seq'); + ALTER TABLE testtool.tbl_externe_ueberwachung ADD CONSTRAINT fk_prestudent_externe_ueberwachung FOREIGN KEY (prestudent_id) REFERENCES public.tbl_prestudent (prestudent_id) ON DELETE RESTRICT ON UPDATE CASCADE; + ALTER TABLE testtool.tbl_externe_ueberwachung ADD CONSTRAINT unique_externe_ueberwachung_session_id UNIQUE (session_id); + GRANT SELECT, INSERT ON testtool.tbl_externe_ueberwachung TO vilesci; + GRANT SELECT, INSERT ON testtool.tbl_externe_ueberwachung TO web; + GRANT SELECT, UPDATE ON testtool.tbl_externe_ueberwachungg_id_seq TO vilesci; + GRANT SELECT, UPDATE ON testtool.tbl_externe_ueberwachungg_id_seq TO web;"; + + if(!$db->db_query($qry)) + echo 'testtool.tbl_externe_ueberwachung: '.$db->db_last_error().'
'; + else + echo '
testtool.tbl_externe_ueberwachung: table created'; +} diff --git a/vilesci/stammdaten/reihungstestverwaltung.php b/vilesci/stammdaten/reihungstestverwaltung.php index 07e88183c..babbc3ce4 100644 --- a/vilesci/stammdaten/reihungstestverwaltung.php +++ b/vilesci/stammdaten/reihungstestverwaltung.php @@ -1458,6 +1458,7 @@ if(isset($_POST['speichern']) || isset($_POST['kopieren'])) $reihungstest->anmeldefrist = $datum_obj->formatDatum($_POST['anmeldefrist']); $reihungstest->zugangs_ueberpruefung = false; $reihungstest->zugangscode = null; + $reihungstest->externe_ueberwachung = false; } else { @@ -1474,6 +1475,7 @@ if(isset($_POST['speichern']) || isset($_POST['kopieren'])) $reihungstest->updatevon = $user; $reihungstest->zugangs_ueberpruefung = isset($_POST['zugangs_ueberpruefung']); $reihungstest->zugangscode = ($_POST['zugangcode'] === '' ? null : $_POST['zugangcode']); + $reihungstest->externe_ueberwachung = isset($_POST['externe_ueberwachung']); } $reihungstest->studiengang_kz = $_POST['studiengang_kz']; //$reihungstest->ort_kurzbz = $_POST['ort_kurzbz']; @@ -2571,6 +2573,12 @@ $studienplaene_list = implode(',', array_keys($studienplaene_arr)); (Verpflichtend, wenn die Zugangsüberprüfung aktiviert ist) + + Externe Überwachnung + + externe_ueberwachung ? 'checked="checked"' : '' ?>> + +