summaryrefslogtreecommitdiff
path: root/server/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/main.rs')
-rw-r--r--server/src/main.rs164
1 files changed, 164 insertions, 0 deletions
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 = "<data>")]
+async fn user_key_add(
+ mut db: Connection<Db>,
+ session: auth::Session,
+ data: Json<api_model::UserKeyData<'_>>,
+) -> Result<Json<api_model::UserKey>, 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/<id>")]
+async fn user_key_get(
+ mut db: Connection<Db>,
+ session: auth::Session,
+ id: u64,
+) -> Result<Json<api_model::UserKey>, 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/<id>")]
+async fn user_key_del(
+ mut db: Connection<Db>,
+ 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?<limit>&<offset>")]
+async fn user_keys(
+ mut db: Connection<Db>,
+ session: auth::Session,
+ limit: Option<u32>,
+ offset: Option<u32>,
+) -> Json<api_model::UserKeys> {
+ 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::<Vec<_>>()
+ .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<Build>) -> 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<Build> {
review,
review_encoded_path,
users,
+ user_key_add,
+ user_key_get,
+ user_key_del,
+ user_keys,
],
)
.attach(auth::stage(basepath))