Skip to content

Commit

Permalink
feat: optimize server codes (#34)
Browse files Browse the repository at this point in the history
* feat: optimize server codes

* chore: bump version
  • Loading branch information
fu050409 authored Dec 2, 2024
1 parent 439002c commit dde16a7
Show file tree
Hide file tree
Showing 21 changed files with 203 additions and 224 deletions.
7 changes: 7 additions & 0 deletions .changes/optimize.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"algohub-server": patch:feat
---

Optimize data structures and code for better performance.

Also, make the codes more readable and easier to maintain.
5 changes: 4 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ jobs:
--user root --pass root
- name: Rust Cache
uses: Swatinem/rust-cache@v2
- run: cargo test --verbose --all-features
- name: Test
run: cargo test --verbose --all-features
- name: Lint
run: cargo fmt --all -- --check && cargo clippy --all-features -- -D warnings
8 changes: 8 additions & 0 deletions src/models/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,11 @@ pub struct Session {
pub account_id: Thing,
pub token: String,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(crate = "rocket::serde")]
pub struct MergeProfile<'r> {
pub id: &'r str,
pub token: &'r str,
pub profile: Profile,
}
15 changes: 14 additions & 1 deletion src/models/asset.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use std::path::PathBuf;

use rocket::fs::TempFile;
use rocket::{
fs::{NamedFile, TempFile},
response::Responder,
};
use serde::{Deserialize, Serialize};
use surrealdb::sql::Thing;

Expand All @@ -25,3 +28,13 @@ pub struct CreateAsset<'a> {
pub struct UserContent {
pub id: String,
}

pub struct AssetFile(pub(crate) NamedFile);

impl<'r, 'o: 'r> Responder<'r, 'o> for AssetFile {
fn respond_to(self, req: &rocket::Request) -> rocket::response::Result<'o> {
rocket::Response::build_from(self.0.respond_to(req)?)
.raw_header("Cache-control", "max-age=86400") // 24h (24*60*60)
.ok()
}
}
18 changes: 16 additions & 2 deletions src/models/category.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,21 @@ pub struct Category {

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct CreateCategory {
pub name: String,
pub struct CategoryData<'c> {
pub name: &'c str,
pub owner: UserRecordId,
}

#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct CreateCategory<'r> {
pub id: &'r str,
pub token: &'r str,

pub data: CategoryData<'r>,
}

#[derive(Serialize, Deserialize)]
pub struct ListCategories {
pub owner: UserRecordId,
}
17 changes: 13 additions & 4 deletions src/models/organization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ pub struct Organization {

pub description: Option<String>,

pub owner: Vec<Thing>,
pub member: Vec<Thing>,
pub owners: Vec<Thing>,
pub members: Vec<Thing>,

pub creator: String,

Expand All @@ -20,8 +20,17 @@ pub struct Organization {

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct CreateOrganization {
pub name: String,
pub struct OrganizationData<'c> {
pub name: &'c str,
pub display_name: Option<String>,
pub description: Option<String>,
}

#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct CreateOrganization<'r> {
pub id: &'r str,
pub token: &'r str,

pub org: OrganizationData<'r>,
}
6 changes: 6 additions & 0 deletions src/models/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ pub struct OwnedCredentials {
pub token: String,
}

#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct OwnedId {
pub id: String,
}

#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Token<'r> {
Expand Down
24 changes: 6 additions & 18 deletions src/routes/account.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use std::path::Path;

use rocket::{get, post, serde::json::Json, tokio::fs::remove_dir_all, State};
use serde::{Deserialize, Serialize};
use surrealdb::{engine::remote::ws::Client, Surreal};

use crate::{
models::{
account::{Login, Profile, Register},
account::{Login, MergeProfile, Profile, Register},
error::{Error, ErrorResponse},
response::{Empty, Response},
OwnedCredentials, Record, Token,
Expand Down Expand Up @@ -50,14 +49,6 @@ pub async fn register(
}
}

#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(crate = "rocket::serde")]
pub struct MergeProfile<'r> {
pub id: &'r str,
pub token: &'r str,
pub profile: Profile,
}

#[post("/profile", data = "<profile>")]
pub async fn profile(
db: &State<Surreal<Client>>,
Expand Down Expand Up @@ -122,22 +113,19 @@ pub async fn delete(db: &State<Surreal<Client>>, id: &str, auth: Json<Token<'_>>
.into())
}

#[derive(Serialize, Deserialize)]
pub struct LoginResponse {
pub id: String,
pub token: String,
}

