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