feat: with persistent session state
Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
parent
1e38b2838c
commit
746fb68684
798
Cargo.lock
generated
798
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
20
Cargo.toml
20
Cargo.toml
@ -21,13 +21,14 @@ async-graphql = { version = "5.0.9", features = ["uuid"] }
|
|||||||
async-graphql-axum = "5.0.9"
|
async-graphql-axum = "5.0.9"
|
||||||
|
|
||||||
axum = { version = "0.6.18", features = ["headers", "macros"] }
|
axum = { version = "0.6.18", features = ["headers", "macros"] }
|
||||||
axum-extra = { version = "*", features = ["cookie", "cookie-private"] }
|
axum-extra = { version = "0.7.4", features = ["cookie", "cookie-private"] }
|
||||||
axum-sessions = { version = "*" }
|
axum-sessions = { version = "0.5.0" }
|
||||||
|
async-sqlx-session = { version = "0.4.0", features = ["pg"] }
|
||||||
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0.68"
|
serde_json = "1.0.68"
|
||||||
|
|
||||||
sqlx = { version = "0.6", features = [
|
sqlx = { version = "0.6.2", features = [
|
||||||
"runtime-tokio-rustls",
|
"runtime-tokio-rustls",
|
||||||
"postgres",
|
"postgres",
|
||||||
"migrate",
|
"migrate",
|
||||||
@ -35,11 +36,14 @@ sqlx = { version = "0.6", features = [
|
|||||||
"offline",
|
"offline",
|
||||||
] }
|
] }
|
||||||
|
|
||||||
tokio = { version = "1.20.1", features = ["full"] }
|
tokio = { version = "1.28.2", features = ["full"] }
|
||||||
|
|
||||||
uuid = { version = "1.1.2", features = ["v4", "fast-rng", "serde"] }
|
uuid = { version = "1.3.3", features = ["v4", "fast-rng", "serde"] }
|
||||||
anyhow = "1.0.60"
|
anyhow = "1.0.71"
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
tracing = "0.1.36"
|
tracing = "0.1.37"
|
||||||
tracing-subscriber = { version = "0.3.15", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
||||||
clap = { version = "4.3.0", features = ["derive", "env"] }
|
clap = { version = "4.3.0", features = ["derive", "env"] }
|
||||||
|
|
||||||
|
argon2 = { version = "0.5.0" }
|
||||||
|
rand_core = { version = "0.6.4" }
|
||||||
|
@ -24,6 +24,7 @@ sqlx.workspace = true
|
|||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
dotenv.workspace = true
|
dotenv.workspace = true
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
|
async-sqlx-session.workspace = true
|
||||||
|
|
||||||
zitadel = { version = "3.3.1", features = ["axum"] }
|
zitadel = { version = "3.3.1", features = ["axum"] }
|
||||||
tower = "0.4.13"
|
tower = "0.4.13"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::router::AppState;
|
use crate::router::AppState;
|
||||||
use crate::zitadel::{IntrospectionConfig, IntrospectionState};
|
use crate::zitadel::{IntrospectionConfig, IntrospectionState};
|
||||||
|
|
||||||
|
use async_sqlx_session::PostgresSessionStore;
|
||||||
use axum::extract::{FromRef, FromRequestParts, Query, State};
|
use axum::extract::{FromRef, FromRequestParts, Query, State};
|
||||||
use axum::headers::Cookie;
|
use axum::headers::Cookie;
|
||||||
use axum::http::request::Parts;
|
use axum::http::request::Parts;
|
||||||
@ -9,7 +10,7 @@ use axum::http::{header::SET_COOKIE, HeaderMap};
|
|||||||
use axum::response::{IntoResponse, Redirect};
|
use axum::response::{IntoResponse, Redirect};
|
||||||
use axum::routing::get;
|
use axum::routing::get;
|
||||||
use axum::{async_trait, RequestPartsExt, Router, TypedHeader};
|
use axum::{async_trait, RequestPartsExt, Router, TypedHeader};
|
||||||
use axum_sessions::async_session::{MemoryStore, Session, SessionStore};
|
use axum_sessions::async_session::{Session, SessionStore};
|
||||||
use como_domain::users::User;
|
use como_domain::users::User;
|
||||||
use como_infrastructure::register::ServiceRegister;
|
use como_infrastructure::register::ServiceRegister;
|
||||||
use oauth2::basic::BasicClient;
|
use oauth2::basic::BasicClient;
|
||||||
@ -39,7 +40,7 @@ pub struct AuthRequest {
|
|||||||
|
|
||||||
pub async fn login_authorized(
|
pub async fn login_authorized(
|
||||||
Query(query): Query<AuthRequest>,
|
Query(query): Query<AuthRequest>,
|
||||||
State(store): State<MemoryStore>,
|
State(store): State<PostgresSessionStore>,
|
||||||
State(oauth_client): State<BasicClient>,
|
State(oauth_client): State<BasicClient>,
|
||||||
State(introspection_state): State<IntrospectionState>,
|
State(introspection_state): State<IntrospectionState>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
@ -99,13 +100,13 @@ pub struct UserFromSession {}
|
|||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<S> FromRequestParts<S> for UserFromSession
|
impl<S> FromRequestParts<S> for UserFromSession
|
||||||
where
|
where
|
||||||
MemoryStore: FromRef<S>,
|
PostgresSessionStore: FromRef<S>,
|
||||||
S: Send + Sync,
|
S: Send + Sync,
|
||||||
{
|
{
|
||||||
type Rejection = (StatusCode, &'static str);
|
type Rejection = (StatusCode, &'static str);
|
||||||
|
|
||||||
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
|
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
|
||||||
let store = MemoryStore::from_ref(state);
|
let store = PostgresSessionStore::from_ref(state);
|
||||||
|
|
||||||
let cookie: Option<TypedHeader<Cookie>> = parts.extract().await.unwrap();
|
let cookie: Option<TypedHeader<Cookie>> = parts.extract().await.unwrap();
|
||||||
|
|
||||||
@ -116,7 +117,7 @@ where
|
|||||||
|
|
||||||
let session_cookie = session_cookie.unwrap();
|
let session_cookie = session_cookie.unwrap();
|
||||||
|
|
||||||
tracing::info!(
|
tracing::debug!(
|
||||||
"UserFromSession: got session cookie from user agent, {}={}",
|
"UserFromSession: got session cookie from user agent, {}={}",
|
||||||
COOKIE_NAME,
|
COOKIE_NAME,
|
||||||
session_cookie
|
session_cookie
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
use async_sqlx_session::PostgresSessionStore;
|
||||||
use axum::extract::FromRef;
|
use axum::extract::FromRef;
|
||||||
use axum::http::{HeaderValue, Method};
|
use axum::http::{HeaderValue, Method};
|
||||||
use axum::Router;
|
use axum::Router;
|
||||||
use axum_sessions::async_session::MemoryStore;
|
|
||||||
use como_infrastructure::register::ServiceRegister;
|
use como_infrastructure::register::ServiceRegister;
|
||||||
use oauth2::basic::BasicClient;
|
use oauth2::basic::BasicClient;
|
||||||
use tower::ServiceBuilder;
|
use tower::ServiceBuilder;
|
||||||
@ -32,11 +32,10 @@ impl Api {
|
|||||||
.build()
|
.build()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let store = MemoryStore::new();
|
|
||||||
let oauth_client = oauth_client();
|
let oauth_client = oauth_client();
|
||||||
let app_state = AppState {
|
let app_state = AppState {
|
||||||
oauth_client,
|
oauth_client,
|
||||||
store,
|
store: service_register.session_store.clone(),
|
||||||
introspection_state: is,
|
introspection_state: is,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -81,7 +80,7 @@ impl Api {
|
|||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
oauth_client: BasicClient,
|
oauth_client: BasicClient,
|
||||||
introspection_state: IntrospectionState,
|
introspection_state: IntrospectionState,
|
||||||
store: MemoryStore,
|
store: PostgresSessionStore,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRef<AppState> for BasicClient {
|
impl FromRef<AppState> for BasicClient {
|
||||||
@ -90,7 +89,7 @@ impl FromRef<AppState> for BasicClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRef<AppState> for MemoryStore {
|
impl FromRef<AppState> for PostgresSessionStore {
|
||||||
fn from_ref(state: &AppState) -> Self {
|
fn from_ref(state: &AppState) -> Self {
|
||||||
state.store.clone()
|
state.store.clone()
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
let pool = ConnectionPoolManager::new_pool(&config.database_url, true).await?;
|
let pool = ConnectionPoolManager::new_pool(&config.database_url, true).await?;
|
||||||
|
|
||||||
let service_register = ServiceRegister::new(pool, config.clone());
|
let service_register = ServiceRegister::new(pool, config.clone()).await?;
|
||||||
|
|
||||||
Api::new(
|
Api::new(
|
||||||
config.api_port,
|
config.api_port,
|
||||||
|
@ -6,32 +6,20 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
como_core = { path = "../como_core" }
|
como_core.workspace = true
|
||||||
como_domain = { path = "../como_domain" }
|
como_domain.workspace = true
|
||||||
|
|
||||||
async-graphql = "4.0.6"
|
|
||||||
async-graphql-axum = "*"
|
|
||||||
axum = "0.5.13"
|
|
||||||
axum-extra = { version = "*", features = ["cookie", "cookie-private"] }
|
|
||||||
axum-sessions = { version = "*" }
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
|
||||||
serde_json = "1.0.68"
|
|
||||||
tokio = { version = "1.20.1", features = ["full"] }
|
|
||||||
uuid = { version = "1.1.2", features = ["v4", "fast-rng"] }
|
|
||||||
sqlx = { version = "0.6", features = [
|
|
||||||
"runtime-tokio-rustls",
|
|
||||||
"postgres",
|
|
||||||
"migrate",
|
|
||||||
"uuid",
|
|
||||||
"offline",
|
|
||||||
] }
|
|
||||||
anyhow = "1.0.60"
|
|
||||||
dotenv = "0.15.0"
|
|
||||||
tracing = "0.1.36"
|
|
||||||
tracing-subscriber = { version = "0.3.15", features = ["env-filter"] }
|
|
||||||
tower-http = { version = "0.3.4", features = ["full"] }
|
|
||||||
argon2 = "0.4"
|
|
||||||
rand_core = { version = "0.6", features = ["std"] }
|
|
||||||
cookie = { version = "0.16", features = ["secure", "percent-encode"] }
|
|
||||||
|
|
||||||
|
axum.workspace = true
|
||||||
|
async-trait.workspace = true
|
||||||
|
uuid.workspace = true
|
||||||
|
anyhow.workspace = true
|
||||||
|
sqlx.workspace = true
|
||||||
|
|
||||||
|
async-sqlx-session.workspace = true
|
||||||
|
|
||||||
|
tokio.workspace = true
|
||||||
clap.workspace = true
|
clap.workspace = true
|
||||||
|
tracing.workspace = true
|
||||||
|
argon2.workspace = true
|
||||||
|
rand_core.workspace = true
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use async_sqlx_session::PostgresSessionStore;
|
||||||
use como_core::{items::DynItemService, projects::DynProjectService, users::DynUserService};
|
use como_core::{items::DynItemService, projects::DynProjectService, users::DynUserService};
|
||||||
use tracing::log::info;
|
use tracing::log::info;
|
||||||
|
|
||||||
@ -17,22 +18,25 @@ pub struct ServiceRegister {
|
|||||||
pub item_service: DynItemService,
|
pub item_service: DynItemService,
|
||||||
pub project_service: DynProjectService,
|
pub project_service: DynProjectService,
|
||||||
pub user_service: DynUserService,
|
pub user_service: DynUserService,
|
||||||
|
pub session_store: PostgresSessionStore,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServiceRegister {
|
impl ServiceRegister {
|
||||||
pub fn new(pool: ConnectionPool, _config: Arc<AppConfig>) -> Self {
|
pub async fn new(pool: ConnectionPool, config: Arc<AppConfig>) -> anyhow::Result<Self> {
|
||||||
info!("creating services");
|
info!("creating services");
|
||||||
|
|
||||||
let item_service = Arc::new(MemoryItemService::new()) as DynItemService;
|
let item_service = Arc::new(MemoryItemService::new()) as DynItemService;
|
||||||
let project_service = Arc::new(MemoryProjectService::new()) as DynProjectService;
|
let project_service = Arc::new(MemoryProjectService::new()) as DynProjectService;
|
||||||
let user_service = Arc::new(DefaultUserService::new(pool.clone())) as DynUserService;
|
let user_service = Arc::new(DefaultUserService::new(pool.clone())) as DynUserService;
|
||||||
|
let store = PostgresSessionStore::new(&config.database_url).await?;
|
||||||
|
|
||||||
info!("services created succesfully");
|
info!("services created succesfully");
|
||||||
|
|
||||||
return Self {
|
Ok(Self {
|
||||||
item_service,
|
item_service,
|
||||||
user_service,
|
user_service,
|
||||||
project_service,
|
project_service,
|
||||||
};
|
session_store: store,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use std::{
|
|||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use axum::async_trait;
|
use async_trait::async_trait;
|
||||||
use como_core::items::ItemService;
|
use como_core::items::ItemService;
|
||||||
use como_domain::item::{
|
use como_domain::item::{
|
||||||
queries::{GetItemQuery, GetItemsQuery},
|
queries::{GetItemQuery, GetItemsQuery},
|
||||||
|
Loading…
Reference in New Issue
Block a user