Fixed security issues and added enrolcohortsync service

This commit is contained in:
PMKuipers 2023-06-26 11:41:13 +02:00
parent cbb738b4f4
commit ee12a8e152
2 changed files with 85 additions and 3 deletions

View file

@ -1,10 +1,15 @@
<?php
namespace local_treestudyplan;
use local_treestudyplan\local\helpers\webservicehelper;
require_once($CFG->libdir.'/externallib.php');
class associationservice extends \external_api
{
const CAP_EDIT = "local/treestudyplan:editstudyplan";
const CAP_VIEW = "local/treestudyplan:viewuserreports";
public static function user_structure(){
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'user id'),
@ -76,6 +81,7 @@ class associationservice extends \external_api
return new \external_function_parameters( [
'like' => new \external_value(PARAM_TEXT, 'search text', VALUE_OPTIONAL),
'exclude_id' => new \external_value(PARAM_INT, 'exclude members of this studyplan', VALUE_OPTIONAL),
'context_ic' => new \external_value(PARAM_INT, 'context for this request', VALUE_OPTIONAL),
] );
}
@ -85,9 +91,14 @@ class associationservice extends \external_api
}
// Actual functions
public static function list_cohort($like='',$exclude_id=null)
public static function list_cohort($like='',$exclude_id=null,$context_id=1)
{
global $CFG, $DB;
// Only allow this if the user has the right to edit in this context
$context = webservicehelper::find_context($context_id);
webservicehelper::require_capabilities(self::CAP_EDIT, $context);
$pattern = "%{$like}%";
$params = ["pattern_nm" => $pattern,"pattern_id" => $pattern,];
@ -98,6 +109,11 @@ class associationservice extends \external_api
$sql .= " AND (j.studyplan_id IS NULL OR j.studyplan_id != :exclude_id)";
$params['exclude_id'] = $exclude_id;
}
if($context_id > 1){ // system context returns all cohorts, including system cohorts
// otherwise,
$sql .= " AND contextid = :context_id";
$params['context_id'] = $context_id;
}
$cohorts = [];
$rs = $DB->get_recordset_sql($sql,$params);
@ -113,6 +129,7 @@ class associationservice extends \external_api
return new \external_function_parameters( [
'like' => new \external_value(PARAM_TEXT, 'search text'),
'exclude_id' => new \external_value(PARAM_INT, 'exclude members of this studyplan', VALUE_OPTIONAL),
'context_id' => new \external_value(PARAM_INT, 'context for this request', VALUE_OPTIONAL),
] );
}
@ -122,10 +139,14 @@ class associationservice extends \external_api
}
// Actual functions
public static function find_user($like,$exclude_id=null)
public static function find_user($like,$exclude_id=null,$context_id=1)
{
global $CFG, $DB;
// Only allow this if the user has the right to edit in this context (using system rights would make things more confusing)
$context = webservicehelper::find_context($context_id);
webservicehelper::require_capabilities(self::CAP_EDIT,);
$pattern = "%{$like}%";
$params = ["pattern_fn" => $pattern,
"pattern_ln" => $pattern,
@ -169,6 +190,10 @@ class associationservice extends \external_api
public static function connect_cohort($studyplan_id,$cohort_id)
{
global $CFG, $DB;
$studyplan = studyplan::findById($studyplan_id);
webservicehelper::require_capabilities(self::CAP_EDIT,$studyplan->context());
if(!$DB->record_exists('local_treestudyplan_cohort', ['studyplan_id' => $studyplan_id, 'cohort_id' => $cohort_id]))
{
$id = $DB->insert_record('local_treestudyplan_cohort', [
@ -205,6 +230,9 @@ class associationservice extends \external_api
{
global $CFG, $DB;
$studyplan = studyplan::findById($studyplan_id);
webservicehelper::require_capabilities(self::CAP_EDIT,$studyplan->context());
if($DB->record_exists('local_treestudyplan_cohort', ['studyplan_id' => $studyplan_id, 'cohort_id' => $cohort_id]))
{
$DB->delete_records('local_treestudyplan_cohort', [
@ -239,6 +267,10 @@ class associationservice extends \external_api
public static function connect_user($studyplan_id,$user_id)
{
global $CFG, $DB;
$studyplan = studyplan::findById($studyplan_id);
webservicehelper::require_capabilities(self::CAP_EDIT,$studyplan->context());
if(!$DB->record_exists('local_treestudyplan_user', ['studyplan_id' => $studyplan_id, 'user_id' => $user_id]))
{
$id = $DB->insert_record('local_treestudyplan_user', [
@ -273,6 +305,8 @@ class associationservice extends \external_api
public static function disconnect_user($studyplan_id,$user_id)
{
global $CFG, $DB;
$studyplan = studyplan::findById($studyplan_id);
webservicehelper::require_capabilities(self::CAP_EDIT,$studyplan->context());
if($DB->record_exists('local_treestudyplan_user', ['studyplan_id' => $studyplan_id, 'user_id' => $user_id]))
{
@ -303,6 +337,8 @@ class associationservice extends \external_api
public static function associated_users($studyplan_id)
{
global $CFG, $DB;
$studyplan = studyplan::findById($studyplan_id);
webservicehelper::require_capabilities(self::CAP_VIEW,$studyplan->context());
$sql = "SELECT DISTINCT u.* FROM {user} u INNER JOIN {local_treestudyplan_user} j ON j.user_id = u.id";
$sql .= " WHERE j.studyplan_id = :studyplan_id";
@ -334,6 +370,8 @@ class associationservice extends \external_api
public static function associated_cohorts($studyplan_id)
{
global $CFG, $DB;
$studyplan = studyplan::findById($studyplan_id);
webservicehelper::require_capabilities(self::CAP_VIEW,$studyplan->context());
$sql = "SELECT DISTINCT c.* FROM {cohort} c INNER JOIN {local_treestudyplan_cohort} j ON j.cohort_id = c.id";
$sql .= " WHERE j.studyplan_id = :studyplan_id";
@ -365,6 +403,10 @@ class associationservice extends \external_api
{
global $CFG, $DB;
$studyplan = studyplan::findById($studyplan_id);
webservicehelper::require_capabilities(self::CAP_VIEW,$studyplan->context());
$users = [];
// SQL JOIN script selecting all users that have a cohort linked to this studyplan
// or are directly linked
@ -405,4 +447,35 @@ class associationservice extends \external_api
return ($cmp != 0)?$cmp:$a['firstname'] <=> $b['firstname'];
});
}
public static function enrol_cohortsync_parameters()
{
return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL),
] );
}
public static function enrol_cohortsync_returns()
{
return success::structure();
}
// Actual functions
public static function enrol_cohortsync($studyplan_id)
{
$studyplan = studyplan::findById($studyplan_id);
webservicehelper::require_capabilities(self::CAP_EDIT,$studyplan->context());
$enroller = new enrolcohortsync($studyplan);
$result = $enroller->sync();
return $result?success::success():success::fail();
}
}

View file

@ -542,4 +542,13 @@ $functions = [
'ajax' => true,
'loginrequired' => true,
],
'local_treestudyplan_enrol_cohortsync' => [ //web service function name
'classname' => '\local_treestudyplan\associationservice', //class containing the external function
'methodname' => 'enrol_cohortsync', //external function name
'description' => 'Sync cohortsync to studyplan association', //human readable description of the web service function
'type' => 'read', //database rights of the web service function (read, write)
'capabilities' => 'local/treestudyplan:editstudyplan', // Advises the admin which capabilities are required
'ajax' => true,
'loginrequired' => true,
],
];