reworked coodle external participants

This commit is contained in:
adisposkofh
2026-07-31 13:23:09 +02:00
parent 0c1abacebe
commit 2af177ae87
8 changed files with 65 additions and 60 deletions
+1 -1
View File
@@ -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';
@@ -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 [
@@ -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);
}
+6 -4
View File
@@ -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,
},
};
+1 -1
View File
@@ -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
@@ -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,
),
);
@@ -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,
),
);
@@ -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)