Compare commits
7 Commits
feat/axum-
...
renovate/a
Author | SHA1 | Date | |
---|---|---|---|
cff947857b | |||
63c29999bf
|
|||
a470122745
|
|||
d32d343695
|
|||
251d3922bf
|
|||
1b8924e7f6
|
|||
f586d157b1 |
2
.drone.yml
Normal file
2
.drone.yml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
kind: template
|
||||||
|
load: cuddle-rust-lib-plan.yaml
|
@@ -1,34 +0,0 @@
|
|||||||
when:
|
|
||||||
- event: [pull_request, tag]
|
|
||||||
- event: push
|
|
||||||
branch:
|
|
||||||
- main
|
|
||||||
|
|
||||||
variables:
|
|
||||||
- &rust_image 'rustlang/rust:nightly'
|
|
||||||
|
|
||||||
steps:
|
|
||||||
build:
|
|
||||||
image: *rust_image
|
|
||||||
group: ci
|
|
||||||
commands:
|
|
||||||
- "cargo build"
|
|
||||||
|
|
||||||
test:
|
|
||||||
image: *rust_image
|
|
||||||
group: ci
|
|
||||||
commands:
|
|
||||||
- "cargo test"
|
|
||||||
|
|
||||||
lint:
|
|
||||||
image: *rust_image
|
|
||||||
group: ci
|
|
||||||
commands:
|
|
||||||
- "cargo clippy"
|
|
||||||
|
|
||||||
fmt:
|
|
||||||
image: *rust_image
|
|
||||||
group: ci
|
|
||||||
commands:
|
|
||||||
- "cargo fmt --all --check"
|
|
||||||
|
|
1193
Cargo.lock
generated
1193
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
16
Cargo.toml
16
Cargo.toml
@@ -13,10 +13,10 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
|||||||
clap = { version = "4", features = ["derive", "env"] }
|
clap = { version = "4", features = ["derive", "env"] }
|
||||||
async-trait = { version = "0.1", features = [] }
|
async-trait = { version = "0.1", features = [] }
|
||||||
|
|
||||||
axum = { version = "0.7.1", features = [
|
axum = { version = "0.8.0", features = [
|
||||||
"macros",
|
"macros",
|
||||||
] }
|
] }
|
||||||
axum-extra = { version = "0.9.0", features = [
|
axum-extra = { version = "0.10.0", features = [
|
||||||
"cookie",
|
"cookie",
|
||||||
"cookie-private",
|
"cookie-private",
|
||||||
"typed-header",
|
"typed-header",
|
||||||
@@ -28,17 +28,17 @@ serde = { version = "1", features = ["derive"] }
|
|||||||
serde_json = { version = "1" }
|
serde_json = { version = "1" }
|
||||||
|
|
||||||
uuid = {version = "1.5.0", features = ["v4"]}
|
uuid = {version = "1.5.0", features = ["v4"]}
|
||||||
sqlx = { version = "0.7", features = [
|
sqlx = { version = "0.8", features = [
|
||||||
"runtime-tokio",
|
"runtime-tokio",
|
||||||
"postgres",
|
"postgres",
|
||||||
"migrate",
|
"migrate",
|
||||||
] }
|
] }
|
||||||
|
|
||||||
zitadel = { version = "3.4", features = ["axum"] }
|
zitadel = { version = "5.0", features = ["axum"] }
|
||||||
tower = "0.4"
|
tower = "0.5"
|
||||||
tower-http = { version = "0.4", features = ["cors", "trace"] }
|
tower-http = { version = "0.6", features = ["cors", "trace"] }
|
||||||
oauth2 = "4.4.2"
|
oauth2 = "5.0.0"
|
||||||
openidconnect = "3.4"
|
openidconnect = "4.0"
|
||||||
|
|
||||||
pretty_assertions = "1.4.0"
|
pretty_assertions = "1.4.0"
|
||||||
sealed_test = "1.0.0"
|
sealed_test = "1.0.0"
|
||||||
|
@@ -2,8 +2,8 @@ use std::fmt::Display;
|
|||||||
|
|
||||||
use axum::extract::{FromRef, FromRequestParts, Query, State};
|
use axum::extract::{FromRef, FromRequestParts, Query, State};
|
||||||
use axum::http::request::Parts;
|
use axum::http::request::Parts;
|
||||||
use axum::http::StatusCode;
|
use axum::http::{HeaderMap, StatusCode, Uri};
|
||||||
use axum::response::{ErrorResponse, IntoResponse, Redirect};
|
use axum::response::{ErrorResponse, IntoResponse, Redirect, Response};
|
||||||
use axum::routing::get;
|
use axum::routing::get;
|
||||||
use axum::{async_trait, Json, RequestPartsExt, Router};
|
use axum::{async_trait, Json, RequestPartsExt, Router};
|
||||||
|
|
||||||
@@ -97,13 +97,21 @@ pub struct UserFromSession {
|
|||||||
|
|
||||||
pub static COOKIE_NAME: &str = "SESSION";
|
pub static COOKIE_NAME: &str = "SESSION";
|
||||||
|
|
||||||
|
pub struct AuthRedirect((HeaderMap, String));
|
||||||
|
|
||||||
|
impl IntoResponse for AuthRedirect {
|
||||||
|
fn into_response(self) -> Response {
|
||||||
|
(self.0 .0, Redirect::temporary(&self.0 .1.as_str())).into_response()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<S> FromRequestParts<S> for UserFromSession
|
impl<S> FromRequestParts<S> for UserFromSession
|
||||||
where
|
where
|
||||||
AuthService: FromRef<S>,
|
AuthService: FromRef<S>,
|
||||||
S: Send + Sync,
|
S: Send + Sync,
|
||||||
{
|
{
|
||||||
type Rejection = (StatusCode, &'static str);
|
type Rejection = AuthRedirect;
|
||||||
|
|
||||||
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 auth_service = AuthService::from_ref(state);
|
let auth_service = AuthService::from_ref(state);
|
||||||
@@ -114,16 +122,21 @@ where
|
|||||||
let basic: Option<TypedHeader<Authorization<Basic>>> = parts.extract().await.unwrap();
|
let basic: Option<TypedHeader<Authorization<Basic>>> = parts.extract().await.unwrap();
|
||||||
|
|
||||||
if let Some(basic) = basic {
|
if let Some(basic) = basic {
|
||||||
let token = auth_service
|
let token = match auth_service
|
||||||
.login_token(basic.username(), basic.password())
|
.login_token(basic.username(), basic.password())
|
||||||
.await
|
.await
|
||||||
.into_response()
|
.into_response()
|
||||||
.map_err(|_| {
|
{
|
||||||
(
|
Ok(login) => login,
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
Err(e) => {
|
||||||
"could not get token from basic",
|
tracing::info!("did not find a basic login token, will trigger login");
|
||||||
)
|
let (headers, url) = auth_service
|
||||||
})?;
|
.login(Some(parts.uri.to_string()))
|
||||||
|
.await
|
||||||
|
.expect("to be able to request login");
|
||||||
|
return Err(AuthRedirect((headers, url.to_string())));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return Ok(UserFromSession {
|
return Ok(UserFromSession {
|
||||||
user: User {
|
user: User {
|
||||||
@@ -134,24 +147,32 @@ where
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return Err(anyhow::anyhow!("No session was found"))
|
tracing::info!("did not find a cookie, will trigger login");
|
||||||
.into_response()
|
let (headers, url) = auth_service
|
||||||
.map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "did not find a cookie"))?;
|
.login(Some(parts.uri.to_string()))
|
||||||
|
.await
|
||||||
|
.expect("to be able to request login");
|
||||||
|
return Err(AuthRedirect((headers, url.to_string())));
|
||||||
}
|
}
|
||||||
|
|
||||||
let session_cookie = session_cookie.unwrap();
|
let session_cookie = session_cookie.unwrap();
|
||||||
|
|
||||||
// continue to decode the session cookie
|
// continue to decode the session cookie
|
||||||
let user = auth_service
|
let user = match auth_service
|
||||||
.get_user_from_session(session_cookie)
|
.get_user_from_session(session_cookie)
|
||||||
.await
|
.await
|
||||||
.into_response()
|
.into_response()
|
||||||
.map_err(|_| {
|
{
|
||||||
(
|
Ok(user) => user,
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
Err(_) => {
|
||||||
"failed to decode session cookie",
|
tracing::info!("could not get user from session, will trigger login");
|
||||||
)
|
let (headers, url) = auth_service
|
||||||
})?;
|
.login(Some(parts.uri.to_string()))
|
||||||
|
.await
|
||||||
|
.expect("to be able to request login");
|
||||||
|
return Err(AuthRedirect((headers, url.to_string())));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(UserFromSession { user })
|
Ok(UserFromSession { user })
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user