#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize)]
pub enum AuthType {
#[serde(rename = "oauth2_user")]
OAuth2User,
#[serde(rename = "oauth1")]
OAuth1,
#[serde(rename = "bearer")]
Bearer,
#[serde(rename = "none")]
None,
}
impl std::fmt::Display for AuthType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
AuthType::OAuth2User => write!(f, "oauth2_user"),
AuthType::OAuth1 => write!(f, "oauth1"),
AuthType::Bearer => write!(f, "bearer"),
AuthType::None => write!(f, "none"),
}
}
}
#[derive(Clone, Debug)]
pub struct CommandReqs {
pub accepted: &'static [AuthType],
}
pub fn auth_flag(auth_type: &AuthType) -> Option<&'static str> {
match auth_type {
AuthType::OAuth2User => None, AuthType::OAuth1 => Some("oauth1"),
AuthType::Bearer => Some("app"),
AuthType::None => None,
}
}
const ME_ACCEPTED: &[AuthType] = &[AuthType::OAuth2User, AuthType::OAuth1];
const OAUTH2_ONLY: &[AuthType] = &[AuthType::OAuth2User];
const PROFILE_ACCEPTED: &[AuthType] = &[AuthType::OAuth2User, AuthType::OAuth1, AuthType::Bearer];
const SEARCH_ACCEPTED: &[AuthType] = &[AuthType::OAuth2User, AuthType::OAuth1, AuthType::Bearer];
const THREAD_ACCEPTED: &[AuthType] = &[AuthType::OAuth2User, AuthType::OAuth1, AuthType::Bearer];
const RAW_ACCEPTED: &[AuthType] = &[AuthType::OAuth2User, AuthType::OAuth1, AuthType::Bearer];
pub fn requirements_for_command(name: &str) -> Option<CommandReqs> {
Some(match name {
"me" => CommandReqs {
accepted: ME_ACCEPTED,
},
"bookmarks" => CommandReqs {
accepted: OAUTH2_ONLY,
},
"get" | "post" | "put" | "delete" => CommandReqs {
accepted: RAW_ACCEPTED,
},
"profile" => CommandReqs {
accepted: PROFILE_ACCEPTED,
},
"search" => CommandReqs {
accepted: SEARCH_ACCEPTED,
},
"thread" => CommandReqs {
accepted: THREAD_ACCEPTED,
},
"tweet" | "reply" | "like" | "unlike" | "repost" | "unrepost" | "follow" | "unfollow"
| "dm" | "block" | "unblock" | "mute" | "unmute" => CommandReqs {
accepted: OAUTH2_ONLY,
},
"watchlist_check" => CommandReqs {
accepted: SEARCH_ACCEPTED,
},
"watchlist_add" | "watchlist_remove" | "watchlist_list" => CommandReqs {
accepted: &[AuthType::None],
},
"usage" => CommandReqs {
accepted: &[AuthType::None],
},
"usage_sync" => CommandReqs {
accepted: &[AuthType::Bearer],
},
"login" => return None,
_ => return None,
})
}
pub fn command_names_with_auth() -> &'static [&'static str] {
&[
"login",
"me",
"bookmarks",
"profile",
"search",
"thread",
"tweet",
"reply",
"like",
"unlike",
"repost",
"unrepost",
"follow",
"unfollow",
"dm",
"block",
"unblock",
"mute",
"unmute",
"watchlist_check",
"watchlist_add",
"watchlist_remove",
"watchlist_list",
"usage",
"usage_sync",
"get",
"post",
"put",
"delete",
]
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn command_names_and_requirements_in_sync() {
for &name in command_names_with_auth() {
if name == "login" {
continue;
}
assert!(
requirements_for_command(name).is_some(),
"command '{}' in command_names_with_auth() but missing from requirements_for_command()",
name
);
}
}
}