tag2upload_service_manager/
ui_vhost.rs1
2use crate::prelude::*;
3
4use rocket::{Request, request::{FromRequest, Outcome}};
5use rocket::http::uncased::UncasedStr;
6
7const HEADER: &str = "Host";
8
9#[derive(Deserialize, Debug, Deftly)]
16#[derive_deftly(Guards)]
17pub struct Vhosts {
18 pub webhook: Vec<String>,
19 pub ui: Vec<String>,
20}
21
22pub struct Is<S>(S);
23
24pub struct ResultGuard<S>(Result<Is<S>, WrongVhost>);
32
33impl<S> ResultGuard<S> {
34 pub fn check(
35 self,
36 map_err: impl FnOnce(AE) -> WebError,
37 ) -> Result<Is<S>, WE> {
38 self.0.map_err(|e| map_err(e.0))
39 }
40}
41
42#[derive(Error, Debug)]
43#[error("{0}")]
44pub struct WrongVhost(AE);
45
46fn check_core(supplied: &UncasedStr, configured: &[String])
47 -> Result<(), WrongVhost>
48{
49 if !configured.iter().any({
50 |c| c == "*" || c == supplied}
51 ) {
52 return Err(WrongVhost(anyhow!(
53 "wrong server name (vhost) requested: {HEADER:?} was {:?}, expected {}",
54 supplied.as_str(), configured.join(" / "),
55 )));
56 }
57
58 Ok(())
59}
60
61pub trait Selector: Default {
62 fn configured(vhosts: &Vhosts) -> &[String];
63}
64
65impl<S: Selector> Is<S> {
66 pub async fn from_request<'r>(req: &'r Request<'_>)
67 -> Result<Self, WrongVhost>
68 {
69 let supplied: &rocket::http::uri::Host = match {
70 FromRequest::from_request(req).await
71 } {
72 Outcome::Success(y) => Ok(y),
73 x @ Outcome::Forward(..) => Err(WrongVhost(
74 internal!("internal error {x:?} from Host!")
75 .into()
76 )),
77 Outcome::Error((_s, i)) => match i {},
78 }?;
79
80 let gl = globals();
81 let configured = S::configured(&gl.config.vhosts);
82 let () = check_core(supplied.domain(), configured)?;
83 Ok(Is(S::default()))
84 }
85}
86
87#[async_trait]
88impl<'r, S: Selector> FromRequest<'r> for ResultGuard<S> {
89 type Error = String;
90
91 async fn from_request(req: &'r Request<'_>) -> Outcome<Self, String> {
92 Outcome::Success(ResultGuard(Is::from_request(req).await))
93 }
94}
95
96define_derive_deftly! {
97 Guards:
98
99 ${define V $<${pascal_case $fname}>}
100 ${define S $<$V Selector>}
101
102 $(
103 pub type $<Is $V> = Is<$S>;
105
106 pub type $<$V Result> = ResultGuard<$S>;
108
109 #[derive(Default)]
110 pub struct $S;
111
112 impl Selector for $S {
113 fn configured(vhosts: &Vhosts) -> &[String] {
114 &vhosts.$fname
115 }
116 }
117 )
118}
119use derive_deftly_template_Guards;