#[post("/login", data = "<login>")]
pub async fn login(db: &State<Surreal<Client>>, login: Json<Login<'_>>) -> Result<LoginResponse> {
pub async fn login(
db: &State<Surreal<Client>>,
login: Json<Login<'_>>,
) -> Result<OwnedCredentials> {
let session = session::authenticate(db, login.identity, login.password)
.await
.map_err(|e| Error::ServerError(Json(e.to_string().into())))?
.ok_or(Error::Unauthorized(Json("Invalid credentials".into())))?;
Ok(Response {
success: true,
message: "Login successful".into(),
data: Some(LoginResponse {
data: Some(OwnedCredentials {
id: session.account_id.id.to_string(),
token: session.token.clone(),
}),
Expand Down
15 changes: 2 additions & 13 deletions src/routes/asset.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use rocket::{
form::Form,
fs::NamedFile,
response::Responder,
serde::json::Json,
tokio::fs::{create_dir_all, File},
State,
Expand All @@ -10,7 +9,7 @@ use surrealdb::{engine::remote::ws::Client, Surreal};

use crate::{
models::{
asset::{CreateAsset, UserContent},
asset::{AssetFile, CreateAsset, UserContent},
error::Error,
response::{Empty, Response},
Credentials,
Expand Down Expand Up @@ -82,16 +81,6 @@ pub async fn upload(
}))
}

pub struct AssetFile(NamedFile);

impl<'r, 'o: 'r> Responder<'r, 'o> for AssetFile {
fn respond_to(self, req: &rocket::Request) -> rocket::response::Result<'o> {
rocket::Response::build_from(self.0.respond_to(req)?)
.raw_header("Cache-control", "max-age=86400") // 24h (24*60*60)
.ok()
}
}

#[get("/<id>")]
pub async fn get(db: &State<Surreal<Client>>, id: &str) -> Option<AssetFile> {
let asset = asset::get_by_id(db, id).await.ok()??;
Expand All @@ -113,7 +102,7 @@ pub async fn delete(

let asset = asset::get_by_id(db, id)
.await
.map_err(|e| Error::from(e))?
.map_err(Error::from)?
.ok_or(Error::NotFound(Json("Asset not found".into())))?;

rocket::tokio::fs::remove_file(&asset.path)
Expand Down
32 changes: 6 additions & 26 deletions src/routes/category.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,21 @@
use crate::{
models::{
category::{Category, CreateCategory},
category::{Category, CreateCategory, ListCategories},
error::Error,
response::{Empty, Response},
UserRecordId,
OwnedId,
},
utils::{category, session},
Result,
};
use rocket::{post, serde::json::Json, State};
use serde::{Deserialize, Serialize};
use surrealdb::{engine::remote::ws::Client, Surreal};

#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct CategoryData<'r> {
pub id: &'r str,
pub token: &'r str,

pub data: CreateCategory,
}

#[derive(Serialize, Deserialize)]
pub struct CreateCatResponse {
pub id: String,
}

#[post("/create", data = "<category>")]
pub async fn create(
db: &State<Surreal<Client>>,
category: Json<CategoryData<'_>>,
) -> Result<CreateCatResponse> {
category: Json<CreateCategory<'_>>,
) -> Result<OwnedId> {
if !session::verify(db, category.id, category.token).await {
return Err(Error::Unauthorized(Json(
"Failed to grant permission".into(),
Expand All @@ -45,7 +30,7 @@ pub async fn create(
Ok(Json(Response {
success: true,
message: "Category created successfully".into(),
data: Some(CreateCatResponse {
data: Some(OwnedId {
id: data.id.unwrap().id.to_string(),
}),
}))
Expand All @@ -55,7 +40,7 @@ pub async fn create(
pub async fn delete(
db: &State<Surreal<Client>>,
id: &str,
category: Json<CategoryData<'_>>,
category: Json<CreateCategory<'_>>,
) -> Result<Empty> {
if !session::verify(db, category.id, category.token).await {
return Err(Error::Unauthorized(Json(
Expand All @@ -75,11 +60,6 @@ pub async fn delete(
.into())
}

#[derive(Serialize, Deserialize)]
pub struct ListCategories {
pub owner: UserRecordId,
}

#[post("/list", data = "<data>")]
pub async fn list(
db: &State<Surreal<Client>>,
Expand Down
14 changes: 3 additions & 11 deletions src/routes/contest.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
use rocket::{serde::json::Json, State};
use serde::{Deserialize, Serialize};
use surrealdb::{engine::remote::ws::Client, sql::Thing, Surreal};

use crate::{
models::{
contest::{AddProblems, CreateContest},
error::Error,
response::{Empty, Response},
OwnedId,
},
utils::{contest, session},
Result,
};

#[derive(Serialize, Deserialize)]
pub struct CreateResponse {
pub id: String,
}

#[post("/create", data = "<contest>")]
pub async fn create(
db: &State<Surreal<Client>>,
contest: Json<CreateContest>,
) -> Result<CreateResponse> {
pub async fn create(db: &State<Surreal<Client>>, contest: Json<CreateContest>) -> Result<OwnedId> {
if !session::verify(db, &contest.auth.id, &contest.auth.token).await {
return Err(Error::Unauthorized(Json("Invalid session".into())));
}
Expand All @@ -35,7 +27,7 @@ pub async fn create(
Ok(Json(Response {
success: true,
message: "Contest created successfully".into(),
data: Some(CreateResponse {
data: Some(OwnedId {
id: contest.id.unwrap().id.to_string(),
}),
}))
Expand Down
4 changes: 2 additions & 2 deletions src/routes/index.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use std::path::{Path, PathBuf};

use super::asset;
use super::category;
use super::contest;
use super::organization;
use super::problem;
use super::submission;
use super::category;
use crate::{cors::CORS, routes::account};
use anyhow::Result;
use rocket::fs::NamedFile;
use surrealdb::{engine::remote::ws::Ws, opt::auth::Root, Surreal};

#[get("/")]
async fn index() -> Result<NamedFile, std::io::Error> {
NamedFile::open("dist/index.html").await
Expand Down Expand Up @@ -43,7 +44,6 @@ pub async fn rocket() -> rocket::Rocket<rocket::Build> {
.mount("/problem", problem::routes())
.mount("/org", organization::routes())
.mount("/category", category::routes())

.mount("/contest", contest::routes())
.mount("/code", submission::routes())
.manage(db)
Expand Down
Loading

0 comments on commit dde16a7

Please sign in to comment.