Skip to content

Commit

Permalink
feat(org): support organization (#10)
Browse files Browse the repository at this point in the history
* feat/org(WIP): add create

* feat:get by id

* chore: organising the code format

* fix: modify data type

* feat: delete organization

---------

Co-authored-by: 苏向夜 <[email protected]>
  • Loading branch information
K0nnyaku and fu050409 authored Nov 28, 2024
1 parent 9152d3a commit ed3831a
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ extern crate rocket;
pub mod models;
pub mod utils {
pub mod account;
pub mod organization;
pub mod problem;
pub mod session;
}
Expand All @@ -12,6 +13,7 @@ pub mod routes {
pub mod account;
pub mod index;
pub mod problem;
pub mod organization;
}

pub mod cors;
Expand Down
1 change: 1 addition & 0 deletions src/models/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod account;
pub mod error;
pub mod organization;
pub mod problem;
pub mod response;
pub mod shared;
Expand Down
27 changes: 27 additions & 0 deletions src/models/organization.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use serde::{Deserialize, Serialize};
use surrealdb::sql::Thing;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Organization {
pub id: Option<Thing>,
pub name: String,
pub display_name: Option<String>,

pub description: Option<String>,

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

pub creator: String,

pub created_at: chrono::NaiveDateTime,
pub updated_at: chrono::NaiveDateTime,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct CreateOrganization {
pub name: String,
pub display_name: Option<String>,
pub description: Option<String>,
}
5 changes: 3 additions & 2 deletions src/routes/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ use crate::{cors::CORS, routes::account};
use anyhow::Result;
use rocket::fs::NamedFile;
use surrealdb::{engine::remote::ws::Ws, opt::auth::Root, Surreal};

use super::problem;

use super::organization;
#[get("/")]
async fn index() -> Result<NamedFile, std::io::Error> {
NamedFile::open("dist/index.html").await
Expand Down Expand Up @@ -37,5 +36,7 @@ pub async fn rocket() -> rocket::Rocket<rocket::Build> {
.mount("/", routes![index, files])
.mount("/account", account::routes())
.mount("/problem", problem::routes())
.mount("/org", organization::routes())
.manage(db)

}
88 changes: 88 additions & 0 deletions src/routes/organization.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use rocket::{post, serde::json::Json, tokio::fs::remove_dir_all, State};
use serde::{Deserialize, Serialize};
use std::path::Path;
use surrealdb::{engine::remote::ws::Client, Surreal};

use crate::{
models::{
error::Error,
organization::CreateOrganization,
response::{Empty, Response},
},
utils::{organization, session},
Result,
};

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

pub org: CreateOrganization,
}

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

#[post("/create", data = "<organization>")]
pub async fn create(
db: &State<Surreal<Client>>,
organization: Json<OrgData<'_>>,
) -> Result<CreateOrgResponse> {
if !session::verify(db, organization.id, organization.token).await {
return Err(Error::Unauthorized(Json(
"Failed to grant permission".into(),
)));
}

let org = organization::create(db, organization.id, organization.into_inner().org)
.await
.map_err(|e| Error::ServerError(Json(e.to_string().into())))?
.ok_or(Error::ServerError(Json(
"Failed to create a new organization".into(),
)))?;

Ok(Json(Response {
success: true,
message: "Organization created successfully".to_string(),
data: Some(CreateOrgResponse {
id: org.id.unwrap().id.to_string(),
}),
}))
}

#[post("/delete/<id>", data = "<organization>")]
pub async fn delete(
db: &State<Surreal<Client>>,
id: &str,
organization: Json<OrgData<'_>>,
) -> Result<Empty> {
if !session::verify(db, organization.id, organization.token).await {
return Err(Error::Unauthorized(Json(
"Failed to grant permission".into(),
)));
}

organization::delete(db, id)
.await
.map_err(|e| Error::ServerError(Json(e.to_string().into())))?;

remove_dir_all(Path::new("content/").join(id))
.await
.map_err(|e| Error::ServerError(Json(e.to_string().into())))?;

Ok(Response {
success: true,
message: "Organization deleted successfully".into(),
data: None,
}
.into())
}

pub fn routes() -> Vec<rocket::Route> {
use rocket::routes;
routes![create]
}
37 changes: 37 additions & 0 deletions src/utils/organization.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use anyhow::Result;
use serde::Deserialize;
use surrealdb::{engine::remote::ws::Client, Surreal};

use crate::models::organization::{CreateOrganization, Organization};

pub async fn create(
db: &Surreal<Client>,
id: &str,
org: CreateOrganization,
) -> Result<Option<Organization>> {
Ok(db
.create("organization")
.content(Organization {
id: None,
name: org.name,
display_name: org.display_name,
description: org.description,
owner: vec![("account", id).into()],
member: vec![],
creator: id.to_string(),
created_at: chrono::Local::now().naive_local(),
updated_at: chrono::Local::now().naive_local(),
})
.await?)
}

pub async fn get_by_id<M>(db: &Surreal<Client>, id: &str) -> Result<Option<M>>
where
for<'de> M: Deserialize<'de>,
{
Ok(db.select(("organization", id)).await?)
}

pub async fn delete(db: &Surreal<Client>, id: &str) -> Result<Option<Organization>> {
Ok(db.delete(("organization", id)).await?)
}

0 comments on commit ed3831a

Please sign in to comment.