algohub_server/routes/
submission.rs

1use eval_stack::compile::Language;
2use rocket::{serde::json::Json, State};
3use serde::{Deserialize, Serialize};
4use surrealdb::{engine::remote::ws::Client, Surreal};
5
6use crate::{
7    models::{
8        error::Error, response::Response, submission::Submission, Credentials, OwnedCredentials,
9    },
10    utils::{session, submission},
11    Result,
12};
13
14#[derive(Serialize, Deserialize)]
15pub struct CreateSubmission {
16    pub auth: OwnedCredentials,
17    pub code: String,
18    pub lang: Language,
19}
20
21#[derive(Serialize, Deserialize)]
22pub struct SubmitResponse {
23    pub id: String,
24}
25
26#[post("/submit/<id>", data = "<data>")]
27pub async fn submit(
28    db: &State<Surreal<Client>>,
29    id: &str,
30    data: Json<CreateSubmission>,
31) -> Result<SubmitResponse> {
32    if !session::verify(db, &data.auth.id, &data.auth.token).await {
33        return Err(Error::Unauthorized(Json("Invalid token".into())));
34    }
35
36    let data = data.into_inner();
37    let submission = submission::create(db, &data.auth.id, id, data.code, data.lang)
38        .await?
39        .ok_or(Error::ServerError(Json(
40            "Failed to submit, please try again later.".into(),
41        )))?;
42
43    Ok(Json(Response {
44        success: true,
45        message: "Submission created successfully".to_string(),
46        data: Some(SubmitResponse {
47            id: submission.id.unwrap().id.to_string(),
48        }),
49    }))
50}
51
52#[post("/get/<id>", data = "<_auth>")]
53pub async fn get(
54    db: &State<Surreal<Client>>,
55    id: &str,
56    _auth: Json<Credentials<'_>>,
57) -> Result<Submission> {
58    let submission = submission::get_by_id(db, id)
59        .await?
60        .ok_or(Error::NotFound(Json("Submission not found".into())))?;
61
62    Ok(Json(Response {
63        success: true,
64        message: "Submission fetched successfully".to_string(),
65        data: Some(submission),
66    }))
67}
68
69#[post("/list/user/<id>", data = "<_auth>")]
70pub async fn list_by_user(
71    db: &State<Surreal<Client>>,
72    id: &str,
73    _auth: Json<Credentials<'_>>,
74) -> Result<Vec<Submission>> {
75    let submissions = submission::list_by_user(db, ("account", id).into()).await?;
76
77    Ok(Json(Response {
78        success: true,
79        message: "submission fetched successfully".to_string(),
80        data: Some(submissions),
81    }))
82}
83
84#[post("/list/contest/<id>", data = "<_auth>")]
85pub async fn list_by_contest(
86    db: &State<Surreal<Client>>,
87    id: &str,
88    _auth: Json<Credentials<'_>>,
89) -> Result<Vec<Submission>> {
90    let submissions = submission::list_by_contest(db, ("contest", id).into()).await?;
91
92    Ok(Json(Response {
93        success: true,
94        message: "submission fetched successfully".to_string(),
95        data: Some(submissions),
96    }))
97}
98
99#[post("/list/problem/<id>", data = "<_auth>")]
100pub async fn list_by_problem(
101    db: &State<Surreal<Client>>,
102    id: &str,
103    _auth: Json<Credentials<'_>>,
104) -> Result<Vec<Submission>> {
105    let submissions = submission::list_by_problem(db, ("problem", id).into()).await?;
106
107    Ok(Json(Response {
108        success: true,
109        message: "submission fetched successfully".to_string(),
110        data: Some(submissions),
111    }))
112}
113
114#[post("/list/<id>/account/<user_id>", data = "<auth>")]
115pub async fn list_by_problem_for_account(
116    db: &State<Surreal<Client>>,
117    id: &str,
118    user_id: &str,
119    auth: Json<Credentials<'_>>,
120) -> Result<Vec<Submission>> {
121    if !session::verify(db, auth.id, auth.token).await {
122        return Err(Error::Unauthorized(Json("Invalid credentials".into())));
123    }
124    let submissions = submission::list_by_problem_for_account(db, id, user_id).await?;
125
126    Ok(Json(Response {
127        success: true,
128        message: "submission fetched successfully".to_string(),
129        data: Some(submissions),
130    }))
131}
132
133pub fn routes() -> Vec<rocket::Route> {
134    use rocket::routes;
135    routes![
136        submit,
137        get,
138        list_by_user,
139        list_by_contest,
140        list_by_problem_for_account,
141        list_by_problem,
142    ]
143}