mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-04 09:28:11 +00:00
generics, endpoint
This commit is contained in:
1 parent
87b4cfb3f2
commit
1fbbbc5d7d
9 files changed
+142
-11
No files matched your search
@@ -1,5 +1,6 @@
|
||||
pub mod database_insert_error;
|
||||
pub mod database_query_error;
|
||||
pub mod mysql_error;
|
||||
pub mod select_exactly_one_error;
|
||||
pub mod select_optional_record_error;
|
||||
pub mod mysql_upsert_error;
|
||||
pub mod subtypes;
|
||||
@@ -0,0 +1,26 @@
|
||||
use std::error::Error;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
|
||||
|
||||
/// Implement this marker trait for subtypes.
|
||||
pub trait CrateError : Error + Debug + Display {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MysqlError<E: CrateError> {
|
||||
/// Inner error type
|
||||
pub inner: E
|
||||
}
|
||||
|
||||
impl <E> Error for MysqlError <E> where E: CrateError {}
|
||||
|
||||
impl <E> Display for MysqlError<E> where E: CrateError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "MysqlError: {}", self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
// impl From<UpsertError> for MysqlError<UpsertError> {
|
||||
// fn from(value: UpsertError) -> Self {
|
||||
// MysqlError { inner: value }
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1 @@
|
||||
pub mod upsert_error;
|
||||
+16
-6
@@ -1,9 +1,10 @@
|
||||
use crate::errors::mysql_error::{CrateError, MysqlError};
|
||||
use log::error;
|
||||
use std::error::Error;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MysqlUpsertError {
|
||||
pub enum UpsertError {
|
||||
/// A duplicate key error occurred.
|
||||
DuplicateKeyError(String),
|
||||
|
||||
@@ -11,18 +12,20 @@ pub enum MysqlUpsertError {
|
||||
SqlxError(sqlx::Error),
|
||||
}
|
||||
|
||||
impl Error for MysqlUpsertError {}
|
||||
impl Error for UpsertError {}
|
||||
|
||||
impl Display for MysqlUpsertError {
|
||||
impl CrateError for UpsertError {}
|
||||
|
||||
impl Display for UpsertError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
MysqlUpsertError::DuplicateKeyError(reason) => write!(f, "DuplicateKeyError: {}", reason),
|
||||
MysqlUpsertError::SqlxError(e) => write!(f, "SQLx error: {:?}", e),
|
||||
UpsertError::DuplicateKeyError(reason) => write!(f, "DuplicateKeyError: {}", reason),
|
||||
UpsertError::SqlxError(e) => write!(f, "SQLx error: {:?}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<sqlx::Error> for MysqlUpsertError {
|
||||
impl From<sqlx::Error> for UpsertError {
|
||||
fn from(err: sqlx::Error) -> Self {
|
||||
if let Some(db_err) = err.as_database_error() {
|
||||
// NB: SQLSTATE[23000]: Integrity constraint violation
|
||||
@@ -39,3 +42,10 @@ impl From<sqlx::Error> for MysqlUpsertError {
|
||||
Self::SqlxError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<sqlx::Error> for MysqlError<UpsertError> {
|
||||
fn from(err: sqlx::Error) -> Self {
|
||||
let inner = UpsertError::from(err);
|
||||
MysqlError { inner }
|
||||
}
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
mod upsert_analytics_app_active_user;
|
||||
pub mod upsert_analytics_app_active_user;
|
||||
+6
-2
@@ -1,4 +1,5 @@
|
||||
use crate::errors::mysql_upsert_error::MysqlUpsertError;
|
||||
use crate::errors::mysql_error::MysqlError;
|
||||
use crate::errors::subtypes::upsert_error::UpsertError;
|
||||
use enums::common::payments_namespace::PaymentsNamespace;
|
||||
use sqlx::mysql::MySqlArguments;
|
||||
use sqlx::pool::PoolConnection;
|
||||
@@ -44,7 +45,10 @@ ON DUPLICATE KEY UPDATE
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn upsert_with_connection(&self, mysql_connection: &mut PoolConnection<MySql>) -> Result<(), MysqlUpsertError> {
|
||||
pub async fn upsert_with_connection(
|
||||
&self,
|
||||
mysql_connection: &mut PoolConnection<MySql>
|
||||
) -> Result<(), MysqlError<UpsertError>> {
|
||||
let _query_result = self.query()
|
||||
.execute(&mut **mysql_connection)
|
||||
.await?;
|
||||
|
||||
+15
@@ -3,6 +3,7 @@ use actix_web::{HttpResponse, HttpResponseBuilder, ResponseError};
|
||||
use std::error::Error;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use log::error;
|
||||
use mysql_queries::errors::mysql_error::{CrateError, MysqlError};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CommonWebError {
|
||||
@@ -84,6 +85,20 @@ impl From<sqlx::Error> for CommonWebError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<anyhow::Error> for CommonWebError {
|
||||
fn from(value: anyhow::Error) -> Self {
|
||||
error!("Uncaught anyhow::Error being coerced to CommonWebError : {:?}", value);
|
||||
CommonWebError::ServerError
|
||||
}
|
||||
}
|
||||
|
||||
impl <T: CrateError> From<MysqlError<T>> for CommonWebError {
|
||||
fn from(value: MysqlError<T>) -> Self {
|
||||
error!("MysqlError being coerced to CommonWebError : {:?}", value);
|
||||
CommonWebError::ServerError
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
use actix_web::web::Json;
|
||||
use actix_web::{web, HttpRequest};
|
||||
use enums::common::payments_namespace::PaymentsNamespace;
|
||||
use http_server_common::request::get_request_ip::get_request_ip;
|
||||
use mysql_queries::queries::analytics_active_users::upsert_analytics_app_active_user::UpsertAnalyticsAppActiveUser;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
pub struct LogAppActiveUserRequest {
|
||||
/// An override for the application version.
|
||||
maybe_app_version: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
pub struct LogAppActiveUserResponse {
|
||||
pub success: bool,
|
||||
}
|
||||
|
||||
/// Log an active app user - user must be logged in.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
tag = "Analytics",
|
||||
path = "/v1/analytics/active_user",
|
||||
responses(
|
||||
(status = 200, description = "Success", body = LogAppActiveUserSuccessResponse),
|
||||
),
|
||||
params(
|
||||
("request" = LogAppActiveUserRequest, description = "Payload for Request"),
|
||||
)
|
||||
)]
|
||||
pub async fn log_browser_session_handler(
|
||||
http_request: HttpRequest,
|
||||
request: Json<LogAppActiveUserRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>,
|
||||
) -> Result<Json<LogAppActiveUserResponse>, CommonWebError>
|
||||
{
|
||||
let mut mysql_connection = server_state.mysql_pool
|
||||
.acquire()
|
||||
.await?;
|
||||
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
.maybe_get_user_session_from_connection(&http_request, &mut mysql_connection)
|
||||
.await?;
|
||||
|
||||
let user_token = maybe_user_session
|
||||
.ok_or(CommonWebError::NotAuthorized)?
|
||||
.user_token;
|
||||
|
||||
let ip_address = get_request_ip(&http_request);
|
||||
|
||||
let app_version = request.maybe_app_version
|
||||
.as_deref()
|
||||
.unwrap_or("unknown");
|
||||
|
||||
let upsert = UpsertAnalyticsAppActiveUser {
|
||||
namespace: PaymentsNamespace::Artcraft,
|
||||
user_token: &user_token,
|
||||
ip_address: &ip_address,
|
||||
app_version,
|
||||
};
|
||||
|
||||
upsert.upsert_with_connection(&mut mysql_connection).await?;
|
||||
|
||||
Ok(Json(LogAppActiveUserResponse {
|
||||
success: true,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
pub mod log_browser_session_handler;
|
||||
pub mod log_browser_session_handler;
|
||||
pub mod log_app_active_user_handler;
|
||||
Reference in new issue
Block a user