use serde::{Deserialize, Serialize};
use url::Url;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PublicKey {
pub id: Url,
pub owner: Url,
pub public_key_pem: String,
}
impl PublicKey {
#[must_use]
pub fn new(id: Url, owner: Url, public_key_pem: impl Into<String>) -> Self {
Self {
id,
owner,
public_key_pem: public_key_pem.into(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Endpoints {
#[serde(skip_serializing_if = "Option::is_none")]
pub shared_inbox: Option<Url>,
#[serde(skip_serializing_if = "Option::is_none")]
pub oauth_authorization_endpoint: Option<Url>,
#[serde(skip_serializing_if = "Option::is_none")]
pub oauth_token_endpoint: Option<Url>,
#[serde(skip_serializing_if = "Option::is_none")]
pub provide_client_key: Option<Url>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sign_client_key: Option<Url>,
#[serde(skip_serializing_if = "Option::is_none")]
pub proxy_url: Option<Url>,
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;
use serde_json::json;
use super::*;
#[test]
fn public_key_roundtrips_in_mastodon_shape() {
let raw = json!({
"id": "https://mastodon.social/users/alice#main-key",
"owner": "https://mastodon.social/users/alice",
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIB…\n-----END PUBLIC KEY-----\n"
});
let key: PublicKey = serde_json::from_value(raw.clone()).unwrap();
assert_eq!(key.owner.as_str(), "https://mastodon.social/users/alice");
let back = serde_json::to_value(&key).unwrap();
assert_eq!(back, raw);
}
#[test]
fn endpoints_with_only_shared_inbox_omits_other_fields() {
let endpoints = Endpoints {
shared_inbox: Some(Url::parse("https://mastodon.social/inbox").unwrap()),
..Endpoints::default()
};
let v = serde_json::to_value(&endpoints).unwrap();
assert_eq!(v, json!({ "sharedInbox": "https://mastodon.social/inbox" }));
}
#[test]
fn endpoints_full_roundtrip() {
let raw = json!({
"sharedInbox": "https://example.com/inbox",
"oauthAuthorizationEndpoint": "https://example.com/oauth/authorize",
"oauthTokenEndpoint": "https://example.com/oauth/token"
});
let endpoints: Endpoints = serde_json::from_value(raw.clone()).unwrap();
assert!(endpoints.shared_inbox.is_some());
assert!(endpoints.oauth_authorization_endpoint.is_some());
let back = serde_json::to_value(&endpoints).unwrap();
assert_eq!(back, raw);
}
}