diff --git a/application/config/routes.php b/application/config/routes.php index 25a1923bc..bcd56732f 100644 --- a/application/config/routes.php +++ b/application/config/routes.php @@ -68,7 +68,7 @@ $route['Cis/OtherLvPlan/.*'] = 'Cis/OtherLvPlan/index/$1'; //Route for LV Plan Stg/Semester/Verband/Gruppe $route['Cis/StgOrgLvPlan/.*'] = 'Cis/StgOrgLvPlan/index/$1'; -$route['Cis/CoodleExternal/.*'] = 'Cis/CoodleExternal/index/$1'; +$route['Cis/CoodleExternal/(:any)/(:any)'] = 'Cis/CoodleExternal/index/$1/$2'; $route['CoodleFreeBusy/(:any)'] = 'api/frontend/v1/coodle/FreeBusy/getCoodleFreeBusy/$1'; $route['CoodleIcal/encrypted/(:any)'] = 'api/frontend/v1/coodle/CoodleSurvey/getCoodleIcalEncrypted/$1'; diff --git a/application/controllers/api/frontend/v1/coodle/CoodleSurvey.php b/application/controllers/api/frontend/v1/coodle/CoodleSurvey.php index f29f24422..3eb531262 100644 --- a/application/controllers/api/frontend/v1/coodle/CoodleSurvey.php +++ b/application/controllers/api/frontend/v1/coodle/CoodleSurvey.php @@ -60,7 +60,7 @@ class CoodleSurvey extends FHCAPI_Controller $this->load->helper('hlp_sancho_helper'); $this->coodlePageUrl = APP_ROOT . "cis.php/Cis/Coodle"; - $this->coodlePageExternalUrl = APP_ROOT . "cis.php/Cis/CoodleExternal/{key}"; + $this->coodlePageExternalUrl = APP_ROOT . "cis.php/Cis/CoodleExternal/{surveyId}/{accessKey}"; $this->coodleIcalUrl = APP_ROOT . "cis.php/CoodleIcal/{uid}"; $this->coodleIcalUrlWithEncryptedUid = APP_ROOT . "cis.php/CoodleIcal/encrypted/{encryptedUid}"; @@ -119,13 +119,14 @@ class CoodleSurvey extends FHCAPI_Controller public function getSurveyForExternalParticipant() { - $key = $this->input->post("key"); - $validatedKey = $this->validateEncryptedExternalParticipantKey($this->safeDecode($key)); - if (!$validatedKey) + $surveyId = $this->input->post("surveyId"); + $accessKey = $this->input->post("accessKey"); + $validatedAccessKey = $this->validateExternalParticipantAccessKey($surveyId, $accessKey); + if (!$validatedAccessKey) $this->terminateWithError($this->p->t("coodle", "invalid_access_key_error")); - $survey = $validatedKey["survey"]; - $externalParticipant = $validatedKey["externalParticipant"]; + $survey = $validatedAccessKey["survey"]; + $externalParticipant = $validatedAccessKey["externalParticipant"]; $timeslots = $this->CoodleSurveyTimeslotModel->getTimeslots($survey->id); $survey->timeslots = $timeslots; @@ -234,10 +235,8 @@ class CoodleSurvey extends FHCAPI_Controller ); } - $externalParticipants = $this->CoodleSurveyExternalParticipantModel->getExternalParticipants($surveyId); + $externalParticipants = $this->CoodleSurveyExternalParticipantModel->getExternalParticipants($surveyId, true); foreach ($externalParticipants as $externalParticipant) { - $encryptedAccessKey = $this->safeEncode($this->getEncryptedExternalParticipantKey($externalParticipant)); - sendSanchoMail( "Sancho_Mail_Coodle_Created_Ext", [ @@ -245,7 +244,7 @@ class CoodleSurvey extends FHCAPI_Controller "surveyCreatorName" => $authUserFullName, "org" => CAMPUS_NAME, "surveyTitle" => $survey->title, - "surveyHref" => str_replace("{key}", $encryptedAccessKey, $this->coodlePageExternalUrl), + "surveyHref" => $this->getUrlForExternalParticipant($externalParticipant), ], $externalParticipant->email, "Coodle Umfrage erstellt / Coodle survey created" @@ -313,10 +312,8 @@ class CoodleSurvey extends FHCAPI_Controller ); } - $externalParticipants = $this->CoodleSurveyExternalParticipantModel->getExternalParticipants($surveyId); + $externalParticipants = $this->CoodleSurveyExternalParticipantModel->getExternalParticipants($surveyId, true); foreach ($externalParticipants as $externalParticipant) { - $encryptedAccessKey = $this->safeEncode($this->getEncryptedExternalParticipantKey($externalParticipant)); - sendSanchoMail( "Sancho_Mail_Coodle_Updated_Ext", [ @@ -324,7 +321,7 @@ class CoodleSurvey extends FHCAPI_Controller "surveyCreatorName" => $authUserFullName, "org" => CAMPUS_NAME, "surveyTitle" => $survey->title, - "surveyHref" => str_replace("{key}", $encryptedAccessKey, $this->coodlePageExternalUrl), + "surveyHref" => $this->getUrlForExternalParticipant($externalParticipant), ], $externalParticipant->email, "Coodle Umfrage modifiziert / Coodle survey modified" @@ -401,16 +398,16 @@ class CoodleSurvey extends FHCAPI_Controller public function submitExternalParticipantSelection() { - $key = $this->input->post("key"); + $surveyId = $this->input->post("surveyId"); + $accessKey = $this->input->post("accessKey"); $selection = $this->input->post("selection"); - $key = $this->input->post("key"); - $validatedKey = $this->validateEncryptedExternalParticipantKey($this->safeDecode($key)); - if (!$validatedKey) + $validatedAccessKey = $this->validateExternalParticipantAccessKey($surveyId, $accessKey); + if (!$validatedAccessKey) $this->terminateWithError($this->p->t("coodle", "invalid_access_key_error")); - $survey = $validatedKey["survey"]; - $externalParticipant = $validatedKey["externalParticipant"]; + $survey = $validatedAccessKey["survey"]; + $externalParticipant = $validatedAccessKey["externalParticipant"]; if ($survey->completed_at || $survey->canceled_at) { $this->terminateWithError("You can no longer vote in this survey!"); @@ -459,7 +456,7 @@ class CoodleSurvey extends FHCAPI_Controller if ($shouldInformParticipants) { $survey = $this->CoodleSurveyModel->getSurvey($surveyId); $participants = $this->CoodleSurveyParticipantModel->getParticipants($surveyId); - $externalParticipants = $this->CoodleSurveyExternalParticipantModel->getExternalParticipants($surveyId); + $externalParticipants = $this->CoodleSurveyExternalParticipantModel->getExternalParticipants($surveyId, true); $authUserFullName = getData($this->PersonModel->getFullName(getAuthUID())); foreach ($participants as $participant) { @@ -477,8 +474,6 @@ class CoodleSurvey extends FHCAPI_Controller } foreach ($externalParticipants as $externalParticipant) { - $encryptedAccessKey = $this->safeEncode($this->getEncryptedExternalParticipantKey($externalParticipant)); - sendSanchoMail( "Sancho_Mail_Coodle_Canceled_Ext", [ @@ -486,7 +481,7 @@ class CoodleSurvey extends FHCAPI_Controller "surveyCreatorName" => $authUserFullName, "org" => CAMPUS_NAME, "surveyTitle" => $survey->title, - "surveyHref" => str_replace("{key}", $encryptedAccessKey, $this->coodlePageExternalUrl), + "surveyHref" => $this->getUrlForExternalParticipant($externalParticipant), ], $externalParticipant->email, 'Coodle Umfrage storniert / Coodle survey canceled' @@ -544,7 +539,7 @@ class CoodleSurvey extends FHCAPI_Controller if ($shouldInformParticipants) { $survey = $this->CoodleSurveyModel->getSurvey($surveyId); $participants = $this->CoodleSurveyParticipantModel->getParticipants($surveyId); - $externalParticipants = $this->CoodleSurveyExternalParticipantModel->getExternalParticipants($surveyId); + $externalParticipants = $this->CoodleSurveyExternalParticipantModel->getExternalParticipants($surveyId, true); $authUserFullName = getData($this->PersonModel->getFullName(getAuthUID())); if ($selectedTimeslot) { @@ -597,8 +592,6 @@ class CoodleSurvey extends FHCAPI_Controller } foreach ($externalParticipants as $externalParticipant) { - $encryptedAccessKey = $this->safeEncode($this->getEncryptedExternalParticipantKey($externalParticipant)); - sendSanchoMail( "Sancho_Mail_Coodle_Completed_Ext", [ @@ -607,7 +600,7 @@ class CoodleSurvey extends FHCAPI_Controller "org" => CAMPUS_NAME, "surveyTitle" => $survey->title, "selectedSurveyTimeslot" => $formattedTimeslot, - "surveyHref" => str_replace("{key}", $encryptedAccessKey, $this->coodlePageExternalUrl), + "surveyHref" => $this->getUrlForExternalParticipant($externalParticipant), ], $externalParticipant->email, "Coodle Umfrage vollendet / Coodle survey completed", @@ -642,8 +635,6 @@ class CoodleSurvey extends FHCAPI_Controller } foreach ($externalParticipants as $externalParticipant) { - $encryptedAccessKey = $this->safeEncode($this->getEncryptedExternalParticipantKey($externalParticipant)); - sendSanchoMail( "Sancho_Mail_Coodle_Cmpltd_No_Ext", [ @@ -651,7 +642,7 @@ class CoodleSurvey extends FHCAPI_Controller "surveyParticipantName" => $externalParticipant->name, "org" => CAMPUS_NAME, "surveyTitle" => $survey->title, - "surveyHref" => str_replace("{key}", $encryptedAccessKey, $this->coodlePageExternalUrl), + "surveyHref" => $this->getUrlForExternalParticipant($externalParticipant), ], $externalParticipant->email, "Coodle Umfrage vollendet / Coodle survey completed" @@ -682,7 +673,7 @@ class CoodleSurvey extends FHCAPI_Controller } ); - $externalParticipants = $this->CoodleSurveyExternalParticipantModel->getExternalParticipants($surveyId); + $externalParticipants = $this->CoodleSurveyExternalParticipantModel->getExternalParticipants($surveyId, true); $externalParticipantsWithoutVote = array_filter( $externalParticipants, function ($externalParticipant) { @@ -711,8 +702,6 @@ class CoodleSurvey extends FHCAPI_Controller } foreach ($externalParticipantsWithoutVote as $externalParticipant) { - $encryptedAccessKey = $this->safeEncode($this->getEncryptedExternalParticipantKey($externalParticipant)); - sendSanchoMail( "Sancho_Mail_Coodle_Reminder_Ext", [ @@ -720,7 +709,7 @@ class CoodleSurvey extends FHCAPI_Controller "surveyParticipantName" => $externalParticipant->name, "org" => CAMPUS_NAME, "surveyTitle" => $survey->title, - "surveyHref" => str_replace("{key}", $encryptedAccessKey, $this->coodlePageExternalUrl), + "surveyHref" => $this->getUrlForExternalParticipant($externalParticipant), ], $externalParticipant->email, "Coodle Umfrage Erinnerung / Coodle survey reminder" @@ -1023,26 +1012,24 @@ class CoodleSurvey extends FHCAPI_Controller return $decodedValue; } - private function getEncryptedExternalParticipantKey($externalParticipant) + private function getUrlForExternalParticipant($externalParticipant) { - $value = "coodleExt_" . $externalParticipant->survey_id . "_" . $externalParticipant->id; - return $this->cryptlib->RIJNDAEL_256_ECB(str_pad($value, 32, chr(0)), LVPLAN_CYPHER_KEY, true); + return str_replace( + ["{surveyId}", "{accessKey}"], + [$externalParticipant->survey_id, $externalParticipant->access_key], + $this->coodlePageExternalUrl + ); } - private function validateEncryptedExternalParticipantKey($encryptedKey) + private function validateExternalParticipantAccessKey($surveyId, $accessKey) { - $decryptedKey = trim($this->cryptlib->RIJNDAEL_256_ECB_DECRYPT($encryptedKey, LVPLAN_CYPHER_KEY, true)); - $values = explode("_", $decryptedKey); - if (count($values) !== 3 || $values[0] !== "coodleExt") + if (!$surveyId || !$accessKey) return null; - $surveyId = $values[1]; - $externalParticipantId = $values[2]; - $survey = $this->CoodleSurveyModel->getSurvey($surveyId); - $externalParticipant = $this->CoodleSurveyExternalParticipantModel->getExternalParticipant($externalParticipantId); + $externalParticipant = $this->CoodleSurveyExternalParticipantModel->getExternalParticipantByAccessKey($surveyId, $accessKey); - if (!$survey || !$externalParticipant || $survey->id !== $externalParticipant->survey_id) + if (!$survey || !$externalParticipant) return null; return [ diff --git a/application/models/ressource/CoodleSurveyExternalParticipant_model.php b/application/models/ressource/CoodleSurveyExternalParticipant_model.php index d3ee005ba..cd6ba9906 100644 --- a/application/models/ressource/CoodleSurveyExternalParticipant_model.php +++ b/application/models/ressource/CoodleSurveyExternalParticipant_model.php @@ -16,17 +16,19 @@ class CoodleSurveyExternalParticipant_model extends DB_Model $this->_ci =& get_instance(); } - public function getExternalParticipants($surveyId) + public function getExternalParticipants($surveyId, $includeAccessKeys = false) { - $query = "SELECT * + $selectedColumns = $includeAccessKeys ? "*" : "id, survey_id, name, email, selection"; + $query = "SELECT $selectedColumns FROM $this->dbTable WHERE survey_id = $surveyId "; return $this->execQuery($query)->retval; } - public function getExternalParticipant($externalParticipantId) + public function getExternalParticipant($externalParticipantId, $includeAccessKey = false) { + $selectedColumns = $includeAccessKey ? "*" : "id, survey_id, name, email, selection"; $query = "SELECT * FROM $this->dbTable WHERE id = $externalParticipantId @@ -35,6 +37,16 @@ class CoodleSurveyExternalParticipant_model extends DB_Model return $this->execQuery($query)->retval[0]; } + public function getExternalParticipantByAccessKey($surveyId, $accessKey) + { + $query = "SELECT * + FROM $this->dbTable + WHERE survey_id = $surveyId AND access_key = '$accessKey' + LIMIT 1 + "; + return $this->execQuery($query)->retval[0]; + } + public function updateExternalParticipants($surveyId, $externalParticipants, $timeslots) { $oldExternalParticipants = $this->getExternalParticipants($surveyId); @@ -82,12 +94,13 @@ class CoodleSurveyExternalParticipant_model extends DB_Model function ($newExternalParticipant) use ($surveyId) { $name = $newExternalParticipant["name"]; $email = $newExternalParticipant["email"]; - return "($surveyId, '$name', '$email', NULL)"; + $accessKey = uniqid(); + return "($surveyId, '$name', '$email', '$accessKey', NULL)"; }, $newExternalParticipants ); $insertValues = implode(", ", $insertValues); - $insertQuery = "INSERT INTO $this->dbTable (survey_id, name, email, selection) VALUES $insertValues"; + $insertQuery = "INSERT INTO $this->dbTable (survey_id, name, email, access_key, selection) VALUES $insertValues"; $this->execQuery($insertQuery); } diff --git a/public/js/api/factory/coodle.js b/public/js/api/factory/coodle.js index ec5fa683f..940cdfd75 100644 --- a/public/js/api/factory/coodle.js +++ b/public/js/api/factory/coodle.js @@ -55,12 +55,13 @@ export default { }, }; }, - getSurveyForExternalParticipant(key) { + getSurveyForExternalParticipant(surveyId, accessKey) { return { method: "post", url: "/api/frontend/v1/coodle/CoodleSurvey/getSurveyForExternalParticipant", params: { - key, + surveyId, + accessKey, }, }; }, @@ -86,12 +87,13 @@ export default { }, }; }, - submitExternalParticipantSelection(key, selection) { + submitExternalParticipantSelection(surveyId, accessKey, selection) { return { method: "post", url: "/api/frontend/v1/coodle/CoodleSurvey/submitExternalParticipantSelection", params: { - key, + surveyId, + accessKey, selection, }, }; diff --git a/public/js/apps/Cis/Cis.js b/public/js/apps/Cis/Cis.js index 0a6b55823..f67a9de18 100644 --- a/public/js/apps/Cis/Cis.js +++ b/public/js/apps/Cis/Cis.js @@ -228,7 +228,7 @@ const router = VueRouter.createRouter({ props: true }, { - path: `/Cis/CoodleExternal/:key`, + path: `/Cis/CoodleExternal/:surveyId/:accessKey`, name: 'CoodleExternal', component: CoodleExternal, props: true diff --git a/public/js/components/Cis/Coodle/Components/CoodleSurvey/CoodleSurveyVotingTable.js b/public/js/components/Cis/Coodle/Components/CoodleSurvey/CoodleSurveyVotingTable.js index 64ed1db68..b244eec87 100644 --- a/public/js/components/Cis/Coodle/Components/CoodleSurvey/CoodleSurveyVotingTable.js +++ b/public/js/components/Cis/Coodle/Components/CoodleSurvey/CoodleSurveyVotingTable.js @@ -263,7 +263,8 @@ export default { if (this.$props.authExternalParticipantId) { selectionSubmissionResponse = await this.$api.call( CoodleApi.submitExternalParticipantSelection( - this.$route.params.key, + this.$route.params.surveyId, + this.$route.params.accessKey, selection, ), ); diff --git a/public/js/components/Cis/Coodle/CoodleExternal.js b/public/js/components/Cis/Coodle/CoodleExternal.js index 7ee2032a6..1bf34f197 100644 --- a/public/js/components/Cis/Coodle/CoodleExternal.js +++ b/public/js/components/Cis/Coodle/CoodleExternal.js @@ -15,7 +15,8 @@ export default { async fetchSurvey() { const surveyResponse = await this.$api.call( CoodleApi.getSurveyForExternalParticipant( - this.$route.params.key, + this.$route.params.surveyId, + this.$route.params.accessKey, ), ); diff --git a/system/dbupdate_3.4/77174_cis4_coodle_tables.php b/system/dbupdate_3.4/77174_cis4_coodle_tables.php index 11ddd176d..8bae74f8e 100644 --- a/system/dbupdate_3.4/77174_cis4_coodle_tables.php +++ b/system/dbupdate_3.4/77174_cis4_coodle_tables.php @@ -102,6 +102,7 @@ if (!$result = @$db->db_query("SELECT 1 FROM campus.tbl_coodle_survey_external_p survey_id int NOT NULL, name varchar(255) NOT NULL, email varchar(255) NOT NULL, + access_key varchar(64), selection varchar(255), CONSTRAINT tbl_coodle_surveys_external_participants_id_pk PRIMARY KEY(id), CONSTRAINT tbl_coodle_survey_external_participants_survey_id_fk FOREIGN KEY (survey_id) REFERENCES campus.tbl_coodle_surveys(id)