From 9d14d9ca39b46042c4196382613dd9c4bf711fcb Mon Sep 17 00:00:00 2001 From: Joel Klinghed Date: Mon, 27 Jan 2025 22:57:15 +0100 Subject: Add user keys to database Next step is to generate authorized_keys files for git server based on keys. --- server/src/main.rs | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) (limited to 'server/src/main.rs') diff --git a/server/src/main.rs b/server/src/main.rs index d0547c1..298a418 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -44,6 +44,10 @@ struct Db(sqlx::MySqlPool); reviews, review, users, + user_key_add, + user_key_get, + user_key_del, + user_keys, ), modifiers(&AuthApiAddon), )] @@ -662,6 +666,162 @@ async fn users( }) } +#[utoipa::path( + responses( + (status = 200, description = "Key added to current user", body = api_model::UserKey), + (status = 400, description = "Key too large"), + ), + security( + ("session" = []), + ), +)] +#[post("/user/keys/add", data = "")] +async fn user_key_add( + mut db: Connection, + session: auth::Session, + data: Json>, +) -> Result, Custom<&'static str>> { + if data.data.len() > 8192 { + return Err(Custom(Status::BadRequest, "Key is too large")); + } + + let comment = data.comment.unwrap_or(""); + let result = sqlx::query!( + "INSERT INTO user_keys (user, kind, data, comment) VALUES (?, ?, ?, ?)", + session.user_id, + data.kind, + data.data, + comment, + ) + .execute(&mut **db) + .await + .unwrap(); + + Ok(Json(api_model::UserKey { + id: result.last_insert_id(), + kind: data.kind.to_string(), + data: data.data.to_string(), + comment: comment.to_string(), + })) +} + +#[utoipa::path( + responses( + (status = 200, description = "User key", body = api_model::UserKey), + (status = 404, description = "No such key"), + ), + security( + ("session" = []), + ), +)] +#[get("/user/keys/")] +async fn user_key_get( + mut db: Connection, + session: auth::Session, + id: u64, +) -> Result, NotFound<&'static str>> { + let user_key = sqlx::query!( + "SELECT id,kind,data,comment FROM user_keys WHERE id=? AND user=?", + id, + session.user_id, + ) + .fetch_one(&mut **db) + .map_ok(|r| api_model::UserKey { + id: r.id, + kind: r.kind, + data: r.data, + comment: r.comment, + }) + .map_err(|_| NotFound("No such user key")) + .await?; + + Ok(Json(user_key)) +} + +#[utoipa::path( + responses( + (status = 200, description = "Key removed from current user"), + (status = 404, description = "No such key for current user"), + ), + security( + ("session" = []), + ), +)] +#[delete("/user/keys/")] +async fn user_key_del( + mut db: Connection, + session: auth::Session, + id: u64, +) -> Result<&'static str, Custom<&'static str>> { + let result = sqlx::query!( + "DELETE FROM user_keys WHERE id=? AND user=?", + id, + session.user_id, + ) + .execute(&mut **db) + .await + .unwrap(); + if result.rows_affected() == 0 { + return Err(Custom(Status::NotFound, "No such key for current user")); + } + + Ok("") +} + +#[utoipa::path( + responses( + (status = 200, description = "Get all keys for user", body = api_model::UserKeys), + ), + security( + ("session" = []), + ), +)] +#[get("/user/keys?&")] +async fn user_keys( + mut db: Connection, + session: auth::Session, + limit: Option, + offset: Option, +) -> Json { + let uw_offset = offset.unwrap_or(0); + let uw_limit = limit.unwrap_or(10); + let entries = sqlx::query!( + "SELECT id,kind,data,comment FROM user_keys WHERE user=? ORDER BY id LIMIT ? OFFSET ?", + session.user_id, + uw_limit, + uw_offset + ) + .fetch(&mut **db) + .map_ok(|r| api_model::UserKey { + id: r.id, + kind: r.kind, + data: r.data, + comment: r.comment, + }) + .try_collect::>() + .await + .unwrap(); + + let count = sqlx::query!( + "SELECT COUNT(id) AS count FROM user_keys WHERE user=?", + session.user_id, + ) + .fetch_one(&mut **db) + .map_ok(|r| r.count) + .await + .unwrap(); + + let u32_count = u32::try_from(count).unwrap(); + + Json(api_model::UserKeys { + offset: uw_offset, + limit: uw_limit, + total_count: u32_count, + more: uw_offset + uw_limit < u32_count, + keys: entries, + }) +} + async fn run_migrations(rocket: Rocket) -> fairing::Result { match Db::fetch(&rocket) { Some(db) => match sqlx::migrate!().run(&**db).await { @@ -695,6 +855,10 @@ fn rocket_from_config(figment: Figment) -> Rocket { review, review_encoded_path, users, + user_key_add, + user_key_get, + user_key_del, + user_keys, ], ) .attach(auth::stage(basepath)) -- cgit v1.2.3-70-g09d2