use crate::auth::claims::common::ArrayOrValue;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(transparent)]
pub struct Audience(ArrayOrValue<String>);
impl From<ArrayOrValue<String>> for Audience {
fn from(audience: ArrayOrValue<String>) -> Self {
Self(audience)
}
}
impl Audience {
pub fn new(audience: impl Into<String>) -> Self {
Self(ArrayOrValue::single(audience.into()))
}
pub fn add_audience(self, audience: impl Into<String>) -> Self {
Self(self.0.add(audience.into()))
}
pub fn contains(&self, audience: &str) -> bool {
self.0.contains(audience)
}
}
impl From<String> for Audience {
fn from(audience: String) -> Self {
Self::new(audience)
}
}
impl From<Vec<String>> for Audience {
fn from(audiences: Vec<String>) -> Self {
Self(ArrayOrValue::from_iter(audiences))
}
}
#[cfg(feature = "test_utils")]
impl<T> fake::Dummy<T> for Audience {
fn dummy_with_rng<R: rand::Rng + ?Sized>(_: &T, _rng: &mut R) -> Self {
Self::new("https://console-api.stashdata.net")
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
mod single {
use super::*;
#[test]
fn serializes_as_literal() {
let audience = Audience::new("http://example.com");
let serialized = serde_json::to_value(&audience).unwrap();
assert_eq!(serialized, json!("http://example.com"));
}
#[test]
fn deserializes_from_literal() {
let audience: Audience = serde_json::from_str(r#""http://example.com""#).unwrap();
assert_eq!(
audience.0,
ArrayOrValue::single("http://example.com".to_string())
);
}
}
mod multiple {
use super::*;
#[test]
fn serializes_as_array() {
let target_a = "http://example.com";
let target_b = "http://another-example.com";
let audience = Audience::new(target_a).add_audience(target_b);
let serialized = serde_json::to_value(&audience).unwrap();
assert!(
serialized == json!([target_a, target_b])
|| serialized == json!([target_b, target_a]),
"Serialized audience should be an array of two URLs, got: {serialized}"
);
}
#[test]
fn deserializes_from_array() {
let audience: Audience =
serde_json::from_str(r#"["http://example.com","http://another-example.com"]"#)
.unwrap();
assert_eq!(
audience.0,
ArrayOrValue::from_iter(vec![
"http://example.com".to_string(),
"http://another-example.com".to_string(),
])
);
}
}
}