refactor: remove loco-rs

This commit is contained in:
2025-02-28 03:19:48 +08:00
parent c0707d17bb
commit a68aab1452
66 changed files with 1321 additions and 829 deletions

View File

@@ -1,15 +1,17 @@
use async_trait::async_trait;
use axum::http::{HeaderValue, request::Parts};
use base64::{self, Engine};
use loco_rs::app::AppContext;
use reqwest::header::AUTHORIZATION;
use super::{
config::BasicAuthConfig,
errors::AuthError,
service::{AuthService, AuthUserInfo},
service::{AuthServiceTrait, AuthUserInfo},
};
use crate::{
app::AppContext,
models::{auth::AuthType, subscribers::SEED_SUBSCRIBER},
};
use crate::models::{auth::AuthType, subscribers::SEED_SUBSCRIBER};
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct AuthBasic {
@@ -59,7 +61,7 @@ pub struct BasicAuthService {
}
#[async_trait]
impl AuthService for BasicAuthService {
impl AuthServiceTrait for BasicAuthService {
async fn extract_user_info(
&self,
ctx: &AppContext,

View File

@@ -1,6 +1,6 @@
use jwt_authorizer::OneOrArray;
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, NoneAsEmptyString};
use serde_with::{NoneAsEmptyString, serde_as};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BasicAuthConfig {
@@ -33,7 +33,7 @@ pub struct OidcAuthConfig {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "auth_type", rename_all = "snake_case")]
pub enum AppAuthConfig {
pub enum AuthConfig {
Basic(BasicAuthConfig),
Oidc(OidcAuthConfig),
}

View File

@@ -1,9 +1,4 @@
import { InjectionToken } from '@outposts/injection-js';
import {
type EventTypes,
LogLevel,
type OpenIdConfiguration,
} from 'oidc-client-rx';
import { LogLevel, type OpenIdConfiguration } from 'oidc-client-rx';
export const isBasicAuth = process.env.AUTH_TYPE === 'basic';

View File

@@ -6,7 +6,6 @@ use axum::{
http::StatusCode,
response::{IntoResponse, Response},
};
use loco_rs::model::ModelError;
use openidconnect::{
ConfigurationError, RequestTokenError, SignatureVerificationError, SigningError,
StandardErrorResponse, core::CoreErrorResponseType,
@@ -14,7 +13,7 @@ use openidconnect::{
use serde::{Deserialize, Serialize};
use thiserror::Error;
use crate::{fetch::HttpClientError, models::auth::AuthType};
use crate::{errors::RError, fetch::HttpClientError, models::auth::AuthType};
#[derive(Debug, Error)]
pub enum AuthError {
@@ -24,7 +23,7 @@ pub enum AuthError {
current: AuthType,
},
#[error("Failed to find auth record")]
FindAuthRecordError(ModelError),
FindAuthRecordError(RError),
#[error("Invalid credentials")]
BasicInvalidCredentials,
#[error(transparent)]

View File

@@ -6,16 +6,15 @@ use axum::{
middleware::Next,
response::{IntoResponse, Response},
};
use loco_rs::prelude::AppContext;
use crate::{app::AppContextExt, auth::AuthService};
use crate::{app::AppContext, auth::AuthServiceTrait};
pub async fn api_auth_middleware(
pub async fn header_www_authenticate_middleware(
State(ctx): State<Arc<AppContext>>,
request: Request,
next: Next,
) -> Response {
let auth_service = ctx.get_auth_service();
let auth_service = &ctx.auth;
let (mut parts, body) = request.into_parts();

View File

@@ -5,7 +5,7 @@ pub mod middleware;
pub mod oidc;
pub mod service;
pub use config::{AppAuthConfig, BasicAuthConfig, OidcAuthConfig};
pub use config::{AuthConfig, BasicAuthConfig, OidcAuthConfig};
pub use errors::AuthError;
pub use middleware::api_auth_middleware;
pub use service::{AppAuthService, AuthService, AuthUserInfo};
pub use middleware::header_www_authenticate_middleware;
pub use service::{AuthService, AuthServiceTrait, AuthUserInfo};

View File

@@ -7,13 +7,13 @@ use async_trait::async_trait;
use axum::http::{HeaderValue, request::Parts};
use itertools::Itertools;
use jwt_authorizer::{NumericDate, OneOrArray, authorizer::Authorizer};
use loco_rs::{app::AppContext, model::ModelError};
use moka::future::Cache;
use openidconnect::{
AccessTokenHash, AuthorizationCode, ClientId, ClientSecret, CsrfToken, IssuerUrl, Nonce,
OAuth2TokenResponse, PkceCodeChallenge, PkceCodeVerifier, RedirectUrl, TokenResponse,
core::{CoreAuthenticationFlow, CoreClient, CoreProviderMetadata},
};
use sea_orm::DbErr;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use url::Url;
@@ -21,9 +21,9 @@ use url::Url;
use super::{
config::OidcAuthConfig,
errors::AuthError,
service::{AuthService, AuthUserInfo},
service::{AuthServiceTrait, AuthUserInfo},
};
use crate::{fetch::HttpClient, models::auth::AuthType};
use crate::{app::AppContext, errors::RError, fetch::HttpClient, models::auth::AuthType};
#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct OidcAuthClaims {
@@ -258,7 +258,7 @@ impl OidcAuthService {
}
#[async_trait]
impl AuthService for OidcAuthService {
impl AuthServiceTrait for OidcAuthService {
async fn extract_user_info(
&self,
ctx: &AppContext,
@@ -306,7 +306,7 @@ impl AuthService for OidcAuthService {
}
}
let subscriber_auth = match crate::models::auth::Model::find_by_pid(ctx, sub).await {
Err(ModelError::EntityNotFound) => {
Err(RError::DbError(DbErr::RecordNotFound(..))) => {
crate::models::auth::Model::create_from_oidc(ctx, sub.to_string()).await
}
r => r,

View File

@@ -7,20 +7,17 @@ use axum::{
response::{IntoResponse as _, Response},
};
use jwt_authorizer::{JwtAuthorizer, Validation};
use loco_rs::app::{AppContext, Initializer};
use moka::future::Cache;
use once_cell::sync::OnceCell;
use reqwest::header::HeaderValue;
use super::{
AppAuthConfig,
AuthConfig,
basic::BasicAuthService,
errors::AuthError,
oidc::{OidcAuthClaims, OidcAuthService},
};
use crate::{
app::AppContextExt as _,
config::AppConfigExt,
app::AppContext,
fetch::{
HttpClient, HttpClientConfig,
client::{HttpClientCacheBackendConfig, HttpClientCachePresetConfig},
@@ -41,7 +38,7 @@ impl FromRequestParts<AppContext> for AuthUserInfo {
parts: &mut Parts,
state: &AppContext,
) -> Result<Self, Self::Rejection> {
let auth_service = state.get_auth_service();
let auth_service = &state.auth;
auth_service
.extract_user_info(state, parts)
@@ -51,7 +48,7 @@ impl FromRequestParts<AppContext> for AuthUserInfo {
}
#[async_trait]
pub trait AuthService {
pub trait AuthServiceTrait {
async fn extract_user_info(
&self,
ctx: &AppContext,
@@ -61,24 +58,16 @@ pub trait AuthService {
fn auth_type(&self) -> AuthType;
}
pub enum AppAuthService {
pub enum AuthService {
Basic(BasicAuthService),
Oidc(OidcAuthService),
}
static APP_AUTH_SERVICE: OnceCell<AppAuthService> = OnceCell::new();
impl AppAuthService {
pub fn app_instance() -> &'static Self {
APP_AUTH_SERVICE
.get()
.expect("AppAuthService is not initialized")
}
pub async fn from_conf(config: AppAuthConfig) -> Result<Self, AuthError> {
impl AuthService {
pub async fn from_conf(config: AuthConfig) -> Result<Self, AuthError> {
let result = match config {
AppAuthConfig::Basic(config) => AppAuthService::Basic(BasicAuthService { config }),
AppAuthConfig::Oidc(config) => {
AuthConfig::Basic(config) => AuthService::Basic(BasicAuthService { config }),
AuthConfig::Oidc(config) => {
let validation = Validation::new()
.iss(&[&config.issuer])
.aud(&[&config.audience]);
@@ -96,7 +85,7 @@ impl AppAuthService {
.build()
.await?;
AppAuthService::Oidc(OidcAuthService {
AuthService::Oidc(OidcAuthService {
config,
api_authorizer,
oidc_provider_client,
@@ -112,50 +101,29 @@ impl AppAuthService {
}
#[async_trait]
impl AuthService for AppAuthService {
impl AuthServiceTrait for AuthService {
async fn extract_user_info(
&self,
ctx: &AppContext,
request: &mut Parts,
) -> Result<AuthUserInfo, AuthError> {
match self {
AppAuthService::Basic(service) => service.extract_user_info(ctx, request).await,
AppAuthService::Oidc(service) => service.extract_user_info(ctx, request).await,
AuthService::Basic(service) => service.extract_user_info(ctx, request).await,
AuthService::Oidc(service) => service.extract_user_info(ctx, 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(),
AuthService::Basic(service) => service.www_authenticate_header_value(),
AuthService::Oidc(service) => service.www_authenticate_header_value(),
}
}
fn auth_type(&self) -> AuthType {
match self {
AppAuthService::Basic(service) => service.auth_type(),
AppAuthService::Oidc(service) => service.auth_type(),
AuthService::Basic(service) => service.auth_type(),
AuthService::Oidc(service) => service.auth_type(),
}
}
}
pub struct AppAuthServiceInitializer;
#[async_trait]
impl Initializer for AppAuthServiceInitializer {
fn name(&self) -> String {
String::from("AppAuthServiceInitializer")
}
async fn before_run(&self, ctx: &AppContext) -> Result<(), loco_rs::Error> {
let auth_conf = ctx.config.get_app_conf()?.auth;
let service = AppAuthService::from_conf(auth_conf)
.await
.map_err(loco_rs::Error::wrap)?;
APP_AUTH_SERVICE.get_or_init(|| service);
Ok(())
}
}