Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 110 additions & 22 deletions edu-ws/src/ws.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ pub enum Error {
#[error("invalid token: {message}")]
#[serde(rename = "invalidtoken")]
InvalidToken { message: String },
#[error("invalid param: {message}{}", {
match debuginfo {
Some(debuginfo) => format!(", debuginfo: {debuginfo}"),
None => String::new(),
}
})]
#[serde(rename = "errorinvalidparam")]
#[serde(alias = "invalidparameter")]
InvalidParam {
message: String,
debuginfo: Option<String>,
},
}

#[derive(Error, Debug)]
Expand Down Expand Up @@ -152,19 +164,45 @@ impl Client {
struct Params {
#[serde(rename = "userid")]
user_id: u64,
#[serde_as(as = "NumBool")]
#[serde_as(as = "Option<NumBool>")]
#[serde(rename = "returnusercount")]
return_user_count: bool,
return_user_count: Option<bool>,
}

let mut res = self
.call_web_service::<Vec<Course>, _>(
"core_enrol_get_users_courses",
Some(&Params {
user_id,
return_user_count: Some(return_user_count),
}),
)
.await;

// moodle has introduced `includestealthmodules` in version 3.7:
// https://tracker.moodle.org/browse/MDL-64886
// If the current moodle instance rejects the parameter, we try again without
// it.
if let Err(RequestError::WsError(Error::InvalidParam {
debuginfo: Some(debuginfo),
..
})) = &res
{
if debuginfo.contains("returnusercount") {
debug!("retrying without returnusercount");
res = self
.call_web_service::<Vec<Course>, _>(
"core_enrol_get_users_courses",
Some(&Params {
user_id,
return_user_count: None,
}),
)
.await;
}
}

self.call_web_service(
"core_enrol_get_users_courses",
Some(&Params {
user_id,
return_user_count,
}),
)
.await
res
}

pub async fn get_contents(&self, course_id: u64) -> Result<Vec<Section>> {
Expand All @@ -174,21 +212,43 @@ impl Client {
#[serde(rename = "courseid")]
course_id: u64,
#[serde(rename = "options[0][name]")]
include_stealth_modules_name: &'a str,
#[serde_as(as = "NumBool")]
include_stealth_modules_name: Option<&'a str>,
#[serde_as(as = "Option<NumBool>")]
#[serde(rename = "options[0][value]")]
include_stealth_modules_value: bool,
include_stealth_modules_value: Option<bool>,
}

let mut res = self
.call_web_service(
"core_course_get_contents",
Some(&Params {
course_id,
include_stealth_modules_name: Some("includestealthmodules"),
include_stealth_modules_value: Some(true),
}),
)
.await;

// moodle has introduced `includestealthmodules` in version 3.5.3:
// https://tracker.moodle.org/browse/MDL-63542
// If the current moodle instance complains rejects parameter, we try again
// without it.
if let Err(RequestError::WsError(Error::InvalidParam { message, .. })) = &res {
if message.contains("includestealthmodules") {
res = self
.call_web_service(
"core_course_get_contents",
Some(&Params {
course_id,
include_stealth_modules_name: None,
include_stealth_modules_value: None,
}),
)
.await;
}
}

self.call_web_service(
"core_course_get_contents",
Some(&Params {
course_id,
include_stealth_modules_name: "includestealthmodules",
include_stealth_modules_value: true,
}),
)
.await
res
}
}

Expand All @@ -210,6 +270,34 @@ mod tests {
"message": "message",
}))?
);

assert_eq!(
Error::InvalidParam {
message: "The param \"includestealthmodules\" is invalid.".to_string(),
debuginfo: None,
},
serde_json::from_value(json!({
"errorcode": "errorinvalidparam",
"exception": "moodle_exception",
"message": "The param \"includestealthmodules\" is invalid.",
}))?
);

assert_eq!(
Error::InvalidParam {
message: "Invalid parameter value detected".to_string(),
debuginfo: Some(
"Unexpected keys (returnusercount) detected in parameter array.".to_string()
),
},
serde_json::from_value(json!({
"errorcode": "invalidparameter",
"exception": "invalid_parameter_exception",
"message": "Invalid parameter value detected",
"debuginfo": "Unexpected keys (returnusercount) detected in parameter array.",
}))?
);

Ok(())
}
}