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}