feat: implement surrealdb and redis
This commit is contained in:
Generated
+2363
-105
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,8 @@ utoipa = { version = "5.3.1", features = ["axum_extras"] }
|
|||||||
utoipa-swagger-ui = { version = "9.0.0", features = ["axum"] }
|
utoipa-swagger-ui = { version = "9.0.0", features = ["axum"] }
|
||||||
redis = "0.28.2"
|
redis = "0.28.2"
|
||||||
lettre = { version = "0.11.12", features = ["tokio1-native-tls"] }
|
lettre = { version = "0.11.12", features = ["tokio1-native-tls"] }
|
||||||
|
surrealdb = "2.2.1"
|
||||||
|
thiserror = "2.0.11"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = "fat"
|
lto = "fat"
|
||||||
|
|||||||
+8
-9
@@ -1,15 +1,14 @@
|
|||||||
use axum::{routing::get, Router};
|
use crate::{AppState, RedisClient, SurrealClient};
|
||||||
use v1::auth_router;
|
use axum::{Extension, Router};
|
||||||
|
|
||||||
pub mod v1;
|
pub mod v1;
|
||||||
pub mod v2;
|
pub mod v2;
|
||||||
|
|
||||||
pub async fn apps() -> Router {
|
pub async fn apps(surrealdb: SurrealClient, redisdb: RedisClient) -> Router {
|
||||||
let v1_routes = Router::new()
|
let state = AppState { surrealdb, redisdb };
|
||||||
.nest("/auth", auth_router())
|
|
||||||
.route("/", get(|| async { "Comming Soon v1" }));
|
|
||||||
|
|
||||||
let v2_routes = Router::new().route("/", get(|| async { "Comming Soon v2" }));
|
Router::new()
|
||||||
|
.nest("/v1", v1::routes().await)
|
||||||
Router::new().nest("/v1", v1_routes).nest("/v2", v2_routes)
|
.nest("/v2", v2::routes().await)
|
||||||
|
.layer(Extension(state))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
use super::{mutation_login, AuthLoginRequestDto};
|
use axum::{response::IntoResponse, Extension, Json};
|
||||||
use axum::{response::Response, Json};
|
|
||||||
|
|
||||||
pub async fn post_login(Json(payload): Json<AuthLoginRequestDto>) -> Response {
|
use super::{mutation_login, AuthLoginRequestDto};
|
||||||
mutation_login(payload).await
|
use crate::AppState;
|
||||||
|
|
||||||
|
pub async fn post_login(
|
||||||
|
Extension(state): Extension<AppState>,
|
||||||
|
Json(payload): Json<AuthLoginRequestDto>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
mutation_login(payload, &state).await
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,30 @@
|
|||||||
use super::auth_dto::AuthLoginRequestDto;
|
use super::auth_dto::AuthLoginRequestDto;
|
||||||
use crate::{success_response, ResponseSuccessDto};
|
use crate::{success_response, AppState, ResponseSuccessDto};
|
||||||
use axum::response::Response;
|
use axum::response::Response;
|
||||||
|
|
||||||
pub async fn mutation_login(params: AuthLoginRequestDto) -> Response {
|
const USERS_KEY: &str = "users";
|
||||||
|
|
||||||
|
pub async fn mutation_login(
|
||||||
|
params: AuthLoginRequestDto,
|
||||||
|
state: &AppState,
|
||||||
|
) -> Response {
|
||||||
|
let _users: Option<AuthLoginRequestDto> = state
|
||||||
|
.surrealdb
|
||||||
|
.select((USERS_KEY, &*params.email))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut redis_conn = state
|
||||||
|
.redisdb
|
||||||
|
.get_connection()
|
||||||
|
.expect("failed to get connection");
|
||||||
|
|
||||||
|
redis::cmd("SET")
|
||||||
|
.arg("some_key")
|
||||||
|
.arg("some_value")
|
||||||
|
.query::<()>(&mut redis_conn)
|
||||||
|
.expect("failed to set value");
|
||||||
|
|
||||||
let response = ResponseSuccessDto {
|
let response = ResponseSuccessDto {
|
||||||
data: AuthLoginRequestDto {
|
data: AuthLoginRequestDto {
|
||||||
email: params.email,
|
email: params.email,
|
||||||
|
|||||||
+5
-1
@@ -1,3 +1,7 @@
|
|||||||
|
use axum::Router;
|
||||||
|
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
|
|
||||||
pub use auth::*;
|
pub async fn routes() -> Router {
|
||||||
|
Router::new().nest("/auth", auth::auth_router())
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
use axum::{response::IntoResponse, routing::post, Router};
|
||||||
|
|
||||||
|
async fn dummy_login() -> impl IntoResponse {
|
||||||
|
"Logged in successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn auth_router() -> Router {
|
||||||
|
Router::new().route("/login", post(dummy_login))
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
use axum::Router;
|
||||||
|
|
||||||
|
pub mod auth;
|
||||||
|
pub use auth::*;
|
||||||
|
|
||||||
|
pub async fn routes() -> Router {
|
||||||
|
let public_routes = Router::new().nest("/auth", auth::auth_router());
|
||||||
|
Router::new().merge(public_routes)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use surrealdb::{engine::remote::ws::Client, Surreal};
|
||||||
use utoipa::{IntoParams, ToSchema};
|
use utoipa::{IntoParams, ToSchema};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||||
@@ -35,3 +36,12 @@ pub struct ResponseListSuccessDto<T: Serialize> {
|
|||||||
pub data: T,
|
pub data: T,
|
||||||
pub meta: Option<MetaResponseDto>,
|
pub meta: Option<MetaResponseDto>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type SurrealClient = Surreal<Client>;
|
||||||
|
pub type RedisClient = redis::Client;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct AppState {
|
||||||
|
pub surrealdb: SurrealClient,
|
||||||
|
pub redisdb: RedisClient,
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
pub mod error {
|
||||||
|
use axum::http::StatusCode;
|
||||||
|
use axum::response::IntoResponse;
|
||||||
|
use axum::response::Response;
|
||||||
|
use axum::Json;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error("database error")]
|
||||||
|
Db,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoResponse for Error {
|
||||||
|
fn into_response(self) -> Response {
|
||||||
|
(StatusCode::INTERNAL_SERVER_ERROR, Json(self.to_string()))
|
||||||
|
.into_response()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<surrealdb::Error> for Error {
|
||||||
|
fn from(error: surrealdb::Error) -> Self {
|
||||||
|
eprintln!("{error}");
|
||||||
|
Self::Db
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
pub mod common_dto;
|
pub mod common_dto;
|
||||||
|
pub mod error_dto;
|
||||||
|
|
||||||
pub use common_dto::*;
|
pub use common_dto::*;
|
||||||
|
pub use error_dto::*;
|
||||||
|
|||||||
+11
-3
@@ -3,21 +3,29 @@ use std::env;
|
|||||||
use std::{future::Future, net::SocketAddr};
|
use std::{future::Future, net::SocketAddr};
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
|
|
||||||
|
use crate::{redisdb_init, RedisClient};
|
||||||
|
use crate::{surrealdb_init, SurrealClient};
|
||||||
|
|
||||||
pub async fn axum_init<F, Fut>(router_fn: F)
|
pub async fn axum_init<F, Fut>(router_fn: F)
|
||||||
where
|
where
|
||||||
F: Fn() -> Fut,
|
F: FnOnce(SurrealClient, RedisClient) -> Fut,
|
||||||
Fut: Future<Output = Router>,
|
Fut: Future<Output = Router>,
|
||||||
{
|
{
|
||||||
let router = router_fn().await;
|
let surrealdb = surrealdb_init().await.expect("Failed surrealdb");
|
||||||
|
let redisdb = redisdb_init().await.expect("Failed redisdb");
|
||||||
|
let router = router_fn(surrealdb, redisdb).await;
|
||||||
|
|
||||||
let addr = SocketAddr::from((
|
let addr = SocketAddr::from((
|
||||||
[0, 0, 0, 0],
|
[0, 0, 0, 0],
|
||||||
env::var("PORT")
|
env::var("PORT")
|
||||||
.unwrap_or("3000".to_string())
|
.unwrap_or_else(|_| "3000".to_string())
|
||||||
.parse()
|
.parse()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
));
|
));
|
||||||
|
|
||||||
let listener = TcpListener::bind(&addr).await.unwrap();
|
let listener = TcpListener::bind(&addr).await.unwrap();
|
||||||
println!("Listening on http://{}", addr);
|
println!("Listening on http://{}", addr);
|
||||||
|
|
||||||
match serve(listener, router).await {
|
match serve(listener, router).await {
|
||||||
Ok(_) => println!("Server stopped gracefully."),
|
Ok(_) => println!("Server stopped gracefully."),
|
||||||
Err(err) => println!("Server encountered an error: {}", err),
|
Err(err) => println!("Server encountered an error: {}", err),
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ pub mod jsonwebtoken;
|
|||||||
pub mod lettre;
|
pub mod lettre;
|
||||||
pub mod redis;
|
pub mod redis;
|
||||||
pub mod seaorm;
|
pub mod seaorm;
|
||||||
|
pub mod surrealdb;
|
||||||
|
|
||||||
pub use argon::*;
|
pub use argon::*;
|
||||||
pub use axum::*;
|
pub use axum::*;
|
||||||
@@ -11,3 +12,4 @@ pub use jsonwebtoken::*;
|
|||||||
pub use lettre::*;
|
pub use lettre::*;
|
||||||
pub use redis::*;
|
pub use redis::*;
|
||||||
pub use seaorm::*;
|
pub use seaorm::*;
|
||||||
|
pub use surrealdb::*;
|
||||||
|
|||||||
+7
-11
@@ -1,20 +1,16 @@
|
|||||||
|
use redis::Client;
|
||||||
|
use redis::RedisResult;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
use redis::Client;
|
pub async fn redisdb_init() -> RedisResult<Client> {
|
||||||
|
let host_name =
|
||||||
pub fn db_redis() -> redis::Connection {
|
env::var("REDIS_HOSTNAME").unwrap_or_else(|_| "localhost".to_string());
|
||||||
let host_name = env::var("REDIS_HOSTNAME").unwrap_or("localhost".to_string());
|
|
||||||
|
|
||||||
let uri_scheme = if env::var("IS_TLS").is_ok() {
|
let uri_scheme = if env::var("IS_TLS").is_ok() {
|
||||||
"rediss"
|
"rediss"
|
||||||
} else {
|
} else {
|
||||||
"redis"
|
"redis"
|
||||||
};
|
};
|
||||||
|
|
||||||
let url = format!("{}://{}", uri_scheme, host_name);
|
let url = format!("{}://{}", uri_scheme, host_name);
|
||||||
|
let client = Client::open(url)?;
|
||||||
Client::open(url)
|
Ok(client)
|
||||||
.expect("Invalid connection URL")
|
|
||||||
.get_connection()
|
|
||||||
.expect("Failed to connect to Redis")
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
use surrealdb::engine::remote::ws::{Client, Ws};
|
||||||
|
use surrealdb::{Result, Surreal};
|
||||||
|
|
||||||
|
use crate::SurrealClient;
|
||||||
|
|
||||||
|
pub async fn surrealdb_init() -> Result<SurrealClient> {
|
||||||
|
let db = Surreal::<Client>::init();
|
||||||
|
db.connect::<Ws>("ws://localhost:8000").await?;
|
||||||
|
db.use_ns("test").use_db("test").await?;
|
||||||
|
Ok(db)
|
||||||
|
}
|
||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
use imphnen_cms_be::{apps, libs::axum_init};
|
use imphnen_cms_be::{apps, axum_init};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
axum_init(apps).await;
|
axum_init(|db, redis| async { apps(db, redis).await }).await;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user