mirror of
https://github.com/lldap/lldap.git
synced 2026-03-31 15:07:48 +01:00
server: Allow custom path to front-end assets
This commit is contained in:
@@ -33,6 +33,9 @@
|
|||||||
## The public URL of the server, for password reset links.
|
## The public URL of the server, for password reset links.
|
||||||
#http_url = "http://localhost"
|
#http_url = "http://localhost"
|
||||||
|
|
||||||
|
## The path to the front-end assets (relative to the working directory).
|
||||||
|
#assets_path = "./app"
|
||||||
|
|
||||||
## Random secret for JWT signature.
|
## Random secret for JWT signature.
|
||||||
## This secret should be random, and should be shared with application
|
## This secret should be random, and should be shared with application
|
||||||
## servers that need to consume the JWTs.
|
## servers that need to consume the JWTs.
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ use figment_file_provider_adapter::FileAdapter;
|
|||||||
use lldap_auth::opaque::{server::ServerSetup, KeyPair};
|
use lldap_auth::opaque::{server::ServerSetup, KeyPair};
|
||||||
use secstr::SecUtf8;
|
use secstr::SecUtf8;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::path::PathBuf;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
@@ -125,6 +126,8 @@ pub struct Configuration {
|
|||||||
// "***SECRET***".
|
// "***SECRET***".
|
||||||
#[builder(default)]
|
#[builder(default)]
|
||||||
pub key_seed: Option<SecUtf8>,
|
pub key_seed: Option<SecUtf8>,
|
||||||
|
#[builder(default = r#"PathBuf::from("./app")"#)]
|
||||||
|
pub assets_path: PathBuf,
|
||||||
#[builder(default)]
|
#[builder(default)]
|
||||||
pub smtp_options: MailOptions,
|
pub smtp_options: MailOptions,
|
||||||
#[builder(default)]
|
#[builder(default)]
|
||||||
|
|||||||
@@ -21,11 +21,12 @@ use anyhow::{Context, Result};
|
|||||||
use hmac::Hmac;
|
use hmac::Hmac;
|
||||||
use sha2::Sha512;
|
use sha2::Sha512;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
use tracing::info;
|
use tracing::{info, warn};
|
||||||
|
|
||||||
async fn index<Backend>(data: web::Data<AppState<Backend>>) -> actix_web::Result<impl Responder> {
|
async fn index<Backend>(data: web::Data<AppState<Backend>>) -> actix_web::Result<impl Responder> {
|
||||||
let mut file = std::fs::read_to_string(r"./app/index.html")?;
|
let mut file = std::fs::read_to_string(data.assets_path.join("index.html"))?;
|
||||||
|
|
||||||
if data.server_url.path() != "/" {
|
if data.server_url.path() != "/" {
|
||||||
file = file.replace(
|
file = file.replace(
|
||||||
@@ -80,7 +81,7 @@ pub(crate) fn error_to_http_response(error: TcpError) -> HttpResponse {
|
|||||||
async fn main_js_handler<Backend>(
|
async fn main_js_handler<Backend>(
|
||||||
data: web::Data<AppState<Backend>>,
|
data: web::Data<AppState<Backend>>,
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<impl Responder> {
|
||||||
let mut file = std::fs::read_to_string(r"./app/static/main.js")?;
|
let mut file = std::fs::read_to_string(data.assets_path.join("static/main.js"))?;
|
||||||
|
|
||||||
if data.server_url.path() != "/" {
|
if data.server_url.path() != "/" {
|
||||||
file = file.replace("/pkg/", format!("{}/pkg/", data.server_url.path()).as_str());
|
file = file.replace("/pkg/", format!("{}/pkg/", data.server_url.path()).as_str());
|
||||||
@@ -91,13 +92,20 @@ async fn main_js_handler<Backend>(
|
|||||||
.insert_header((header::CONTENT_TYPE, "text/javascript")))
|
.insert_header((header::CONTENT_TYPE, "text/javascript")))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn wasm_handler() -> actix_web::Result<impl Responder> {
|
async fn wasm_handler<Backend>(
|
||||||
Ok(actix_files::NamedFile::open_async("./app/pkg/lldap_app_bg.wasm").await?)
|
data: web::Data<AppState<Backend>>,
|
||||||
|
) -> actix_web::Result<impl Responder> {
|
||||||
|
Ok(
|
||||||
|
actix_files::NamedFile::open_async(data.assets_path.join("pkg/lldap_app_bg.wasm.gz"))
|
||||||
|
.await?,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn wasm_handler_compressed() -> actix_web::Result<impl Responder> {
|
async fn wasm_handler_compressed<Backend>(
|
||||||
|
data: web::Data<AppState<Backend>>,
|
||||||
|
) -> actix_web::Result<impl Responder> {
|
||||||
Ok(
|
Ok(
|
||||||
actix_files::NamedFile::open_async("./app/pkg/lldap_app_bg.wasm.gz")
|
actix_files::NamedFile::open_async(data.assets_path.join("pkg/lldap_app_bg.wasm.gz"))
|
||||||
.await?
|
.await?
|
||||||
.customize()
|
.customize()
|
||||||
.insert_header(header::ContentEncoding::Gzip)
|
.insert_header(header::ContentEncoding::Gzip)
|
||||||
@@ -111,6 +119,7 @@ fn http_config<Backend>(
|
|||||||
jwt_secret: secstr::SecUtf8,
|
jwt_secret: secstr::SecUtf8,
|
||||||
jwt_blacklist: HashSet<u64>,
|
jwt_blacklist: HashSet<u64>,
|
||||||
server_url: url::Url,
|
server_url: url::Url,
|
||||||
|
assets_path: PathBuf,
|
||||||
mail_options: MailOptions,
|
mail_options: MailOptions,
|
||||||
) where
|
) where
|
||||||
Backend: TcpBackendHandler + BackendHandler + LoginHandler + OpaqueHandler + Clone + 'static,
|
Backend: TcpBackendHandler + BackendHandler + LoginHandler + OpaqueHandler + Clone + 'static,
|
||||||
@@ -121,6 +130,7 @@ fn http_config<Backend>(
|
|||||||
jwt_key: hmac::Mac::new_from_slice(jwt_secret.unsecure().as_bytes()).unwrap(),
|
jwt_key: hmac::Mac::new_from_slice(jwt_secret.unsecure().as_bytes()).unwrap(),
|
||||||
jwt_blacklist: RwLock::new(jwt_blacklist),
|
jwt_blacklist: RwLock::new(jwt_blacklist),
|
||||||
server_url,
|
server_url,
|
||||||
|
assets_path: assets_path.clone(),
|
||||||
mail_options,
|
mail_options,
|
||||||
}))
|
}))
|
||||||
.route(
|
.route(
|
||||||
@@ -138,16 +148,22 @@ fn http_config<Backend>(
|
|||||||
.configure(super::graphql::api::configure_endpoint::<Backend>),
|
.configure(super::graphql::api::configure_endpoint::<Backend>),
|
||||||
)
|
)
|
||||||
.service(
|
.service(
|
||||||
web::resource("/pkg/lldap_app_bg.wasm.gz").route(web::route().to(wasm_handler_compressed)),
|
web::resource("/pkg/lldap_app_bg.wasm.gz")
|
||||||
|
.route(web::route().to(wasm_handler_compressed::<Backend>)),
|
||||||
|
)
|
||||||
|
.service(
|
||||||
|
web::resource("/pkg/lldap_app_bg.wasm").route(web::route().to(wasm_handler::<Backend>)),
|
||||||
)
|
)
|
||||||
.service(web::resource("/pkg/lldap_app_bg.wasm").route(web::route().to(wasm_handler)))
|
|
||||||
.service(web::resource("/static/main.js").route(web::route().to(main_js_handler::<Backend>)))
|
.service(web::resource("/static/main.js").route(web::route().to(main_js_handler::<Backend>)))
|
||||||
// Serve the /pkg path with the compiled WASM app.
|
// Serve the /pkg path with the compiled WASM app.
|
||||||
.service(Files::new("/pkg", "./app/pkg"))
|
.service(Files::new("/pkg", assets_path.join("pkg")))
|
||||||
// Serve static files
|
// Serve static files
|
||||||
.service(Files::new("/static", "./app/static"))
|
.service(Files::new("/static", assets_path.join("static")))
|
||||||
// Serve static fonts
|
// Serve static fonts
|
||||||
.service(Files::new("/static/fonts", "./app/static/fonts"))
|
.service(Files::new(
|
||||||
|
"/static/fonts",
|
||||||
|
assets_path.join("static/fonts"),
|
||||||
|
))
|
||||||
// Default to serve index.html for unknown routes, to support routing.
|
// Default to serve index.html for unknown routes, to support routing.
|
||||||
.default_service(web::route().guard(guard::Get()).to(index::<Backend>));
|
.default_service(web::route().guard(guard::Get()).to(index::<Backend>));
|
||||||
}
|
}
|
||||||
@@ -157,6 +173,7 @@ pub(crate) struct AppState<Backend> {
|
|||||||
pub jwt_key: Hmac<Sha512>,
|
pub jwt_key: Hmac<Sha512>,
|
||||||
pub jwt_blacklist: RwLock<HashSet<u64>>,
|
pub jwt_blacklist: RwLock<HashSet<u64>>,
|
||||||
pub server_url: url::Url,
|
pub server_url: url::Url,
|
||||||
|
pub assets_path: PathBuf,
|
||||||
pub mail_options: MailOptions,
|
pub mail_options: MailOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,8 +212,12 @@ where
|
|||||||
.await
|
.await
|
||||||
.context("while getting the jwt blacklist")?;
|
.context("while getting the jwt blacklist")?;
|
||||||
let server_url = config.http_url.0.clone();
|
let server_url = config.http_url.0.clone();
|
||||||
|
let assets_path = config.assets_path.clone();
|
||||||
let mail_options = config.smtp_options.clone();
|
let mail_options = config.smtp_options.clone();
|
||||||
let verbose = config.verbose;
|
let verbose = config.verbose;
|
||||||
|
if !assets_path.join("index.html").exists() {
|
||||||
|
warn!("Cannot find {}, please ensure that assets_path is set correctly and that the front-end files exist.", assets_path.to_string_lossy())
|
||||||
|
}
|
||||||
info!("Starting the API/web server on port {}", config.http_port);
|
info!("Starting the API/web server on port {}", config.http_port);
|
||||||
server_builder
|
server_builder
|
||||||
.bind(
|
.bind(
|
||||||
@@ -207,6 +228,7 @@ where
|
|||||||
let jwt_secret = jwt_secret.clone();
|
let jwt_secret = jwt_secret.clone();
|
||||||
let jwt_blacklist = jwt_blacklist.clone();
|
let jwt_blacklist = jwt_blacklist.clone();
|
||||||
let server_url = server_url.clone();
|
let server_url = server_url.clone();
|
||||||
|
let assets_path = assets_path.clone();
|
||||||
let mail_options = mail_options.clone();
|
let mail_options = mail_options.clone();
|
||||||
HttpServiceBuilder::default()
|
HttpServiceBuilder::default()
|
||||||
.finish(map_config(
|
.finish(map_config(
|
||||||
@@ -222,6 +244,7 @@ where
|
|||||||
jwt_secret,
|
jwt_secret,
|
||||||
jwt_blacklist,
|
jwt_blacklist,
|
||||||
server_url,
|
server_url,
|
||||||
|
assets_path,
|
||||||
mail_options,
|
mail_options,
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
|
|||||||
Reference in New Issue
Block a user