Fixed insert
This commit is contained in:
@@ -11,5 +11,5 @@ post {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auth:bearer {
|
auth:bearer {
|
||||||
token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjI1MDg0MjI2MTIyMTI3NzY5NywibmFtZSI6ImJzaGVycmlmZiIsImlhdCI6MTczNDgwODA5MiwiZXhwIjoxNzM0ODk0NDkyLCJqdGkiOiJsSWFHaU15Wll5cnFVYmFJTGs2dzAyZTY4YkFPZjFZWSJ9.fCeooH2IdtXiy2s23WykXtOaR8dvnUinmSGFcV-fOwQ
|
token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjI1MDg0MjI2MTIyMTI3NzY5NywibmFtZSI6ImJzaGVycmlmZiIsImlhdCI6MTczNDg0MzA0NywiZXhwIjoxNzM0OTI5NDQ3LCJqdGkiOiIycEowbmN5YmF1TVo4TG1aQ0VwU1B2OWgzMXFzU1FwaCJ9.gYf6oAm2POBXOHUnG4dTy5maKxTjUk8WxawOrIafjEE
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ use crate::api::auth::{csprng, AuthCredential};
|
|||||||
use crate::api::auth::AuthorizationMiddleware;
|
use crate::api::auth::AuthorizationMiddleware;
|
||||||
use crate::AppState;
|
use crate::AppState;
|
||||||
use crate::data::condition::Condition;
|
use crate::data::condition::Condition;
|
||||||
|
use crate::data::insert::InsertBuilder;
|
||||||
use crate::data::query::QueryBuilder;
|
use crate::data::query::QueryBuilder;
|
||||||
|
use crate::data::update::UpdateBuilder;
|
||||||
use crate::data::Value;
|
use crate::data::Value;
|
||||||
use crate::error::{Error, SirenResult};
|
use crate::error::{Error, SirenResult};
|
||||||
|
|
||||||
@@ -43,65 +45,38 @@ impl ApiKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn insert(&self) -> SirenResult<()> {
|
pub async fn insert(&self) -> SirenResult<()> {
|
||||||
let pool = crate::data::pool();
|
InsertBuilder::new(TABLE_NAME)
|
||||||
sqlx::query(&format!(
|
.column("key", Value::Text(self.key.clone()))
|
||||||
"INSERT INTO {} (
|
.column("user_id", Value::BigInt(self.user_id))
|
||||||
key,
|
.column("user_name", Value::Text(self.user_name.clone()))
|
||||||
user_id,
|
.column("access_mask", Value::Int(self.access_mask))
|
||||||
user_name,
|
.column("created_at", Value::DateTime(self.created_at))
|
||||||
access_mask,
|
.column("last_used_at", Value::OptionalDateTime(self.last_used_at))
|
||||||
created_at,
|
.execute().await?;
|
||||||
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?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update(&self) -> SirenResult<()> {
|
pub async fn update(&self) -> SirenResult<()> {
|
||||||
let pool = crate::data::pool();
|
match UpdateBuilder::new(TABLE_NAME)
|
||||||
sqlx::query(&format!(
|
.column("user_id", Value::BigInt(self.user_id))
|
||||||
"UPDATE {} SET
|
.column("user_name", Value::Text(self.user_name.clone()))
|
||||||
user_id = $2,
|
.column("access_mask", Value::Int(self.access_mask))
|
||||||
user_name = $3,
|
.column("created_at", Value::DateTime(self.created_at))
|
||||||
access_mask = $4,
|
.column("last_used_at", Value::OptionalDateTime(self.last_used_at))
|
||||||
created_at = $5,
|
.where_condition(Condition::is_equal("key", Value::Text(self.key.clone())))
|
||||||
last_used_at = $6
|
.execute().await {
|
||||||
WHERE key = $1",
|
Ok(_) => Ok(()),
|
||||||
TABLE_NAME
|
Err(err) => {
|
||||||
))
|
log::error!("error: {}", err);
|
||||||
.bind(&self.key)
|
Err(err.into())
|
||||||
.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(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn find_by_key(key: &str) -> SirenResult<Option<Self>> {
|
pub async fn find_by_key(key: &str) -> Option<Self> {
|
||||||
let pool = crate::data::pool();
|
QueryBuilder::new(TABLE_NAME)
|
||||||
let query = QueryBuilder::new(TABLE_NAME)
|
|
||||||
.where_condition(Condition::is_equal("key", Value::Text(key.to_string())))
|
.where_condition(Condition::is_equal("key", Value::Text(key.to_string())))
|
||||||
.build();
|
.fetch_optional().await
|
||||||
let item = sqlx::query_as(&query.0)
|
|
||||||
.bind(key)
|
|
||||||
.fetch_optional(pool)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(item)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn delete_by_id(key: &str) -> SirenResult<()> {
|
pub async fn delete_by_id(key: &str) -> SirenResult<()> {
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ async fn check_bearer_auth(bearer_token: &str) -> SirenResult<Session> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn check_api_key_auth(key: &str) -> SirenResult<ApiKey> {
|
async fn check_api_key_auth(key: &str) -> SirenResult<ApiKey> {
|
||||||
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,
|
Some(api_key) => api_key,
|
||||||
None => return Err(StatusCode::UNAUTHORIZED.into()),
|
None => return Err(StatusCode::UNAUTHORIZED.into()),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ impl InsertBuilder {
|
|||||||
Value::OptionalBool(n) => query = query.bind(n),
|
Value::OptionalBool(n) => query = query.bind(n),
|
||||||
Value::Text(n) => query = query.bind(n),
|
Value::Text(n) => query = query.bind(n),
|
||||||
Value::OptionalText(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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::{fmt, sync::OnceLock, time::Duration};
|
use std::{fmt, sync::OnceLock, time::Duration};
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use redis::{aio::MultiplexedConnection as RedisConnection, Client as RedisClient, RedisResult};
|
use redis::{aio::MultiplexedConnection as RedisConnection, Client as RedisClient, RedisResult};
|
||||||
use sqlx::{postgres::PgPoolOptions, Pool, Postgres};
|
use sqlx::{postgres::PgPoolOptions, Pool, Postgres};
|
||||||
use crate::error::SirenResult;
|
use crate::error::SirenResult;
|
||||||
@@ -11,6 +12,7 @@ pub mod insert;
|
|||||||
pub mod messages;
|
pub mod messages;
|
||||||
pub mod query;
|
pub mod query;
|
||||||
pub mod update;
|
pub mod update;
|
||||||
|
mod executable_query;
|
||||||
|
|
||||||
static POOL: OnceLock<Pool<Postgres>> = OnceLock::new();
|
static POOL: OnceLock<Pool<Postgres>> = OnceLock::new();
|
||||||
static REDIS: OnceLock<RedisClient> = OnceLock::new();
|
static REDIS: OnceLock<RedisClient> = OnceLock::new();
|
||||||
@@ -102,6 +104,8 @@ pub enum Value {
|
|||||||
OptionalBool(Option<bool>),
|
OptionalBool(Option<bool>),
|
||||||
Text(String),
|
Text(String),
|
||||||
OptionalText(Option<String>),
|
OptionalText(Option<String>),
|
||||||
|
DateTime(DateTime<Utc>),
|
||||||
|
OptionalDateTime(Option<DateTime<Utc>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Value {
|
impl Display for Value {
|
||||||
@@ -125,6 +129,9 @@ impl Display for Value {
|
|||||||
Value::Text(s) => write!(f, "'{}'", s.replace("'", "''")),
|
Value::Text(s) => write!(f, "'{}'", s.replace("'", "''")),
|
||||||
Value::OptionalText(Some(s)) => write!(f, "'{}'", s.replace("'", "''")),
|
Value::OptionalText(Some(s)) => write!(f, "'{}'", s.replace("'", "''")),
|
||||||
Value::OptionalText(None) => write!(f, "NULL"),
|
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"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ impl QueryBuilder {
|
|||||||
Value::OptionalBool(n) => query_as = query_as.bind(n),
|
Value::OptionalBool(n) => query_as = query_as.bind(n),
|
||||||
Value::Text(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::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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ use crate::data::Value;
|
|||||||
|
|
||||||
pub struct UpdateBuilder {
|
pub struct UpdateBuilder {
|
||||||
table: String,
|
table: String,
|
||||||
columns: Vec<(String, Value)>,
|
columns: Vec<String>,
|
||||||
|
values: Vec<Value>,
|
||||||
condition: Option<Condition>,
|
condition: Option<Condition>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12,12 +13,14 @@ impl UpdateBuilder {
|
|||||||
Self {
|
Self {
|
||||||
table: table.to_string(),
|
table: table.to_string(),
|
||||||
columns: Vec::new(),
|
columns: Vec::new(),
|
||||||
|
values: Vec::new(),
|
||||||
condition: None,
|
condition: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn column(mut self, column: &str, value: Value) -> Self {
|
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
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,6 +51,8 @@ impl UpdateBuilder {
|
|||||||
Value::OptionalBool(n) => query = query.bind(n),
|
Value::OptionalBool(n) => query = query.bind(n),
|
||||||
Value::Text(n) => query = query.bind(n),
|
Value::Text(n) => query = query.bind(n),
|
||||||
Value::OptionalText(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
|
.columns
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, (col, _))| format!("{} = ${}", col, i + 1))
|
.map(|(i, col)| format!("{} = ${}", col, i + 1))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
|
|
||||||
// Prepare the WHERE clause if conditions are present
|
|
||||||
let mut query = format!("UPDATE {} SET {}", self.table, set_clause);
|
let mut query = format!("UPDATE {} SET {}", self.table, set_clause);
|
||||||
|
let mut counter = self.values.len();
|
||||||
|
let mut values: Vec<Value> = self.values;
|
||||||
|
|
||||||
let mut values: Vec<Value> = Vec::new();
|
// Build where clause
|
||||||
if let Some(condition) = self.condition {
|
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));
|
query.push_str(&format!(" WHERE {}", where_condition.0));
|
||||||
values = where_condition.1;
|
values.extend(where_condition.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
(query, values)
|
(query, values)
|
||||||
|
|||||||
Reference in New Issue
Block a user