headless_lms_models/
exercise_repositories.rs1use crate::prelude::*;
2
3#[derive(Debug, Serialize, sqlx::Type)]
4#[cfg_attr(feature = "ts_rs", derive(TS))]
5#[sqlx(type_name = "exercise_repository_status", rename_all = "kebab-case")]
6pub enum ExerciseRepositoryStatus {
7 Pending,
8 Success,
9 Failure,
10}
11
12#[derive(Debug, Serialize)]
13#[cfg_attr(feature = "ts_rs", derive(TS))]
14pub struct ExerciseRepository {
15 pub id: Uuid,
16 pub url: String,
17 pub course_id: Option<Uuid>,
18 pub exam_id: Option<Uuid>,
19 pub status: ExerciseRepositoryStatus,
20 pub error_message: Option<String>,
21}
22
23pub async fn get(conn: &mut PgConnection, id: Uuid) -> ModelResult<ExerciseRepository> {
24 let res = sqlx::query_as!(
25 ExerciseRepository,
26 r#"
27SELECT id,
28 url,
29 course_id,
30 exam_id,
31 status AS "status: ExerciseRepositoryStatus",
32 error_message
33FROM exercise_repositories
34WHERE id = $1
35 AND deleted_at IS NULL
36"#,
37 id
38 )
39 .fetch_one(conn)
40 .await?;
41 Ok(res)
42}
43
44pub async fn new(
45 conn: &mut PgConnection,
46 id: Uuid,
47 course_or_exam_id: CourseOrExamId,
48 url: &str,
49 public_key: Option<&str>,
50 deploy_key: Option<&str>,
51) -> ModelResult<()> {
52 let (course_id, exam_id) = course_or_exam_id.to_course_and_exam_ids();
53 sqlx::query!(
54 "
55INSERT INTO exercise_repositories (id, course_id, exam_id, url, public_key, deploy_key)
56VALUES ($1, $2, $3, $4, $5, $6)
57",
58 id,
59 course_id,
60 exam_id,
61 url,
62 public_key,
63 deploy_key
64 )
65 .execute(conn)
66 .await?;
67 Ok(())
68}
69
70pub async fn mark_success(conn: &mut PgConnection, id: Uuid) -> ModelResult<()> {
71 sqlx::query!(
72 "
73UPDATE exercise_repositories
74SET status = 'success'
75WHERE id = $1
76",
77 id
78 )
79 .execute(conn)
80 .await?;
81 Ok(())
82}
83
84pub async fn mark_failure(
85 conn: &mut PgConnection,
86 id: Uuid,
87 error_message: &str,
88) -> ModelResult<()> {
89 sqlx::query!(
90 "
91UPDATE exercise_repositories
92SET status = 'failure',
93 error_message = $2
94WHERE id = $1
95",
96 id,
97 error_message
98 )
99 .execute(conn)
100 .await?;
101 Ok(())
102}
103
104pub async fn delete(conn: &mut PgConnection, id: Uuid) -> ModelResult<()> {
105 sqlx::query!(
106 "
107UPDATE exercise_repositories
108SET deleted_at = now()
109WHERE id = $1
110",
111 id
112 )
113 .execute(conn)
114 .await?;
115 Ok(())
116}
117
118pub async fn get_for_course_or_exam(
119 conn: &mut PgConnection,
120 id: CourseOrExamId,
121) -> ModelResult<Vec<ExerciseRepository>> {
122 let (course_id, exam_id) = id.to_course_and_exam_ids();
123 let res = sqlx::query_as!(
124 ExerciseRepository,
125 r#"
126SELECT id,
127 url,
128 course_id,
129 exam_id,
130 status AS "status: ExerciseRepositoryStatus",
131 error_message
132FROM exercise_repositories
133WHERE (
134 course_id = $1
135 OR exam_id = $2
136 )
137 AND deleted_at IS NULL
138"#,
139 course_id,
140 exam_id
141 )
142 .fetch_all(conn)
143 .await?;
144 Ok(res)
145}
146
147#[derive(Debug, Deserialize)]
148pub struct ExerciseRepositoryUpdate {
149 pub url: String,
150}
151
152pub async fn update(
153 conn: &mut PgConnection,
154 id: Uuid,
155 update: &ExerciseRepositoryUpdate,
156) -> ModelResult<()> {
157 sqlx::query!(
158 "
159UPDATE exercise_repositories SET url = $1 WHERE id = $2
160",
161 update.url,
162 id
163 )
164 .execute(conn)
165 .await?;
166 Ok(())
167}