feat: initialize k-tv-frontend with Next.js and Tailwind CSS
- Added package.json with dependencies and scripts for development, build, and linting. - Created postcss.config.mjs for Tailwind CSS integration. - Added SVG assets for UI components including file, globe, next, vercel, and window icons. - Configured TypeScript with tsconfig.json for strict type checking and module resolution.
This commit is contained in:
125
k-tv-backend/api/src/state.rs
Normal file
125
k-tv-backend/api/src/state.rs
Normal file
@@ -0,0 +1,125 @@
|
||||
//! Application State
|
||||
//!
|
||||
//! Holds shared state for the application.
|
||||
|
||||
use axum::extract::FromRef;
|
||||
use axum_extra::extract::cookie::Key;
|
||||
#[cfg(feature = "auth-jwt")]
|
||||
use infra::auth::jwt::{JwtConfig, JwtValidator};
|
||||
#[cfg(feature = "auth-oidc")]
|
||||
use infra::auth::oidc::OidcService;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::config::Config;
|
||||
use domain::{ChannelService, ScheduleEngineService, UserService};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AppState {
|
||||
pub user_service: Arc<UserService>,
|
||||
pub channel_service: Arc<ChannelService>,
|
||||
pub schedule_engine: Arc<ScheduleEngineService>,
|
||||
pub cookie_key: Key,
|
||||
#[cfg(feature = "auth-oidc")]
|
||||
pub oidc_service: Option<Arc<OidcService>>,
|
||||
#[cfg(feature = "auth-jwt")]
|
||||
pub jwt_validator: Option<Arc<JwtValidator>>,
|
||||
pub config: Arc<Config>,
|
||||
}
|
||||
|
||||
impl AppState {
|
||||
pub async fn new(
|
||||
user_service: UserService,
|
||||
channel_service: ChannelService,
|
||||
schedule_engine: ScheduleEngineService,
|
||||
config: Config,
|
||||
) -> anyhow::Result<Self> {
|
||||
let cookie_key = Key::derive_from(config.cookie_secret.as_bytes());
|
||||
|
||||
#[cfg(feature = "auth-oidc")]
|
||||
let oidc_service = if let (Some(issuer), Some(id), secret, Some(redirect), resource_id) = (
|
||||
&config.oidc_issuer,
|
||||
&config.oidc_client_id,
|
||||
&config.oidc_client_secret,
|
||||
&config.oidc_redirect_url,
|
||||
&config.oidc_resource_id,
|
||||
) {
|
||||
tracing::info!("Initializing OIDC service with issuer: {}", issuer);
|
||||
|
||||
let issuer_url = domain::IssuerUrl::new(issuer)
|
||||
.map_err(|e| anyhow::anyhow!("Invalid OIDC issuer URL: {}", e))?;
|
||||
let client_id = domain::ClientId::new(id)
|
||||
.map_err(|e| anyhow::anyhow!("Invalid OIDC client ID: {}", e))?;
|
||||
let client_secret = secret.as_ref().map(|s| domain::ClientSecret::new(s));
|
||||
let redirect_url = domain::RedirectUrl::new(redirect)
|
||||
.map_err(|e| anyhow::anyhow!("Invalid OIDC redirect URL: {}", e))?;
|
||||
let resource = resource_id
|
||||
.as_ref()
|
||||
.map(|r| domain::ResourceId::new(r))
|
||||
.transpose()
|
||||
.map_err(|e| anyhow::anyhow!("Invalid OIDC resource ID: {}", e))?;
|
||||
|
||||
Some(Arc::new(
|
||||
OidcService::new(issuer_url, client_id, client_secret, redirect_url, resource)
|
||||
.await?,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
#[cfg(feature = "auth-jwt")]
|
||||
let jwt_validator = {
|
||||
let secret = match &config.jwt_secret {
|
||||
Some(s) if !s.is_empty() => s.clone(),
|
||||
_ => {
|
||||
if config.is_production {
|
||||
anyhow::bail!("JWT_SECRET is required in production");
|
||||
}
|
||||
tracing::warn!(
|
||||
"⚠️ JWT_SECRET not set — using insecure development secret. DO NOT USE IN PRODUCTION!"
|
||||
);
|
||||
"k-template-dev-secret-not-for-production-use-only".to_string()
|
||||
}
|
||||
};
|
||||
|
||||
tracing::info!("Initializing JWT validator");
|
||||
let jwt_config = JwtConfig::new(
|
||||
secret,
|
||||
config.jwt_issuer.clone(),
|
||||
config.jwt_audience.clone(),
|
||||
Some(config.jwt_expiry_hours),
|
||||
config.is_production,
|
||||
)?;
|
||||
Some(Arc::new(JwtValidator::new(jwt_config)))
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
user_service: Arc::new(user_service),
|
||||
channel_service: Arc::new(channel_service),
|
||||
schedule_engine: Arc::new(schedule_engine),
|
||||
cookie_key,
|
||||
#[cfg(feature = "auth-oidc")]
|
||||
oidc_service,
|
||||
#[cfg(feature = "auth-jwt")]
|
||||
jwt_validator,
|
||||
config: Arc::new(config),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRef<AppState> for Arc<UserService> {
|
||||
fn from_ref(input: &AppState) -> Self {
|
||||
input.user_service.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRef<AppState> for Arc<Config> {
|
||||
fn from_ref(input: &AppState) -> Self {
|
||||
input.config.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRef<AppState> for Key {
|
||||
fn from_ref(input: &AppState) -> Self {
|
||||
input.cookie_key.clone()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user