use ruma::{
OwnedDeviceId,
api::client::discovery::get_authorization_server_metadata::v1::AccountManagementAction,
};
use url::Url;
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum AccountManagementActionFull {
Profile,
SessionsList,
SessionView {
device_id: OwnedDeviceId,
},
SessionEnd {
device_id: OwnedDeviceId,
},
AccountDeactivate,
CrossSigningReset,
}
impl AccountManagementActionFull {
pub fn action_type(&self) -> AccountManagementAction {
match self {
Self::Profile => AccountManagementAction::Profile,
Self::SessionsList => AccountManagementAction::SessionsList,
Self::SessionView { .. } => AccountManagementAction::SessionView,
Self::SessionEnd { .. } => AccountManagementAction::SessionEnd,
Self::AccountDeactivate => AccountManagementAction::AccountDeactivate,
Self::CrossSigningReset => AccountManagementAction::CrossSigningReset,
}
}
fn append_to_url(&self, url: &mut Url) {
let mut query_pairs = url.query_pairs_mut();
query_pairs.append_pair("action", self.action_type().as_str());
match self {
Self::SessionView { device_id } | Self::SessionEnd { device_id } => {
query_pairs.append_pair("device_id", device_id.as_str());
}
_ => {}
}
}
}
#[derive(Debug, Clone)]
pub struct AccountManagementUrlBuilder {
account_management_uri: Url,
action: Option<AccountManagementActionFull>,
}
impl AccountManagementUrlBuilder {
pub(super) fn new(account_management_uri: Url) -> Self {
Self { account_management_uri, action: None }
}
pub fn action(mut self, action: AccountManagementActionFull) -> Self {
self.action = Some(action);
self
}
pub fn build(self) -> Url {
let mut account_management_uri = self.account_management_uri;
if let Some(action) = &self.action {
action.append_to_url(&mut account_management_uri);
}
account_management_uri
}
}
#[cfg(test)]
mod tests {
use ruma::owned_device_id;
use url::Url;
use super::{AccountManagementActionFull, AccountManagementUrlBuilder};
#[test]
fn test_build_account_management_url_actions() {
let base_url = Url::parse("https://example.org").unwrap();
let device_id = owned_device_id!("ABCDEFG");
let url = AccountManagementUrlBuilder::new(base_url.clone()).build();
assert_eq!(url, base_url);
let url = AccountManagementUrlBuilder::new(base_url.clone())
.action(AccountManagementActionFull::Profile)
.build();
assert_eq!(url.as_str(), "https://example.org/?action=org.matrix.profile");
let url = AccountManagementUrlBuilder::new(base_url.clone())
.action(AccountManagementActionFull::SessionsList)
.build();
assert_eq!(url.as_str(), "https://example.org/?action=org.matrix.sessions_list");
let url = AccountManagementUrlBuilder::new(base_url.clone())
.action(AccountManagementActionFull::SessionView { device_id: device_id.clone() })
.build();
assert_eq!(
url.as_str(),
"https://example.org/?action=org.matrix.session_view&device_id=ABCDEFG"
);
let url = AccountManagementUrlBuilder::new(base_url.clone())
.action(AccountManagementActionFull::SessionEnd { device_id })
.build();
assert_eq!(
url.as_str(),
"https://example.org/?action=org.matrix.session_end&device_id=ABCDEFG"
);
let url = AccountManagementUrlBuilder::new(base_url.clone())
.action(AccountManagementActionFull::AccountDeactivate)
.build();
assert_eq!(url.as_str(), "https://example.org/?action=org.matrix.account_deactivate");
let url = AccountManagementUrlBuilder::new(base_url)
.action(AccountManagementActionFull::CrossSigningReset)
.build();
assert_eq!(url.as_str(), "https://example.org/?action=org.matrix.cross_signing_reset");
}
#[test]
fn test_build_account_management_url_with_query() {
let base_url = Url::parse("https://example.org/?sid=123456").unwrap();
let url = AccountManagementUrlBuilder::new(base_url.clone())
.action(AccountManagementActionFull::Profile)
.build();
assert_eq!(url.as_str(), "https://example.org/?sid=123456&action=org.matrix.profile");
let url = AccountManagementUrlBuilder::new(base_url)
.action(AccountManagementActionFull::SessionView {
device_id: owned_device_id!("ABCDEFG"),
})
.build();
assert_eq!(
url.as_str(),
"https://example.org/?sid=123456&action=org.matrix.session_view&device_id=ABCDEFG"
);
}
}