headless_lms_models/
lib.rs1#![allow(rustdoc::private_intra_doc_links)]
8pub mod certificate_configuration_to_requirements;
9pub mod certificate_configurations;
10pub mod certificate_fonts;
11pub mod chapters;
12pub mod chatbot_configurations;
13pub mod chatbot_configurations_models;
14pub mod chatbot_conversation_message_tool_calls;
15pub mod chatbot_conversation_message_tool_outputs;
16pub mod chatbot_conversation_messages;
17pub mod chatbot_conversation_messages_citations;
18pub mod chatbot_conversations;
19pub mod chatbot_page_sync_statuses;
20pub mod code_giveaway_codes;
21pub mod code_giveaways;
22pub mod course_background_question_answers;
23pub mod course_background_questions;
24pub mod course_custom_privacy_policy_checkbox_texts;
25pub mod course_exams;
26pub mod course_instance_enrollments;
27pub mod course_instances;
28pub mod course_language_groups;
29pub mod course_module_completion_registered_to_study_registries;
30pub mod course_module_completions;
31pub mod course_modules;
32pub mod courses;
33pub mod email_deliveries;
34pub mod email_templates;
35pub mod ended_processed_exams;
36pub mod error;
37pub mod exams;
38pub mod exercise_language_groups;
39pub mod exercise_repositories;
40pub mod exercise_reset_logs;
41pub mod exercise_service_info;
42pub mod exercise_services;
43pub mod exercise_slide_submissions;
44pub mod exercise_slides;
45pub mod exercise_task_gradings;
46pub mod exercise_task_regrading_submissions;
47pub mod exercise_task_submissions;
48pub mod exercise_tasks;
49pub mod exercises;
50pub mod feedback;
51pub mod file_uploads;
52pub mod flagged_answers;
53pub mod generated_certificates;
54pub mod glossary;
55pub mod join_code_uses;
56pub mod library;
57pub mod marketing_consents;
58pub mod material_references;
59pub mod oauth_access_token;
60pub mod oauth_auth_code;
61pub mod oauth_client;
62pub mod oauth_dpop_proofs;
63pub mod oauth_refresh_tokens;
64pub mod oauth_user_client_scopes;
65pub mod offered_answers_to_peer_review_temporary;
66pub mod open_university_registration_links;
67pub mod organizations;
68pub mod other_domain_to_course_redirections;
69pub mod page_audio_files;
70pub mod page_history;
71pub mod page_language_groups;
72pub mod page_visit_datum;
73pub mod page_visit_datum_daily_visit_hashing_keys;
74pub mod page_visit_datum_summary_by_courses;
75pub mod page_visit_datum_summary_by_courses_countries;
76pub mod page_visit_datum_summary_by_courses_device_types;
77pub mod page_visit_datum_summary_by_pages;
78pub mod pages;
79pub mod partner_block;
80pub mod peer_or_self_review_configs;
81pub mod peer_or_self_review_question_submissions;
82pub mod peer_or_self_review_questions;
83pub mod peer_or_self_review_submissions;
84pub mod peer_review_queue_entries;
85pub mod pending_roles;
86pub mod playground_examples;
87pub mod privacy_link;
88pub mod proposed_block_edits;
89pub mod proposed_page_edits;
90pub mod regradings;
91pub mod rejected_exercise_slide_submissions;
92pub mod repository_exercises;
93pub mod research_forms;
94pub mod roles;
95pub mod student_countries;
96pub mod study_registry_registrars;
97pub mod suspected_cheaters;
98pub mod teacher_grading_decisions;
99pub mod url_redirections;
100pub mod user_course_exercise_service_variables;
101pub mod user_course_settings;
102pub mod user_details;
103pub mod user_email_codes;
104pub mod user_exercise_slide_states;
105pub mod user_exercise_states;
106pub mod user_exercise_task_states;
107pub mod user_passwords;
108pub mod user_research_consents;
109pub mod users;
110
111pub mod prelude;
112#[cfg(test)]
113pub mod test_helper;
114
115use exercises::Exercise;
116use futures::future::BoxFuture;
117use url::Url;
118use user_exercise_states::UserExerciseState;
119use uuid::Uuid;
120
121pub use self::error::{HttpErrorType, ModelError, ModelErrorType, ModelResult};
122use crate::prelude::*;
123
124#[macro_use]
125extern crate tracing;
126
127pub enum PKeyPolicy<T> {
220 Fixed(T),
223 Generate,
226}
227
228impl<T> PKeyPolicy<T> {
229 pub fn fixed(&self) -> Option<&T> {
231 match self {
232 PKeyPolicy::Fixed(t) => Some(t),
233 PKeyPolicy::Generate => None,
234 }
235 }
236
237 pub fn map<U, F>(self, f: F) -> PKeyPolicy<U>
239 where
240 F: FnOnce(T) -> U,
241 {
242 match self {
243 PKeyPolicy::Fixed(x) => PKeyPolicy::Fixed(f(x)),
244 PKeyPolicy::Generate => PKeyPolicy::Generate,
245 }
246 }
247
248 pub fn map_ref<U, F>(&self, f: F) -> PKeyPolicy<U>
252 where
253 F: FnOnce(&T) -> U,
254 {
255 match self {
256 PKeyPolicy::Fixed(x) => PKeyPolicy::Fixed(f(x)),
257 PKeyPolicy::Generate => PKeyPolicy::Generate,
258 }
259 }
260}
261
262impl PKeyPolicy<Uuid> {
263 pub fn into_uuid(self) -> Uuid {
265 match self {
266 PKeyPolicy::Fixed(uuid) => uuid,
267 PKeyPolicy::Generate => Uuid::new_v4(),
268 }
269 }
270}
271
272pub trait SpecFetcher:
278 for<'a> Fn(
279 Url,
280 &'a str,
281 Option<&'a serde_json::Value>,
282) -> BoxFuture<'a, ModelResult<serde_json::Value>>
283{
284}
285
286impl<
287 T: for<'a> Fn(
288 Url,
289 &'a str,
290 Option<&'a serde_json::Value>,
291 ) -> BoxFuture<'a, ModelResult<serde_json::Value>>,
292> SpecFetcher for T
293{
294}
295
296#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Copy, Hash)]
301pub enum CourseOrExamId {
302 Course(Uuid),
303 Exam(Uuid),
304}
305
306impl CourseOrExamId {
307 pub fn from_course_and_exam_ids(
308 course_id: Option<Uuid>,
309 exam_id: Option<Uuid>,
310 ) -> ModelResult<Self> {
311 match (course_id, exam_id) {
312 (None, None) => Err(ModelError::new(
313 ModelErrorType::Generic,
314 "Expected either course or exam id, but neither were provided.",
315 None,
316 )),
317 (Some(course_id), None) => Ok(Self::Course(course_id)),
318 (None, Some(exam_id)) => Ok(Self::Exam(exam_id)),
319 (Some(_), Some(_)) => Err(ModelError::new(
320 ModelErrorType::Generic,
321 "Expected either course or exam id, but both were provided.",
322 None,
323 )),
324 }
325 }
326
327 pub fn to_course_and_exam_ids(&self) -> (Option<Uuid>, Option<Uuid>) {
328 match self {
329 CourseOrExamId::Course(course_id) => (Some(*course_id), None),
330 CourseOrExamId::Exam(exam_id) => (None, Some(*exam_id)),
331 }
332 }
333}
334
335impl TryFrom<UserExerciseState> for CourseOrExamId {
336 type Error = ModelError;
337
338 fn try_from(user_exercise_state: UserExerciseState) -> Result<Self, Self::Error> {
339 Self::from_course_and_exam_ids(user_exercise_state.course_id, user_exercise_state.exam_id)
340 }
341}
342
343impl TryFrom<&UserExerciseState> for CourseOrExamId {
344 type Error = ModelError;
345
346 fn try_from(user_exercise_state: &UserExerciseState) -> Result<Self, Self::Error> {
347 Self::from_course_and_exam_ids(user_exercise_state.course_id, user_exercise_state.exam_id)
348 }
349}
350
351impl TryFrom<Exercise> for CourseOrExamId {
352 type Error = ModelError;
353
354 fn try_from(exercise: Exercise) -> Result<Self, Self::Error> {
355 Self::from_course_and_exam_ids(exercise.course_id, exercise.exam_id)
356 }
357}
358
359impl TryFrom<&Exercise> for CourseOrExamId {
360 type Error = ModelError;
361
362 fn try_from(exercise: &Exercise) -> Result<Self, Self::Error> {
363 Self::from_course_and_exam_ids(exercise.course_id, exercise.exam_id)
364 }
365}