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