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