diff options
Diffstat (limited to 'backend/src')
-rw-r--r-- | backend/src/db/bots.rs | 54 | ||||
-rw-r--r-- | backend/src/db/mod.rs | 1 | ||||
-rw-r--r-- | backend/src/db/sessions.rs | 2 | ||||
-rw-r--r-- | backend/src/db/users.rs | 2 | ||||
-rw-r--r-- | backend/src/lib.rs | 9 | ||||
-rw-r--r-- | backend/src/routes/bots.rs | 96 | ||||
-rw-r--r-- | backend/src/routes/mod.rs | 1 | ||||
-rw-r--r-- | backend/src/routes/users.rs | 2 | ||||
-rw-r--r-- | backend/src/schema.rs | 21 |
9 files changed, 181 insertions, 7 deletions
diff --git a/backend/src/db/bots.rs b/backend/src/db/bots.rs new file mode 100644 index 0000000..d359e28 --- /dev/null +++ b/backend/src/db/bots.rs @@ -0,0 +1,54 @@ +use diesel::prelude::*; +use serde::{Deserialize, Serialize}; + +use crate::schema::{bots, code_bundles}; +use crate::DbConn; +use chrono; + +#[derive(Insertable)] +#[table_name = "bots"] +pub struct NewBot<'a> { + pub owner_id: i32, + pub name: &'a str, +} + +#[derive(Queryable, Debug, PartialEq, Serialize, Deserialize)] +pub struct Bot { + pub id: i32, + pub owner_id: i32, + pub name: String, +} + +pub fn create_bot(new_bot: &NewBot, conn: &PgConnection) -> QueryResult<Bot> { + diesel::insert_into(bots::table) + .values(new_bot) + .get_result(conn) +} + +pub fn find_bot(id: i32, conn: &PgConnection) -> QueryResult<Bot> { + bots::table.find(id).first(conn) +} + +#[derive(Insertable)] +#[table_name = "code_bundles"] +pub struct NewCodeBundle<'a> { + pub bot_id: i32, + pub path: &'a str, +} + +#[derive(Queryable, Serialize, Deserialize, Debug)] +pub struct CodeBundle { + pub id: i32, + pub bot_id: i32, + pub path: String, + pub created_at: chrono::NaiveDateTime, +} + +pub fn create_code_bundle( + new_code_bundle: &NewCodeBundle, + conn: &PgConnection, +) -> QueryResult<CodeBundle> { + diesel::insert_into(code_bundles::table) + .values(new_code_bundle) + .get_result(conn) +} diff --git a/backend/src/db/mod.rs b/backend/src/db/mod.rs index b6e3efc..947b789 100644 --- a/backend/src/db/mod.rs +++ b/backend/src/db/mod.rs @@ -1,2 +1,3 @@ +pub mod bots; pub mod sessions; pub mod users; diff --git a/backend/src/db/sessions.rs b/backend/src/db/sessions.rs index 0cc3f1a..96f3926 100644 --- a/backend/src/db/sessions.rs +++ b/backend/src/db/sessions.rs @@ -22,7 +22,7 @@ pub struct Session { pub fn create_session(user: &User, conn: &PgConnection) -> Session { let new_session = NewSession { token: gen_session_token(), - user_id: user.user_id, + user_id: user.id, }; let session = insert_into(sessions::table) .values(&new_session) diff --git a/backend/src/db/users.rs b/backend/src/db/users.rs index 29cee88..0817766 100644 --- a/backend/src/db/users.rs +++ b/backend/src/db/users.rs @@ -20,7 +20,7 @@ pub struct NewUser<'a> { #[derive(Queryable, Debug)] pub struct User { - pub user_id: i32, + pub id: i32, pub username: String, pub password_salt: Vec<u8>, pub password_hash: Vec<u8>, diff --git a/backend/src/lib.rs b/backend/src/lib.rs index 0a21850..8807637 100644 --- a/backend/src/lib.rs +++ b/backend/src/lib.rs @@ -8,9 +8,9 @@ extern crate rocket; #[macro_use] extern crate diesel; -mod db; -mod routes; -mod schema; +pub mod db; +pub mod routes; +pub mod schema; #[database("postgresql_database")] pub struct DbConn(diesel::PgConnection); @@ -29,6 +29,9 @@ pub fn rocket() -> Rocket<Build> { routes::users::register, routes::users::login, routes::users::current_user, + routes::bots::create_bot, + routes::bots::get_bot, + routes::bots::upload_bot_code, ], ) .attach(DbConn::fairing()) diff --git a/backend/src/routes/bots.rs b/backend/src/routes/bots.rs new file mode 100644 index 0000000..413c145 --- /dev/null +++ b/backend/src/routes/bots.rs @@ -0,0 +1,96 @@ +use rand::Rng; +use rocket::data::ToByteUnit; +use rocket::fs::TempFile; +use rocket::Data; +use rocket::{response::status, serde::json::Json}; +use serde::{Deserialize, Serialize}; +use std::io::Cursor; +use std::path::Path; + +use crate::DbConn; + +use crate::db::bots::{self, CodeBundle}; +use crate::db::users::User; +use bots::Bot; + +#[derive(Serialize, Deserialize, Debug)] +pub struct BotParams { + name: String, +} + +// TODO: handle errors +#[post("/bots", data = "<params>")] +pub async fn create_bot( + db_conn: DbConn, + user: User, + params: Json<BotParams>, +) -> status::Created<Json<Bot>> { + db_conn + .run(move |conn| { + let bot_params = bots::NewBot { + owner_id: user.id, + name: ¶ms.name, + }; + let bot = bots::create_bot(&bot_params, conn).unwrap(); + let bot_url = uri!(get_bot(bot.id)).to_string(); + status::Created::new(bot_url).body(Json(bot)) + }) + .await +} + +// TODO: handle errors +#[get("/bots/<bot_id>")] +pub async fn get_bot(db_conn: DbConn, bot_id: i32) -> Json<Bot> { + db_conn + .run(move |conn| { + let bot = bots::find_bot(bot_id, conn).unwrap(); + Json(bot) + }) + .await +} + +// TODO: proper error handling +#[post("/bots/<bot_id>/upload", data = "<data>")] +pub async fn upload_bot_code( + db_conn: DbConn, + user: User, + bot_id: i32, + data: Data<'_>, +) -> status::Created<Json<CodeBundle>> { + // TODO: put in config somewhere + let data_path = "./data/bots"; + + let bot = db_conn + .run(move |conn| bots::find_bot(bot_id, conn)) + .await + .expect("Bot not found"); + + assert_eq!(user.id, bot.owner_id); + + // generate a random filename + let token: [u8; 16] = rand::thread_rng().gen(); + let name = base64::encode(&token); + + let path = Path::new(data_path).join(name); + let capped_buf = data.open(10usize.megabytes()).into_bytes().await.unwrap(); + assert!(capped_buf.is_complete()); + let buf = capped_buf.into_inner(); + + zip::ZipArchive::new(Cursor::new(buf)) + .unwrap() + .extract(&path) + .unwrap(); + + let code_bundle = db_conn + .run(move |conn| { + let bundle = bots::NewCodeBundle { + bot_id: bot.id, + path: path.to_str().unwrap(), + }; + bots::create_code_bundle(&bundle, conn).expect("Failed to create code bundle") + }) + .await; + + // TODO: proper location + status::Created::new("").body(Json(code_bundle)) +} diff --git a/backend/src/routes/mod.rs b/backend/src/routes/mod.rs index 913bd46..718d7ef 100644 --- a/backend/src/routes/mod.rs +++ b/backend/src/routes/mod.rs @@ -1 +1,2 @@ +pub mod bots; pub mod users; diff --git a/backend/src/routes/users.rs b/backend/src/routes/users.rs index 72a857f..45a94b9 100644 --- a/backend/src/routes/users.rs +++ b/backend/src/routes/users.rs @@ -55,7 +55,7 @@ pub struct UserData { impl From<User> for UserData { fn from(user: User) -> Self { UserData { - user_id: user.user_id, + user_id: user.id, username: user.username, } } diff --git a/backend/src/schema.rs b/backend/src/schema.rs index 04ecbd7..bf58434 100644 --- a/backend/src/schema.rs +++ b/backend/src/schema.rs @@ -1,4 +1,21 @@ table! { + bots (id) { + id -> Int4, + owner_id -> Int4, + name -> Text, + } +} + +table! { + code_bundles (id) { + id -> Int4, + bot_id -> Int4, + path -> Text, + created_at -> Timestamp, + } +} + +table! { sessions (id) { id -> Int4, user_id -> Int4, @@ -15,6 +32,8 @@ table! { } } +joinable!(bots -> users (owner_id)); +joinable!(code_bundles -> bots (bot_id)); joinable!(sessions -> users (user_id)); -allow_tables_to_appear_in_same_query!(sessions, users,); +allow_tables_to_appear_in_same_query!(bots, code_bundles, sessions, users,); |