Skip to main content

tablo_test/protocol/
impersonation.rs

1//! Reads the banner a panel page shows while its signed-in user is acted as another:
2//! `[data-impersonating]`, naming the target's id, and the form its Stop button posts; and the
3//! buttons `auth::impersonate_button` renders, `form[data-impersonate]`.
4
5use super::dom::{attr_value, elements, strip_text};
6
7/// The banner over a page a user reads while acting as another.
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct ImpersonationBanner {
10    /// The `user_id` of the user being acted as.
11    pub user_id: String,
12    /// What the banner says, the Stop button's label included.
13    pub text: String,
14    /// Where its Stop button posts.
15    pub stop: String,
16}
17
18/// The banner `html` shows, or `None` while the signed-in user acts as themselves.
19pub fn impersonation_banner(html: &str) -> Option<ImpersonationBanner> {
20    let (_, attrs, inner) = elements(html, "div")
21        .into_iter()
22        .find(|(_, attrs, _)| attr_value(attrs, "data-impersonating").is_some())?;
23    let stop = elements(&inner, "form")
24        .into_iter()
25        .find_map(|(_, attrs, _)| attr_value(&attrs, "action"))?;
26    Some(ImpersonationBanner {
27        user_id: attr_value(&attrs, "data-impersonating")?,
28        text: strip_text(&inner),
29        stop,
30    })
31}
32
33/// The `user_id`s the `auth::impersonate_button` forms of `html` act as, in document order.
34pub fn impersonate_buttons(html: &str) -> Vec<String> {
35    elements(html, "form")
36        .into_iter()
37        .filter_map(|(_, attrs, _)| attr_value(&attrs, "data-impersonate"))
38        .collect()
39}