summaryrefslogtreecommitdiff
path: root/src/weather_thresholds.rs
diff options
context:
space:
mode:
authorDawid Rycerz <dawid@rycerz.xyz>2025-07-14 20:35:00 +0300
committerDawid Rycerz <dawid@rycerz.xyz>2025-07-14 20:35:00 +0300
commit1c2873b3059f3e4d6bd02307ec5b22f761ce1c80 (patch)
treede196a57b76fcacbbc842bbb5bf2641c8f82be91 /src/weather_thresholds.rs
parent50ce8cb96b2b218751c2fc2a6b19372f51846acc (diff)
feat: Update routes and fix issues
Diffstat (limited to 'src/weather_thresholds.rs')
-rw-r--r--src/weather_thresholds.rs153
1 files changed, 135 insertions, 18 deletions
diff --git a/src/weather_thresholds.rs b/src/weather_thresholds.rs
index bfb9cdf..dadfeda 100644
--- a/src/weather_thresholds.rs
+++ b/src/weather_thresholds.rs
@@ -1,5 +1,12 @@
+use crate::auth::AuthUser;
+use axum::Json;
+use axum::extract::{Query, State};
+use axum::http::StatusCode;
+use axum::response::IntoResponse;
use serde::{Deserialize, Serialize};
use sqlx::FromRow;
+use std::collections::HashMap;
+use std::sync::Arc;
#[derive(Debug, Serialize, Deserialize, FromRow, Clone, PartialEq)]
pub struct WeatherThreshold {
@@ -17,7 +24,10 @@ pub struct WeatherThresholdRepository<'a> {
}
impl<'a> WeatherThresholdRepository<'a> {
- pub async fn list_thresholds(&self, user_id: i64) -> Result<Vec<WeatherThreshold>, sqlx::Error> {
+ pub async fn list_thresholds(
+ &self,
+ user_id: i64,
+ ) -> Result<Vec<WeatherThreshold>, sqlx::Error> {
sqlx::query_as::<_, WeatherThreshold>(
"SELECT id, user_id, condition_type, threshold_value, operator, enabled, description FROM weather_thresholds WHERE user_id = ?"
)
@@ -26,7 +36,11 @@ impl<'a> WeatherThresholdRepository<'a> {
.await
}
- pub async fn get_threshold(&self, id: i64, user_id: i64) -> Result<Option<WeatherThreshold>, sqlx::Error> {
+ pub async fn get_threshold(
+ &self,
+ id: i64,
+ user_id: i64,
+ ) -> Result<Option<WeatherThreshold>, sqlx::Error> {
sqlx::query_as::<_, WeatherThreshold>(
"SELECT id, user_id, condition_type, threshold_value, operator, enabled, description FROM weather_thresholds WHERE id = ? AND user_id = ?"
)
@@ -36,7 +50,15 @@ impl<'a> WeatherThresholdRepository<'a> {
.await
}
- pub async fn create_threshold(&self, user_id: i64, condition_type: String, threshold_value: f64, operator: String, enabled: bool, description: Option<String>) -> Result<WeatherThreshold, sqlx::Error> {
+ pub async fn create_threshold(
+ &self,
+ user_id: i64,
+ condition_type: String,
+ threshold_value: f64,
+ operator: String,
+ enabled: bool,
+ description: Option<String>,
+ ) -> Result<WeatherThreshold, sqlx::Error> {
sqlx::query_as::<_, WeatherThreshold>(
"INSERT INTO weather_thresholds (user_id, condition_type, threshold_value, operator, enabled, description) VALUES (?, ?, ?, ?, ?, ?) RETURNING id, user_id, condition_type, threshold_value, operator, enabled, description"
)
@@ -50,7 +72,16 @@ impl<'a> WeatherThresholdRepository<'a> {
.await
}
- pub async fn update_threshold(&self, id: i64, user_id: i64, condition_type: String, threshold_value: f64, operator: String, enabled: bool, description: Option<String>) -> Result<WeatherThreshold, sqlx::Error> {
+ pub async fn update_threshold(
+ &self,
+ id: i64,
+ user_id: i64,
+ condition_type: String,
+ threshold_value: f64,
+ operator: String,
+ enabled: bool,
+ description: Option<String>,
+ ) -> Result<WeatherThreshold, sqlx::Error> {
sqlx::query_as::<_, WeatherThreshold>(
"UPDATE weather_thresholds SET condition_type = ?, threshold_value = ?, operator = ?, enabled = ?, description = ? WHERE id = ? AND user_id = ? RETURNING id, user_id, condition_type, threshold_value, operator, enabled, description"
)
@@ -75,11 +106,35 @@ impl<'a> WeatherThresholdRepository<'a> {
}
}
+pub async fn list_thresholds(
+ AuthUser(_): AuthUser,
+ State(pool): State<Arc<sqlx::SqlitePool>>,
+ Query(query): Query<HashMap<String, String>>,
+) -> impl IntoResponse {
+ let repo = WeatherThresholdRepository { db: &pool };
+ let user_id = match query.get("user_id").and_then(|s| s.parse().ok()) {
+ Some(uid) => uid,
+ None => {
+ return crate::error_response(
+ StatusCode::BAD_REQUEST,
+ "user_id required as query param",
+ );
+ }
+ };
+ match repo.list_thresholds(user_id).await {
+ Ok(thresholds) => Json(thresholds).into_response(),
+ Err(e) => crate::error_response(StatusCode::INTERNAL_SERVER_ERROR, &e.to_string()),
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
use crate::users::{UserRepository, UserRole};
- use sqlx::{SqlitePool, Executor};
+ use axum::extract::{Json, State};
+ use hyper::StatusCode;
+ use sqlx::{Executor, SqlitePool};
+ use std::sync::Arc;
use tokio;
async fn setup_db() -> SqlitePool {
@@ -89,8 +144,10 @@ mod tests {
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL UNIQUE,
role TEXT NOT NULL DEFAULT 'user'
- );"
- ).await.unwrap();
+ );",
+ )
+ .await
+ .unwrap();
pool.execute(
"CREATE TABLE weather_thresholds (
id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -101,8 +158,10 @@ mod tests {
enabled BOOLEAN NOT NULL DEFAULT 1,
description TEXT,
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
- );"
- ).await.unwrap();
+ );",
+ )
+ .await
+ .unwrap();
pool
}
@@ -117,12 +176,21 @@ mod tests {
let db = setup_db().await;
let user_id = create_user(&db).await;
let repo = WeatherThresholdRepository { db: &db };
- let th = repo.create_threshold(user_id, "wind_speed".to_string(), 10.0, ">".to_string(), true, Some("desc".to_string())).await.unwrap();
+ let th = repo
+ .create_threshold(
+ user_id,
+ "wind_speed".to_string(),
+ 10.0,
+ ">".to_string(),
+ true,
+ Some("desc".to_string()),
+ )
+ .await
+ .unwrap();
let fetched = repo.get_threshold(th.id, user_id).await.unwrap().unwrap();
assert_eq!(fetched.condition_type, "wind_speed");
assert_eq!(fetched.threshold_value, 10.0);
- assert_eq!(fetched.operator, ">"
- );
+ assert_eq!(fetched.operator, ">");
assert_eq!(fetched.enabled, true);
assert_eq!(fetched.description, Some("desc".to_string()));
}
@@ -132,8 +200,29 @@ mod tests {
let db = setup_db().await;
let user_id = create_user(&db).await;
let repo = WeatherThresholdRepository { db: &db };
- let th = repo.create_threshold(user_id, "wind_speed".to_string(), 10.0, ">".to_string(), true, None).await.unwrap();
- let updated = repo.update_threshold(th.id, user_id, "rain".to_string(), 5.0, "<".to_string(), false, Some("rain desc".to_string())).await.unwrap();
+ let th = repo
+ .create_threshold(
+ user_id,
+ "wind_speed".to_string(),
+ 10.0,
+ ">".to_string(),
+ true,
+ None,
+ )
+ .await
+ .unwrap();
+ let updated = repo
+ .update_threshold(
+ th.id,
+ user_id,
+ "rain".to_string(),
+ 5.0,
+ "<".to_string(),
+ false,
+ Some("rain desc".to_string()),
+ )
+ .await
+ .unwrap();
assert_eq!(updated.condition_type, "rain");
assert_eq!(updated.threshold_value, 5.0);
assert_eq!(updated.operator, "<");
@@ -146,7 +235,17 @@ mod tests {
let db = setup_db().await;
let user_id = create_user(&db).await;
let repo = WeatherThresholdRepository { db: &db };
- let th = repo.create_threshold(user_id, "wind_speed".to_string(), 10.0, ">".to_string(), true, None).await.unwrap();
+ let th = repo
+ .create_threshold(
+ user_id,
+ "wind_speed".to_string(),
+ 10.0,
+ ">".to_string(),
+ true,
+ None,
+ )
+ .await
+ .unwrap();
repo.delete_threshold(th.id, user_id).await.unwrap();
let fetched = repo.get_threshold(th.id, user_id).await.unwrap();
assert!(fetched.is_none());
@@ -157,9 +256,27 @@ mod tests {
let db = setup_db().await;
let user_id = create_user(&db).await;
let repo = WeatherThresholdRepository { db: &db };
- repo.create_threshold(user_id, "wind_speed".to_string(), 10.0, ">".to_string(), true, None).await.unwrap();
- repo.create_threshold(user_id, "rain".to_string(), 5.0, "<".to_string(), false, None).await.unwrap();
+ repo.create_threshold(
+ user_id,
+ "wind_speed".to_string(),
+ 10.0,
+ ">".to_string(),
+ true,
+ None,
+ )
+ .await
+ .unwrap();
+ repo.create_threshold(
+ user_id,
+ "rain".to_string(),
+ 5.0,
+ "<".to_string(),
+ false,
+ None,
+ )
+ .await
+ .unwrap();
let thresholds = repo.list_thresholds(user_id).await.unwrap();
assert_eq!(thresholds.len(), 2);
}
-} \ No newline at end of file
+}