diff --git a/bruno/oauth/Create API Key.bru b/bruno/oauth/Create API Key.bru index 08a5b80..98fc8b7 100644 --- a/bruno/oauth/Create API Key.bru +++ b/bruno/oauth/Create API Key.bru @@ -11,5 +11,5 @@ post { } auth:bearer { - token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjI1MDg0MjI2MTIyMTI3NzY5NywibmFtZSI6ImJzaGVycmlmZiIsImlhdCI6MTczNDgwODA5MiwiZXhwIjoxNzM0ODk0NDkyLCJqdGkiOiJsSWFHaU15Wll5cnFVYmFJTGs2dzAyZTY4YkFPZjFZWSJ9.fCeooH2IdtXiy2s23WykXtOaR8dvnUinmSGFcV-fOwQ + token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjI1MDg0MjI2MTIyMTI3NzY5NywibmFtZSI6ImJzaGVycmlmZiIsImlhdCI6MTczNDg0MzA0NywiZXhwIjoxNzM0OTI5NDQ3LCJqdGkiOiIycEowbmN5YmF1TVo4TG1aQ0VwU1B2OWgzMXFzU1FwaCJ9.gYf6oAm2POBXOHUnG4dTy5maKxTjUk8WxawOrIafjEE } diff --git a/src/api/auth/api_key.rs b/src/api/auth/api_key.rs index 0b1c430..1a477db 100644 --- a/src/api/auth/api_key.rs +++ b/src/api/auth/api_key.rs @@ -8,7 +8,9 @@ use crate::api::auth::{csprng, AuthCredential}; use crate::api::auth::AuthorizationMiddleware; use crate::AppState; use crate::data::condition::Condition; +use crate::data::insert::InsertBuilder; use crate::data::query::QueryBuilder; +use crate::data::update::UpdateBuilder; use crate::data::Value; use crate::error::{Error, SirenResult}; @@ -43,65 +45,38 @@ impl ApiKey { } pub async fn insert(&self) -> SirenResult<()> { - let pool = crate::data::pool(); - sqlx::query(&format!( - "INSERT INTO {} ( - key, - user_id, - user_name, - access_mask, - created_at, - last_used_at - ) VALUES ( - $1, $2, $3, $4, $5, $6 - )", - TABLE_NAME - )) - .bind(&self.key) - .bind(self.user_id) - .bind(&self.user_name) - .bind(self.access_mask) - .bind(self.created_at) - .bind(self.last_used_at) - .execute(pool) - .await?; + InsertBuilder::new(TABLE_NAME) + .column("key", Value::Text(self.key.clone())) + .column("user_id", Value::BigInt(self.user_id)) + .column("user_name", Value::Text(self.user_name.clone())) + .column("access_mask", Value::Int(self.access_mask)) + .column("created_at", Value::DateTime(self.created_at)) + .column("last_used_at", Value::OptionalDateTime(self.last_used_at)) + .execute().await?; Ok(()) } pub async fn update(&self) -> SirenResult<()> { - let pool = crate::data::pool(); - sqlx::query(&format!( - "UPDATE {} SET - user_id = $2, - user_name = $3, - access_mask = $4, - created_at = $5, - last_used_at = $6 - WHERE key = $1", - TABLE_NAME - )) - .bind(&self.key) - .bind(self.user_id) - .bind(&self.user_name) - .bind(self.access_mask) - .bind(self.created_at) - .bind(self.last_used_at) - .execute(pool) - .await?; - Ok(()) + match UpdateBuilder::new(TABLE_NAME) + .column("user_id", Value::BigInt(self.user_id)) + .column("user_name", Value::Text(self.user_name.clone())) + .column("access_mask", Value::Int(self.access_mask)) + .column("created_at", Value::DateTime(self.created_at)) + .column("last_used_at", Value::OptionalDateTime(self.last_used_at)) + .where_condition(Condition::is_equal("key", Value::Text(self.key.clone()))) + .execute().await { + Ok(_) => Ok(()), + Err(err) => { + log::error!("error: {}", err); + Err(err.into()) + } + } } - pub async fn find_by_key(key: &str) -> SirenResult> { - let pool = crate::data::pool(); - let query = QueryBuilder::new(TABLE_NAME) + pub async fn find_by_key(key: &str) -> Option { + QueryBuilder::new(TABLE_NAME) .where_condition(Condition::is_equal("key", Value::Text(key.to_string()))) - .build(); - let item = sqlx::query_as(&query.0) - .bind(key) - .fetch_optional(pool) - .await?; - - Ok(item) + .fetch_optional().await } pub async fn delete_by_id(key: &str) -> SirenResult<()> { diff --git a/src/api/auth/middleware.rs b/src/api/auth/middleware.rs index f00342e..77d1f6b 100644 --- a/src/api/auth/middleware.rs +++ b/src/api/auth/middleware.rs @@ -87,7 +87,7 @@ async fn check_bearer_auth(bearer_token: &str) -> SirenResult { } async fn check_api_key_auth(key: &str) -> SirenResult { - let mut api_key = match ApiKey::find_by_key(key).await? { + let mut api_key = match ApiKey::find_by_key(key).await { Some(api_key) => api_key, None => return Err(StatusCode::UNAUTHORIZED.into()), }; diff --git a/src/data/insert.rs b/src/data/insert.rs index 174353d..816575a 100644 --- a/src/data/insert.rs +++ b/src/data/insert.rs @@ -50,6 +50,8 @@ impl InsertBuilder { Value::OptionalBool(n) => query = query.bind(n), Value::Text(n) => query = query.bind(n), Value::OptionalText(n) => query = query.bind(n), + Value::DateTime(n) => query = query.bind(n), + Value::OptionalDateTime(n) => query = query.bind(n), } } diff --git a/src/data/mod.rs b/src/data/mod.rs index bdbe59f..c3b1da3 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -1,5 +1,6 @@ use std::{fmt, sync::OnceLock, time::Duration}; use std::fmt::Display; +use chrono::{DateTime, Utc}; use redis::{aio::MultiplexedConnection as RedisConnection, Client as RedisClient, RedisResult}; use sqlx::{postgres::PgPoolOptions, Pool, Postgres}; use crate::error::SirenResult; @@ -11,6 +12,7 @@ pub mod insert; pub mod messages; pub mod query; pub mod update; +mod executable_query; static POOL: OnceLock> = OnceLock::new(); static REDIS: OnceLock = OnceLock::new(); @@ -102,6 +104,8 @@ pub enum Value { OptionalBool(Option), Text(String), OptionalText(Option), + DateTime(DateTime), + OptionalDateTime(Option>), } impl Display for Value { @@ -125,6 +129,9 @@ impl Display for Value { Value::Text(s) => write!(f, "'{}'", s.replace("'", "''")), Value::OptionalText(Some(s)) => write!(f, "'{}'", s.replace("'", "''")), Value::OptionalText(None) => write!(f, "NULL"), + Value::DateTime(n) => write!(f, "{}", n), + Value::OptionalDateTime(Some(n)) => write!(f, "{}", n), + Value::OptionalDateTime(None) => write!(f, "NULL"), } } } diff --git a/src/data/query.rs b/src/data/query.rs index 4cf3607..a0afe76 100644 --- a/src/data/query.rs +++ b/src/data/query.rs @@ -66,6 +66,8 @@ impl QueryBuilder { Value::OptionalBool(n) => query_as = query_as.bind(n), Value::Text(n) => query_as = query_as.bind(n), Value::OptionalText(n) => query_as = query_as.bind(n), + Value::DateTime(n) => query_as = query_as.bind(n), + Value::OptionalDateTime(n) => query_as = query_as.bind(n), } } diff --git a/src/data/update.rs b/src/data/update.rs index b33848e..2061ee4 100644 --- a/src/data/update.rs +++ b/src/data/update.rs @@ -3,7 +3,8 @@ use crate::data::Value; pub struct UpdateBuilder { table: String, - columns: Vec<(String, Value)>, + columns: Vec, + values: Vec, condition: Option, } @@ -12,12 +13,14 @@ impl UpdateBuilder { Self { table: table.to_string(), columns: Vec::new(), + values: Vec::new(), condition: None, } } pub fn column(mut self, column: &str, value: Value) -> Self { - self.columns.push((column.to_string(), value)); + self.columns.push(column.to_string()); + self.values.push(value); self } @@ -48,6 +51,8 @@ impl UpdateBuilder { Value::OptionalBool(n) => query = query.bind(n), Value::Text(n) => query = query.bind(n), Value::OptionalText(n) => query = query.bind(n), + Value::DateTime(n) => query = query.bind(n), + Value::OptionalDateTime(n) => query = query.bind(n), } } @@ -65,18 +70,19 @@ impl UpdateBuilder { .columns .iter() .enumerate() - .map(|(i, (col, _))| format!("{} = ${}", col, i + 1)) + .map(|(i, col)| format!("{} = ${}", col, i + 1)) .collect::>() .join(", "); - // Prepare the WHERE clause if conditions are present let mut query = format!("UPDATE {} SET {}", self.table, set_clause); + let mut counter = self.values.len(); + let mut values: Vec = self.values; - let mut values: Vec = Vec::new(); + // Build where clause if let Some(condition) = self.condition { - let where_condition = condition.to_sql(&mut 0); + let where_condition = condition.to_sql(&mut counter); query.push_str(&format!(" WHERE {}", where_condition.0)); - values = where_condition.1; + values.extend(where_condition.1); } (query, values)