-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: support solution * fix: Optimize variable types and fix the delete function * fix: fmt * feat(sol): support list, get, and update --------- Co-authored-by: 苏向夜 <[email protected]>
- Loading branch information
Showing
8 changed files
with
470 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"algohub-server": patch:feat | ||
--- | ||
|
||
Support create, delete, get, list, update solutions |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
use serde::{Deserialize, Serialize}; | ||
use surrealdb::sql::Thing; | ||
|
||
#[derive(Debug, Serialize, Deserialize)] | ||
pub struct Solution { | ||
pub id: Option<Thing>, | ||
|
||
pub problem: Thing, | ||
pub creator: Thing, | ||
pub title: String, | ||
pub content: String, | ||
|
||
pub created_at: chrono::NaiveDateTime, | ||
pub updated_at: chrono::NaiveDateTime, | ||
} | ||
|
||
#[derive(Debug, Serialize, Deserialize)] | ||
#[serde(crate = "rocket::serde")] | ||
pub struct SolutionData<'r> { | ||
pub title: &'r str, | ||
pub content: &'r str, | ||
pub problem: &'r str, | ||
} | ||
|
||
#[derive(Debug, Serialize, Deserialize)] | ||
#[serde(crate = "rocket::serde")] | ||
pub struct CreateSolution<'r> { | ||
pub id: &'r str, | ||
pub token: &'r str, | ||
pub data: SolutionData<'r>, | ||
} | ||
|
||
#[derive(Debug, Serialize, Deserialize)] | ||
pub struct UserSolution { | ||
pub id: String, | ||
|
||
pub problem: String, | ||
pub title: String, | ||
pub content: String, | ||
pub creator: String, | ||
|
||
pub created_at: chrono::NaiveDateTime, | ||
pub updated_at: chrono::NaiveDateTime, | ||
} | ||
|
||
impl From<Solution> for UserSolution { | ||
fn from(value: Solution) -> Self { | ||
UserSolution { | ||
id: value.id.unwrap().id.to_string(), | ||
problem: value.problem.id.to_string(), | ||
creator: value.creator.id.to_string(), | ||
title: value.title, | ||
content: value.content, | ||
|
||
created_at: value.created_at, | ||
updated_at: value.updated_at, | ||
} | ||
} | ||
} | ||
|
||
impl From<CreateSolution<'_>> for Solution { | ||
fn from(val: CreateSolution<'_>) -> Self { | ||
Solution { | ||
id: None, | ||
title: val.data.title.to_string(), | ||
content: val.data.content.to_string(), | ||
problem: ("problem", val.data.problem).into(), | ||
creator: ("account", val.id).into(), | ||
|
||
created_at: chrono::Local::now().naive_local(), | ||
updated_at: chrono::Local::now().naive_local(), | ||
} | ||
} | ||
} | ||
|
||
#[derive(Debug, Serialize, Deserialize)] | ||
pub struct ListSolutions { | ||
pub problem: String, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
use crate::{ | ||
models::{ | ||
error::Error, | ||
response::{Empty, Response}, | ||
solution::{CreateSolution, ListSolutions, Solution, UserSolution}, | ||
Credentials, OwnedId, | ||
}, | ||
utils::{session, solution}, | ||
Result, | ||
}; | ||
use rocket::{post, serde::json::Json, State}; | ||
use surrealdb::{engine::remote::ws::Client, Surreal}; | ||
|
||
#[post("/create", data = "<sol>")] | ||
pub async fn create(db: &State<Surreal<Client>>, sol: Json<CreateSolution<'_>>) -> Result<OwnedId> { | ||
if !session::verify(db, sol.id, sol.token).await { | ||
return Err(Error::Unauthorized(Json( | ||
"Failed to grant permission".into(), | ||
))); | ||
} | ||
|
||
let solution = solution::create(db, sol.into_inner()) | ||
.await? | ||
.ok_or(Error::ServerError(Json("Failed to create solution".into())))?; | ||
|
||
Ok(Json(Response { | ||
success: true, | ||
message: "Solution created successfully".to_string(), | ||
data: Some(OwnedId { | ||
id: solution.id.unwrap().id.to_string(), | ||
}), | ||
})) | ||
} | ||
|
||
#[post("/get/<id>", data = "<auth>")] | ||
pub async fn get( | ||
db: &State<Surreal<Client>>, | ||
id: &str, | ||
auth: Json<Option<Credentials<'_>>>, | ||
) -> Result<UserSolution> { | ||
let solution = solution::get::<Solution>(db, id) | ||
.await? | ||
.ok_or(Error::NotFound(Json( | ||
"Solution with specified id not found".into(), | ||
)))?; | ||
|
||
let authed_id = if let Some(auth) = auth.into_inner() { | ||
if !session::verify(db, auth.id, auth.token).await { | ||
return Err(Error::Unauthorized(Json("Invalid credentials".into()))); | ||
} else { | ||
Some(auth.id) | ||
} | ||
} else { | ||
None | ||
}; | ||
|
||
if authed_id.is_none() { | ||
return Err(Error::Unauthorized(Json( | ||
"You have no permission to access this solution".into(), | ||
))); | ||
} | ||
|
||
Ok(Json(Response { | ||
success: true, | ||
message: "Solution found".to_string(), | ||
data: Some(solution.into()), | ||
})) | ||
} | ||
|
||
#[post("/update/<id>", data = "<sol>")] | ||
pub async fn update( | ||
db: &State<Surreal<Client>>, | ||
id: &str, | ||
sol: Json<CreateSolution<'_>>, | ||
) -> Result<Empty> { | ||
if !session::verify(db, sol.id, sol.token).await { | ||
return Err(Error::Unauthorized(Json("Invalid credentials".into()))); | ||
} | ||
|
||
solution::update(db, id, sol.into_inner()) | ||
.await? | ||
.ok_or(Error::ServerError(Json( | ||
"Failed to update solution, please try again later.".into(), | ||
)))?; | ||
|
||
Ok(Json(Response { | ||
success: true, | ||
message: "Solution updated successful".to_string(), | ||
data: None, | ||
})) | ||
} | ||
|
||
#[post("/list", data = "<data>")] | ||
pub async fn list(db: &State<Surreal<Client>>, data: Json<ListSolutions>) -> Result<Vec<Solution>> { | ||
let result = solution::list( | ||
db, | ||
("problem".to_string(), data.into_inner().problem).into(), | ||
) | ||
.await?; | ||
|
||
if result.is_empty() { | ||
return Err(Error::NotFound(Json("Solution not found".into()))); | ||
} | ||
|
||
Ok(Json(Response { | ||
success: true, | ||
message: "Solution found successfully".to_string(), | ||
data: Some(result), | ||
})) | ||
} | ||
|
||
#[post("/delete/<id>", data = "<sol>")] | ||
pub async fn delete( | ||
db: &State<Surreal<Client>>, | ||
id: &str, | ||
sol: Json<Credentials<'_>>, | ||
) -> Result<Empty> { | ||
if !session::verify(db, sol.id, sol.token).await { | ||
return Err(Error::Unauthorized(Json( | ||
"Failed to grant permission".into(), | ||
))); | ||
} | ||
|
||
solution::delete(db, id).await?; | ||
|
||
Ok(Response { | ||
success: true, | ||
message: "Solution deleted successfully".to_string(), | ||
data: None, | ||
} | ||
.into()) | ||
} | ||
|
||
pub fn routes() -> Vec<rocket::Route> { | ||
use rocket::routes; | ||
routes![create, get, update, list, delete] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
use anyhow::Result; | ||
use serde::Deserialize; | ||
use surrealdb::{engine::remote::ws::Client, sql::Thing, Surreal}; | ||
|
||
use crate::models::solution::{CreateSolution, Solution}; | ||
|
||
pub async fn create(db: &Surreal<Client>, sol: CreateSolution<'_>) -> Result<Option<Solution>> { | ||
Ok(db | ||
.create("solution") | ||
.content(Into::<Solution>::into(sol)) | ||
.await?) | ||
} | ||
|
||
pub async fn delete(db: &Surreal<Client>, id: &str) -> Result<Option<Solution>> { | ||
Ok(db.delete(("solution", id)).await?) | ||
} | ||
|
||
pub async fn get<M>(db: &Surreal<Client>, id: &str) -> Result<Option<M>> | ||
where | ||
for<'de> M: Deserialize<'de>, | ||
{ | ||
Ok(db.select(("solution", id)).await?) | ||
} | ||
|
||
pub async fn list(db: &Surreal<Client>, problem: Thing) -> Result<Vec<Solution>> { | ||
Ok(db | ||
.query("SELECT * FROM solution WHERE problem = $problem") | ||
.bind(("problem", problem)) | ||
.await? | ||
.take(0)?) | ||
} | ||
|
||
pub async fn update( | ||
db: &Surreal<Client>, | ||
id: &str, | ||
solution: CreateSolution<'_>, | ||
) -> Result<Option<Solution>> { | ||
Ok(db | ||
.update(("solution", id)) | ||
.content(Into::<Solution>::into(solution)) | ||
.await?) | ||
} |
Oops, something went wrong.