Add server config route
This commit is contained in:
12
matrixgw_backend/Cargo.lock
generated
12
matrixgw_backend/Cargo.lock
generated
@@ -68,6 +68,17 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "actix-remote-ip"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7629b357d4705cf3f1e31f989f48ecd56027112f7d52dcf06dd96ee197065f8e"
|
||||||
|
dependencies = [
|
||||||
|
"actix-web",
|
||||||
|
"futures-util",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "actix-router"
|
name = "actix-router"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
@@ -1405,6 +1416,7 @@ checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
|
|||||||
name = "matrixgw_backend"
|
name = "matrixgw_backend"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"actix-remote-ip",
|
||||||
"actix-session",
|
"actix-session",
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
|||||||
@@ -14,3 +14,4 @@ rust-s3 = { version = "0.37.0", features = ["tokio"] }
|
|||||||
tokio = { version = "1.48.0", features = ["full"] }
|
tokio = { version = "1.48.0", features = ["full"] }
|
||||||
actix-web = "4.11.0"
|
actix-web = "4.11.0"
|
||||||
actix-session = { version = "0.11.0", features = ["redis-session"] }
|
actix-session = { version = "0.11.0", features = ["redis-session"] }
|
||||||
|
actix-remote-ip = "0.1.0"
|
||||||
@@ -18,6 +18,11 @@ pub struct AppConfig {
|
|||||||
#[clap(short, long, env)]
|
#[clap(short, long, env)]
|
||||||
pub proxy_ip: Option<String>,
|
pub proxy_ip: Option<String>,
|
||||||
|
|
||||||
|
/// Unsecure : for development, bypass authentication, using the account with the given
|
||||||
|
/// email address by default
|
||||||
|
#[clap(long, env)]
|
||||||
|
unsecure_auto_login_email: Option<String>,
|
||||||
|
|
||||||
/// Secret key, used to secure some resources. Must be randomly generated
|
/// Secret key, used to secure some resources. Must be randomly generated
|
||||||
#[clap(short = 'S', long, env, default_value = "")]
|
#[clap(short = 'S', long, env, default_value = "")]
|
||||||
secret: String,
|
secret: String,
|
||||||
@@ -54,6 +59,10 @@ pub struct AppConfig {
|
|||||||
)]
|
)]
|
||||||
pub oidc_configuration_url: String,
|
pub oidc_configuration_url: String,
|
||||||
|
|
||||||
|
/// OpenID provider name
|
||||||
|
#[arg(long, env, default_value = "3rd party provider")]
|
||||||
|
pub oidc_provider_name: String,
|
||||||
|
|
||||||
/// OpenID client ID
|
/// OpenID client ID
|
||||||
#[arg(long, env, default_value = "foo")]
|
#[arg(long, env, default_value = "foo")]
|
||||||
pub oidc_client_id: String,
|
pub oidc_client_id: String,
|
||||||
@@ -103,6 +112,14 @@ impl AppConfig {
|
|||||||
&ARGS
|
&ARGS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get auto login email (if not empty)
|
||||||
|
pub fn unsecure_auto_login_email(&self) -> Option<&str> {
|
||||||
|
match self.unsecure_auto_login_email.as_deref() {
|
||||||
|
None | Some("") => None,
|
||||||
|
s => s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get app secret
|
/// Get app secret
|
||||||
pub fn secret(&self) -> &str {
|
pub fn secret(&self) -> &str {
|
||||||
let mut secret = self.secret.as_str();
|
let mut secret = self.secret.as_str();
|
||||||
@@ -118,6 +135,11 @@ impl AppConfig {
|
|||||||
secret
|
secret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if auth is disabled
|
||||||
|
pub fn is_auth_disabled(&self) -> bool {
|
||||||
|
self.unsecure_auto_login_email().is_some()
|
||||||
|
}
|
||||||
|
|
||||||
/// Get Redis connection configuration
|
/// Get Redis connection configuration
|
||||||
pub fn redis_connection_string(&self) -> String {
|
pub fn redis_connection_string(&self) -> String {
|
||||||
format!(
|
format!(
|
||||||
@@ -136,6 +158,7 @@ impl AppConfig {
|
|||||||
client_id: self.oidc_client_id.as_str(),
|
client_id: self.oidc_client_id.as_str(),
|
||||||
client_secret: self.oidc_client_secret.as_str(),
|
client_secret: self.oidc_client_secret.as_str(),
|
||||||
configuration_url: self.oidc_configuration_url.as_str(),
|
configuration_url: self.oidc_configuration_url.as_str(),
|
||||||
|
name: self.oidc_provider_name.as_str(),
|
||||||
redirect_url: self
|
redirect_url: self
|
||||||
.oidc_redirect_url
|
.oidc_redirect_url
|
||||||
.replace("APP_ORIGIN", &self.website_origin),
|
.replace("APP_ORIGIN", &self.website_origin),
|
||||||
@@ -169,6 +192,7 @@ impl AppConfig {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize)]
|
#[derive(Debug, Clone, serde::Serialize)]
|
||||||
pub struct OIDCProvider<'a> {
|
pub struct OIDCProvider<'a> {
|
||||||
|
pub name: &'a str,
|
||||||
pub client_id: &'a str,
|
pub client_id: &'a str,
|
||||||
pub client_secret: &'a str,
|
pub client_secret: &'a str,
|
||||||
pub configuration_url: &'a str,
|
pub configuration_url: &'a str,
|
||||||
|
|||||||
1
matrixgw_backend/src/controllers/mod.rs
Normal file
1
matrixgw_backend/src/controllers/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod server_controller;
|
||||||
74
matrixgw_backend/src/controllers/server_controller.rs
Normal file
74
matrixgw_backend/src/controllers/server_controller.rs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
use crate::app_config::AppConfig;
|
||||||
|
use actix_web::HttpResponse;
|
||||||
|
|
||||||
|
/// Serve robots.txt (disallow ranking)
|
||||||
|
pub async fn robots_txt() -> HttpResponse {
|
||||||
|
HttpResponse::Ok()
|
||||||
|
.content_type("text/plain")
|
||||||
|
.body("User-agent: *\nDisallow: /\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Serialize)]
|
||||||
|
pub struct LenConstraints {
|
||||||
|
min: usize,
|
||||||
|
max: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LenConstraints {
|
||||||
|
pub fn new(min: usize, max: usize) -> Self {
|
||||||
|
Self { min, max }
|
||||||
|
}
|
||||||
|
pub fn not_empty(max: usize) -> Self {
|
||||||
|
Self { min: 1, max }
|
||||||
|
}
|
||||||
|
pub fn max_only(max: usize) -> Self {
|
||||||
|
Self { min: 0, max }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_str(&self, s: &str) -> bool {
|
||||||
|
s.len() >= self.min && s.len() <= self.max
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_u32(&self, v: u32) -> bool {
|
||||||
|
v >= self.min as u32 && v <= self.max as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Serialize)]
|
||||||
|
pub struct ServerConstraints {
|
||||||
|
pub token_name: LenConstraints,
|
||||||
|
pub token_ip_net: LenConstraints,
|
||||||
|
pub token_max_inactivity: LenConstraints,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ServerConstraints {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
token_name: LenConstraints::new(5, 255),
|
||||||
|
token_ip_net: LenConstraints::max_only(44),
|
||||||
|
token_max_inactivity: LenConstraints::new(3600, 3600 * 24 * 365),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Serialize)]
|
||||||
|
struct ServerConfig {
|
||||||
|
auth_disabled: bool,
|
||||||
|
oidc_provider_name: &'static str,
|
||||||
|
constraints: ServerConstraints,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ServerConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
auth_disabled: AppConfig::get().is_auth_disabled(),
|
||||||
|
oidc_provider_name: AppConfig::get().openid_provider().name,
|
||||||
|
constraints: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get server static configuration
|
||||||
|
pub async fn config() -> HttpResponse {
|
||||||
|
HttpResponse::Ok().json(ServerConfig::default())
|
||||||
|
}
|
||||||
@@ -1 +1,2 @@
|
|||||||
pub mod app_config;
|
pub mod app_config;
|
||||||
|
pub mod controllers;
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
use actix_remote_ip::RemoteIPConfig;
|
||||||
|
use actix_session::SessionMiddleware;
|
||||||
|
use actix_session::config::SessionLifecycle;
|
||||||
use actix_session::storage::RedisSessionStore;
|
use actix_session::storage::RedisSessionStore;
|
||||||
use actix_web::cookie::Key;
|
use actix_web::cookie::Key;
|
||||||
use actix_web::{App, HttpServer};
|
use actix_web::{App, HttpServer, web};
|
||||||
use matrixgw_backend::app_config::AppConfig;
|
use matrixgw_backend::app_config::AppConfig;
|
||||||
|
use matrixgw_backend::controllers::server_controller;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
@@ -19,9 +23,26 @@ async fn main() -> std::io::Result<()> {
|
|||||||
AppConfig::get().website_origin
|
AppConfig::get().website_origin
|
||||||
);
|
);
|
||||||
|
|
||||||
HttpServer::new(move || App::new())
|
HttpServer::new(move || {
|
||||||
.workers(4)
|
App::new()
|
||||||
.bind(&AppConfig::get().listen_address)?
|
.wrap(
|
||||||
.run()
|
SessionMiddleware::builder(redis_store.clone(), secret_key.clone())
|
||||||
.await
|
.cookie_name("matrixgw-session".to_string())
|
||||||
|
.session_lifecycle(SessionLifecycle::BrowserSession(Default::default()))
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
.app_data(web::Data::new(RemoteIPConfig {
|
||||||
|
proxy: AppConfig::get().proxy_ip.clone(),
|
||||||
|
}))
|
||||||
|
// Server controller
|
||||||
|
.route("/robots.txt", web::get().to(server_controller::robots_txt))
|
||||||
|
.route(
|
||||||
|
"/api/server/config",
|
||||||
|
web::get().to(server_controller::config),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.workers(4)
|
||||||
|
.bind(&AppConfig::get().listen_address)?
|
||||||
|
.run()
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user