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_messages;
17pub mod chatbot_conversation_message_reasoning;
18pub mod chatbot_conversation_message_tool_calls;
19pub mod chatbot_conversation_message_tool_outputs;
20pub mod chatbot_conversation_messages;
21pub mod chatbot_conversation_messages_citations;
22pub mod chatbot_conversation_suggested_messages;
23pub mod chatbot_conversations;
24pub mod chatbot_page_sync_statuses;
25pub mod cheating_confirmation_grade_snapshots;
26pub mod cms_ai;
27pub mod code_giveaway_codes;
28pub mod code_giveaways;
29pub mod course_background_question_answers;
30pub mod course_background_questions;
31pub mod course_custom_privacy_policy_checkbox_texts;
32pub mod course_designer_analysis_workspace;
33pub mod course_designer_plan_members;
34pub mod course_designer_plans;
35pub mod course_exams;
36pub mod course_instance_enrollments;
37pub mod course_instances;
38pub mod course_language_groups;
39pub mod course_module_completion_registered_to_study_registries;
40pub mod course_module_completions;
41pub mod course_modules;
42pub mod courses;
43pub mod email_deliveries;
44pub mod email_templates;
45pub mod email_verification_tokens;
46pub mod ended_processed_exams;
47pub mod error;
48pub mod errors;
49pub mod exams;
50pub mod exercise_language_groups;
51pub mod exercise_repositories;
52pub mod exercise_reset_logs;
53pub mod exercise_service_info;
54pub mod exercise_services;
55pub mod exercise_slide_submissions;
56pub mod exercise_slides;
57pub mod exercise_task_gradings;
58pub mod exercise_task_regrading_submissions;
59pub mod exercise_task_submissions;
60pub mod exercise_tasks;
61pub mod exercises;
62pub mod feedback;
63pub mod file_uploads;
64pub mod flagged_answers;
65pub mod generated_certificates;
66pub mod glossary;
67pub mod join_code_uses;
68pub mod library;
69pub mod marketing_consents;
70pub mod material_references;
71pub mod oauth_access_token;
72pub mod oauth_auth_code;
73pub mod oauth_client;
74pub mod oauth_dpop_proofs;
75pub mod oauth_refresh_tokens;
76pub mod oauth_user_client_scopes;
77pub mod offered_answers_to_peer_review_temporary;
78pub mod open_university_registration_links;
79pub mod organizations;
80pub mod other_domain_to_course_redirections;
81pub mod page_audio_files;
82pub mod page_history;
83pub mod page_language_groups;
84pub mod page_visit_datum;
85pub mod page_visit_datum_daily_visit_hashing_keys;
86pub mod page_visit_datum_summary_by_courses;
87pub mod page_visit_datum_summary_by_courses_countries;
88pub mod page_visit_datum_summary_by_courses_device_types;
89pub mod page_visit_datum_summary_by_pages;
90pub mod pages;
91pub mod partner_block;
92pub mod peer_or_self_review_configs;
93pub mod peer_or_self_review_question_submissions;
94pub mod peer_or_self_review_questions;
95pub mod peer_or_self_review_submissions;
96pub mod peer_review_queue_entries;
97pub mod pending_roles;
98pub mod playground_examples;
99pub mod privacy_link;
100pub mod proposed_block_edits;
101pub mod proposed_page_edits;
102pub mod re_exports;
103pub mod regradings;
104pub mod rejected_exercise_slide_submissions;
105pub mod repository_exercises;
106pub mod research_forms;
107pub mod roles;
108pub mod secret;
109pub mod student_countries;
110pub mod study_registry_registrars;
111pub mod suspected_cheaters;
112pub mod teacher_grading_decisions;
113pub mod url_redirections;
114pub mod user_ai_usage_notice_acknowledgements;
115pub mod user_chapter_locking_statuses;
116pub mod user_course_exercise_service_variables;
117pub mod user_course_settings;
118pub mod user_details;
119pub mod user_email_codes;
120pub mod user_exercise_slide_states;
121pub mod user_exercise_states;
122pub mod user_exercise_task_states;
123pub mod user_passwords;
124pub mod user_research_consents;
125pub mod users;
126
127pub mod prelude;
128#[cfg(test)]
129pub mod test_helper;
130
131use exercises::Exercise;
132use futures::future::BoxFuture;
133use url::Url;
134use user_exercise_states::UserExerciseState;
135use uuid::Uuid;
136
137pub use self::error::{HttpErrorType, ModelError, ModelErrorType, ModelResult};
138use crate::prelude::*;
139
140#[macro_use]
141extern crate tracing;
142
143pub enum PKeyPolicy<T> {
236 Fixed(T),
239 Generate,
242}
243
244impl<T> PKeyPolicy<T> {
245 pub fn fixed(&self) -> Option<&T> {
247 match self {
248 PKeyPolicy::Fixed(t) => Some(t),
249 PKeyPolicy::Generate => None,
250 }
251 }
252
253 pub fn map<U, F>(self, f: F) -> PKeyPolicy<U>
255 where
256 F: FnOnce(T) -> U,
257 {
258 match self {
259 PKeyPolicy::Fixed(x) => PKeyPolicy::Fixed(f(x)),
260 PKeyPolicy::Generate => PKeyPolicy::Generate,
261 }
262 }
263
264 pub fn map_ref<U, F>(&self, f: F) -> PKeyPolicy<U>
268 where
269 F: FnOnce(&T) -> U,
270 {
271 match self {
272 PKeyPolicy::Fixed(x) => PKeyPolicy::Fixed(f(x)),
273 PKeyPolicy::Generate => PKeyPolicy::Generate,
274 }
275 }
276}
277
278impl PKeyPolicy<Uuid> {
279 pub fn into_uuid(self) -> Uuid {
281 match self {
282 PKeyPolicy::Fixed(uuid) => uuid,
283 PKeyPolicy::Generate => Uuid::new_v4(),
284 }
285 }
286}
287
288pub trait SpecFetcher:
294 for<'a> Fn(
295 Url,
296 &'a str,
297 Option<&'a serde_json::Value>,
298) -> BoxFuture<'a, ModelResult<serde_json::Value>>
299{
300}
301
302impl<
303 T: for<'a> Fn(
304 Url,
305 &'a str,
306 Option<&'a serde_json::Value>,
307 ) -> BoxFuture<'a, ModelResult<serde_json::Value>>,
308> SpecFetcher for T
309{
310}
311
312#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Copy, Hash)]
317pub enum CourseOrExamId {
318 Course(Uuid),
319 Exam(Uuid),
320}
321
322impl CourseOrExamId {
323 pub fn from_course_and_exam_ids(
324 course_id: Option<Uuid>,
325 exam_id: Option<Uuid>,
326 ) -> ModelResult<Self> {
327 match (course_id, exam_id) {
328 (None, None) => Err(ModelError::new(
329 ModelErrorType::Generic,
330 "Expected either course or exam id, but neither were provided.",
331 None,
332 )),
333 (Some(course_id), None) => Ok(Self::Course(course_id)),
334 (None, Some(exam_id)) => Ok(Self::Exam(exam_id)),
335 (Some(_), Some(_)) => Err(ModelError::new(
336 ModelErrorType::Generic,
337 "Expected either course or exam id, but both were provided.",
338 None,
339 )),
340 }
341 }
342
343 pub fn to_course_and_exam_ids(&self) -> (Option<Uuid>, Option<Uuid>) {
344 match self {
345 CourseOrExamId::Course(course_id) => (Some(*course_id), None),
346 CourseOrExamId::Exam(exam_id) => (None, Some(*exam_id)),
347 }
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<&UserExerciseState> for CourseOrExamId {
360 type Error = ModelError;
361
362 fn try_from(user_exercise_state: &UserExerciseState) -> Result<Self, Self::Error> {
363 Self::from_course_and_exam_ids(user_exercise_state.course_id, user_exercise_state.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}
374
375impl TryFrom<&Exercise> for CourseOrExamId {
376 type Error = ModelError;
377
378 fn try_from(exercise: &Exercise) -> Result<Self, Self::Error> {
379 Self::from_course_and_exam_ids(exercise.course_id, exercise.exam_id)
380 }
381}