From 5203148ffdd8e27ae158d7bfb8527508a716ce6c Mon Sep 17 00:00:00 2001 From: Joel Klinghed Date: Tue, 7 Jan 2025 22:08:56 +0100 Subject: Add remote & branch to project and review Preparing for git connection. --- server/migrations/1_initial_eyeballs.sql | 6 ++- server/src/api_model.rs | 12 ++++++ server/src/db_utils.rs | 10 +++++ server/src/main.rs | 70 +++++++++++++++++--------------- server/src/tests.rs | 12 ++++++ 5 files changed, 77 insertions(+), 33 deletions(-) (limited to 'server') diff --git a/server/migrations/1_initial_eyeballs.sql b/server/migrations/1_initial_eyeballs.sql index 2e5f771..b839c42 100644 --- a/server/migrations/1_initial_eyeballs.sql +++ b/server/migrations/1_initial_eyeballs.sql @@ -1,7 +1,9 @@ CREATE TABLE IF NOT EXISTS projects ( id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, title VARCHAR(1024) NOT NULL, - description MEDIUMTEXT NOT NULL DEFAULT '' + description MEDIUMTEXT NOT NULL DEFAULT '', + remote VARCHAR(2048) NOT NULL, + main_branch VARCHAR(1024) NOT NULL ); CREATE TABLE IF NOT EXISTS users ( @@ -37,6 +39,8 @@ CREATE TABLE IF NOT EXISTS reviews ( description MEDIUMTEXT NOT NULL DEFAULT '', state TINYINT UNSIGNED NOT NULL DEFAULT 0, progress FLOAT NOT NULL DEFAULT 0, + branch VARCHAR(1024) NOT NULL, + archived BOOLEAN NOT NULL DEFAULT 0, CONSTRAINT `fk_reviews_project` FOREIGN KEY (project) REFERENCES projects (id) diff --git a/server/src/api_model.rs b/server/src/api_model.rs index b08ad5c..1b0d7b2 100644 --- a/server/src/api_model.rs +++ b/server/src/api_model.rs @@ -62,6 +62,10 @@ pub struct Review { pub state: ReviewState, #[schema(example = 37.5)] pub progress: f32, + #[schema(example = "r/user/TASK-123456")] + pub branch: String, + #[schema(example = false)] + pub archived: bool, } #[derive(Serialize, ToSchema)] @@ -115,6 +119,10 @@ pub struct Project { pub title: String, #[schema(example = "Example project")] pub description: String, + #[schema(example = "ssh://git.example.org/srv/git/")] + pub remote: String, + #[schema(example = "main")] + pub main_branch: String, pub users: Vec, } @@ -124,6 +132,10 @@ pub struct ProjectData<'r> { pub title: Option<&'r str>, #[schema(example = "Example project")] pub description: Option<&'r str>, + #[schema(example = "ssh://git.example.org/srv/git/")] + pub remote: Option<&'r str>, + #[schema(example = "main")] + pub main_branch: Option<&'r str>, } #[derive(Deserialize, Serialize, ToSchema)] diff --git a/server/src/db_utils.rs b/server/src/db_utils.rs index e74fd68..b7e1fd5 100644 --- a/server/src/db_utils.rs +++ b/server/src/db_utils.rs @@ -92,6 +92,16 @@ where self } + pub fn ok(&self) -> bool { + self.sanity_check(); + + return !self + .names + .as_ref() + .expect("BUG: names taken already") + .is_empty(); + } + pub fn build(&mut self) -> (String, >::Arguments) { self.sanity_check(); diff --git a/server/src/main.rs b/server/src/main.rs index 596eb5b..88546cb 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -153,7 +153,7 @@ async fn get_project( .unwrap(); let project = sqlx::query!( - "SELECT id,title,description FROM projects WHERE id=?", + "SELECT id,title,description,remote,main_branch FROM projects WHERE id=?", projectid ) .fetch_one(&mut ***db) @@ -161,6 +161,8 @@ async fn get_project( id: r.id, title: r.title, description: r.description, + remote: r.remote, + main_branch: r.main_branch, users, }) .map_err(|_| NotFound("No such project")) @@ -189,7 +191,7 @@ async fn project( #[utoipa::path( responses( - (status = 200, description = "Project updated", body = api_model::Project), + (status = 200, description = "Project created", body = api_model::Project), ), security( ("session" = []), @@ -207,9 +209,11 @@ async fn project_new( let mut tx = db.begin().await.unwrap(); projectid = sqlx::query!( - "INSERT INTO projects (title, description) VALUES (?, ?)", + "INSERT INTO projects (title, description, remote, main_branch) VALUES (?, ?, ?, ?)", data.title.unwrap_or("Unnamed"), - data.description.unwrap_or("") + data.description.unwrap_or(""), + data.remote.unwrap_or(""), + data.main_branch.unwrap_or("main"), ) .execute(&mut *tx) .map_ok(|r| r.last_insert_id()) @@ -274,21 +278,24 @@ async fn project_update( ) -> Result<&'static str, Custom<&'static str>> { project_check_maintainer(&mut db, session, projectid).await?; - if data.title.is_none() && data.description.is_none() { - // Nothing to update. Treat as "success". - } else { - let mut update_builder: db_utils::UpdateBuilder = - db_utils::UpdateBuilder::new(); - update_builder.table("projects"); + let mut update_builder: db_utils::UpdateBuilder = db_utils::UpdateBuilder::new(); + update_builder.table("projects"); - if let Some(title) = &data.title { - update_builder.set("title", title); - } - if let Some(description) = &data.description { - update_builder.set("description", description); - } - update_builder.and_where("id", "=", projectid); + if let Some(title) = &data.title { + update_builder.set("title", title); + } + if let Some(description) = &data.description { + update_builder.set("description", description); + } + if let Some(remote) = &data.remote { + update_builder.set("remote", remote); + } + if let Some(main_branch) = &data.main_branch { + update_builder.set("main_branch", main_branch); + } + update_builder.and_where("id", "=", projectid); + if update_builder.ok() { let (query, args) = update_builder.build(); let mut query_builder: sqlx::QueryBuilder = @@ -360,22 +367,19 @@ async fn project_user_update( project_check_maintainer(&mut db, session, projectid).await?; } - if data.default_role.is_none() && data.maintainer.is_none() { - // Nothing to update. Treat as "success". - } else { - let mut update_builder: db_utils::UpdateBuilder = - db_utils::UpdateBuilder::new(); - update_builder.table("project_users"); + let mut update_builder: db_utils::UpdateBuilder = db_utils::UpdateBuilder::new(); + update_builder.table("project_users"); - if let Some(default_role) = &data.default_role { - update_builder.set("default_role", u8::from(*default_role)); - } - if let Some(maintainer) = &data.maintainer { - update_builder.set("maintainer", maintainer); - } - update_builder.and_where("project", "=", projectid); - update_builder.and_where("user", "=", userid); + if let Some(default_role) = &data.default_role { + update_builder.set("default_role", u8::from(*default_role)); + } + if let Some(maintainer) = &data.maintainer { + update_builder.set("maintainer", maintainer); + } + update_builder.and_where("project", "=", projectid); + update_builder.and_where("user", "=", userid); + if update_builder.ok() { let (query, args) = update_builder.build(); let mut query_builder: sqlx::QueryBuilder = @@ -497,7 +501,7 @@ async fn review( let mut projectid = 0; let mut review = sqlx::query!( - "SELECT reviews.id AS id,project,title,description,state,progress,users.id AS user_id,users.username AS username,users.name AS name,users.dn AS user_dn FROM reviews JOIN users ON users.id=owner WHERE reviews.id=?", + "SELECT reviews.id AS id,project,title,description,state,progress,branch,archived,users.id AS user_id,users.username AS username,users.name AS name,users.dn AS user_dn FROM reviews JOIN users ON users.id=owner WHERE reviews.id=?", reviewid) .fetch_one(&mut **db) .map_ok(|r| { @@ -516,6 +520,8 @@ async fn review( users: Vec::new(), state: api_model::ReviewState::try_from(r.state).unwrap(), progress: r.progress, + branch: r.branch, + archived: r.archived != 0, } }) .map_err(|_| NotFound("No such review")) diff --git a/server/src/tests.rs b/server/src/tests.rs index a658c33..ca7217b 100644 --- a/server/src/tests.rs +++ b/server/src/tests.rs @@ -184,6 +184,8 @@ async fn new_project(client: &Client) -> api_model::Project { .json(&api_model::ProjectData { title: Some("foo"), description: Some("bar"), + remote: Some("fum"), + main_branch: Some("zod"), }), ) .await @@ -281,6 +283,8 @@ async fn test_project_new() { assert_eq!(project.title, "foo"); assert_eq!(project.description, "bar"); + assert_eq!(project.remote, "fum"); + assert_eq!(project.main_branch, "zod"); assert_eq!(project.users.len(), 1); let user = project.users.get(0).unwrap(); assert_eq!(user.user.username, "user"); @@ -309,6 +313,8 @@ async fn test_project_update() { &api_model::ProjectData { title: Some("foo"), description: None, + remote: Some("fum"), + main_branch: None, }, )) .await; @@ -320,6 +326,8 @@ async fn test_project_update() { .json(&api_model::ProjectData { title: None, description: Some("bar"), + remote: None, + main_branch: Some("zod"), }) .header(&FAKE_IP) .dispatch() @@ -329,6 +337,8 @@ async fn test_project_update() { let updated_project = get_project_from(client.get(project_url)).await; assert_eq!(updated_project.title, project.title); assert_eq!(updated_project.description, "bar"); + assert_eq!(updated_project.remote, project.remote); + assert_eq!(updated_project.main_branch, "zod"); } #[rocket::async_test] @@ -453,6 +463,8 @@ async fn test_project_check_maintainer() { .json(&api_model::ProjectData { title: None, description: Some("fool"), + remote: None, + main_branch: None, }) .header(&FAKE_IP) .dispatch() -- cgit v1.2.3-70-g09d2