diff options
author | Galen Guyer <galen@galenguyer.com> | 2022-05-22 17:48:29 -0400 |
---|---|---|
committer | Galen Guyer <galen@galenguyer.com> | 2022-05-22 17:48:29 -0400 |
commit | 842d0f14b8ef5291dd0cd7ce422a73dd634b14e8 (patch) | |
tree | c19692c4d388a17cd1d3fa84eec582a130388583 | |
parent | 2145e15274776bcdadd86d9f011251fbe7cc85ff (diff) |
update record
-rw-r--r-- | src/db/records.rs | 21 | ||||
-rw-r--r-- | src/db/strings.rs | 3 | ||||
-rw-r--r-- | src/main.rs | 5 | ||||
-rw-r--r-- | src/routes/v1/records.rs | 58 |
4 files changed, 85 insertions, 2 deletions
diff --git a/src/db/records.rs b/src/db/records.rs index d92e489..1f2e5bf 100644 --- a/src/db/records.rs +++ b/src/db/records.rs @@ -24,6 +24,27 @@ pub async fn create_record( Ok(zone) } +pub async fn update_record( + pool: &Pool<Postgres>, + record_id: &Uuid, + name: &str, + record_type: &str, + content: &str, + ttl: u32, +) -> Result<Record, sqlx::Error> { + let mut transaction = pool.begin().await?; + let record = sqlx::query_as::<_, Record>(&strings::UPDATE_RECORD) + .bind(name) + .bind(record_type) + .bind(content) + .bind(ttl) + .bind(record_id) + .fetch_one(&mut transaction) + .await?; + transaction.commit().await?; + Ok(record) +} + pub async fn get_records(pool: &Pool<Postgres>, zone_id: &str) -> Result<Vec<Record>, sqlx::Error> { let records = sqlx::query_as::<_, Record>(&strings::GET_RECORDS) .bind(zone_id) diff --git a/src/db/strings.rs b/src/db/strings.rs index aa0249a..ceb71b9 100644 --- a/src/db/strings.rs +++ b/src/db/strings.rs @@ -27,6 +27,9 @@ lazy_static! { pub(crate) static ref CREATE_RECORD: &'static str = r" INSERT INTO records(zone_id,name,type,content,ttl) VALUES ($1, $2, $3, $4, $5) RETURNING * "; + pub(crate) static ref UPDATE_RECORD: &'static str = r" + UPDATE records SET name = $1, type = $2, content = $3, ttl = $4 WHERE id = $5 RETURNING * + "; pub(crate) static ref GET_RECORDS: &'static str = r" SELECT id,zone_id,name,type,content,ttl,created_at,modified_at FROM records WHERE zone_id = $1 diff --git a/src/main.rs b/src/main.rs index 01a70b9..373f953 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ use axum::extract::Extension; use axum::{ response::IntoResponse, - routing::{get, post}, + routing::{get, post, put}, Router, Server, }; use dotenvy::dotenv; @@ -65,7 +65,8 @@ async fn main() { get(routes::v1::records::get_records) .post(routes::v1::zones::create_zone) .put(routes::v1::records::create_record), - ), + ) + .route("/:zone_id/:record_id", put(routes::v1::records::update_record)), ), ), ) diff --git a/src/routes/v1/records.rs b/src/routes/v1/records.rs index 6c71749..18e0d18 100644 --- a/src/routes/v1/records.rs +++ b/src/routes/v1/records.rs @@ -7,6 +7,7 @@ use axum::response::IntoResponse; use axum::Extension; use serde_json::json; use sqlx::{Pool, Postgres}; +use uuid::Uuid; use std::sync::Arc; pub async fn get_records( @@ -60,6 +61,13 @@ pub async fn create_record( ); } + if !data.name.ends_with(&zone.id) { + return ( + StatusCode::BAD_REQUEST, + Json(json!({"error": "Record name must be fully qualified"})), + ); + } + let record = db::records::create_record( &pool, &zone.id, @@ -79,3 +87,53 @@ pub async fn create_record( (StatusCode::OK, Json(json!(record))) } + +pub async fn update_record( + Path((zone_id, record_id)): Path<(String, String)>, + Jwt(user): Jwt, + Json(data): Json<requests::Record>, + Extension(pool): Extension<Arc<Pool<Postgres>>>, +) -> impl IntoResponse { + let zone = db::zones::get_zone(&pool, &zone_id).await; + + if zone.is_err() { + return ( + StatusCode::NOT_FOUND, + Json(json!({"error": "Zone not found"})), + ); + } + let zone = zone.unwrap(); + + if zone.owner_uuid != user.sub { + return ( + StatusCode::FORBIDDEN, + Json(json!({"error": "You do not have permissions to access this zone"})), + ); + } + + if !data.name.ends_with(&zone.id) { + return ( + StatusCode::BAD_REQUEST, + Json(json!({"error": "Record name must be fully qualified"})), + ); + } + + let record = db::records::update_record( + &pool, + &Uuid::parse_str(&record_id).unwrap(), + &data.name, + &data.record_type, + &data.content, + data.ttl, + ) + .await; + if record.is_err() { + return ( + StatusCode::INTERNAL_SERVER_ERROR, + Json(json!({"error": record.unwrap_err().to_string()})), + ); + } + let record = record.unwrap(); + + (StatusCode::OK, Json(json!(record))) +} |