summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGalen Guyer <galen@galenguyer.com>2022-05-22 17:48:29 -0400
committerGalen Guyer <galen@galenguyer.com>2022-05-22 17:48:29 -0400
commit842d0f14b8ef5291dd0cd7ce422a73dd634b14e8 (patch)
treec19692c4d388a17cd1d3fa84eec582a130388583
parent2145e15274776bcdadd86d9f011251fbe7cc85ff (diff)
update record
-rw-r--r--src/db/records.rs21
-rw-r--r--src/db/strings.rs3
-rw-r--r--src/main.rs5
-rw-r--r--src/routes/v1/records.rs58
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)))
+}