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
110AND deleted_at IS NULL
111",
112 id
113 )
114 .execute(conn)
115 .await?;
116 Ok(())
117}
118
119pub async fn get_for_course_or_exam(
120 conn: &mut PgConnection,
121 id: CourseOrExamId,
122) -> ModelResult<Vec<ExerciseRepository>> {
123 let (course_id, exam_id) = id.to_course_and_exam_ids();
124 let res = sqlx::query_as!(
125 ExerciseRepository,
126 r#"
127SELECT id,
128 url,
129 course_id,
130 exam_id,
131 status AS "status: ExerciseRepositoryStatus",
132 error_message
133FROM exercise_repositories
134WHERE (
135 course_id = $1
136 OR exam_id = $2
137 )
138 AND deleted_at IS NULL
139"#,
140 course_id,
141 exam_id
142 )
143 .fetch_all(conn)
144 .await?;
145 Ok(res)
146}
147
148#[derive(Debug, Deserialize)]
149pub struct ExerciseRepositoryUpdate {
150 pub url: String,
151}
152
153pub async fn update(
154 conn: &mut PgConnection,
155 id: Uuid,
156 update: &ExerciseRepositoryUpdate,
157) -> ModelResult<()> {
158 sqlx::query!(
159 "
160UPDATE exercise_repositories SET url = $1 WHERE id = $2
161",
162 update.url,
163 id
164 )
165 .execute(conn)
166 .await?;
167 Ok(())
168}