1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-11-21 23:00:50 +03:00

Link between login & register + "back to client" link

This commit is contained in:
Quentin Gliech
2021-12-14 10:29:19 +01:00
parent daf5542e6d
commit 5d7619827b
16 changed files with 313 additions and 47 deletions

View File

@@ -14,10 +14,16 @@
//! Additional functions, tests and filters used in templates
use std::{collections::HashMap, str::FromStr};
use tera::{helpers::tests::number_args_allowed, Tera, Value};
use url::Url;
pub fn register(tera: &mut Tera) {
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);
}
fn tester_empty(value: Option<&Value>, params: &[Value]) -> Result<bool, tera::Error> {
@@ -28,3 +34,84 @@ fn tester_empty(value: Option<&Value>, params: &[Value]) -> Result<bool, tera::E
Some(_) => Ok(false),
}
}
enum ParamsWhere {
Fragment,
Query,
}
fn function_add_params_to_uri(params: &HashMap<String, Value>) -> Result<Value, tera::Error> {
use ParamsWhere::{Fragment, Query};
// First, get the `uri`, `mode` and `params` parameters
let uri = params
.get("uri")
.and_then(Value::as_str)
.ok_or_else(|| tera::Error::msg("Invalid parameter `uri`"))?;
let uri = Url::from_str(uri).map_err(|e| tera::Error::chain(uri, e))?;
let mode = params
.get("mode")
.and_then(Value::as_str)
.ok_or_else(|| tera::Error::msg("Invalid parameter `mode`"))?;
let mode = match mode {
"fragment" => Fragment,
"query" => Query,
_ => return Err(tera::Error::msg("Invalid mode")),
};
let params = params
.get("params")
.and_then(Value::as_object)
.ok_or_else(|| tera::Error::msg("Invalid parameter `params`"))?;
// Get the relevant part of the URI and parse for existing parameters
let existing = match mode {
Fragment => uri.fragment(),
Query => uri.query(),
};
let existing: HashMap<String, Value> = existing
.map(serde_urlencoded::from_str)
.transpose()
.map_err(|e| tera::Error::chain(e, "Could not parse existing `uri` parameters"))?
.unwrap_or_default();
// Merge the exising and the additional parameters together
let params: HashMap<&String, &Value> = params
.iter()
// Filter out the `uri` and `mode` params
.filter(|(k, _v)| k != &"uri" && k != &"mode")
.chain(existing.iter())
.collect();
// Transform them back to urlencoded
let params = serde_urlencoded::to_string(params)
.map_err(|e| tera::Error::chain(e, "Could not serialize back parameters"))?;
let uri = {
let mut uri = uri;
match mode {
Fragment => uri.set_fragment(Some(&params)),
Query => uri.set_query(Some(&params)),
};
uri
};
Ok(Value::String(uri.to_string()))
}
fn function_merge(params: &HashMap<String, Value>) -> Result<Value, tera::Error> {
let mut ret = serde_json::Map::new();
for (k, v) in params {
let v = v
.as_object()
.ok_or_else(|| tera::Error::msg(format!("Parameter {:?} should be an object", k)))?;
ret.extend(v.clone());
}
Ok(Value::Object(ret))
}
#[allow(clippy::unnecessary_wraps)]
fn function_dict(params: &HashMap<String, Value>) -> Result<Value, tera::Error> {
let ret = params.clone().into_iter().collect();
Ok(Value::Object(ret))
}