feat: replace graphql playground to altair
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use async_trait::async_trait;
|
||||
use axum::http::request::Parts;
|
||||
use axum::http::{request::Parts, HeaderValue};
|
||||
use base64::{self, Engine};
|
||||
use reqwest::header::AUTHORIZATION;
|
||||
|
||||
@@ -76,4 +76,8 @@ impl AuthService for BasicAuthService {
|
||||
}
|
||||
Err(AuthError::BasicInvalidCredentials)
|
||||
}
|
||||
|
||||
fn www_authenticate_header_value(&self) -> Option<HeaderValue> {
|
||||
Some(HeaderValue::from_static(r#"Basic realm="konobangu""#))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,15 +3,16 @@ use axum::{
|
||||
response::{IntoResponse, Response},
|
||||
Json,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum AuthError {
|
||||
#[error(transparent)]
|
||||
OidcInitError(#[from] jwt_authorizer::error::InitError),
|
||||
#[error("Invalid credentials")]
|
||||
BasicInvalidCredentials,
|
||||
#[error(transparent)]
|
||||
OidcInitError(#[from] jwt_authorizer::error::InitError),
|
||||
#[error(transparent)]
|
||||
OidcJwtAuthError(#[from] jwt_authorizer::AuthError),
|
||||
#[error("Extra scopes {expected} do not match found scopes {found}")]
|
||||
OidcExtraScopesMatchError { expected: String, found: String },
|
||||
@@ -29,8 +30,23 @@ pub enum AuthError {
|
||||
OidcSubMissingError,
|
||||
}
|
||||
|
||||
impl IntoResponse for AuthError {
|
||||
fn into_response(self) -> Response {
|
||||
(StatusCode::UNAUTHORIZED, Json(self.to_string())).into_response()
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AuthErrorBody {
|
||||
pub error_code: i32,
|
||||
pub error_msg: String,
|
||||
}
|
||||
|
||||
impl From<AuthError> for AuthErrorBody {
|
||||
fn from(value: AuthError) -> Self {
|
||||
AuthErrorBody {
|
||||
error_code: StatusCode::UNAUTHORIZED.as_u16() as i32,
|
||||
error_msg: value.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoResponse for AuthError {
|
||||
fn into_response(self) -> Response {
|
||||
(StatusCode::UNAUTHORIZED, Json(AuthErrorBody::from(self))).into_response()
|
||||
}
|
||||
}
|
||||
|
||||
63
apps/recorder/src/auth/middleware.rs
Normal file
63
apps/recorder/src/auth/middleware.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
use axum::{
|
||||
extract::{Request, State},
|
||||
http::header,
|
||||
middleware::Next,
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
use loco_rs::prelude::AppContext;
|
||||
|
||||
use crate::{app::AppContextExt, auth::AuthService};
|
||||
|
||||
pub async fn api_auth_middleware(
|
||||
State(ctx): State<AppContext>,
|
||||
request: Request,
|
||||
next: Next,
|
||||
) -> Response {
|
||||
let auth_service = ctx.get_auth_service();
|
||||
|
||||
let (mut parts, body) = request.into_parts();
|
||||
|
||||
let mut response = match auth_service.extract_user_info(&mut parts).await {
|
||||
Ok(auth_user_info) => {
|
||||
let mut request = Request::from_parts(parts, body);
|
||||
request.extensions_mut().insert(auth_user_info);
|
||||
next.run(request).await
|
||||
}
|
||||
Err(auth_error) => auth_error.into_response(),
|
||||
};
|
||||
|
||||
if let Some(header_value) = auth_service.www_authenticate_header_value() {
|
||||
response
|
||||
.headers_mut()
|
||||
.insert(header::WWW_AUTHENTICATE, header_value);
|
||||
};
|
||||
|
||||
response
|
||||
}
|
||||
|
||||
pub async fn webui_auth_middleware(
|
||||
State(ctx): State<AppContext>,
|
||||
request: Request,
|
||||
next: Next,
|
||||
) -> Response {
|
||||
let auth_service = ctx.get_auth_service();
|
||||
|
||||
let (mut parts, body) = request.into_parts();
|
||||
|
||||
let mut response = match auth_service.extract_user_info(&mut parts).await {
|
||||
Ok(auth_user_info) => {
|
||||
let mut request = Request::from_parts(parts, body);
|
||||
request.extensions_mut().insert(auth_user_info);
|
||||
next.run(request).await
|
||||
}
|
||||
Err(auth_error) => auth_error.into_response(),
|
||||
};
|
||||
|
||||
if let Some(header_value) = auth_service.www_authenticate_header_value() {
|
||||
response
|
||||
.headers_mut()
|
||||
.insert(header::WWW_AUTHENTICATE, header_value);
|
||||
};
|
||||
|
||||
response
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
pub mod basic;
|
||||
pub mod config;
|
||||
pub mod errors;
|
||||
pub mod middleware;
|
||||
pub mod oidc;
|
||||
pub mod service;
|
||||
|
||||
pub use config::{AppAuthConfig, BasicAuthConfig, OidcAuthConfig};
|
||||
pub use errors::AuthError;
|
||||
pub use middleware::{api_auth_middleware, webui_auth_middleware};
|
||||
pub use service::{AppAuthService, AuthService, AuthUserInfo};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use axum::http::request::Parts;
|
||||
use axum::http::{request::Parts, HeaderValue};
|
||||
use itertools::Itertools;
|
||||
use jwt_authorizer::{authorizer::Authorizer, NumericDate, OneOrArray};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -135,4 +135,8 @@ impl AuthService for OidcAuthService {
|
||||
auth_type: AuthType::Oidc,
|
||||
})
|
||||
}
|
||||
|
||||
fn www_authenticate_header_value(&self) -> Option<HeaderValue> {
|
||||
Some(HeaderValue::from_static(r#"Bearer realm="konobangu""#))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ use axum::{
|
||||
use jwt_authorizer::{JwtAuthorizer, Validation};
|
||||
use loco_rs::app::{AppContext, Initializer};
|
||||
use once_cell::sync::OnceCell;
|
||||
use reqwest::header::HeaderValue;
|
||||
|
||||
use super::{
|
||||
basic::BasicAuthService,
|
||||
@@ -16,6 +17,7 @@ use super::{
|
||||
};
|
||||
use crate::{app::AppContextExt as _, config::AppConfigExt, models::auth::AuthType};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AuthUserInfo {
|
||||
pub user_pid: String,
|
||||
pub auth_type: AuthType,
|
||||
@@ -40,6 +42,7 @@ impl FromRequestParts<AppContext> for AuthUserInfo {
|
||||
#[async_trait]
|
||||
pub trait AuthService {
|
||||
async fn extract_user_info(&self, request: &mut Parts) -> Result<AuthUserInfo, AuthError>;
|
||||
fn www_authenticate_header_value(&self) -> Option<HeaderValue>;
|
||||
}
|
||||
|
||||
pub enum AppAuthService {
|
||||
@@ -87,6 +90,13 @@ impl AuthService for AppAuthService {
|
||||
AppAuthService::Oidc(service) => service.extract_user_info(request).await,
|
||||
}
|
||||
}
|
||||
|
||||
fn www_authenticate_header_value(&self) -> Option<HeaderValue> {
|
||||
match self {
|
||||
AppAuthService::Basic(service) => service.www_authenticate_header_value(),
|
||||
AppAuthService::Oidc(service) => service.www_authenticate_header_value(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AppAuthServiceInitializer;
|
||||
|
||||
Reference in New Issue
Block a user