headless_lms_models/
exercise_repositories.rs

1use 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}