use async_trait::async_trait;
use reqwest::{Client, RequestBuilder, Url};
use static_assertions::assert_impl_all;
use super::internal::Internal;
use super::protocol;
use super::{IdOrName, Scope};
use crate::{AuthType, EndpointFilters, Error};
#[derive(Debug, Clone)]
pub struct Token {
inner: Internal,
}
assert_impl_all!(Token: Send, Sync);
impl Token {
pub fn new<U, S>(auth_url: U, token: S) -> Result<Self, Error>
where
U: AsRef<str>,
S: Into<String>,
{
let body = protocol::AuthRoot {
auth: protocol::Auth {
identity: protocol::Identity::Token(token.into()),
scope: None,
},
};
Ok(Self {
inner: Internal::new(auth_url.as_ref(), body)?,
})
}
#[inline]
pub fn set_project_scope(&mut self, project: IdOrName, domain: impl Into<Option<IdOrName>>) {
self.set_scope(Scope::Project {
project,
domain: domain.into(),
});
}
#[inline]
pub fn set_scope(&mut self, scope: Scope) {
self.inner.set_scope(scope);
}
#[inline]
pub fn with_project_scope(
mut self,
project: IdOrName,
domain: impl Into<Option<IdOrName>>,
) -> Token {
self.set_project_scope(project, domain);
self
}
#[inline]
pub fn with_scope(mut self, scope: Scope) -> Self {
self.set_scope(scope);
self
}
#[inline]
pub fn project(&self) -> Option<&IdOrName> {
self.inner.project()
}
}
#[async_trait]
impl AuthType for Token {
async fn authenticate(
&self,
client: &Client,
request: RequestBuilder,
) -> Result<RequestBuilder, Error> {
self.inner.authenticate(client, request).await
}
async fn get_endpoint(
&self,
client: &Client,
service_type: &str,
filters: &EndpointFilters,
) -> Result<Url, Error> {
self.inner.get_endpoint(client, service_type, filters).await
}
async fn refresh(&self, client: &Client) -> Result<(), Error> {
self.inner.refresh(client, true).await
}
}
#[cfg(test)]
pub mod test {
#![allow(unused_results)]
use reqwest::Url;
use super::Token;
use crate::identity::IdOrName;
#[test]
fn test_identity_new() {
let id = Token::new("http://127.0.0.1:8080/", "abcdef").unwrap();
let e = Url::parse(id.inner.token_endpoint()).unwrap();
assert_eq!(e.scheme(), "http");
assert_eq!(e.host_str().unwrap(), "127.0.0.1");
assert_eq!(e.port().unwrap(), 8080u16);
assert_eq!(e.path(), "/v3/auth/tokens");
}
#[test]
fn test_identity_new_invalid() {
Token::new("http://127.0.0.1 8080/", "abcdef")
.err()
.unwrap();
}
#[test]
fn test_identity_create() {
let id = Token::new("http://127.0.0.1:8080/identity", "abcdef")
.unwrap()
.with_project_scope(
IdOrName::Name("cool project".to_string()),
IdOrName::Name("example.com".to_string()),
);
assert_eq!(
id.project(),
Some(&IdOrName::Name("cool project".to_string()))
);
assert_eq!(
id.inner.token_endpoint(),
"http://127.0.0.1:8080/identity/v3/auth/tokens"
);
}
#[test]
fn test_token_endpoint_with_trailing_slash() {
let id = Token::new("http://127.0.0.1:8080/identity/", "abcdef")
.unwrap()
.with_project_scope(
IdOrName::Name("cool project".to_string()),
IdOrName::Name("example.com".to_string()),
);
assert_eq!(
id.project(),
Some(&IdOrName::Name("cool project".to_string()))
);
assert_eq!(
id.inner.token_endpoint(),
"http://127.0.0.1:8080/identity/v3/auth/tokens"
);
}
#[test]
fn test_token_endpoint_with_v3() {
let id = Token::new("http://127.0.0.1:8080/identity/v3", "abcdef")
.unwrap()
.with_project_scope(
IdOrName::Name("cool project".to_string()),
IdOrName::Name("example.com".to_string()),
);
assert_eq!(
id.project(),
Some(&IdOrName::Name("cool project".to_string()))
);
assert_eq!(
id.inner.token_endpoint(),
"http://127.0.0.1:8080/identity/v3/auth/tokens"
);
}
#[test]
fn test_token_endpoint_with_trailing_slash_v3() {
let id = Token::new("http://127.0.0.1:8080/identity/v3/", "abcdef")
.unwrap()
.with_project_scope(
IdOrName::Name("cool project".to_string()),
IdOrName::Name("example.com".to_string()),
);
assert_eq!(
id.project(),
Some(&IdOrName::Name("cool project".to_string()))
);
assert_eq!(
id.inner.token_endpoint(),
"http://127.0.0.1:8080/identity/v3/auth/tokens"
);
}
#[test]
fn test_token_endpoint_root() {
let id = Token::new("http://127.0.0.1:8080", "abcdef")
.unwrap()
.with_project_scope(
IdOrName::Name("cool project".to_string()),
IdOrName::Name("example.com".to_string()),
);
assert_eq!(
id.project(),
Some(&IdOrName::Name("cool project".to_string()))
);
assert_eq!(
id.inner.token_endpoint(),
"http://127.0.0.1:8080/v3/auth/tokens"
);
}
}