You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-08-07 17:03:01 +03:00
Mount the static assets on /assets
This commit is contained in:
@@ -27,7 +27,7 @@ use mas_email::Mailer;
|
||||
use mas_handlers::{AppState, MatrixHomeserver};
|
||||
use mas_http::ServerLayer;
|
||||
use mas_policy::PolicyFactory;
|
||||
use mas_router::UrlBuilder;
|
||||
use mas_router::{Route, UrlBuilder};
|
||||
use mas_storage::MIGRATOR;
|
||||
use mas_tasks::TaskQueue;
|
||||
use mas_templates::Templates;
|
||||
@@ -201,8 +201,14 @@ impl Options {
|
||||
.context("failed to load the policy")?;
|
||||
let policy_factory = Arc::new(policy_factory);
|
||||
|
||||
let url_builder = UrlBuilder::new(config.http.public_base.clone());
|
||||
|
||||
// Load and compile the templates
|
||||
let templates = Templates::load(config.templates.path.clone(), config.templates.builtin)
|
||||
let templates = Templates::load(
|
||||
config.templates.path.clone(),
|
||||
config.templates.builtin,
|
||||
url_builder.clone(),
|
||||
)
|
||||
.await
|
||||
.context("could not load templates")?;
|
||||
|
||||
@@ -213,8 +219,6 @@ impl Options {
|
||||
&config.email.reply_to,
|
||||
);
|
||||
|
||||
let url_builder = UrlBuilder::new(config.http.public_base.clone());
|
||||
|
||||
let static_files = mas_static_files::service(&config.http.web_root);
|
||||
|
||||
let homeserver = MatrixHomeserver::new(config.matrix.homeserver.clone());
|
||||
@@ -246,7 +250,7 @@ impl Options {
|
||||
};
|
||||
|
||||
let router = mas_handlers::router(state)
|
||||
.fallback_service(static_files)
|
||||
.nest(mas_router::StaticAsset::route(), static_files)
|
||||
.layer(ServerLayer::default());
|
||||
|
||||
info!("Listening on http://{}", listener.local_addr().unwrap());
|
||||
|
@@ -15,7 +15,6 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::Parser;
|
||||
use mas_config::TemplatesConfig;
|
||||
use mas_templates::Templates;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
@@ -58,11 +57,9 @@ impl Options {
|
||||
}
|
||||
|
||||
SC::Check { path, skip_builtin } => {
|
||||
let config = TemplatesConfig {
|
||||
path: Some(path.to_string()),
|
||||
builtin: !skip_builtin,
|
||||
};
|
||||
let templates = Templates::load(config.path.clone(), config.builtin).await?;
|
||||
let url_builder = mas_router::UrlBuilder::new("https://example.com/".parse()?);
|
||||
let templates =
|
||||
Templates::load(Some(path.into()), !skip_builtin, url_builder).await?;
|
||||
templates.check_render().await?;
|
||||
|
||||
Ok(())
|
||||
|
@@ -280,7 +280,9 @@ where
|
||||
async fn test_state(pool: PgPool) -> Result<Arc<AppState>, anyhow::Error> {
|
||||
use mas_email::MailTransport;
|
||||
|
||||
let templates = Templates::load(None, true).await?;
|
||||
let url_builder = UrlBuilder::new("https://example.com/".parse()?);
|
||||
|
||||
let templates = Templates::load(None, true, url_builder.clone()).await?;
|
||||
|
||||
// TODO: add test keys to the store
|
||||
let key_store = Keystore::default();
|
||||
@@ -291,8 +293,6 @@ async fn test_state(pool: PgPool) -> Result<Arc<AppState>, anyhow::Error> {
|
||||
let mailbox = "server@example.com".parse()?;
|
||||
let mailer = Mailer::new(&templates, &transport, &mailbox, &mailbox);
|
||||
|
||||
let url_builder = UrlBuilder::new("https://example.com/".parse()?);
|
||||
|
||||
let homeserver = MatrixHomeserver::new("example.com".to_owned());
|
||||
let policy_factory = PolicyFactory::load_default(serde_json::json!({})).await?;
|
||||
let policy_factory = Arc::new(policy_factory);
|
||||
|
@@ -522,3 +522,26 @@ impl Route for CompatLoginSsoComplete {
|
||||
format!("/complete-compat-sso/{}", self.id).into()
|
||||
}
|
||||
}
|
||||
|
||||
/// `GET /assets`
|
||||
pub struct StaticAsset {
|
||||
path: String,
|
||||
}
|
||||
|
||||
impl StaticAsset {
|
||||
#[must_use]
|
||||
pub fn new(path: String) -> Self {
|
||||
Self { path }
|
||||
}
|
||||
}
|
||||
|
||||
impl Route for StaticAsset {
|
||||
type Query = ();
|
||||
fn route() -> &'static str {
|
||||
"/assets"
|
||||
}
|
||||
|
||||
fn path(&self) -> std::borrow::Cow<'static, str> {
|
||||
format!("/assets/{}", self.path).into()
|
||||
}
|
||||
}
|
||||
|
@@ -91,4 +91,10 @@ impl UrlBuilder {
|
||||
pub fn jwks_uri(&self) -> Url {
|
||||
self.url_for(&crate::endpoints::OAuth2Keys)
|
||||
}
|
||||
|
||||
/// Static asset
|
||||
#[must_use]
|
||||
pub fn static_asset(&self, path: String) -> Url {
|
||||
self.url_for(&crate::endpoints::StaticAsset::new(path))
|
||||
}
|
||||
}
|
||||
|
@@ -16,14 +16,16 @@
|
||||
|
||||
use std::{collections::HashMap, str::FromStr};
|
||||
|
||||
use mas_router::{Route, UrlBuilder};
|
||||
use tera::{helpers::tests::number_args_allowed, Tera, Value};
|
||||
use url::Url;
|
||||
|
||||
pub fn register(tera: &mut Tera) {
|
||||
pub fn register(tera: &mut Tera, url_builder: UrlBuilder) {
|
||||
tera.register_tester("empty", self::tester_empty);
|
||||
tera.register_function("add_params_to_uri", function_add_params_to_uri);
|
||||
tera.register_function("merge", function_merge);
|
||||
tera.register_function("dict", function_dict);
|
||||
tera.register_function("static_asset", make_static_asset(url_builder));
|
||||
}
|
||||
|
||||
fn tester_empty(value: Option<&Value>, params: &[Value]) -> Result<bool, tera::Error> {
|
||||
@@ -115,3 +117,26 @@ fn function_dict(params: &HashMap<String, Value>) -> Result<Value, tera::Error>
|
||||
let ret = params.clone().into_iter().collect();
|
||||
Ok(Value::Object(ret))
|
||||
}
|
||||
|
||||
fn make_static_asset(url_builder: UrlBuilder) -> impl tera::Function {
|
||||
Box::new(
|
||||
move |args: &HashMap<String, Value>| -> Result<Value, tera::Error> {
|
||||
if let Some(path) = args.get("path").and_then(Value::as_str) {
|
||||
let absolute = args
|
||||
.get("absolute")
|
||||
.and_then(Value::as_bool)
|
||||
.unwrap_or(false);
|
||||
let path = path.to_owned();
|
||||
let url = if absolute {
|
||||
url_builder.static_asset(path).into()
|
||||
} else {
|
||||
let destination = mas_router::StaticAsset::new(path);
|
||||
destination.relative_url().into_owned()
|
||||
};
|
||||
Ok(Value::String(url))
|
||||
} else {
|
||||
Err(tera::Error::msg("Invalid parameter 'path'"))
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@@ -34,6 +34,7 @@ use std::{
|
||||
|
||||
use anyhow::{bail, Context as _};
|
||||
use mas_data_model::StorageBackend;
|
||||
use mas_router::UrlBuilder;
|
||||
use serde::Serialize;
|
||||
use tera::{Context, Error as TeraError, Tera};
|
||||
use thiserror::Error;
|
||||
@@ -62,6 +63,7 @@ pub use self::{
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Templates {
|
||||
tera: Arc<RwLock<Tera>>,
|
||||
url_builder: UrlBuilder,
|
||||
path: Option<String>,
|
||||
builtin: bool,
|
||||
}
|
||||
@@ -134,16 +136,25 @@ impl Templates {
|
||||
}
|
||||
|
||||
/// Load the templates from the given config
|
||||
pub async fn load(path: Option<String>, builtin: bool) -> Result<Self, TemplateLoadingError> {
|
||||
let tera = Self::load_(path.as_deref(), builtin).await?;
|
||||
pub async fn load(
|
||||
path: Option<String>,
|
||||
builtin: bool,
|
||||
url_builder: UrlBuilder,
|
||||
) -> Result<Self, TemplateLoadingError> {
|
||||
let tera = Self::load_(path.as_deref(), builtin, url_builder.clone()).await?;
|
||||
Ok(Self {
|
||||
tera: Arc::new(RwLock::new(tera)),
|
||||
path,
|
||||
url_builder,
|
||||
builtin,
|
||||
})
|
||||
}
|
||||
|
||||
async fn load_(path: Option<&str>, builtin: bool) -> Result<Tera, TemplateLoadingError> {
|
||||
async fn load_(
|
||||
path: Option<&str>,
|
||||
builtin: bool,
|
||||
url_builder: UrlBuilder,
|
||||
) -> Result<Tera, TemplateLoadingError> {
|
||||
let mut teras = Vec::new();
|
||||
|
||||
let roots = Self::roots(path, builtin).await;
|
||||
@@ -183,7 +194,7 @@ impl Templates {
|
||||
tera.build_inheritance_chains()?;
|
||||
tera.check_macro_files()?;
|
||||
|
||||
self::functions::register(&mut tera);
|
||||
self::functions::register(&mut tera, url_builder);
|
||||
|
||||
let loaded: HashSet<_> = tera.get_template_names().collect();
|
||||
let needed: HashSet<_> = TEMPLATES.into_iter().map(|(name, _)| name).collect();
|
||||
@@ -202,7 +213,8 @@ impl Templates {
|
||||
/// Reload the templates on disk
|
||||
pub async fn reload(&self) -> anyhow::Result<()> {
|
||||
// Prepare the new Tera instance
|
||||
let new_tera = Self::load_(self.path.as_deref(), self.builtin).await?;
|
||||
let new_tera =
|
||||
Self::load_(self.path.as_deref(), self.builtin, self.url_builder.clone()).await?;
|
||||
|
||||
// Swap it
|
||||
*self.tera.write().await = new_tera;
|
||||
@@ -378,7 +390,8 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn check_builtin_templates() {
|
||||
let templates = Templates::load(None, true).await.unwrap();
|
||||
let url_builder = UrlBuilder::new("https://example.com/".parse().unwrap());
|
||||
let templates = Templates::load(None, true, url_builder).await.unwrap();
|
||||
templates.check_render().await.unwrap();
|
||||
}
|
||||
}
|
||||
|
@@ -27,7 +27,7 @@ limitations under the License.
|
||||
<meta charset="utf-8">
|
||||
<title>{% block title %}matrix-authentication-service{% endblock title %}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="/tailwind.css">
|
||||
<link rel="stylesheet" href="{{ static_asset(path='tailwind.css') }}">
|
||||
</head>
|
||||
<body class="bg-white text-black-900 dark:bg-black-800 dark:text-white flex flex-col min-h-screen">
|
||||
{% block content %}{% endblock content %}
|
||||
|
Reference in New Issue
Block a user